notify about SpaceShared

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2023-03-02 15:56:37 +01:00
parent 00c8d68700
commit 49914e1c6b
4 changed files with 104 additions and 69 deletions

View File

@@ -69,6 +69,42 @@ func (ul *UserlogService) SpaceDisabled(ctx context.Context, eventid string, ev
}
// SpaceShared converts a SpaceShared event to an OC10Notification
func (ul *UserlogService) SpaceShared(ctx context.Context, eventid string, ev events.SpaceShared) (OC10Notification, error) {
user, err := ul.getUser(ctx, ev.Executant)
if err != nil {
return OC10Notification{}, err
}
space, err := ul.getSpace(ul.impersonate(user.GetId()), ev.ID.GetOpaqueId())
if err != nil {
return OC10Notification{}, err
}
subj, subjraw, msg, msgraw, err := ul.composeMessage(SpaceShared, map[string]string{
"username": user.GetDisplayName(),
"spacename": space.GetName(),
})
if err != nil {
return OC10Notification{}, err
}
return OC10Notification{
EventID: eventid,
Service: ul.cfg.Service.Name,
UserName: user.GetUsername(),
Timestamp: time.Now().Format(time.RFC3339Nano),
ResourceID: ev.ID.GetOpaqueId(),
ResourceType: _resourceTypeSpace,
Subject: subj,
SubjectRaw: subjraw,
Message: msg,
MessageRaw: msgraw,
MessageDetails: ul.getDetails(user, space, nil),
}, nil
}
func (ul *UserlogService) composeMessage(eventname string, vars map[string]string) (string, string, string, string, error) {
tpl, ok := _templates[eventname]
if !ok {

View File

@@ -106,8 +106,7 @@ func (ul *UserlogService) convertEvent(ctx context.Context, event *ehmsg.Event)
noti.Subject = "Space deleted"
noti.Message = fmt.Sprintf("Space '%s' was deleted", space.Name)
case events.SpaceShared:
noti.Subject = "Space shared"
noti.Message = fmt.Sprintf("Space '%s' was shared", space.Name)
return ul.SpaceShared(ctx, event.Id, ev)
case events.SpaceUnshared:
noti.Subject = "Space unshared"
noti.Message = fmt.Sprintf("Space '%s' was unshared", space.Name)

View File

@@ -91,21 +91,22 @@ func (ul *UserlogService) MemorizeEvents(ch <-chan events.Event) {
case events.SpaceDisabled:
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
case events.SpaceDeleted:
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
// won't work - space is deleted
users, err = nil, errors.New("i do not know whom to inform")
case events.SpaceShared:
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
users, err = ul.resolveID(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID)
case events.SpaceUnshared:
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
users, err = ul.resolveID(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID)
case events.SpaceMembershipExpired:
users, err = ul.resolveShare(ul.impersonate(e.SpaceOwner), e.GranteeUserID, e.GranteeGroupID, e.SpaceID.GetOpaqueId())
users, err = ul.resolveID(ul.impersonate(e.SpaceOwner), e.GranteeUserID, e.GranteeGroupID)
// share related
case events.ShareCreated:
users, err = ul.resolveShare(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
users, err = ul.resolveID(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID)
case events.ShareRemoved:
err = errors.New("no grantee in share removed event")
case events.ShareExpired:
users, err = ul.resolveShare(ul.impersonate(e.ShareOwner), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
users, err = ul.resolveID(ul.impersonate(e.ShareOwner), e.GranteeUserID, e.GranteeGroupID)
}
if err != nil {
@@ -183,20 +184,6 @@ func (ul *UserlogService) DeleteEvents(userid string, evids []string) error {
})
}
func (ul *UserlogService) impersonate(u *user.UserId) context.Context {
if u == nil {
ul.log.Debug().Msg("cannot impersonate nil user")
return nil
}
ctx, _, err := utils.Impersonate(u, ul.gwClient, ul.cfg.MachineAuthAPIKey)
if err != nil {
ul.log.Error().Err(err).Str("userid", u.GetOpaqueId()).Msg("failed to impersonate user")
return nil
}
return ctx
}
func (ul *UserlogService) addEventsToUser(userid string, eventids ...string) error {
return ul.alterUserEventList(userid, func(ids []string) []string {
return append(ids, eventids...)
@@ -283,23 +270,6 @@ func (ul *UserlogService) findSpaceMembers(ctx context.Context, spaceID string,
return users, nil
}
func (ul *UserlogService) getSpace(ctx context.Context, spaceID string) (*storageprovider.StorageSpace, error) {
res, err := ul.gwClient.ListStorageSpaces(ctx, listStorageSpaceRequest(spaceID))
if err != nil {
return nil, err
}
if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
return nil, fmt.Errorf("Unexpected status code while getting space: %v", res.GetStatus().GetCode())
}
if len(res.StorageSpaces) == 0 {
return nil, fmt.Errorf("error getting storage space %s: no space returned", spaceID)
}
return res.StorageSpaces[0], nil
}
func (ul *UserlogService) gatherSpaceMembers(ctx context.Context, space *storageprovider.StorageSpace, hasRequiredRole permissionChecker) ([]string, error) {
var permissionsMap map[string]*storageprovider.ResourcePermissions
if err := utils.ReadJSONFromOpaque(space.GetOpaque(), "grants", &permissionsMap); err != nil {
@@ -343,29 +313,6 @@ func (ul *UserlogService) gatherSpaceMembers(ctx context.Context, space *storage
return users, nil
}
// resolves the users of a group
func (ul *UserlogService) resolveGroup(ctx context.Context, groupID string) ([]string, error) {
if ctx == nil {
return nil, errors.New("need authenticated context to resolve groups")
}
r, err := ul.gwClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: &group.GroupId{OpaqueId: groupID}})
if err != nil {
return nil, err
}
if r.GetStatus().GetCode() != rpc.Code_CODE_OK {
return nil, fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode())
}
var userIDs []string
for _, m := range r.GetGroup().GetMembers() {
userIDs = append(userIDs, m.GetOpaqueId())
}
return userIDs, nil
}
func (ul *UserlogService) resolveID(ctx context.Context, userid *user.UserId, groupid *group.GroupId) ([]string, error) {
if userid != nil {
return []string{userid.GetOpaqueId()}, nil
@@ -374,18 +321,50 @@ func (ul *UserlogService) resolveID(ctx context.Context, userid *user.UserId, gr
return ul.resolveGroup(ctx, groupid.GetOpaqueId())
}
func (ul *UserlogService) resolveShare(ctx context.Context, userid *user.UserId, groupid *group.GroupId, spaceid string) ([]string, error) {
users, err := ul.resolveID(ctx, userid, groupid)
// resolves the users of a group
func (ul *UserlogService) resolveGroup(ctx context.Context, groupID string) ([]string, error) {
grp, err := ul.getGroup(ctx, groupID)
if err != nil {
return nil, err
}
usr, err := ul.findSpaceMembers(ctx, spaceid, editor)
var userIDs []string
for _, m := range grp.GetMembers() {
userIDs = append(userIDs, m.GetOpaqueId())
}
return userIDs, nil
}
func (ul *UserlogService) impersonate(u *user.UserId) context.Context {
if u == nil {
ul.log.Debug().Msg("cannot impersonate nil user")
return nil
}
ctx, _, err := utils.Impersonate(u, ul.gwClient, ul.cfg.MachineAuthAPIKey)
if err != nil {
ul.log.Error().Err(err).Str("userid", u.GetOpaqueId()).Msg("failed to impersonate user")
return nil
}
return ctx
}
func (ul *UserlogService) getSpace(ctx context.Context, spaceID string) (*storageprovider.StorageSpace, error) {
res, err := ul.gwClient.ListStorageSpaces(ctx, listStorageSpaceRequest(spaceID))
if err != nil {
return nil, err
}
return append(users, usr...), nil
if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
return nil, fmt.Errorf("Unexpected status code while getting space: %v", res.GetStatus().GetCode())
}
if len(res.StorageSpaces) == 0 {
return nil, fmt.Errorf("error getting storage space %s: no space returned", spaceID)
}
return res.StorageSpaces[0], nil
}
func (ul *UserlogService) getUser(ctx context.Context, userid *user.UserId) (*user.User, error) {
@@ -403,6 +382,19 @@ func (ul *UserlogService) getUser(ctx context.Context, userid *user.UserId) (*us
return getUserResponse.GetUser(), nil
}
func (ul *UserlogService) getGroup(ctx context.Context, groupid string) (*group.Group, error) {
r, err := ul.gwClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: &group.GroupId{OpaqueId: groupid}})
if err != nil {
return nil, err
}
if r.GetStatus().GetCode() != rpc.Code_CODE_OK {
return nil, fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode())
}
return r.GetGroup(), nil
}
func listStorageSpaceRequest(spaceID string) *storageprovider.ListStorageSpacesRequest {
return &storageprovider.ListStorageSpacesRequest{
Filters: []*storageprovider.ListStorageSpacesRequest_Filter{

View File

@@ -5,8 +5,12 @@ import "text/template"
// the available templates
var (
SpaceDisabled = "space-disabled"
SpaceDisabledSubject = "space disabled"
SpaceDisabledMessage = "{{ .username }} disabled space {{ .spacename }}"
SpaceDisabledSubject = "Space disabled"
SpaceDisabledMessage = "{{ .username }} disabled Space {{ .spacename }}"
SpaceShared = "space-shared"
SpaceSharedSubject = "Space shared"
SpaceSharedMessage = "{{ .username }} shared Space {{ .spacename }} with you"
)
// NotificationTemplate is the data structure for the notifications
@@ -19,8 +23,12 @@ type NotificationTemplate struct {
var (
_templates = map[string]NotificationTemplate{
SpaceDisabled: {
Subject: template.Must(template.New(SpaceDisabled).Parse(SpaceDisabledSubject)),
Subject: template.Must(template.New("").Parse(SpaceDisabledSubject)),
Message: template.Must(template.New("").Parse(SpaceDisabledMessage)),
},
SpaceShared: {
Subject: template.Must(template.New("").Parse(SpaceSharedSubject)),
Message: template.Must(template.New("").Parse(SpaceSharedMessage)),
},
}
)