From ddac9fac9caacdfdd916db2b70e0e9435548cb57 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Mon, 30 Sep 2019 12:18:53 +0200 Subject: [PATCH] Allow use of user ID as notification rcpt --- compose/rest/notification.go | 10 +++++----- compose/service/notification.go | 26 ++++++++++++++++++++++---- compose/service/system_user.go | 4 ++++ system/service/user.go | 32 ++++++++++++++++++++++++-------- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/compose/rest/notification.go b/compose/rest/notification.go index 564727e73..d8aaecb55 100644 --- a/compose/rest/notification.go +++ b/compose/rest/notification.go @@ -24,8 +24,8 @@ type ( } notificationService interface { - SendEmail(*gomail.Message) error - AttachEmailRecipients(*gomail.Message, string, ...string) error + SendEmail(context.Context, *gomail.Message) error + AttachEmailRecipients(context.Context, *gomail.Message, string, ...string) error AttachRemoteFiles(context.Context, *gomail.Message, ...string) error } ) @@ -41,11 +41,11 @@ func (ctrl *Notification) EmailSend(ctx context.Context, r *request.Notification ntf := ctrl.notification msg := mail.New() - if err := ntf.AttachEmailRecipients(msg, "To", r.To...); err != nil { + if err := ntf.AttachEmailRecipients(ctx, msg, "To", r.To...); err != nil { return false, err } - if err := ntf.AttachEmailRecipients(msg, "Cc", r.Cc...); err != nil { + if err := ntf.AttachEmailRecipients(ctx, msg, "Cc", r.Cc...); err != nil { return false, err } @@ -72,7 +72,7 @@ func (ctrl *Notification) EmailSend(ctx context.Context, r *request.Notification } } - if err := ntf.SendEmail(msg); err != nil { + if err := ntf.SendEmail(ctx, msg); err != nil { return false, err } else { return true, nil diff --git a/compose/service/notification.go b/compose/service/notification.go index 772b764c1..ae12e6ac3 100644 --- a/compose/service/notification.go +++ b/compose/service/notification.go @@ -4,6 +4,7 @@ import ( "context" "net/http" "path" + "strconv" "strings" "sync" @@ -15,17 +16,24 @@ import ( httpClient "github.com/cortezaproject/corteza-server/pkg/http" "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/pkg/mail" + "github.com/cortezaproject/corteza-server/system/types" ) type ( notification struct { logger *zap.Logger + users notificationUserFinder + } + + notificationUserFinder interface { + FindByID(context.Context, uint64) (*types.User, error) } ) func Notification() *notification { return ¬ification{ logger: DefaultLogger.Named("notification"), + users: DefaultSystemUser, } } @@ -34,7 +42,7 @@ func (svc notification) log(ctx context.Context, fields ...zapcore.Field) *zap.L return logger.AddRequestID(ctx, svc.logger).With(fields...) } -func (svc notification) SendEmail(message *gomail.Message) error { +func (svc notification) SendEmail(ctx context.Context, message *gomail.Message) error { return mail.Send(message) } @@ -45,7 +53,7 @@ func (svc notification) SendEmail(message *gomail.Message) error { // - // - // Last one is then translated into valid email + name (when/if possible) -func (svc notification) AttachEmailRecipients(message *gomail.Message, field string, recipients ...string) (err error) { +func (svc notification) AttachEmailRecipients(ctx context.Context, message *gomail.Message, field string, recipients ...string) (err error) { var ( email string name string @@ -59,10 +67,20 @@ func (svc notification) AttachEmailRecipients(message *gomail.Message, field str name, email = "", "" rcpt = strings.TrimSpace(rcpt) - // First, get userID off the table - if spaceAt := strings.Index(rcpt, " "); spaceAt > -1 { + if userID, err := strconv.ParseUint(rcpt, 10, 64); err == nil && userID > 0 { + // handle user ID + if user, err := svc.users.FindByID(ctx, userID); err != nil { + return errors.Wrap(err, "could not get notification address") + } else { + email = user.Email + name = user.Name + } + + } else if spaceAt := strings.Index(rcpt, " "); spaceAt > -1 { + // handle: ("foo@bar.baz foo baz") email, name = rcpt[:spaceAt], strings.TrimSpace(rcpt[spaceAt+1:]) } else { + // handle: email = rcpt } diff --git a/compose/service/system_user.go b/compose/service/system_user.go index 14e8aba6e..355eeb0c3 100644 --- a/compose/service/system_user.go +++ b/compose/service/system_user.go @@ -39,6 +39,10 @@ func (svc systemUser) MakeJWT(ctx context.Context, ID uint64) (string, error) { } func (svc systemUser) FindByID(ctx context.Context, ID uint64) (*types.User, error) { + ctx = metadata.NewOutgoingContext(ctx, metadata.MD{ + "jwt": []string{auth.GetJwtFromContext(ctx)}, + }) + rsp, err := svc.client.FindByID(ctx, &proto.FindByIDUserRequest{UserID: ID}) if err != nil { return nil, err diff --git a/system/service/user.go b/system/service/user.go index 82060ccd6..06833fbb4 100644 --- a/system/service/user.go +++ b/system/service/user.go @@ -109,23 +109,31 @@ func (svc user) FindByID(ID uint64) (*types.User, error) { return nil, ErrInvalidID } - return svc.user.FindByID(ID) -} - -func (svc user) FindByIDs(userIDs ...uint64) (types.UserSet, error) { - return svc.user.FindByIDs(userIDs...) + return svc.proc(svc.user.FindByID(ID)) } func (svc user) FindByEmail(email string) (*types.User, error) { - return svc.user.FindByEmail(email) + return svc.proc(svc.user.FindByEmail(email)) } func (svc user) FindByUsername(username string) (*types.User, error) { - return svc.user.FindByUsername(username) + return svc.proc(svc.user.FindByUsername(username)) } func (svc user) FindByHandle(handle string) (*types.User, error) { - return svc.user.FindByHandle(handle) + return svc.proc(svc.user.FindByHandle(handle)) +} + +func (svc user) proc(u *types.User, err error) (*types.User, error) { + if err != nil { + return nil, err + } + + return u, nil +} + +func (svc user) FindByIDs(userIDs ...uint64) (types.UserSet, error) { + return svc.procSet(svc.user.FindByIDs(userIDs...)) } func (svc user) Find(f types.UserFilter) (types.UserSet, types.UserFilter, error) { @@ -138,6 +146,14 @@ func (svc user) Find(f types.UserFilter) (types.UserSet, types.UserFilter, error return svc.user.Find(f) } +func (svc user) procSet(u types.UserSet, err error) (types.UserSet, error) { + if err != nil { + return nil, err + } + + return u, nil +} + func (svc user) Create(input *types.User) (out *types.User, err error) { if !svc.ac.CanCreateUser(svc.ctx) { return nil, ErrNoCreatePermissions.withStack()