support set gravatar as user avatar provider

This commit is contained in:
MaysWind
2023-07-01 00:51:45 +08:00
parent a8b76d5537
commit 652b3e1954
7 changed files with 61 additions and 2 deletions
+5
View File
@@ -106,6 +106,11 @@ request_id_header = true
# Set to true to allow users to register account by themselves
enable_register = true
# User avatar provider, supports the following types:
# "gravatar": https://gravatar.com
# Leave blank if you want to disable user avatar
avatar_provider =
[data]
# Set to true to allow users to export their data
enable_export = true
+15
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"time"
"github.com/mayswind/ezbookkeeping/pkg/settings"
"github.com/mayswind/ezbookkeeping/pkg/utils"
)
@@ -77,6 +78,7 @@ type UserBasicInfo struct {
Username string `json:"username"`
Email string `json:"email"`
Nickname string `json:"nickname"`
AvatarUrl string `json:"avatar"`
DefaultAccountId int64 `json:"defaultAccountId,string"`
TransactionEditScope TransactionEditScope `json:"transactionEditScope"`
Language string `json:"language"`
@@ -133,6 +135,7 @@ type UserProfileResponse struct {
Username string `json:"username"`
Email string `json:"email"`
Nickname string `json:"nickname"`
AvatarUrl string `json:"avatar"`
DefaultAccountId int64 `json:"defaultAccountId,string"`
TransactionEditScope TransactionEditScope `json:"transactionEditScope"`
Language string `json:"language"`
@@ -193,6 +196,7 @@ func (u *User) ToUserBasicInfo() *UserBasicInfo {
Username: u.Username,
Email: u.Email,
Nickname: u.Nickname,
AvatarUrl: u.getAvatarUrl(),
DefaultAccountId: u.DefaultAccountId,
TransactionEditScope: u.TransactionEditScope,
Language: u.Language,
@@ -211,6 +215,7 @@ func (u *User) ToUserProfileResponse() *UserProfileResponse {
Username: u.Username,
Email: u.Email,
Nickname: u.Nickname,
AvatarUrl: u.getAvatarUrl(),
DefaultAccountId: u.DefaultAccountId,
TransactionEditScope: u.TransactionEditScope,
Language: u.Language,
@@ -223,3 +228,13 @@ func (u *User) ToUserProfileResponse() *UserProfileResponse {
LastLoginAt: u.LastLoginUnixTime,
}
}
func (u *User) getAvatarUrl() string {
avatarProvider := settings.Container.Current.AvatarProvider
if avatarProvider == settings.GravatarProvider {
return utils.GetGravatarUrl(u.Email)
}
return ""
}
+12
View File
@@ -62,6 +62,11 @@ const (
InternalUuidGeneratorType string = "internal"
)
// User avatar provider types
const (
GravatarProvider string = "gravatar"
)
// Map provider types
const (
OpenStreetMapProvider string = "openstreetmap"
@@ -185,6 +190,7 @@ type Config struct {
// User
EnableUserRegister bool
AvatarProvider string
// Data
EnableDataExport bool
@@ -444,6 +450,12 @@ func loadSecurityConfiguration(config *Config, configFile *ini.File, sectionName
func loadUserConfiguration(config *Config, configFile *ini.File, sectionName string) error {
config.EnableUserRegister = getConfigItemBoolValue(configFile, sectionName, "enable_register", false)
if getConfigItemStringValue(configFile, sectionName, "avatar_provider") == "" {
config.AvatarProvider = ""
} else if getConfigItemStringValue(configFile, sectionName, "avatar_provider") == GravatarProvider {
config.AvatarProvider = GravatarProvider
}
return nil
}
+11
View File
@@ -0,0 +1,11 @@
package utils
import "fmt"
const gravatarUrlFormat = "https://www.gravatar.com/avatar/%s"
// GetGravatarUrl returns the Gravatar url according to the specified user email address
func GetGravatarUrl(email string) string {
emailMd5 := MD5EncodeToString([]byte(email))
return fmt.Sprintf(gravatarUrlFormat, emailMd5)
}
+7
View File
@@ -7,6 +7,7 @@ import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"strings"
"unicode"
@@ -133,6 +134,12 @@ func MD5Encode(data []byte) []byte {
return m.Sum(nil)
}
// MD5EncodeToString returns a hashed string by md5
func MD5EncodeToString(data []byte) string {
hash := MD5Encode(data)
return hex.EncodeToString(hash)
}
// AESGCMEncrypt returns a encrypted string by aes-gcm
func AESGCMEncrypt(key []byte, plainText []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
+4
View File
@@ -16,6 +16,10 @@ export const useUserStore = defineStore('user', {
const userInfo = state.currentUserInfo || {};
return userInfo.nickname || userInfo.username || null;
},
currentUserAvatar(state) {
const userInfo = state.currentUserInfo || {};
return userInfo.avatar || null;
},
currentUserDefaultAccountId(state) {
const userInfo = state.currentUserInfo || {};
return userInfo.defaultAccountId || '';
+7 -2
View File
@@ -113,14 +113,16 @@
<v-icon :icon="(theme === 'light' ? icons.themeLight : (theme === 'dark' ? icons.themeDark : icons.themeAuto))" size="24" />
</v-btn>
<v-avatar class="cursor-pointer" color="primary" variant="tonal">
<v-icon :icon="icons.user"/>
<v-img :src="currentUserAvatar" v-if="currentUserAvatar"/>
<v-icon :icon="icons.user" v-else-if="!currentUserAvatar"/>
<v-menu activator="parent" width="230" location="bottom end" offset="14px">
<v-list>
<v-list-item>
<template #prepend>
<v-list-item-action start>
<v-avatar color="primary" variant="tonal">
<v-icon :icon="icons.user"/>
<v-img :src="currentUserAvatar" v-if="currentUserAvatar"/>
<v-icon :icon="icons.user" v-else-if="!currentUserAvatar"/>
</v-avatar>
</v-list-item-action>
</template>
@@ -264,6 +266,9 @@ export default {
currentNickName() {
return this.userStore.currentUserNickname || this.$t('User');
},
currentUserAvatar() {
return this.userStore.currentUserAvatar;
},
theme: {
get: function () {
return this.settingsStore.appSettings.theme;