mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-31 01:10:20 -06:00
Determine the users preferred language to translate emails via Transifex. #6087
This commit is contained in:
5
changelog/unreleased/users-preferred-language-email.md
Normal file
5
changelog/unreleased/users-preferred-language-email.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Enhancement: Determine the users language to translate via Transifex
|
||||
|
||||
Enhance userlog service with proper api and messages
|
||||
https://github.com/owncloud/ocis/pull/6089
|
||||
https://github.com/owncloud/ocis/issues/6087
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"github.com/go-micro/plugins/v4/events/natsjs"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/crypto"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/channels"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/config/parser"
|
||||
@@ -93,8 +95,8 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Str("addr", cfg.Notifications.RevaGateway).Msg("could not get reva client")
|
||||
}
|
||||
|
||||
svc := service.NewEventsNotifier(evts, channel, logger, gwclient, cfg.Notifications.MachineAuthAPIKey, cfg.Notifications.EmailTemplatePath, cfg.WebUIURL)
|
||||
valueService := settingssvc.NewValueService("com.owncloud.api.settings", grpc.DefaultClient())
|
||||
svc := service.NewEventsNotifier(evts, channel, logger, gwclient, valueService, cfg.Notifications.MachineAuthAPIKey, cfg.Notifications.EmailTemplatePath, cfg.WebUIURL)
|
||||
return svc.Run()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -17,11 +17,17 @@ import (
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/channels"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/email"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults"
|
||||
"go-micro.dev/v4/metadata"
|
||||
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
)
|
||||
|
||||
var _defaultLocale = "en"
|
||||
|
||||
// Service should be named `Runner`
|
||||
type Service interface {
|
||||
Run() error
|
||||
@@ -33,13 +39,16 @@ func NewEventsNotifier(
|
||||
channel channels.Channel,
|
||||
logger log.Logger,
|
||||
gwClient gateway.GatewayAPIClient,
|
||||
valueService settingssvc.ValueService,
|
||||
machineAuthAPIKey, emailTemplatePath, ocisURL string) Service {
|
||||
|
||||
return eventsNotifier{
|
||||
logger: logger,
|
||||
channel: channel,
|
||||
events: events,
|
||||
signals: make(chan os.Signal, 1),
|
||||
gwClient: gwClient,
|
||||
valueService: valueService,
|
||||
machineAuthAPIKey: machineAuthAPIKey,
|
||||
emailTemplatePath: emailTemplatePath,
|
||||
ocisURL: ocisURL,
|
||||
@@ -52,6 +61,7 @@ type eventsNotifier struct {
|
||||
events <-chan events.Event
|
||||
signals chan os.Signal
|
||||
gwClient gateway.GatewayAPIClient
|
||||
valueService settingssvc.ValueService
|
||||
machineAuthAPIKey string
|
||||
emailTemplatePath string
|
||||
translationPath string
|
||||
@@ -87,52 +97,101 @@ func (s eventsNotifier) Run() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (s eventsNotifier) render(template email.MessageTemplate, values map[string]interface{}) (string, string, error) {
|
||||
// The locate have to come from the user setting
|
||||
return email.RenderEmailTemplate(template, "en", s.emailTemplatePath, s.translationPath, values)
|
||||
// recipient represent the already rendered message including the user id opaqueID
|
||||
type recipient struct {
|
||||
opaqueID string
|
||||
subject string
|
||||
msg string
|
||||
}
|
||||
|
||||
func (s eventsNotifier) send(ctx context.Context, u *user.UserId, g *group.GroupId, msg, subj, sender string) error {
|
||||
if u != nil {
|
||||
return s.channel.SendMessage(ctx, []string{u.GetOpaqueId()}, msg, subj, sender)
|
||||
func (s eventsNotifier) render(ctx context.Context, template email.MessageTemplate,
|
||||
granteeFieldName string, fields map[string]interface{}, granteeList []*user.UserId) ([]recipient, error) {
|
||||
// Render the Email Template for each user
|
||||
recipientList := make([]recipient, len(granteeList))
|
||||
for i, userID := range granteeList {
|
||||
locale, err := s.getUserLang(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
grantee, err := s.getUserName(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fields[granteeFieldName] = grantee
|
||||
|
||||
subj, msg, err := email.RenderEmailTemplate(template, locale, s.emailTemplatePath, s.translationPath, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
recipientList[i] = recipient{opaqueID: userID.GetOpaqueId(), subject: subj, msg: msg}
|
||||
}
|
||||
|
||||
if g != nil {
|
||||
return s.channel.SendMessageToGroup(ctx, g, msg, subj, sender)
|
||||
}
|
||||
|
||||
return nil
|
||||
return recipientList, nil
|
||||
}
|
||||
|
||||
func (s eventsNotifier) getGranteeName(ctx context.Context, u *user.UserId, g *group.GroupId) (string, error) {
|
||||
func (s eventsNotifier) send(ctx context.Context, recipientList []recipient, sender string) {
|
||||
for _, r := range recipientList {
|
||||
err := s.channel.SendMessage(ctx, []string{r.opaqueID}, r.msg, r.subject, sender)
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "SendEmail").Msg("failed to send a message")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s eventsNotifier) getGranteeList(ctx context.Context, owner, u *user.UserId, g *group.GroupId) ([]*user.UserId, error) {
|
||||
switch {
|
||||
case u != nil:
|
||||
r, err := s.gwClient.GetUser(ctx, &user.GetUserRequest{UserId: u})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if r.Status.Code != rpc.Code_CODE_OK {
|
||||
return "", fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode())
|
||||
}
|
||||
|
||||
return r.GetUser().GetDisplayName(), nil
|
||||
return []*user.UserId{u}, nil
|
||||
case g != nil:
|
||||
r, err := s.gwClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: g})
|
||||
res, err := s.gwClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: g})
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r.GetStatus().GetCode() != rpc.Code_CODE_OK {
|
||||
return "", fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode())
|
||||
if res.Status.Code != rpc.Code_CODE_OK {
|
||||
return nil, errors.New("could not get group")
|
||||
}
|
||||
|
||||
return r.GetGroup().GetDisplayName(), nil
|
||||
for i, userID := range res.GetGroup().GetMembers() {
|
||||
// remove an executant from a list
|
||||
if userID.GetOpaqueId() == owner.GetOpaqueId() {
|
||||
res.Group.Members[i] = res.Group.Members[len(res.Group.Members)-1]
|
||||
return res.Group.Members[:len(res.Group.Members)-1], nil
|
||||
}
|
||||
}
|
||||
return res.Group.Members, nil
|
||||
default:
|
||||
return "", errors.New("Need at least one non-nil grantee")
|
||||
return nil, errors.New("need at least one non-nil grantee")
|
||||
}
|
||||
}
|
||||
|
||||
func (s eventsNotifier) getUserName(ctx context.Context, u *user.UserId) (string, error) {
|
||||
if u == nil {
|
||||
return "", errors.New("need at least one non-nil grantee")
|
||||
}
|
||||
r, err := s.gwClient.GetUser(ctx, &user.GetUserRequest{UserId: u})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if r.Status.Code != rpc.Code_CODE_OK {
|
||||
return "", fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode())
|
||||
}
|
||||
return r.GetUser().GetDisplayName(), nil
|
||||
}
|
||||
|
||||
func (s eventsNotifier) getUserLang(ctx context.Context, u *user.UserId) (string, error) {
|
||||
granteeCtx := metadata.Set(ctx, middleware.AccountID, u.OpaqueId)
|
||||
if resp, err := s.valueService.GetValueByUniqueIdentifiers(granteeCtx,
|
||||
&settingssvc.GetValueByUniqueIdentifiersRequest{
|
||||
AccountUuid: u.OpaqueId,
|
||||
SettingId: defaults.SettingUUIDProfileLanguage,
|
||||
}); err == nil {
|
||||
if resp == nil {
|
||||
return _defaultLocale, nil
|
||||
}
|
||||
val := resp.Value.GetValue().GetListValue().GetValues()
|
||||
if len(val) > 0 && val[0] != nil {
|
||||
return val[0].GetStringValue(), nil
|
||||
}
|
||||
}
|
||||
return _defaultLocale, nil
|
||||
}
|
||||
|
||||
func (s eventsNotifier) getResourceInfo(ctx context.Context, resourceID *provider.ResourceId, fieldmask *fieldmaskpb.FieldMask) (*provider.ResourceInfo, error) {
|
||||
|
||||
@@ -15,13 +15,19 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/service"
|
||||
"github.com/test-go/testify/mock"
|
||||
"go-micro.dev/v4/client"
|
||||
)
|
||||
|
||||
var _ = Describe("Notifications", func() {
|
||||
var (
|
||||
gwc *cs3mocks.GatewayAPIClient
|
||||
vs *settingssvc.MockValueService
|
||||
sharer = &user.User{
|
||||
Id: &user.UserId{
|
||||
OpaqueId: "sharer",
|
||||
@@ -43,15 +49,23 @@ var _ = Describe("Notifications", func() {
|
||||
|
||||
BeforeEach(func() {
|
||||
gwc = &cs3mocks.GatewayAPIClient{}
|
||||
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil)
|
||||
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil).Once()
|
||||
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharee}, nil).Once()
|
||||
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil)
|
||||
gwc.On("Stat", mock.Anything, mock.Anything).Return(&provider.StatResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, Info: &provider.ResourceInfo{Name: "secrets of the board", Space: &provider.StorageSpace{Name: "secret space"}}}, nil)
|
||||
vs = &settingssvc.MockValueService{}
|
||||
vs.GetValueByUniqueIdentifiersFunc = func(ctx context.Context, req *settingssvc.GetValueByUniqueIdentifiersRequest, opts ...client.CallOption) (*settingssvc.GetValueResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
})
|
||||
|
||||
DescribeTable("Sending notifications",
|
||||
func(tc testChannel, ev events.Event) {
|
||||
cfg := defaults.FullDefaultConfig()
|
||||
cfg.GRPCClientTLS = &shared.GRPCClientTLS{}
|
||||
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
|
||||
ch := make(chan events.Event)
|
||||
evts := service.NewEventsNotifier(ch, tc, log.NewLogger(), gwc, "", "", "")
|
||||
evts := service.NewEventsNotifier(ch, tc, log.NewLogger(), gwc, vs, "", "", "")
|
||||
go evts.Run()
|
||||
|
||||
ch <- ev
|
||||
@@ -66,7 +80,7 @@ var _ = Describe("Notifications", func() {
|
||||
Entry("Share Created", testChannel{
|
||||
expectedReceipients: map[string]bool{sharee.GetId().GetOpaqueId(): true},
|
||||
expectedSubject: "Dr. S. Harer shared 'secrets of the board' with you",
|
||||
expectedMessage: `Hello Dr. S. Harer
|
||||
expectedMessage: `Hello Eric Expireling
|
||||
|
||||
Dr. S. Harer has shared "secrets of the board" with you.
|
||||
|
||||
@@ -91,7 +105,7 @@ https://owncloud.com
|
||||
Entry("Share Expired", testChannel{
|
||||
expectedReceipients: map[string]bool{sharee.GetId().GetOpaqueId(): true},
|
||||
expectedSubject: "Share to 'secrets of the board' expired at 2023-04-17 16:42:00",
|
||||
expectedMessage: `Hello Dr. S. Harer,
|
||||
expectedMessage: `Hello Eric Expireling,
|
||||
|
||||
Your share to secrets of the board has expired at 2023-04-17 16:42:00
|
||||
|
||||
@@ -116,7 +130,7 @@ https://owncloud.com
|
||||
Entry("Added to Space", testChannel{
|
||||
expectedReceipients: map[string]bool{sharee.GetId().GetOpaqueId(): true},
|
||||
expectedSubject: "Dr. S. Harer invited you to join secret space",
|
||||
expectedMessage: `Hello Dr. S. Harer,
|
||||
expectedMessage: `Hello Eric Expireling,
|
||||
|
||||
Dr. S. Harer has invited you to join "secret space".
|
||||
|
||||
@@ -141,7 +155,7 @@ https://owncloud.com
|
||||
Entry("Removed from Space", testChannel{
|
||||
expectedReceipients: map[string]bool{sharee.GetId().GetOpaqueId(): true},
|
||||
expectedSubject: "Dr. S. Harer removed you from secret space",
|
||||
expectedMessage: `Hello Dr. S. Harer,
|
||||
expectedMessage: `Hello Eric Expireling,
|
||||
|
||||
Dr. S. Harer has removed you from "secret space".
|
||||
|
||||
@@ -167,7 +181,7 @@ https://owncloud.com
|
||||
Entry("Space Expired", testChannel{
|
||||
expectedReceipients: map[string]bool{sharee.GetId().GetOpaqueId(): true},
|
||||
expectedSubject: "Membership of 'secret space' expired at 2023-04-17 16:42:00",
|
||||
expectedMessage: `Hello Dr. S. Harer,
|
||||
expectedMessage: `Hello Eric Expireling,
|
||||
|
||||
Your membership of space secret space has expired at 2023-04-17 16:42:00
|
||||
|
||||
|
||||
@@ -35,28 +35,25 @@ func (s eventsNotifier) handleShareCreated(e events.ShareCreated) {
|
||||
return
|
||||
}
|
||||
|
||||
shareGrantee, err := s.getGranteeName(ownerCtx, e.GranteeUserID, e.GranteeGroupID)
|
||||
granteeList, err := s.getGranteeList(ownerCtx, owner.GetId(), e.GranteeUserID, e.GranteeGroupID)
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("Could not get grantee name")
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("Could not get grantee list")
|
||||
return
|
||||
}
|
||||
|
||||
sharerDisplayName := owner.GetDisplayName()
|
||||
subj, msg, err := s.render(email.ShareCreated, map[string]interface{}{
|
||||
"ShareGrantee": shareGrantee,
|
||||
"ShareSharer": sharerDisplayName,
|
||||
"ShareFolder": resourceInfo.Name,
|
||||
"ShareLink": shareLink,
|
||||
})
|
||||
|
||||
recipientList, err := s.render(ownerCtx, email.ShareCreated,
|
||||
"ShareGrantee",
|
||||
map[string]interface{}{
|
||||
"ShareSharer": sharerDisplayName,
|
||||
"ShareFolder": resourceInfo.Name,
|
||||
"ShareLink": shareLink,
|
||||
}, granteeList)
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("Could not render E-Mail body template for shares")
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("could not get render the email")
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.send(ownerCtx, e.GranteeUserID, e.GranteeGroupID, msg, subj, sharerDisplayName); err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("failed to send a message")
|
||||
}
|
||||
|
||||
s.send(ownerCtx, recipientList, sharerDisplayName)
|
||||
}
|
||||
|
||||
func (s eventsNotifier) handleShareExpired(e events.ShareExpired) {
|
||||
@@ -65,13 +62,13 @@ func (s eventsNotifier) handleShareExpired(e events.ShareExpired) {
|
||||
Str("itemid", e.ItemID.GetOpaqueId()).
|
||||
Logger()
|
||||
|
||||
ctx, owner, err := utils.Impersonate(e.ShareOwner, s.gwClient, s.machineAuthAPIKey)
|
||||
ownerCtx, owner, err := utils.Impersonate(e.ShareOwner, s.gwClient, s.machineAuthAPIKey)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Could not impersonate sharer")
|
||||
return
|
||||
}
|
||||
|
||||
resourceInfo, err := s.getResourceInfo(ctx, e.ItemID, &fieldmaskpb.FieldMask{Paths: []string{"name"}})
|
||||
resourceInfo, err := s.getResourceInfo(ownerCtx, e.ItemID, &fieldmaskpb.FieldMask{Paths: []string{"name"}})
|
||||
if err != nil {
|
||||
logger.Error().
|
||||
Err(err).
|
||||
@@ -79,24 +76,21 @@ func (s eventsNotifier) handleShareExpired(e events.ShareExpired) {
|
||||
return
|
||||
}
|
||||
|
||||
shareGrantee, err := s.getGranteeName(ctx, e.GranteeUserID, e.GranteeGroupID)
|
||||
granteeList, err := s.getGranteeList(ownerCtx, owner.GetId(), e.GranteeUserID, e.GranteeGroupID)
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("Could not get grantee name")
|
||||
s.logger.Error().Err(err).Str("event", "ShareExpired").Msg("Could not get grantee name")
|
||||
return
|
||||
}
|
||||
|
||||
subj, msg, err := s.render(email.ShareExpired, map[string]interface{}{
|
||||
"ShareGrantee": shareGrantee,
|
||||
"ShareFolder": resourceInfo.GetName(),
|
||||
"ExpiredAt": e.ExpiredAt.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
|
||||
recipientList, err := s.render(ownerCtx, email.ShareExpired,
|
||||
"ShareGrantee",
|
||||
map[string]interface{}{
|
||||
"ShareFolder": resourceInfo.GetName(),
|
||||
"ExpiredAt": e.ExpiredAt.Format("2006-01-02 15:04:05"),
|
||||
}, granteeList)
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("Could not render E-Mail body template for shares")
|
||||
s.logger.Error().Err(err).Str("event", "ShareExpired").Msg("could not get render the email")
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.send(ctx, e.GranteeUserID, e.GranteeGroupID, msg, subj, owner.GetDisplayName()); err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("failed to send a message")
|
||||
}
|
||||
|
||||
s.send(ownerCtx, recipientList, owner.GetDisplayName())
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ func (s eventsNotifier) handleSpaceShared(e events.SpaceShared) {
|
||||
Str("itemid", e.ID.OpaqueId).
|
||||
Logger()
|
||||
|
||||
ownerCtx, owner, err := utils.Impersonate(e.Executant, s.gwClient, s.machineAuthAPIKey)
|
||||
executantCtx, executant, err := utils.Impersonate(e.Executant, s.gwClient, s.machineAuthAPIKey)
|
||||
if err != nil {
|
||||
logger.Error().
|
||||
Err(err).
|
||||
@@ -29,7 +29,7 @@ func (s eventsNotifier) handleSpaceShared(e events.SpaceShared) {
|
||||
return
|
||||
}
|
||||
|
||||
resourceInfo, err := s.getResourceInfo(ownerCtx, &resourceID, nil)
|
||||
resourceInfo, err := s.getResourceInfo(executantCtx, &resourceID, nil)
|
||||
if err != nil {
|
||||
logger.Error().
|
||||
Err(err).
|
||||
@@ -45,30 +45,28 @@ func (s eventsNotifier) handleSpaceShared(e events.SpaceShared) {
|
||||
return
|
||||
}
|
||||
|
||||
// Note: We're using the 'ownerCtx' (authenticated as the share owner) here for requesting
|
||||
// Note: We're using the 'executantCtx' (authenticated as the share executant) here for requesting
|
||||
// the Grantees of the shares. Ideally the notfication service would use some kind of service
|
||||
// user for this.
|
||||
spaceGrantee, err := s.getGranteeName(ownerCtx, e.GranteeUserID, e.GranteeGroupID)
|
||||
spaceGrantee, err := s.getGranteeList(executantCtx, executant.GetId(), e.GranteeUserID, e.GranteeGroupID)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Could not get grantee name")
|
||||
logger.Error().Err(err).Str("event", "SpaceGrantee").Msg("Could not get grantee list")
|
||||
return
|
||||
}
|
||||
|
||||
sharerDisplayName := owner.GetDisplayName()
|
||||
subj, msg, err := s.render(email.SharedSpace, map[string]interface{}{
|
||||
"SpaceGrantee": spaceGrantee,
|
||||
"SpaceSharer": sharerDisplayName,
|
||||
"SpaceName": resourceInfo.GetSpace().GetName(),
|
||||
"ShareLink": shareLink,
|
||||
})
|
||||
sharerDisplayName := executant.GetDisplayName()
|
||||
recipientList, err := s.render(executantCtx, email.SharedSpace,
|
||||
"SpaceGrantee",
|
||||
map[string]interface{}{
|
||||
"SpaceSharer": sharerDisplayName,
|
||||
"SpaceName": resourceInfo.GetSpace().GetName(),
|
||||
"ShareLink": shareLink,
|
||||
}, spaceGrantee)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Could not render E-Mail template for spaces")
|
||||
s.logger.Error().Err(err).Str("event", "SharedSpace").Msg("could not get render the email")
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.send(ownerCtx, e.GranteeUserID, e.GranteeGroupID, msg, subj, sharerDisplayName); err != nil {
|
||||
logger.Error().Err(err).Msg("failed to send a message")
|
||||
}
|
||||
s.send(executantCtx, recipientList, sharerDisplayName)
|
||||
}
|
||||
|
||||
func (s eventsNotifier) handleSpaceUnshared(e events.SpaceUnshared) {
|
||||
@@ -77,7 +75,7 @@ func (s eventsNotifier) handleSpaceUnshared(e events.SpaceUnshared) {
|
||||
Str("itemid", e.ID.OpaqueId).
|
||||
Logger()
|
||||
|
||||
ownerCtx, owner, err := utils.Impersonate(e.Executant, s.gwClient, s.machineAuthAPIKey)
|
||||
executantCtx, executant, err := utils.Impersonate(e.Executant, s.gwClient, s.machineAuthAPIKey)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("could not handle space unshared event")
|
||||
return
|
||||
@@ -91,7 +89,7 @@ func (s eventsNotifier) handleSpaceUnshared(e events.SpaceUnshared) {
|
||||
return
|
||||
}
|
||||
|
||||
resourceInfo, err := s.getResourceInfo(ownerCtx, &resourceID, nil)
|
||||
resourceInfo, err := s.getResourceInfo(executantCtx, &resourceID, nil)
|
||||
if err != nil {
|
||||
logger.Error().
|
||||
Err(err).
|
||||
@@ -107,31 +105,28 @@ func (s eventsNotifier) handleSpaceUnshared(e events.SpaceUnshared) {
|
||||
return
|
||||
}
|
||||
|
||||
// Note: We're using the 'ownerCtx' (authenticated as the share owner) here for requesting
|
||||
// Note: We're using the 'executantCtx' (authenticated as the share executant) here for requesting
|
||||
// the Grantees of the shares. Ideally the notfication service would use some kind of service
|
||||
// user for this.
|
||||
spaceGrantee, err := s.getGranteeName(ownerCtx, e.GranteeUserID, e.GranteeGroupID)
|
||||
spaceGrantee, err := s.getGranteeList(executantCtx, executant.GetId(), e.GranteeUserID, e.GranteeGroupID)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Could not get grantee name")
|
||||
logger.Error().Err(err).Str("event", "SpaceGrantee").Msg("Could not get grantee list")
|
||||
return
|
||||
}
|
||||
|
||||
sharerDisplayName := owner.GetDisplayName()
|
||||
subj, msg, err := s.render(email.UnsharedSpace, map[string]interface{}{
|
||||
"SpaceGrantee": spaceGrantee,
|
||||
"SpaceSharer": sharerDisplayName,
|
||||
"SpaceName": resourceInfo.GetSpace().Name,
|
||||
"ShareLink": shareLink,
|
||||
})
|
||||
|
||||
sharerDisplayName := executant.GetDisplayName()
|
||||
recipientList, err := s.render(executantCtx, email.UnsharedSpace,
|
||||
"SpaceGrantee",
|
||||
map[string]interface{}{
|
||||
"SpaceSharer": sharerDisplayName,
|
||||
"SpaceName": resourceInfo.GetSpace().Name,
|
||||
"ShareLink": shareLink,
|
||||
}, spaceGrantee)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Could not render E-Mail template for spaces")
|
||||
s.logger.Error().Err(err).Str("event", "UnsharedSpace").Msg("Could not get render the email")
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.send(ownerCtx, e.GranteeUserID, e.GranteeGroupID, msg, subj, sharerDisplayName); err != nil {
|
||||
logger.Error().Err(err).Msg("failed to send a message")
|
||||
}
|
||||
s.send(executantCtx, recipientList, sharerDisplayName)
|
||||
}
|
||||
|
||||
func (s eventsNotifier) handleSpaceMembershipExpired(e events.SpaceMembershipExpired) {
|
||||
@@ -140,30 +135,27 @@ func (s eventsNotifier) handleSpaceMembershipExpired(e events.SpaceMembershipExp
|
||||
Str("itemid", e.SpaceID.GetOpaqueId()).
|
||||
Logger()
|
||||
|
||||
ctx, owner, err := utils.Impersonate(e.SpaceOwner, s.gwClient, s.machineAuthAPIKey)
|
||||
ownerCtx, owner, err := utils.Impersonate(e.SpaceOwner, s.gwClient, s.machineAuthAPIKey)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Could not impersonate sharer")
|
||||
return
|
||||
}
|
||||
|
||||
shareGrantee, err := s.getGranteeName(ctx, e.GranteeUserID, e.GranteeGroupID)
|
||||
granteeList, err := s.getGranteeList(ownerCtx, owner.GetId(), e.GranteeUserID, e.GranteeGroupID)
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("Could not get grantee name")
|
||||
s.logger.Error().Err(err).Str("event", "SpaceUnshared").Msg("Could not get grantee list")
|
||||
return
|
||||
}
|
||||
|
||||
subj, msg, err := s.render(email.MembershipExpired, map[string]interface{}{
|
||||
"SpaceGrantee": shareGrantee,
|
||||
"SpaceName": e.SpaceName,
|
||||
"ExpiredAt": e.ExpiredAt.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
|
||||
recipientList, err := s.render(ownerCtx, email.MembershipExpired,
|
||||
"SpaceGrantee",
|
||||
map[string]interface{}{
|
||||
"SpaceName": e.SpaceName,
|
||||
"ExpiredAt": e.ExpiredAt.Format("2006-01-02 15:04:05"),
|
||||
}, granteeList)
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("Could not render E-Mail body template for shares")
|
||||
s.logger.Error().Err(err).Str("event", "SpaceUnshared").Msg("could not get render the email")
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.send(ctx, e.GranteeUserID, e.GranteeGroupID, msg, subj, owner.GetDisplayName()); err != nil {
|
||||
s.logger.Error().Err(err).Str("event", "ShareCreated").Msg("failed to send a message")
|
||||
}
|
||||
|
||||
s.send(ownerCtx, recipientList, owner.GetDisplayName())
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ const (
|
||||
// CreateSpacePermissionName is the hardcoded setting name for the create space permission
|
||||
CreateSpacePermissionName string = "create-space"
|
||||
|
||||
settingUUIDProfileLanguage = "aa8cfbe5-95d4-4f7e-a032-c3c01f5f062f"
|
||||
// SettingUUIDProfileLanguage is the hardcoded setting UUID for the user profile language
|
||||
SettingUUIDProfileLanguage = "aa8cfbe5-95d4-4f7e-a032-c3c01f5f062f"
|
||||
|
||||
// AccountManagementPermissionID is the hardcoded setting UUID for the account management permission
|
||||
AccountManagementPermissionID string = "8e587774-d929-4215-910b-a317b1e80f73"
|
||||
@@ -207,7 +208,7 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
DisplayName: "Profile",
|
||||
Settings: []*settingsmsg.Setting{
|
||||
{
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
Name: "language",
|
||||
DisplayName: "Language",
|
||||
Description: "User language",
|
||||
@@ -268,7 +269,7 @@ func generatePermissionRequests() []*settingssvc.AddSettingToBundleRequest {
|
||||
DisplayName: "Permission to read and set the language (anyone)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
@@ -286,7 +287,7 @@ func generatePermissionRequests() []*settingssvc.AddSettingToBundleRequest {
|
||||
DisplayName: "Permission to read and set the language (self)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
@@ -304,7 +305,7 @@ func generatePermissionRequests() []*settingssvc.AddSettingToBundleRequest {
|
||||
DisplayName: "Permission to read and set the language (self)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
@@ -523,7 +524,7 @@ func generatePermissionRequests() []*settingssvc.AddSettingToBundleRequest {
|
||||
DisplayName: "Permission to read and set the language (self)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
|
||||
@@ -73,7 +73,8 @@ const (
|
||||
// SpaceAbilityPermissionName is the hardcoded setting name for the space ability permission
|
||||
SpaceAbilityPermissionName string = "Drive.ReadWriteEnabled"
|
||||
|
||||
settingUUIDProfileLanguage = "aa8cfbe5-95d4-4f7e-a032-c3c01f5f062f"
|
||||
// SettingUUIDProfileLanguage is the hardcoded setting UUID for the user profile language
|
||||
SettingUUIDProfileLanguage = "aa8cfbe5-95d4-4f7e-a032-c3c01f5f062f"
|
||||
|
||||
// AccountManagementPermissionID is the hardcoded setting UUID for the account management permission
|
||||
AccountManagementPermissionID string = "8e587774-d929-4215-910b-a317b1e80f73"
|
||||
@@ -159,7 +160,7 @@ func generateBundleAdminRole() *settingsmsg.Bundle {
|
||||
DisplayName: "Permission to read and set the language (anyone)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
@@ -416,7 +417,7 @@ func generateBundleSpaceAdminRole() *settingsmsg.Bundle {
|
||||
DisplayName: "Permission to read and set the language (self)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
@@ -492,7 +493,7 @@ func generateBundleUserRole() *settingsmsg.Bundle {
|
||||
DisplayName: "Permission to read and set the language (self)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
@@ -568,7 +569,7 @@ func generateBundleGuestRole() *settingsmsg.Bundle {
|
||||
DisplayName: "Permission to read and set the language (self)",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SETTING,
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
},
|
||||
Value: &settingsmsg.Setting_PermissionValue{
|
||||
PermissionValue: &settingsmsg.Permission{
|
||||
@@ -593,7 +594,7 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
DisplayName: "Profile",
|
||||
Settings: []*settingsmsg.Setting{
|
||||
{
|
||||
Id: settingUUIDProfileLanguage,
|
||||
Id: SettingUUIDProfileLanguage,
|
||||
Name: "language",
|
||||
DisplayName: "Language",
|
||||
Description: "User language",
|
||||
|
||||
@@ -4,7 +4,6 @@ package store
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
@@ -87,8 +86,39 @@ func (s *Store) ReadValue(valueID string) (*settingsmsg.Value, error) {
|
||||
|
||||
// ReadValueByUniqueIdentifiers tries to find a value given a set of unique identifiers
|
||||
func (s *Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*settingsmsg.Value, error) {
|
||||
fmt.Println("ReadValueByUniqueIdentifiers not implemented")
|
||||
return nil, errors.New("not implemented")
|
||||
if settingID == "" {
|
||||
return nil, fmt.Errorf("settingID can not be empty %w", settings.ErrNotFound)
|
||||
}
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
|
||||
vIDs, err := s.mdc.ReadDir(ctx, valuesFolderLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, vid := range vIDs {
|
||||
b, err := s.mdc.SimpleDownload(ctx, valuePath(vid))
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
continue
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := &settingsmsg.Value{}
|
||||
err = json.Unmarshal(b, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if v.AccountUuid == accountUUID && v.SettingId == settingID {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
return nil, settings.ErrNotFound
|
||||
}
|
||||
|
||||
// WriteValue writes the given value into a file within the dataPath
|
||||
|
||||
Reference in New Issue
Block a user