From 5b3b584c8fe0fc5df7157ae83dcf824775a33b46 Mon Sep 17 00:00:00 2001 From: Mumbi Francis Date: Thu, 2 Feb 2023 12:48:20 +0300 Subject: [PATCH] Add functionality to generate user avatars and enable users to upload and manage their profile photos --- client/web/admin/src/components/CUploader.vue | 2 +- .../Settings/System/CSystemEditorAuth.vue | 7 + .../src/components/User/CUserEditorAvatar.vue | 157 + .../admin/src/views/System/User/Editor.vue | 52 + lib/js/src/api-clients/system.ts | 90 + lib/js/src/system/types/user.ts | 8 + lib/vue/src/components/navigation/CTopbar.vue | 26 +- lib/vue/src/plugins/auth.ts | 4 + locale/en/corteza-server/auth/profile.yaml | 10 + .../en/corteza-webapp-admin/notification.yaml | 6 + .../corteza-webapp-admin/system.settings.yaml | 18 +- .../en/corteza-webapp-admin/system.users.yaml | 11 + server/.env.example | 29 + server/app/app.cue | 1 + server/app/boot_levels.go | 18 +- server/app/options/attachment.cue | 32 + server/auth/assets/public/script.js | 4 + server/auth/assets/public/style.css | 4 + server/auth/assets/templates/profile.html.tpl | 40 + server/auth/auth.go | 1 + server/auth/handlers/handle_oauth2.go | 7 + server/auth/handlers/handle_profile.go | 86 +- server/auth/handlers/handle_profile_test.go | 144 +- server/auth/handlers/handler.go | 7 + server/auth/handlers/links.go | 2 + server/auth/handlers/mock_test.go | 38 +- server/auth/handlers/routes.go | 1 + server/auth/settings/settings.go | 1 + server/go.mod | 2 + server/go.sum | 4 + server/pkg/options/helpers.go | 2 +- server/pkg/options/options.gen.go | 37 + server/pkg/options/options.go | 2 + server/provision/001_settings/auth.yaml | 1 + server/system/rest.yaml | 53 + server/system/rest/attachment.go | 2 +- server/system/rest/handlers/user.go | 95 +- server/system/rest/request/user.go | 308 +- server/system/rest/user.go | 12 + server/system/service/attachment.go | 178 +- .../system/service/attachment_actions.gen.go | 128 +- server/system/service/attachment_actions.yaml | 12 + server/system/service/service.go | 19 +- server/system/service/user.go | 284 +- server/system/service/user_actions.gen.go | 154 +- server/system/service/user_actions.yaml | 13 + server/system/service/user_test.go | 82 + server/system/types/app_settings.go | 2 + server/system/types/attachment.go | 13 +- server/system/types/user.go | 9 +- .../vendor/github.com/fogleman/gg/.gitignore | 2 + .../vendor/github.com/fogleman/gg/LICENSE.md | 19 + .../vendor/github.com/fogleman/gg/README.md | 221 + .../vendor/github.com/fogleman/gg/bezier.go | 59 + .../vendor/github.com/fogleman/gg/context.go | 909 +++ .../vendor/github.com/fogleman/gg/gradient.go | 202 + .../vendor/github.com/fogleman/gg/matrix.go | 88 + server/vendor/github.com/fogleman/gg/path.go | 163 + .../vendor/github.com/fogleman/gg/pattern.go | 123 + server/vendor/github.com/fogleman/gg/point.go | 25 + server/vendor/github.com/fogleman/gg/util.go | 146 + server/vendor/github.com/fogleman/gg/wrap.go | 58 + .../vendor/github.com/golang/freetype/AUTHORS | 20 + .../github.com/golang/freetype/CONTRIBUTORS | 38 + .../vendor/github.com/golang/freetype/LICENSE | 12 + .../github.com/golang/freetype/raster/geom.go | 245 + .../golang/freetype/raster/paint.go | 287 + .../golang/freetype/raster/raster.go | 601 ++ .../golang/freetype/raster/stroke.go | 483 ++ .../golang/freetype/truetype/face.go | 507 ++ .../golang/freetype/truetype/glyph.go | 522 ++ .../golang/freetype/truetype/hint.go | 1770 +++++ .../golang/freetype/truetype/opcodes.go | 289 + .../golang/freetype/truetype/truetype.go | 653 ++ server/vendor/golang.org/x/image/draw/draw.go | 61 + server/vendor/golang.org/x/image/draw/impl.go | 6670 +++++++++++++++++ .../vendor/golang.org/x/image/draw/scale.go | 525 ++ .../x/image/font/basicfont/basicfont.go | 129 + .../golang.org/x/image/font/basicfont/data.go | 1456 ++++ server/vendor/golang.org/x/image/font/font.go | 371 + .../vendor/golang.org/x/image/math/f64/f64.go | 37 + .../golang.org/x/image/math/fixed/fixed.go | 410 + server/vendor/modules.txt | 12 + 83 files changed, 19107 insertions(+), 224 deletions(-) create mode 100644 client/web/admin/src/components/User/CUserEditorAvatar.vue create mode 100644 server/app/options/attachment.cue create mode 100644 server/vendor/github.com/fogleman/gg/.gitignore create mode 100644 server/vendor/github.com/fogleman/gg/LICENSE.md create mode 100644 server/vendor/github.com/fogleman/gg/README.md create mode 100644 server/vendor/github.com/fogleman/gg/bezier.go create mode 100644 server/vendor/github.com/fogleman/gg/context.go create mode 100644 server/vendor/github.com/fogleman/gg/gradient.go create mode 100644 server/vendor/github.com/fogleman/gg/matrix.go create mode 100644 server/vendor/github.com/fogleman/gg/path.go create mode 100644 server/vendor/github.com/fogleman/gg/pattern.go create mode 100644 server/vendor/github.com/fogleman/gg/point.go create mode 100644 server/vendor/github.com/fogleman/gg/util.go create mode 100644 server/vendor/github.com/fogleman/gg/wrap.go create mode 100644 server/vendor/github.com/golang/freetype/AUTHORS create mode 100644 server/vendor/github.com/golang/freetype/CONTRIBUTORS create mode 100644 server/vendor/github.com/golang/freetype/LICENSE create mode 100644 server/vendor/github.com/golang/freetype/raster/geom.go create mode 100644 server/vendor/github.com/golang/freetype/raster/paint.go create mode 100644 server/vendor/github.com/golang/freetype/raster/raster.go create mode 100644 server/vendor/github.com/golang/freetype/raster/stroke.go create mode 100644 server/vendor/github.com/golang/freetype/truetype/face.go create mode 100644 server/vendor/github.com/golang/freetype/truetype/glyph.go create mode 100644 server/vendor/github.com/golang/freetype/truetype/hint.go create mode 100644 server/vendor/github.com/golang/freetype/truetype/opcodes.go create mode 100644 server/vendor/github.com/golang/freetype/truetype/truetype.go create mode 100644 server/vendor/golang.org/x/image/draw/draw.go create mode 100644 server/vendor/golang.org/x/image/draw/impl.go create mode 100644 server/vendor/golang.org/x/image/draw/scale.go create mode 100644 server/vendor/golang.org/x/image/font/basicfont/basicfont.go create mode 100644 server/vendor/golang.org/x/image/font/basicfont/data.go create mode 100644 server/vendor/golang.org/x/image/font/font.go create mode 100644 server/vendor/golang.org/x/image/math/f64/f64.go create mode 100644 server/vendor/golang.org/x/image/math/fixed/fixed.go diff --git a/client/web/admin/src/components/CUploader.vue b/client/web/admin/src/components/CUploader.vue index 281888285..1285620d0 100644 --- a/client/web/admin/src/components/CUploader.vue +++ b/client/web/admin/src/components/CUploader.vue @@ -11,7 +11,7 @@ @vdropzone-error="onError" @vdropzone-upload-progress="onUploadProgress" > -
+
+ + diff --git a/client/web/admin/src/views/System/User/Editor.vue b/client/web/admin/src/views/System/User/Editor.vue index 4a9b1617d..17134bb02 100644 --- a/client/web/admin/src/views/System/User/Editor.vue +++ b/client/web/admin/src/views/System/User/Editor.vue @@ -52,6 +52,18 @@ @sessionsRevoke="onSessionsRevoke" /> + + { + this.fetchUser() + this.$auth.handle() + this.animateSuccess('info') + this.toastSuccess(this.$t('notification:user.avatarUpload.success')) + }) + .catch(this.toastErrorHandler(this.$t('notification:user.avatarUpload.error'))) + .finally(() => { + this.info.processing = false + }) + }, + /** * Handles user delete event, calls user delete API endpoint * and handles response & errors @@ -451,6 +487,22 @@ export default { this.decLoader() }) }, + + onAvatarUpload () { + this.fetchUser() + }, + + onResetAvatar () { + const userID = this.userID + + this.$SystemAPI.userDeleteAvatar({ userID }) + .then(() => { + this.fetchUser() + + this.toastSuccess(this.$t('notification:user.avatarDelete.success')) + }) + .catch(this.toastErrorHandler(this.$t('notification:user.avatarDelete.error'))) + }, }, } diff --git a/lib/js/src/api-clients/system.ts b/lib/js/src/api-clients/system.ts index 5e24a6001..2f5012109 100644 --- a/lib/js/src/api-clients/system.ts +++ b/lib/js/src/api-clients/system.ts @@ -1478,6 +1478,96 @@ export default class System { return `/users/${userID}/credentials/${credentialsID}` } + // User's profile avatar + async userProfileAvatar (a: KV, extra: AxiosRequestConfig = {}): Promise { + const { + userID, + upload, + width, + height, + } = (a as KV) || {} + if (!userID) { + throw Error('field userID is empty') + } + const cfg: AxiosRequestConfig = { + ...extra, + method: 'post', + url: this.userProfileAvatarEndpoint({ + userID, + }), + } + cfg.data = { + upload, + width, + height, + } + return this.api().request(cfg).then(result => stdResolve(result)) + } + + userProfileAvatarEndpoint (a: KV): string { + const { + userID, + } = a || {} + return `/users/${userID}/avatar` + } + + // User profile avatar initial + async userProfileAvatarInitial (a: KV, extra: AxiosRequestConfig = {}): Promise { + const { + userID, + avatarColor, + avatarBgColor, + } = (a as KV) || {} + if (!userID) { + throw Error('field userID is empty') + } + const cfg: AxiosRequestConfig = { + ...extra, + method: 'post', + url: this.userProfileAvatarInitialEndpoint({ + userID, + }), + } + cfg.data = { + avatarColor, + avatarBgColor, + } + return this.api().request(cfg).then(result => stdResolve(result)) + } + + userProfileAvatarInitialEndpoint (a: KV): string { + const { + userID, + } = a || {} + return `/users/${userID}/avatar-initial` + } + + // delete user's profile avatar + async userDeleteAvatar (a: KV, extra: AxiosRequestConfig = {}): Promise { + const { + userID, + } = (a as KV) || {} + if (!userID) { + throw Error('field userID is empty') + } + const cfg: AxiosRequestConfig = { + ...extra, + method: 'delete', + url: this.userDeleteAvatarEndpoint({ + userID, + }), + } + + return this.api().request(cfg).then(result => stdResolve(result)) + } + + userDeleteAvatarEndpoint (a: KV): string { + const { + userID, + } = a || {} + return `/users/${userID}/avatar` + } + // Export users async userExport (a: KV, extra: AxiosRequestConfig = {}): Promise { const { diff --git a/lib/js/src/system/types/user.ts b/lib/js/src/system/types/user.ts index e9654bc49..0de36438b 100644 --- a/lib/js/src/system/types/user.ts +++ b/lib/js/src/system/types/user.ts @@ -11,6 +11,10 @@ interface PartialUser extends Partial