diff --git a/services/userlog/pkg/service/conversion.go b/services/userlog/pkg/service/conversion.go index ee14f1dce..2b66e42a3 100644 --- a/services/userlog/pkg/service/conversion.go +++ b/services/userlog/pkg/service/conversion.go @@ -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 { diff --git a/services/userlog/pkg/service/http.go b/services/userlog/pkg/service/http.go index 481cab410..b9e7ef039 100644 --- a/services/userlog/pkg/service/http.go +++ b/services/userlog/pkg/service/http.go @@ -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) diff --git a/services/userlog/pkg/service/service.go b/services/userlog/pkg/service/service.go index cbf792a65..a0d1de45a 100644 --- a/services/userlog/pkg/service/service.go +++ b/services/userlog/pkg/service/service.go @@ -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{ diff --git a/services/userlog/pkg/service/templates.go b/services/userlog/pkg/service/templates.go index 63c0c6f21..cd83bb74b 100644 --- a/services/userlog/pkg/service/templates.go +++ b/services/userlog/pkg/service/templates.go @@ -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)), + }, } )