diff --git a/services/notifications/pkg/command/server.go b/services/notifications/pkg/command/server.go index c8f9b2e792..f1fbfa4d78 100644 --- a/services/notifications/pkg/command/server.go +++ b/services/notifications/pkg/command/server.go @@ -84,6 +84,7 @@ func Server(cfg *config.Config) *cobra.Command { evs := []events.Unmarshaller{ events.ShareCreated{}, events.ShareExpired{}, + events.ShareRemoved{}, events.SpaceShared{}, events.SpaceUnshared{}, events.SpaceMembershipExpired{}, diff --git a/services/notifications/pkg/email/templates.go b/services/notifications/pkg/email/templates.go index 99091b44b1..5ab5d813c1 100644 --- a/services/notifications/pkg/email/templates.go +++ b/services/notifications/pkg/email/templates.go @@ -23,6 +23,19 @@ var ( CallToAction: l10n.Template(`Click here to view it: {ShareLink}`), } + ShareRemoved = MessageTemplate{ + textTemplate: _textTemplate, + htmlTemplate: _htmlTemplate, + // ShareRemoved email template, Subject field (resolves directly) + Subject: l10n.Template(`{ShareSharer} unshared '{ShareFolder}' with you`), + // ShareRemoved email template, resolves via {{ .Greeting }} + Greeting: l10n.Template(`Hello {ShareGrantee},`), + // ShareRemoved email template, resolves via {{ .MessageBody }} + MessageBody: l10n.Template(`{ShareSharer} has unshared '{ShareFolder}' with you. + +Even though this share has been revoked you still might have access through other shares and/or space memberships.`), + } + ShareExpired = MessageTemplate{ textTemplate: _textTemplate, htmlTemplate: _htmlTemplate, diff --git a/services/notifications/pkg/service/job.go b/services/notifications/pkg/service/job.go index e5a39126cf..96884865e6 100644 --- a/services/notifications/pkg/service/job.go +++ b/services/notifications/pkg/service/job.go @@ -130,6 +130,25 @@ func (s eventsNotifier) createGroupedMail(ctx context.Context, logger zerolog.Lo "ShareFolder": shareFolder, "ExpiredAt": te.ExpiredAt.Format("2006-01-02 15:04:05"), }) + case events.ShareRemoved: + logger := logger.With(). + Str("event", "ShareRemoved"). + Str("eventId", te.ItemID.OpaqueId). + Logger() + + executant, shareFolder, _, err := s.prepareShareRemoved(logger, te) + if err != nil { + logger.Error().Err(err).Msg("could not prepare vars for grouped email") + continue + } + + mts = append(mts, email.ShareRemoved) + mtsVars = append(mtsVars, map[string]string{ + "ShareSharer": executant.GetDisplayName(), + "ShareFolder": shareFolder, + }) + default: + logger.Error().Str("eventType", e.Type).Msg("unsupported event type for grouped email") } } diff --git a/services/notifications/pkg/service/service.go b/services/notifications/pkg/service/service.go index 65707bb355..74b2e491e8 100644 --- a/services/notifications/pkg/service/service.go +++ b/services/notifications/pkg/service/service.go @@ -129,6 +129,8 @@ EventLoop: s.handleShareCreated(e, evt.ID) case events.ShareExpired: s.handleShareExpired(e, evt.ID) + case events.ShareRemoved: + s.handleShareRemoved(e, evt.ID) case events.ScienceMeshInviteTokenGenerated: s.handleScienceMeshInviteTokenGenerated(e) case events.SendEmailsEvent: diff --git a/services/notifications/pkg/service/shares.go b/services/notifications/pkg/service/shares.go index 01d4825ab3..aa905b630a 100644 --- a/services/notifications/pkg/service/shares.go +++ b/services/notifications/pkg/service/shares.go @@ -161,3 +161,73 @@ func (s eventsNotifier) prepareShareExpired(logger zerolog.Logger, e events.Shar return shareFolder, ctx, err } + +func (s eventsNotifier) handleShareRemoved(e events.ShareRemoved, eventId string) { + logger := s.logger.With(). + Str("event", "ShareRemoved"). + Str("itemid", e.ItemID.OpaqueId). + Logger() + + executant, shareFolder, ctx, err := s.prepareShareRemoved(logger, e) + if err != nil { + logger.Error().Err(err).Msg("could not prepare vars for email") + return + } + + granteeList := s.ensureGranteeList(ctx, executant.GetId(), e.GranteeUserID, e.GranteeGroupID) + filteredGrantees := s.filter.execute(ctx, granteeList, defaults.SettingUUIDProfileEventShareRemoved) + + recipientsInstant, recipientsDaily, recipientsInstantWeekly := s.splitter.execute(ctx, filteredGrantees) + recipientsInstant = append(recipientsInstant, s.userEventStore.persist(_intervalDaily, eventId, recipientsDaily)...) + recipientsInstant = append(recipientsInstant, s.userEventStore.persist(_intervalWeekly, eventId, recipientsInstantWeekly)...) + if recipientsInstant == nil { + return + } + + sharerDisplayName := executant.GetDisplayName() + + emails, err := s.render(ctx, email.ShareRemoved, + "ShareGrantee", + map[string]string{ + "ShareSharer": sharerDisplayName, + "ShareFolder": shareFolder, + }, recipientsInstant, sharerDisplayName) + if err != nil { + logger.Error().Err(err).Msg("could not get render the email") + return + } + s.send(ctx, emails) +} + +func (s eventsNotifier) prepareShareRemoved(logger zerolog.Logger, e events.ShareRemoved) (executant *user.User, shareFolder string, ctx context.Context, err error) { + gatewayClient, err := s.gatewaySelector.Next() + if err != nil { + logger.Error().Err(err).Msg("could not select next gateway client") + return executant, shareFolder, ctx, err + } + + ctx, err = utils.GetServiceUserContextWithContext(context.Background(), gatewayClient, s.serviceAccountID, s.serviceAccountSecret) + if err != nil { + logger.Error().Err(err).Msg("could not get service user context") + return executant, shareFolder, ctx, err + } + + resourceInfo, err := s.getResourceInfo(ctx, e.ItemID, &fieldmaskpb.FieldMask{Paths: []string{"name"}}) + if err != nil { + logger.Error(). + Err(err). + Msg("could not stat resource") + return executant, shareFolder, ctx, err + } + shareFolder = resourceInfo.Name + + executant, err = utils.GetUserNoGroups(ctx, e.Executant, gatewayClient) + if err != nil { + logger.Error(). + Err(err). + Msg("could not get user") + return executant, shareFolder, ctx, err + } + + return executant, shareFolder, ctx, err +} diff --git a/services/settings/pkg/store/defaults/defaults.go b/services/settings/pkg/store/defaults/defaults.go index c8d144eefd..5f3d9e0fa1 100644 --- a/services/settings/pkg/store/defaults/defaults.go +++ b/services/settings/pkg/store/defaults/defaults.go @@ -331,7 +331,7 @@ func generateBundleProfileRequest() *settingsmsg.Bundle { MultiChoiceCollectionValue: &settingsmsg.MultiChoiceCollection{ Options: []*settingsmsg.MultiChoiceCollectionOption{ &optionInAppTrue, - &optionMailFalseDisabled, + &optionMailTrue, }, }, },