diff --git a/server/auth/handlers/handle_profile.go b/server/auth/handlers/handle_profile.go index fa256b145..0b3571289 100644 --- a/server/auth/handlers/handle_profile.go +++ b/server/auth/handlers/handle_profile.go @@ -3,9 +3,11 @@ package handlers import ( "fmt" "github.com/cortezaproject/corteza/server/auth/request" + "github.com/cortezaproject/corteza/server/pkg/options" "github.com/cortezaproject/corteza/server/system/service" "github.com/cortezaproject/corteza/server/system/types" "go.uber.org/zap" + "strings" ) func (h *AuthHandlers) profileForm(req *request.AuthReq) (err error) { @@ -32,7 +34,7 @@ func (h *AuthHandlers) profileForm(req *request.AuthReq) (err error) { } } - avatarUrl = fmt.Sprintf("%sapi/system/attachment/avatar/%d/original/%s", GetLinks().Base, u.Meta.AvatarID, types.AttachmentKindAvatar) + avatarUrl = fmt.Sprintf("%s/system/attachment/avatar/%d/original/%s", getApiFullPath(), u.Meta.AvatarID, types.AttachmentKindAvatar) if form := req.PopKV(); len(form) > 0 { req.Data["form"] = form @@ -137,7 +139,7 @@ func (h *AuthHandlers) profileProc(req *request.AuthReq) error { return nil } - avatarUrl := fmt.Sprintf("%sapi/system/attachment/avatar/%d/original/%s", GetLinks().Base, u.Meta.AvatarID, types.AttachmentKindAvatar) + avatarUrl := fmt.Sprintf("%s/system/attachment/avatar/%d/original/%s", getApiFullPath(), u.Meta.AvatarID, types.AttachmentKindAvatar) switch { case service.UserErrInvalidID().Is(err), @@ -172,3 +174,7 @@ func (h *AuthHandlers) profileProc(req *request.AuthReq) error { return err } } + +func getApiFullPath() (path string) { + return fmt.Sprintf("/%s", strings.TrimPrefix(options.CleanBase(options.HttpServer().BaseUrl, options.HttpServer().ApiBaseUrl), "/")) +} diff --git a/server/auth/handlers/handle_profile_test.go b/server/auth/handlers/handle_profile_test.go index 08253d6d6..4071d3813 100644 --- a/server/auth/handlers/handle_profile_test.go +++ b/server/auth/handlers/handle_profile_test.go @@ -46,7 +46,7 @@ func Test_profileForm(t *testing.T) { authHandlers.UserService = userService authReq = prepareClientAuthReq(authHandlers, req, user) - avatarUrl := fmt.Sprintf("/api/system/attachment/avatar/%d/original/%s", user.Meta.AvatarID, types.AttachmentKindAvatar) + avatarUrl := fmt.Sprintf("//system/attachment/avatar/%d/original/%s", user.Meta.AvatarID, types.AttachmentKindAvatar) userForm := map[string]string{ "email": user.Email, @@ -123,7 +123,7 @@ func Test_profileFormProc(t *testing.T) { "name": "name", "initialBgColor": "", "initialTextColor": "", - "avatarUrl": "/api/system/attachment/avatar/0/original/avatar", + "avatarUrl": "//system/attachment/avatar/0/original/avatar", }, fn: func(_ *settings.Settings) { req.PostForm.Add("handle", "handle") @@ -154,7 +154,7 @@ func Test_profileFormProc(t *testing.T) { "name": "name", "initialBgColor": "", "initialTextColor": "", - "avatarUrl": "/api/system/attachment/avatar/0/original/avatar", + "avatarUrl": "//system/attachment/avatar/0/original/avatar", }, fn: func(_ *settings.Settings) { req.PostForm.Add("handle", "handle") @@ -185,7 +185,7 @@ func Test_profileFormProc(t *testing.T) { "name": "name", "initialBgColor": "", "initialTextColor": "", - "avatarUrl": "/api/system/attachment/avatar/0/original/avatar", + "avatarUrl": "//system/attachment/avatar/0/original/avatar", }, fn: func(_ *settings.Settings) { req.PostForm.Add("handle", "handle") @@ -216,7 +216,7 @@ func Test_profileFormProc(t *testing.T) { "name": "name", "initialBgColor": "", "initialTextColor": "", - "avatarUrl": "/api/system/attachment/avatar/0/original/avatar", + "avatarUrl": "//system/attachment/avatar/0/original/avatar", }, fn: func(_ *settings.Settings) { req.PostForm.Add("handle", "handle") @@ -247,7 +247,7 @@ func Test_profileFormProc(t *testing.T) { "name": "name", "initialBgColor": "", "initialTextColor": "", - "avatarUrl": "/api/system/attachment/avatar/0/original/avatar", + "avatarUrl": "//system/attachment/avatar/0/original/avatar", }, fn: func(_ *settings.Settings) { req.PostForm.Add("handle", "handle") diff --git a/server/system/service/attachment.go b/server/system/service/attachment.go index f46516dcb..5a4b0d358 100644 --- a/server/system/service/attachment.go +++ b/server/system/service/attachment.go @@ -3,6 +3,7 @@ package service import ( "bytes" "context" + "errors" "fmt" "github.com/cortezaproject/corteza/server/pkg/actionlog" intAuth "github.com/cortezaproject/corteza/server/pkg/auth" @@ -269,12 +270,12 @@ func (svc attachment) CreateAvatarInitialsAttachment(ctx context.Context, initia dc.SetHexColor(bgColor) dc.Clear() - // Get the font face properties - fontBytes, err := os.ReadFile(svc.opt.AvatarInitialsFontPath) + fontBytes, err := svc.processFontsFile() if err != nil { - fmt.Println(err.Error()) + return nil, err } + // Get the font face properties f, _ := truetype.Parse(fontBytes) face := truetype.NewFace(f, &truetype.Options{ @@ -521,3 +522,28 @@ func (svc attachment) processImage(original io.ReadSeeker, att *types.Attachment return svc.files.Save(att.PreviewUrl, buf) } + +// processFontsFile validates the file path provided in the AVATAR_INITIALS_FONT_PATH environment variable, +// It checks if the file exists and has the correct file extension, then reads and returns the file content +func (svc attachment) processFontsFile() (fontBytes []byte, err error) { + aux, err := filepath.Glob(svc.opt.AvatarInitialsFontPath) + if err != nil { + return nil, err + } + if aux == nil || len(aux) != 1 { + return nil, errors.New("font file not found, please ensure that the correct AVATAR_INITIALS_FONT_PATH is set") + } + + ext := strings.ToLower(filepath.Ext(aux[0])) + + if ext != ".ttf" { + return nil, errors.New("invalid font file extension, please provide a truetype font (.ttf) file") + } + + fontBytes, err = os.ReadFile(aux[0]) + if err != nil { + return nil, err + } + + return fontBytes, nil +} diff --git a/server/system/service/user.go b/server/system/service/user.go index f52422d18..154344559 100644 --- a/server/system/service/user.go +++ b/server/system/service/user.go @@ -431,7 +431,7 @@ func (svc user) Update(ctx context.Context, upd *types.User) (u *types.User, err return UserErrInvalidEmail() } - if u, err = svc.FindByID(ctx, upd.ID); err != nil { + if u, err = loadUser(ctx, svc.store, upd.ID); err != nil { return } @@ -461,7 +461,7 @@ func (svc user) Update(ctx context.Context, upd *types.User) (u *types.User, err } if err = svc.generateUserAvatarInitial(ctx, u); err != nil { - return err + return } if err = svc.eventbus.WaitFor(ctx, event.UserBeforeUpdate(upd, u)); err != nil { @@ -1073,6 +1073,10 @@ func (svc user) UploadAvatar(ctx context.Context, userID uint64, upload *multipa return } + if !svc.ac.CanUpdateUser(ctx, u) { + return UserErrNotAllowedToUpdate() + } + if u.Meta.AvatarID != 0 { if err = svc.att.DeleteByID(ctx, u.Meta.AvatarID); err != nil { return @@ -1236,6 +1240,10 @@ func (svc user) GenerateAvatar(ctx context.Context, userID uint64, bgColor strin return } + if !svc.ac.CanUpdateUser(ctx, u) { + return UserErrNotAllowedToUpdate() + } + u.Meta.AvatarColor = initialColor u.Meta.AvatarBgColor = bgColor if err = svc.generateUserAvatarInitial(ctx, u); err != nil { diff --git a/server/tests/system/main_test.go b/server/tests/system/main_test.go index 9d6f8c58c..47d7cb92e 100644 --- a/server/tests/system/main_test.go +++ b/server/tests/system/main_test.go @@ -99,6 +99,7 @@ func InitTestApp() { sm = request.NewSessionManager(service.DefaultStore, app.Opt.Auth, service.DefaultLogger) + app.Opt.Attachment.AvatarInitialsFontPath = "../../auth/assets/public/fonts/poppins/Poppins-Regular.ttf" return nil })