code refactor
This commit is contained in:
+2
-2
@@ -153,7 +153,7 @@ func startWebServer(c *cli.Context) error {
|
||||
router.StaticFile("/desktop/"+workboxFileNames[i], filepath.Join(config.StaticRootPath, workboxFileNames[i]))
|
||||
}
|
||||
|
||||
if config.AvatarProvider == settings.InternalAvatarProvider {
|
||||
if config.AvatarProvider == core.USER_AVATAR_PROVIDER_INTERNAL {
|
||||
avatarRoute := router.Group("/avatar")
|
||||
avatarRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString))
|
||||
{
|
||||
@@ -261,7 +261,7 @@ func startWebServer(c *cli.Context) error {
|
||||
apiV1Route.GET("/users/profile/get.json", bindApi(api.Users.UserProfileHandler))
|
||||
apiV1Route.POST("/users/profile/update.json", bindApiWithTokenUpdate(api.Users.UserUpdateProfileHandler, config))
|
||||
|
||||
if config.AvatarProvider == settings.InternalAvatarProvider {
|
||||
if config.AvatarProvider == core.USER_AVATAR_PROVIDER_INTERNAL {
|
||||
apiV1Route.POST("/users/avatar/update.json", bindApi(api.Users.UserUpdateAvatarHandler))
|
||||
apiV1Route.POST("/users/avatar/remove.json", bindApi(api.Users.UserRemoveAvatarHandler))
|
||||
}
|
||||
|
||||
+11
-3
@@ -16,12 +16,20 @@ import (
|
||||
|
||||
// AccountsApi represents account api
|
||||
type AccountsApi struct {
|
||||
ApiUsingConfig
|
||||
ApiUsingDuplicateChecker
|
||||
accounts *services.AccountService
|
||||
}
|
||||
|
||||
// Initialize an account api singleton instance
|
||||
var (
|
||||
Accounts = &AccountsApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
ApiUsingDuplicateChecker: ApiUsingDuplicateChecker{
|
||||
container: duplicatechecker.Container,
|
||||
},
|
||||
accounts: services.Accounts,
|
||||
}
|
||||
)
|
||||
@@ -211,8 +219,8 @@ func (a *AccountsApi) AccountCreateHandler(c *core.Context) (any, *errs.Error) {
|
||||
mainAccount := a.createNewAccountModel(uid, &accountCreateReq, maxOrderId+1)
|
||||
childrenAccounts := a.createSubAccountModels(uid, &accountCreateReq)
|
||||
|
||||
if settings.Container.Current.EnableDuplicateSubmissionsCheck && accountCreateReq.ClientSessionId != "" {
|
||||
found, remark := duplicatechecker.Container.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_ACCOUNT, uid, accountCreateReq.ClientSessionId)
|
||||
if a.CurrentConfig().EnableDuplicateSubmissionsCheck && accountCreateReq.ClientSessionId != "" {
|
||||
found, remark := a.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_ACCOUNT, uid, accountCreateReq.ClientSessionId)
|
||||
|
||||
if found {
|
||||
log.InfofWithRequestId(c, "[accounts.AccountCreateHandler] another account \"id:%s\" has been created for user \"uid:%d\"", remark, uid)
|
||||
@@ -256,7 +264,7 @@ func (a *AccountsApi) AccountCreateHandler(c *core.Context) (any, *errs.Error) {
|
||||
|
||||
log.InfofWithRequestId(c, "[accounts.AccountCreateHandler] user \"uid:%d\" has created a new account \"id:%d\" successfully", uid, mainAccount.AccountId)
|
||||
|
||||
duplicatechecker.Container.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_ACCOUNT, uid, accountCreateReq.ClientSessionId, utils.Int64ToString(mainAccount.AccountId))
|
||||
a.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_ACCOUNT, uid, accountCreateReq.ClientSessionId, utils.Int64ToString(mainAccount.AccountId))
|
||||
accountInfoResp := mainAccount.ToAccountInfoResponse()
|
||||
|
||||
if len(childrenAccounts) > 0 {
|
||||
|
||||
@@ -18,11 +18,16 @@ const amapRestApiUrl = "https://restapi.amap.com/"
|
||||
|
||||
// AmapApiProxy represents amap api proxy
|
||||
type AmapApiProxy struct {
|
||||
ApiUsingConfig
|
||||
}
|
||||
|
||||
// Initialize a amap api proxy singleton instance
|
||||
var (
|
||||
AmapApis = &AmapApiProxy{}
|
||||
AmapApis = &AmapApiProxy{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// AmapApiProxyHandler returns amap api response
|
||||
@@ -38,7 +43,7 @@ func (p *AmapApiProxy) AmapApiProxyHandler(c *core.Context) (*httputil.ReversePr
|
||||
}
|
||||
|
||||
director := func(req *http.Request) {
|
||||
targetRawUrl := fmt.Sprintf("%s?%s&jscode=%s", targetUrl, req.URL.RawQuery, settings.Container.Current.AmapApplicationSecret)
|
||||
targetRawUrl := fmt.Sprintf("%s?%s&jscode=%s", targetUrl, req.URL.RawQuery, p.CurrentConfig().AmapApplicationSecret)
|
||||
targetUrl, _ := url.Parse(targetRawUrl)
|
||||
|
||||
oldCookies := req.Cookies()
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
// AuthorizationsApi represents authorization api
|
||||
type AuthorizationsApi struct {
|
||||
ApiUsingConfig
|
||||
users *services.UserService
|
||||
tokens *services.TokenService
|
||||
twoFactorAuthorizations *services.TwoFactorAuthorizationService
|
||||
@@ -21,6 +22,9 @@ type AuthorizationsApi struct {
|
||||
// Initialize a authorization api singleton instance
|
||||
var (
|
||||
Authorizations = &AuthorizationsApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
users: services.Users,
|
||||
tokens: services.Tokens,
|
||||
twoFactorAuthorizations: services.TwoFactorAuthorizations,
|
||||
@@ -49,7 +53,7 @@ func (a *AuthorizationsApi) AuthorizeHandler(c *core.Context) (any, *errs.Error)
|
||||
return nil, errs.ErrUserIsDisabled
|
||||
}
|
||||
|
||||
if settings.Container.Current.EnableUserForceVerifyEmail && !user.EmailVerified {
|
||||
if a.CurrentConfig().EnableUserForceVerifyEmail && !user.EmailVerified {
|
||||
hasValidEmailVerifyToken, err := a.tokens.ExistsValidTokenByType(c, user.Uid, core.USER_TOKEN_TYPE_EMAIL_VERIFY)
|
||||
|
||||
if err != nil {
|
||||
@@ -143,7 +147,7 @@ func (a *AuthorizationsApi) TwoFactorAuthorizeHandler(c *core.Context) (any, *er
|
||||
return nil, errs.ErrUserIsDisabled
|
||||
}
|
||||
|
||||
if settings.Container.Current.EnableUserForceVerifyEmail && !user.EmailVerified {
|
||||
if a.CurrentConfig().EnableUserForceVerifyEmail && !user.EmailVerified {
|
||||
log.WarnfWithRequestId(c, "[authorizations.TwoFactorAuthorizeHandler] user \"uid:%d\" has not verified email", user.Uid)
|
||||
return nil, errs.ErrEmailIsNotVerified
|
||||
}
|
||||
@@ -205,7 +209,7 @@ func (a *AuthorizationsApi) TwoFactorAuthorizeByRecoveryCodeHandler(c *core.Cont
|
||||
return nil, errs.ErrUserIsDisabled
|
||||
}
|
||||
|
||||
if settings.Container.Current.EnableUserForceVerifyEmail && !user.EmailVerified {
|
||||
if a.CurrentConfig().EnableUserForceVerifyEmail && !user.EmailVerified {
|
||||
log.WarnfWithRequestId(c, "[authorizations.TwoFactorAuthorizeByRecoveryCodeHandler] user \"uid:%d\" has not verified email", user.Uid)
|
||||
return nil, errs.ErrEmailIsNotVerified
|
||||
}
|
||||
@@ -244,7 +248,7 @@ func (a *AuthorizationsApi) getAuthResponse(c *core.Context, token string, need2
|
||||
return &models.AuthResponse{
|
||||
Token: token,
|
||||
Need2FA: need2FA,
|
||||
User: user.ToUserBasicInfo(),
|
||||
NotificationContent: settings.Container.GetAfterLoginNotificationContent(user.Language, c.GetClientLocale()),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
NotificationContent: a.GetAfterLoginNotificationContent(user.Language, c.GetClientLocale()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/mayswind/ezbookkeeping/pkg/duplicatechecker"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
)
|
||||
|
||||
// ApiUsingConfig represents an api that need to use config
|
||||
type ApiUsingConfig struct {
|
||||
container *settings.ConfigContainer
|
||||
}
|
||||
|
||||
// CurrentConfig returns the current config
|
||||
func (a *ApiUsingConfig) CurrentConfig() *settings.Config {
|
||||
return a.container.Current
|
||||
}
|
||||
|
||||
// GetUserBasicInfo returns the view-object of user basic info according to the user model
|
||||
func (a *ApiUsingConfig) GetUserBasicInfo(user *models.User) *models.UserBasicInfo {
|
||||
return user.ToUserBasicInfo(a.CurrentConfig().AvatarProvider, a.CurrentConfig().RootUrl)
|
||||
}
|
||||
|
||||
// GetAfterRegisterNotificationContent returns the notification content displayed each time users register
|
||||
func (a *ApiUsingConfig) GetAfterRegisterNotificationContent(userLanguage string, clientLanguage string) string {
|
||||
language := userLanguage
|
||||
|
||||
if language == "" {
|
||||
language = clientLanguage
|
||||
}
|
||||
|
||||
if !a.container.Current.AfterRegisterNotification.Enabled {
|
||||
return ""
|
||||
}
|
||||
|
||||
if multiLanguageContent, exists := a.container.Current.AfterRegisterNotification.MultiLanguageContent[language]; exists {
|
||||
return multiLanguageContent
|
||||
}
|
||||
|
||||
return a.container.Current.AfterRegisterNotification.DefaultContent
|
||||
}
|
||||
|
||||
// GetAfterLoginNotificationContent returns the notification content displayed each time users log in
|
||||
func (a *ApiUsingConfig) GetAfterLoginNotificationContent(userLanguage string, clientLanguage string) string {
|
||||
language := userLanguage
|
||||
|
||||
if language == "" {
|
||||
language = clientLanguage
|
||||
}
|
||||
|
||||
if !a.container.Current.AfterLoginNotification.Enabled {
|
||||
return ""
|
||||
}
|
||||
|
||||
if multiLanguageContent, exists := a.container.Current.AfterLoginNotification.MultiLanguageContent[language]; exists {
|
||||
return multiLanguageContent
|
||||
}
|
||||
|
||||
return a.container.Current.AfterLoginNotification.DefaultContent
|
||||
}
|
||||
|
||||
// GetAfterOpenNotificationContent returns the notification content displayed each time users open the app
|
||||
func (a *ApiUsingConfig) GetAfterOpenNotificationContent(userLanguage string, clientLanguage string) string {
|
||||
language := userLanguage
|
||||
|
||||
if language == "" {
|
||||
language = clientLanguage
|
||||
}
|
||||
|
||||
if !a.container.Current.AfterOpenNotification.Enabled {
|
||||
return ""
|
||||
}
|
||||
|
||||
if multiLanguageContent, exists := a.container.Current.AfterOpenNotification.MultiLanguageContent[language]; exists {
|
||||
return multiLanguageContent
|
||||
}
|
||||
|
||||
return a.container.Current.AfterOpenNotification.DefaultContent
|
||||
}
|
||||
|
||||
// ApiUsingDuplicateChecker represents an api that need to use duplicate checker
|
||||
type ApiUsingDuplicateChecker struct {
|
||||
container *duplicatechecker.DuplicateCheckerContainer
|
||||
}
|
||||
|
||||
// GetSubmissionRemark returns whether the same submission has been processed and related remark by the current duplicate checker
|
||||
func (a *ApiUsingDuplicateChecker) GetSubmissionRemark(checkerType duplicatechecker.DuplicateCheckerType, uid int64, identification string) (bool, string) {
|
||||
return a.container.GetSubmissionRemark(checkerType, uid, identification)
|
||||
}
|
||||
|
||||
// SetSubmissionRemark saves the identification and remark to in-memory cache by the current duplicate checker
|
||||
func (a *ApiUsingDuplicateChecker) SetSubmissionRemark(checkerType duplicatechecker.DuplicateCheckerType, uid int64, identification string, remark string) {
|
||||
a.container.SetSubmissionRemark(checkerType, uid, identification, remark)
|
||||
}
|
||||
@@ -19,6 +19,7 @@ const pageCountForDataExport = 1000
|
||||
|
||||
// DataManagementsApi represents data management api
|
||||
type DataManagementsApi struct {
|
||||
ApiUsingConfig
|
||||
ezBookKeepingCsvExporter *converters.EzBookKeepingCSVFileExporter
|
||||
ezBookKeepingTsvExporter *converters.EzBookKeepingTSVFileExporter
|
||||
tokens *services.TokenService
|
||||
@@ -33,6 +34,9 @@ type DataManagementsApi struct {
|
||||
// Initialize a data management api singleton instance
|
||||
var (
|
||||
DataManagements = &DataManagementsApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
ezBookKeepingCsvExporter: &converters.EzBookKeepingCSVFileExporter{},
|
||||
ezBookKeepingTsvExporter: &converters.EzBookKeepingTSVFileExporter{},
|
||||
tokens: services.Tokens,
|
||||
@@ -162,7 +166,7 @@ func (a *DataManagementsApi) ClearDataHandler(c *core.Context) (any, *errs.Error
|
||||
}
|
||||
|
||||
func (a *DataManagementsApi) getExportedFileContent(c *core.Context, fileType string) ([]byte, string, *errs.Error) {
|
||||
if !settings.Container.Current.EnableDataExport {
|
||||
if !a.CurrentConfig().EnableDataExport {
|
||||
return nil, "", errs.ErrDataExportNotAllowed
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,17 @@ import (
|
||||
)
|
||||
|
||||
// ExchangeRatesApi represents exchange rate api
|
||||
type ExchangeRatesApi struct{}
|
||||
type ExchangeRatesApi struct {
|
||||
ApiUsingConfig
|
||||
}
|
||||
|
||||
// Initialize a exchange rate api singleton instance
|
||||
var (
|
||||
ExchangeRates = &ExchangeRatesApi{}
|
||||
ExchangeRates = &ExchangeRatesApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// LatestExchangeRateHandler returns latest exchange rate data
|
||||
@@ -36,9 +42,9 @@ func (a *ExchangeRatesApi) LatestExchangeRateHandler(c *core.Context) (any, *err
|
||||
uid := c.GetCurrentUid()
|
||||
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
utils.SetProxyUrl(transport, settings.Container.Current.ExchangeRatesProxy)
|
||||
utils.SetProxyUrl(transport, a.CurrentConfig().ExchangeRatesProxy)
|
||||
|
||||
if settings.Container.Current.ExchangeRatesSkipTLSVerify {
|
||||
if a.CurrentConfig().ExchangeRatesSkipTLSVerify {
|
||||
transport.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
@@ -46,7 +52,7 @@ func (a *ExchangeRatesApi) LatestExchangeRateHandler(c *core.Context) (any, *err
|
||||
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: time.Duration(settings.Container.Current.ExchangeRatesRequestTimeout) * time.Millisecond,
|
||||
Timeout: time.Duration(a.CurrentConfig().ExchangeRatesRequestTimeout) * time.Millisecond,
|
||||
}
|
||||
|
||||
urls := dataSource.GetRequestUrls()
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
// ForgetPasswordsApi represents user forget password api
|
||||
type ForgetPasswordsApi struct {
|
||||
ApiUsingConfig
|
||||
users *services.UserService
|
||||
tokens *services.TokenService
|
||||
forgetPasswords *services.ForgetPasswordService
|
||||
@@ -21,6 +22,9 @@ type ForgetPasswordsApi struct {
|
||||
// Initialize a user api singleton instance
|
||||
var (
|
||||
ForgetPasswords = &ForgetPasswordsApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
users: services.Users,
|
||||
tokens: services.Tokens,
|
||||
forgetPasswords: services.ForgetPasswords,
|
||||
@@ -52,12 +56,12 @@ func (a *ForgetPasswordsApi) UserForgetPasswordRequestHandler(c *core.Context) (
|
||||
return nil, errs.ErrUserIsDisabled
|
||||
}
|
||||
|
||||
if settings.Container.Current.ForgetPasswordRequireVerifyEmail && !user.EmailVerified {
|
||||
if a.CurrentConfig().ForgetPasswordRequireVerifyEmail && !user.EmailVerified {
|
||||
log.WarnfWithRequestId(c, "[forget_passwords.UserForgetPasswordRequestHandler] user \"uid:%d\" has not verified email", user.Uid)
|
||||
return nil, errs.ErrEmailIsNotVerified
|
||||
}
|
||||
|
||||
if !settings.Container.Current.EnableSMTP {
|
||||
if !a.CurrentConfig().EnableSMTP {
|
||||
return nil, errs.ErrSMTPServerNotEnabled
|
||||
}
|
||||
|
||||
@@ -105,7 +109,7 @@ func (a *ForgetPasswordsApi) UserResetPasswordHandler(c *core.Context) (any, *er
|
||||
return nil, errs.ErrUserIsDisabled
|
||||
}
|
||||
|
||||
if settings.Container.Current.ForgetPasswordRequireVerifyEmail && !user.EmailVerified {
|
||||
if a.CurrentConfig().ForgetPasswordRequireVerifyEmail && !user.EmailVerified {
|
||||
log.WarnfWithRequestId(c, "[forget_passwords.UserResetPasswordHandler] user \"uid:%d\" has not verified email", user.Uid)
|
||||
return nil, errs.ErrEmailIsNotVerified
|
||||
}
|
||||
|
||||
@@ -24,11 +24,16 @@ const tianDiTuMapAnnotationUrlFormat = "https://t0.tianditu.gov.cn/cva_w/wmts?SE
|
||||
|
||||
// MapImageProxy represents map image proxy
|
||||
type MapImageProxy struct {
|
||||
ApiUsingConfig
|
||||
}
|
||||
|
||||
// Initialize a map image proxy singleton instance
|
||||
var (
|
||||
MapImages = &MapImageProxy{}
|
||||
MapImages = &MapImageProxy{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// MapTileImageProxyHandler returns map tile image
|
||||
@@ -47,7 +52,7 @@ func (p *MapImageProxy) MapTileImageProxyHandler(c *core.Context) (*httputil.Rev
|
||||
} else if mapProvider == settings.CartoDBMapProvider {
|
||||
return cartoDBMapTileImageUrlFormat, nil
|
||||
} else if mapProvider == settings.TomTomMapProvider {
|
||||
targetUrl := tomtomMapTileImageUrlFormat + "?key=" + settings.Container.Current.TomTomMapAPIKey
|
||||
targetUrl := tomtomMapTileImageUrlFormat + "?key=" + p.CurrentConfig().TomTomMapAPIKey
|
||||
language := c.Query("language")
|
||||
|
||||
if language != "" {
|
||||
@@ -56,9 +61,9 @@ func (p *MapImageProxy) MapTileImageProxyHandler(c *core.Context) (*httputil.Rev
|
||||
|
||||
return targetUrl, nil
|
||||
} else if mapProvider == settings.TianDiTuProvider {
|
||||
return tianDiTuMapTileImageUrlFormat + "&tk=" + settings.Container.Current.TianDiTuAPIKey, nil
|
||||
return tianDiTuMapTileImageUrlFormat + "&tk=" + p.CurrentConfig().TianDiTuAPIKey, nil
|
||||
} else if mapProvider == settings.CustomProvider {
|
||||
return settings.Container.Current.CustomMapTileServerTileLayerUrl, nil
|
||||
return p.CurrentConfig().CustomMapTileServerTileLayerUrl, nil
|
||||
}
|
||||
|
||||
return "", errs.ErrParameterInvalid
|
||||
@@ -69,9 +74,9 @@ func (p *MapImageProxy) MapTileImageProxyHandler(c *core.Context) (*httputil.Rev
|
||||
func (p *MapImageProxy) MapAnnotationImageProxyHandler(c *core.Context) (*httputil.ReverseProxy, *errs.Error) {
|
||||
return p.mapImageProxyHandler(c, func(c *core.Context, mapProvider string) (string, *errs.Error) {
|
||||
if mapProvider == settings.TianDiTuProvider {
|
||||
return tianDiTuMapAnnotationUrlFormat + "&tk=" + settings.Container.Current.TianDiTuAPIKey, nil
|
||||
return tianDiTuMapAnnotationUrlFormat + "&tk=" + p.CurrentConfig().TianDiTuAPIKey, nil
|
||||
} else if mapProvider == settings.CustomProvider {
|
||||
return settings.Container.Current.CustomMapTileServerAnnotationLayerUrl, nil
|
||||
return p.CurrentConfig().CustomMapTileServerAnnotationLayerUrl, nil
|
||||
}
|
||||
|
||||
return "", errs.ErrParameterInvalid
|
||||
@@ -82,7 +87,7 @@ func (p *MapImageProxy) mapImageProxyHandler(c *core.Context, fn func(c *core.Co
|
||||
mapProvider := strings.Replace(c.Query("provider"), "-", "_", -1)
|
||||
targetUrl := ""
|
||||
|
||||
if mapProvider != settings.Container.Current.MapProvider {
|
||||
if mapProvider != p.CurrentConfig().MapProvider {
|
||||
return nil, errs.ErrMapProviderNotCurrent
|
||||
}
|
||||
|
||||
@@ -105,7 +110,7 @@ func (p *MapImageProxy) mapImageProxyHandler(c *core.Context, fn func(c *core.Co
|
||||
}
|
||||
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
utils.SetProxyUrl(transport, settings.Container.Current.MapProxy)
|
||||
utils.SetProxyUrl(transport, p.CurrentConfig().MapProxy)
|
||||
|
||||
director := func(req *http.Request) {
|
||||
imageRawUrl := targetUrl
|
||||
|
||||
+7
-2
@@ -19,16 +19,21 @@ const (
|
||||
|
||||
// QrCodesApi represents qrcode generator api
|
||||
type QrCodesApi struct {
|
||||
ApiUsingConfig
|
||||
}
|
||||
|
||||
// Initialize a qrcode generator api singleton instance
|
||||
var (
|
||||
QrCodes = &QrCodesApi{}
|
||||
QrCodes = &QrCodesApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// MobileUrlQrCodeHandler returns a mobile url qr code image
|
||||
func (a *QrCodesApi) MobileUrlQrCodeHandler(c *core.Context) ([]byte, string, *errs.Error) {
|
||||
fullUrl := settings.Container.Current.RootUrl + "mobile"
|
||||
fullUrl := a.CurrentConfig().RootUrl + "mobile"
|
||||
data, err := a.generateUrlQrCode(c, fullUrl)
|
||||
|
||||
if err != nil {
|
||||
|
||||
+9
-5
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
// TokensApi represents token api
|
||||
type TokensApi struct {
|
||||
ApiUsingConfig
|
||||
tokens *services.TokenService
|
||||
users *services.UserService
|
||||
}
|
||||
@@ -22,6 +23,9 @@ type TokensApi struct {
|
||||
// Initialize a token api singleton instance
|
||||
var (
|
||||
Tokens = &TokensApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
tokens: services.Tokens,
|
||||
users: services.Users,
|
||||
}
|
||||
@@ -180,7 +184,7 @@ func (a *TokensApi) TokenRefreshHandler(c *core.Context) (any, *errs.Error) {
|
||||
now := time.Now().Unix()
|
||||
oldTokenClaims := c.GetTokenClaims()
|
||||
|
||||
if now-oldTokenClaims.IssuedAt < int64(settings.Container.Current.TokenMinRefreshInterval) {
|
||||
if now-oldTokenClaims.IssuedAt < int64(a.CurrentConfig().TokenMinRefreshInterval) {
|
||||
log.InfofWithRequestId(c, "[token.TokenRefreshHandler] token of user \"uid:%d\" does not need to be refreshed", uid)
|
||||
|
||||
userTokenId, err := utils.StringToInt64(oldTokenClaims.UserTokenId)
|
||||
@@ -204,8 +208,8 @@ func (a *TokensApi) TokenRefreshHandler(c *core.Context) (any, *errs.Error) {
|
||||
}
|
||||
|
||||
refreshResp := &models.TokenRefreshResponse{
|
||||
User: user.ToUserBasicInfo(),
|
||||
NotificationContent: settings.Container.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
NotificationContent: a.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
}
|
||||
|
||||
return refreshResp, nil
|
||||
@@ -233,8 +237,8 @@ func (a *TokensApi) TokenRefreshHandler(c *core.Context) (any, *errs.Error) {
|
||||
refreshResp := &models.TokenRefreshResponse{
|
||||
NewToken: token,
|
||||
OldTokenId: a.tokens.GenerateTokenId(oldTokenRecord),
|
||||
User: user.ToUserBasicInfo(),
|
||||
NotificationContent: settings.Container.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
NotificationContent: a.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
}
|
||||
|
||||
return refreshResp, nil
|
||||
|
||||
@@ -17,12 +17,20 @@ import (
|
||||
|
||||
// TransactionCategoriesApi represents transaction category api
|
||||
type TransactionCategoriesApi struct {
|
||||
ApiUsingConfig
|
||||
ApiUsingDuplicateChecker
|
||||
categories *services.TransactionCategoryService
|
||||
}
|
||||
|
||||
// Initialize a transaction category api singleton instance
|
||||
var (
|
||||
TransactionCategories = &TransactionCategoriesApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
ApiUsingDuplicateChecker: ApiUsingDuplicateChecker{
|
||||
container: duplicatechecker.Container,
|
||||
},
|
||||
categories: services.TransactionCategories,
|
||||
}
|
||||
)
|
||||
@@ -122,8 +130,8 @@ func (a *TransactionCategoriesApi) CategoryCreateHandler(c *core.Context) (any,
|
||||
|
||||
category := a.createNewCategoryModel(uid, &categoryCreateReq, maxOrderId+1)
|
||||
|
||||
if settings.Container.Current.EnableDuplicateSubmissionsCheck && categoryCreateReq.ClientSessionId != "" {
|
||||
found, remark := duplicatechecker.Container.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_CATEGORY, uid, categoryCreateReq.ClientSessionId)
|
||||
if a.CurrentConfig().EnableDuplicateSubmissionsCheck && categoryCreateReq.ClientSessionId != "" {
|
||||
found, remark := a.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_CATEGORY, uid, categoryCreateReq.ClientSessionId)
|
||||
|
||||
if found {
|
||||
log.InfofWithRequestId(c, "[transaction_categories.CategoryCreateHandler] another category \"id:%s\" has been created for user \"uid:%d\"", remark, uid)
|
||||
@@ -153,7 +161,7 @@ func (a *TransactionCategoriesApi) CategoryCreateHandler(c *core.Context) (any,
|
||||
|
||||
log.InfofWithRequestId(c, "[transaction_categories.CategoryCreateHandler] user \"uid:%d\" has created a new category \"id:%d\" successfully", uid, category.CategoryId)
|
||||
|
||||
duplicatechecker.Container.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_CATEGORY, uid, categoryCreateReq.ClientSessionId, utils.Int64ToString(category.CategoryId))
|
||||
a.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_CATEGORY, uid, categoryCreateReq.ClientSessionId, utils.Int64ToString(category.CategoryId))
|
||||
categoryResp := category.ToTransactionCategoryInfoResponse()
|
||||
|
||||
return categoryResp, nil
|
||||
|
||||
@@ -16,12 +16,20 @@ import (
|
||||
|
||||
// TransactionTemplatesApi represents transaction template api
|
||||
type TransactionTemplatesApi struct {
|
||||
ApiUsingConfig
|
||||
ApiUsingDuplicateChecker
|
||||
templates *services.TransactionTemplateService
|
||||
}
|
||||
|
||||
// Initialize a transaction template api singleton instance
|
||||
var (
|
||||
TransactionTemplates = &TransactionTemplatesApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
ApiUsingDuplicateChecker: ApiUsingDuplicateChecker{
|
||||
container: duplicatechecker.Container,
|
||||
},
|
||||
templates: services.TransactionTemplates,
|
||||
}
|
||||
)
|
||||
@@ -117,8 +125,8 @@ func (a *TransactionTemplatesApi) TemplateCreateHandler(c *core.Context) (any, *
|
||||
serverUtcOffset := utils.GetServerTimezoneOffsetMinutes()
|
||||
template := a.createNewTemplateModel(uid, &templateCreateReq, maxOrderId+1)
|
||||
|
||||
if settings.Container.Current.EnableDuplicateSubmissionsCheck && templateCreateReq.ClientSessionId != "" {
|
||||
found, remark := duplicatechecker.Container.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TEMPLATE, uid, templateCreateReq.ClientSessionId)
|
||||
if a.CurrentConfig().EnableDuplicateSubmissionsCheck && templateCreateReq.ClientSessionId != "" {
|
||||
found, remark := a.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TEMPLATE, uid, templateCreateReq.ClientSessionId)
|
||||
|
||||
if found {
|
||||
log.InfofWithRequestId(c, "[transaction_templates.TemplateCreateHandler] another template \"id:%s\" has been created for user \"uid:%d\"", remark, uid)
|
||||
@@ -148,7 +156,7 @@ func (a *TransactionTemplatesApi) TemplateCreateHandler(c *core.Context) (any, *
|
||||
|
||||
log.InfofWithRequestId(c, "[transaction_templates.TemplateCreateHandler] user \"uid:%d\" has created a new template \"id:%d\" successfully", uid, template.TemplateId)
|
||||
|
||||
duplicatechecker.Container.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TEMPLATE, uid, templateCreateReq.ClientSessionId, utils.Int64ToString(template.TemplateId))
|
||||
a.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TEMPLATE, uid, templateCreateReq.ClientSessionId, utils.Int64ToString(template.TemplateId))
|
||||
templateResp := template.ToTransactionTemplateInfoResponse(serverUtcOffset)
|
||||
|
||||
return templateResp, nil
|
||||
|
||||
+11
-3
@@ -18,6 +18,8 @@ import (
|
||||
|
||||
// TransactionsApi represents transaction api
|
||||
type TransactionsApi struct {
|
||||
ApiUsingConfig
|
||||
ApiUsingDuplicateChecker
|
||||
transactions *services.TransactionService
|
||||
transactionCategories *services.TransactionCategoryService
|
||||
transactionTags *services.TransactionTagService
|
||||
@@ -28,6 +30,12 @@ type TransactionsApi struct {
|
||||
// Initialize a transaction api singleton instance
|
||||
var (
|
||||
Transactions = &TransactionsApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
ApiUsingDuplicateChecker: ApiUsingDuplicateChecker{
|
||||
container: duplicatechecker.Container,
|
||||
},
|
||||
transactions: services.Transactions,
|
||||
transactionCategories: services.TransactionCategories,
|
||||
transactionTags: services.TransactionTags,
|
||||
@@ -663,8 +671,8 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.Context) (any, *errs.
|
||||
return nil, errs.ErrCannotCreateTransactionWithThisTransactionTime
|
||||
}
|
||||
|
||||
if settings.Container.Current.EnableDuplicateSubmissionsCheck && transactionCreateReq.ClientSessionId != "" {
|
||||
found, remark := duplicatechecker.Container.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, transactionCreateReq.ClientSessionId)
|
||||
if a.CurrentConfig().EnableDuplicateSubmissionsCheck && transactionCreateReq.ClientSessionId != "" {
|
||||
found, remark := a.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, transactionCreateReq.ClientSessionId)
|
||||
|
||||
if found {
|
||||
log.InfofWithRequestId(c, "[transactions.TransactionCreateHandler] another transaction \"id:%s\" has been created for user \"uid:%d\"", remark, uid)
|
||||
@@ -694,7 +702,7 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.Context) (any, *errs.
|
||||
|
||||
log.InfofWithRequestId(c, "[transactions.TransactionCreateHandler] user \"uid:%d\" has created a new transaction \"id:%d\" successfully", uid, transaction.TransactionId)
|
||||
|
||||
duplicatechecker.Container.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, transactionCreateReq.ClientSessionId, utils.Int64ToString(transaction.TransactionId))
|
||||
a.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, transactionCreateReq.ClientSessionId, utils.Int64ToString(transaction.TransactionId))
|
||||
transactionResp := transaction.ToTransactionInfoResponse(tagIds, transactionEditable)
|
||||
|
||||
return transactionResp, nil
|
||||
|
||||
+32
-93
@@ -1,8 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -15,13 +13,13 @@ import (
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/services"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/storage"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/validators"
|
||||
)
|
||||
|
||||
// UsersApi represents user api
|
||||
type UsersApi struct {
|
||||
ApiUsingConfig
|
||||
users *services.UserService
|
||||
tokens *services.TokenService
|
||||
accounts *services.AccountService
|
||||
@@ -30,6 +28,9 @@ type UsersApi struct {
|
||||
// Initialize a user api singleton instance
|
||||
var (
|
||||
Users = &UsersApi{
|
||||
ApiUsingConfig: ApiUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
users: services.Users,
|
||||
tokens: services.Tokens,
|
||||
accounts: services.Accounts,
|
||||
@@ -38,7 +39,7 @@ var (
|
||||
|
||||
// UserRegisterHandler saves a new user by request parameters
|
||||
func (a *UsersApi) UserRegisterHandler(c *core.Context) (any, *errs.Error) {
|
||||
if !settings.Container.Current.EnableUserRegister {
|
||||
if !a.CurrentConfig().EnableUserRegister {
|
||||
return nil, errs.ErrUserRegistrationNotAllowed
|
||||
}
|
||||
|
||||
@@ -92,14 +93,14 @@ func (a *UsersApi) UserRegisterHandler(c *core.Context) (any, *errs.Error) {
|
||||
authResp := &models.RegisterResponse{
|
||||
AuthResponse: models.AuthResponse{
|
||||
Need2FA: false,
|
||||
User: user.ToUserBasicInfo(),
|
||||
NotificationContent: settings.Container.GetAfterRegisterNotificationContent(user.Language, c.GetClientLocale()),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
NotificationContent: a.GetAfterRegisterNotificationContent(user.Language, c.GetClientLocale()),
|
||||
},
|
||||
NeedVerifyEmail: settings.Container.Current.EnableUserVerifyEmail && settings.Container.Current.EnableUserForceVerifyEmail,
|
||||
NeedVerifyEmail: a.CurrentConfig().EnableUserVerifyEmail && a.CurrentConfig().EnableUserForceVerifyEmail,
|
||||
PresetCategoriesSaved: presetCategoriesSaved,
|
||||
}
|
||||
|
||||
if settings.Container.Current.EnableUserVerifyEmail && settings.Container.Current.EnableSMTP {
|
||||
if a.CurrentConfig().EnableUserVerifyEmail && a.CurrentConfig().EnableSMTP {
|
||||
token, _, err := a.tokens.CreateEmailVerifyToken(c, user)
|
||||
|
||||
if err != nil {
|
||||
@@ -115,7 +116,7 @@ func (a *UsersApi) UserRegisterHandler(c *core.Context) (any, *errs.Error) {
|
||||
}
|
||||
}
|
||||
|
||||
if settings.Container.Current.EnableUserForceVerifyEmail {
|
||||
if a.CurrentConfig().EnableUserForceVerifyEmail {
|
||||
return authResp, nil
|
||||
}
|
||||
|
||||
@@ -187,8 +188,8 @@ func (a *UsersApi) UserEmailVerifyHandler(c *core.Context) (any, *errs.Error) {
|
||||
}
|
||||
|
||||
resp.NewToken = token
|
||||
resp.User = user.ToUserBasicInfo()
|
||||
resp.NotificationContent = settings.Container.GetAfterLoginNotificationContent(user.Language, c.GetClientLocale())
|
||||
resp.User = a.GetUserBasicInfo(user)
|
||||
resp.NotificationContent = a.GetAfterLoginNotificationContent(user.Language, c.GetClientLocale())
|
||||
|
||||
c.SetTextualToken(token)
|
||||
c.SetTokenClaims(claims)
|
||||
@@ -212,7 +213,7 @@ func (a *UsersApi) UserProfileHandler(c *core.Context) (any, *errs.Error) {
|
||||
return nil, errs.ErrUserNotFound
|
||||
}
|
||||
|
||||
userResp := user.ToUserProfileResponse()
|
||||
userResp := a.getUserProfileResponse(user)
|
||||
return userResp, nil
|
||||
}
|
||||
|
||||
@@ -447,10 +448,10 @@ func (a *UsersApi) UserUpdateProfileHandler(c *core.Context) (any, *errs.Error)
|
||||
log.InfofWithRequestId(c, "[users.UserUpdateProfileHandler] user \"uid:%d\" has updated successfully", user.Uid)
|
||||
|
||||
resp := &models.UserProfileUpdateResponse{
|
||||
User: user.ToUserBasicInfo(),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
}
|
||||
|
||||
if emailSetToUnverified && settings.Container.Current.EnableUserVerifyEmail && settings.Container.Current.EnableSMTP {
|
||||
if emailSetToUnverified && a.CurrentConfig().EnableUserVerifyEmail && a.CurrentConfig().EnableSMTP {
|
||||
err = a.tokens.DeleteTokensByType(c, uid, core.USER_TOKEN_TYPE_EMAIL_VERIFY)
|
||||
|
||||
if err != nil {
|
||||
@@ -547,32 +548,15 @@ func (a *UsersApi) UserUpdateAvatarHandler(c *core.Context) (any, *errs.Error) {
|
||||
return nil, errs.ErrOperationFailed
|
||||
}
|
||||
|
||||
defer avatarFile.Close()
|
||||
|
||||
err = storage.Container.SaveAvatar(user.Uid, avatarFile, fileExtension)
|
||||
err = a.users.UpdateUserAvatar(c, user.Uid, avatarFile, fileExtension, user.CustomAvatarType)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[users.UserUpdateAvatarHandler] failed to save avatar file for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
return nil, errs.ErrOperationFailed
|
||||
}
|
||||
|
||||
err = a.users.UpdateUserAvatar(c, user.Uid, fileExtension)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[users.UserUpdateAvatarHandler] failed to update user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
log.ErrorfWithRequestId(c, "[users.UserUpdateAvatarHandler] failed to update avatar for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
if fileExtension != user.CustomAvatarType && user.CustomAvatarType != "" {
|
||||
err = storage.Container.DeleteAvatar(user.Uid, user.CustomAvatarType)
|
||||
|
||||
if err != nil {
|
||||
log.WarnfWithRequestId(c, "[users.UserUpdateAvatarHandler] failed to delete old avatar with extension \"%s\" for user \"uid:%d\", because %s", user.CustomAvatarType, user.Uid, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
user.CustomAvatarType = fileExtension
|
||||
userResp := user.ToUserProfileResponse()
|
||||
userResp := a.getUserProfileResponse(user)
|
||||
return userResp, nil
|
||||
}
|
||||
|
||||
@@ -593,39 +577,21 @@ func (a *UsersApi) UserRemoveAvatarHandler(c *core.Context) (any, *errs.Error) {
|
||||
return nil, errs.ErrNothingWillBeUpdated
|
||||
}
|
||||
|
||||
err = storage.Container.DeleteAvatar(user.Uid, user.CustomAvatarType)
|
||||
err = a.users.RemoveUserAvatar(c, user.Uid, user.CustomAvatarType)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[users.UserRemoveAvatarHandler] failed to delete avatar file for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
|
||||
exists, err := storage.Container.ExistsAvatar(user.Uid, user.CustomAvatarType)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[users.UserRemoveAvatarHandler] failed to check whether avatar file exist for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
return nil, errs.ErrOperationFailed
|
||||
}
|
||||
|
||||
if exists {
|
||||
log.ErrorfWithRequestId(c, "[users.UserRemoveAvatarHandler] failed to delete whether avatar file exist for user \"uid:%d\", the avatar file still exist", user.Uid)
|
||||
return nil, errs.ErrOperationFailed
|
||||
}
|
||||
}
|
||||
|
||||
err = a.users.UpdateUserAvatar(c, user.Uid, "")
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[users.UserRemoveAvatarHandler] failed to update user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
log.ErrorfWithRequestId(c, "[users.UserRemoveAvatarHandler] failed to remove avatar for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
user.CustomAvatarType = ""
|
||||
userResp := user.ToUserProfileResponse()
|
||||
userResp := a.getUserProfileResponse(user)
|
||||
return userResp, nil
|
||||
}
|
||||
|
||||
// UserSendVerifyEmailByUnloginUserHandler sends unlogin user verify email
|
||||
func (a *UsersApi) UserSendVerifyEmailByUnloginUserHandler(c *core.Context) (any, *errs.Error) {
|
||||
if !settings.Container.Current.EnableUserVerifyEmail {
|
||||
if !a.CurrentConfig().EnableUserVerifyEmail {
|
||||
return nil, errs.ErrEmailValidationNotAllowed
|
||||
}
|
||||
|
||||
@@ -657,7 +623,7 @@ func (a *UsersApi) UserSendVerifyEmailByUnloginUserHandler(c *core.Context) (any
|
||||
return nil, errs.ErrEmailIsVerified
|
||||
}
|
||||
|
||||
if !settings.Container.Current.EnableSMTP {
|
||||
if !a.CurrentConfig().EnableSMTP {
|
||||
return nil, errs.ErrSMTPServerNotEnabled
|
||||
}
|
||||
|
||||
@@ -681,7 +647,7 @@ func (a *UsersApi) UserSendVerifyEmailByUnloginUserHandler(c *core.Context) (any
|
||||
|
||||
// UserSendVerifyEmailByLoginedUserHandler sends logined user verify email
|
||||
func (a *UsersApi) UserSendVerifyEmailByLoginedUserHandler(c *core.Context) (any, *errs.Error) {
|
||||
if !settings.Container.Current.EnableUserVerifyEmail {
|
||||
if !a.CurrentConfig().EnableUserVerifyEmail {
|
||||
return nil, errs.ErrEmailValidationNotAllowed
|
||||
}
|
||||
|
||||
@@ -701,7 +667,7 @@ func (a *UsersApi) UserSendVerifyEmailByLoginedUserHandler(c *core.Context) (any
|
||||
return nil, errs.ErrEmailIsVerified
|
||||
}
|
||||
|
||||
if !settings.Container.Current.EnableSMTP {
|
||||
if !a.CurrentConfig().EnableSMTP {
|
||||
return nil, errs.ErrSMTPServerNotEnabled
|
||||
}
|
||||
|
||||
@@ -741,46 +707,19 @@ func (a *UsersApi) UserGetAvatarHandler(c *core.Context) ([]byte, string, *errs.
|
||||
return nil, "", errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
user, err := a.users.GetUserById(c, uid)
|
||||
avatarData, err := a.users.GetUserAvatar(c, uid, fileExtension)
|
||||
|
||||
if err != nil {
|
||||
if !errs.IsCustomError(err) {
|
||||
log.ErrorfWithRequestId(c, "[users.UserGetAvatarHandler] failed to get user, because %s", err.Error())
|
||||
log.ErrorfWithRequestId(c, "[users.UserGetAvatarHandler] failed to get user avatar, because %s", err.Error())
|
||||
}
|
||||
|
||||
return nil, "", errs.ErrUserNotFound
|
||||
}
|
||||
|
||||
if user.CustomAvatarType == "" {
|
||||
log.WarnfWithRequestId(c, "[users.UserGetAvatarHandler] user does not have avatar for user \"uid:%d\"", user.Uid)
|
||||
return nil, "", errs.ErrUserAvatarNoExists
|
||||
}
|
||||
|
||||
if user.CustomAvatarType != fileExtension {
|
||||
log.WarnfWithRequestId(c, "[users.UserGetAvatarHandler] user avatar extension is invalid \"%s\" for user \"uid:%d\"", fileExtension, user.Uid)
|
||||
return nil, "", errs.ErrUserAvatarNoExists
|
||||
}
|
||||
|
||||
avatarFile, err := storage.Container.ReadAvatar(user.Uid, fileExtension)
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
log.WarnfWithRequestId(c, "[users.UserGetAvatarHandler] user avatar file not exist for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
return nil, "", errs.ErrUserAvatarNoExists
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[users.UserGetAvatarHandler] failed to get user avatar object for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
return nil, "", errs.ErrOperationFailed
|
||||
}
|
||||
|
||||
defer avatarFile.Close()
|
||||
|
||||
avatarData, err := io.ReadAll(avatarFile)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[users.UserGetAvatarHandler] failed to read user avatar object data for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
return nil, "", errs.ErrOperationFailed
|
||||
return nil, "", errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
return avatarData, contentType, nil
|
||||
}
|
||||
|
||||
func (a *UsersApi) getUserProfileResponse(user *models.User) *models.UserProfileResponse {
|
||||
return user.ToUserProfileResponse(a.CurrentConfig().AvatarProvider, a.CurrentConfig().RootUrl)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package cli
|
||||
|
||||
import "github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
|
||||
// CliUsingConfig represents an cli that need to use config
|
||||
type CliUsingConfig struct {
|
||||
container *settings.ConfigContainer
|
||||
}
|
||||
|
||||
// CurrentConfig returns the current config
|
||||
func (l *CliUsingConfig) CurrentConfig() *settings.Config {
|
||||
return l.container.Current
|
||||
}
|
||||
@@ -19,6 +19,7 @@ const pageCountForDataExport = 1000
|
||||
|
||||
// UserDataCli represents user data cli
|
||||
type UserDataCli struct {
|
||||
CliUsingConfig
|
||||
ezBookKeepingCsvExporter *converters.EzBookKeepingCSVFileExporter
|
||||
ezBookKeepingTsvExporter *converters.EzBookKeepingTSVFileExporter
|
||||
accounts *services.AccountService
|
||||
@@ -34,6 +35,9 @@ type UserDataCli struct {
|
||||
// Initialize an user data cli singleton instance
|
||||
var (
|
||||
UserData = &UserDataCli{
|
||||
CliUsingConfig: CliUsingConfig{
|
||||
container: settings.Container,
|
||||
},
|
||||
ezBookKeepingCsvExporter: &converters.EzBookKeepingCSVFileExporter{},
|
||||
ezBookKeepingTsvExporter: &converters.EzBookKeepingTSVFileExporter{},
|
||||
accounts: services.Accounts,
|
||||
@@ -180,7 +184,7 @@ func (l *UserDataCli) SendPasswordResetMail(c *cli.Context, username string) err
|
||||
return err
|
||||
}
|
||||
|
||||
if settings.Container.Current.ForgetPasswordRequireVerifyEmail && !user.EmailVerified {
|
||||
if l.CurrentConfig().ForgetPasswordRequireVerifyEmail && !user.EmailVerified {
|
||||
log.BootWarnf("[user_data.SendPasswordResetMail] user \"uid:%d\" has not verified email", user.Uid)
|
||||
return errs.ErrEmailIsNotVerified
|
||||
}
|
||||
@@ -238,7 +242,7 @@ func (l *UserDataCli) DisableUser(c *cli.Context, username string) error {
|
||||
|
||||
// ResendVerifyEmail resends an email with account activation link
|
||||
func (l *UserDataCli) ResendVerifyEmail(c *cli.Context, username string) error {
|
||||
if !settings.Container.Current.EnableUserVerifyEmail {
|
||||
if !l.CurrentConfig().EnableUserVerifyEmail {
|
||||
return errs.ErrEmailValidationNotAllowed
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package core
|
||||
|
||||
// UserAvatarProviderType represents type of the user avatar provider
|
||||
type UserAvatarProviderType string
|
||||
|
||||
// User avatar provider types
|
||||
const (
|
||||
USER_AVATAR_PROVIDER_INTERNAL UserAvatarProviderType = "internal"
|
||||
USER_AVATAR_PROVIDER_GRAVATAR UserAvatarProviderType = "gravatar"
|
||||
)
|
||||
@@ -34,4 +34,6 @@ var (
|
||||
ErrNoUserAvatar = NewNormalError(NormalSubcategoryUser, 25, http.StatusBadRequest, "no user avatar")
|
||||
ErrUserAvatarIsEmpty = NewNormalError(NormalSubcategoryUser, 26, http.StatusBadRequest, "user avatar is empty")
|
||||
ErrUserAvatarNoExists = NewNormalError(NormalSubcategoryUser, 27, http.StatusNotFound, "user avatar not exists")
|
||||
ErrUserAvatarNotSet = NewNormalError(NormalSubcategoryUser, 28, http.StatusNotFound, "user avatar not set")
|
||||
ErrUserAvatarExtensionInvalid = NewNormalError(NormalSubcategoryUser, 29, http.StatusNotFound, "user avatar file extension invalid")
|
||||
)
|
||||
|
||||
+9
-16
@@ -5,7 +5,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
)
|
||||
|
||||
@@ -253,13 +252,13 @@ func (u *User) CanEditTransactionByTransactionTime(transactionTime int64, utcOff
|
||||
}
|
||||
|
||||
// ToUserBasicInfo returns a user basic view-object according to database model
|
||||
func (u *User) ToUserBasicInfo() *UserBasicInfo {
|
||||
func (u *User) ToUserBasicInfo(avatarProvider core.UserAvatarProviderType, rootUrl string) *UserBasicInfo {
|
||||
return &UserBasicInfo{
|
||||
Username: u.Username,
|
||||
Email: u.Email,
|
||||
Nickname: u.Nickname,
|
||||
AvatarUrl: u.getAvatarUrl(),
|
||||
AvatarProvider: u.getAvatarProvider(),
|
||||
AvatarUrl: u.getAvatarUrl(avatarProvider, rootUrl),
|
||||
AvatarProvider: string(avatarProvider),
|
||||
DefaultAccountId: u.DefaultAccountId,
|
||||
TransactionEditScope: u.TransactionEditScope,
|
||||
Language: u.Language,
|
||||
@@ -280,23 +279,17 @@ func (u *User) ToUserBasicInfo() *UserBasicInfo {
|
||||
}
|
||||
|
||||
// ToUserProfileResponse returns a user profile view-object according to database model
|
||||
func (u *User) ToUserProfileResponse() *UserProfileResponse {
|
||||
func (u *User) ToUserProfileResponse(avatarProvider core.UserAvatarProviderType, rootUrl string) *UserProfileResponse {
|
||||
return &UserProfileResponse{
|
||||
UserBasicInfo: u.ToUserBasicInfo(),
|
||||
UserBasicInfo: u.ToUserBasicInfo(avatarProvider, rootUrl),
|
||||
LastLoginAt: u.LastLoginUnixTime,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *User) getAvatarProvider() string {
|
||||
return settings.Container.Current.AvatarProvider
|
||||
}
|
||||
|
||||
func (u *User) getAvatarUrl() string {
|
||||
avatarProvider := settings.Container.Current.AvatarProvider
|
||||
|
||||
if avatarProvider == settings.InternalAvatarProvider {
|
||||
return utils.GetInternalAvatarUrl(u.Uid, u.CustomAvatarType, settings.Container.Current.RootUrl)
|
||||
} else if avatarProvider == settings.GravatarProvider {
|
||||
func (u *User) getAvatarUrl(avatarProvider core.UserAvatarProviderType, rootUrl string) string {
|
||||
if avatarProvider == core.USER_AVATAR_PROVIDER_INTERNAL {
|
||||
return utils.GetInternalAvatarUrl(u.Uid, u.CustomAvatarType, rootUrl)
|
||||
} else if avatarProvider == core.USER_AVATAR_PROVIDER_GRAVATAR {
|
||||
return utils.GetGravatarUrl(u.Email)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/datastore"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/mail"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/storage"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/uuid"
|
||||
)
|
||||
|
||||
@@ -76,3 +79,32 @@ func (s *ServiceUsingUuid) GenerateUuid(uuidType uuid.UuidType) int64 {
|
||||
func (s *ServiceUsingUuid) GenerateUuids(uuidType uuid.UuidType, count uint8) []int64 {
|
||||
return s.container.GenerateUuids(uuidType, count)
|
||||
}
|
||||
|
||||
// ServiceUsingStorage represents a service that need to use storage
|
||||
type ServiceUsingStorage struct {
|
||||
container *storage.StorageContainer
|
||||
}
|
||||
|
||||
// ExistsAvatar returns whether the user avatar exists from the current avatar object storage
|
||||
func (s *ServiceUsingStorage) ExistsAvatar(uid int64, fileExtension string) (bool, error) {
|
||||
return s.container.ExistsAvatar(s.getUserAvatarPath(uid, fileExtension))
|
||||
}
|
||||
|
||||
// ReadAvatar returns the user avatar from the current avatar object storage
|
||||
func (s *ServiceUsingStorage) ReadAvatar(uid int64, fileExtension string) (storage.ObjectInStorage, error) {
|
||||
return s.container.ReadAvatar(s.getUserAvatarPath(uid, fileExtension))
|
||||
}
|
||||
|
||||
// SaveAvatar returns whether save the user avatar into the current avatar object storage successfully
|
||||
func (s *ServiceUsingStorage) SaveAvatar(uid int64, object storage.ObjectInStorage, fileExtension string) error {
|
||||
return s.container.SaveAvatar(s.getUserAvatarPath(uid, fileExtension), object)
|
||||
}
|
||||
|
||||
// DeleteAvatar returns whether delete the user avatar from the current avatar object storage successfully
|
||||
func (s *ServiceUsingStorage) DeleteAvatar(uid int64, fileExtension string) error {
|
||||
return s.container.DeleteAvatar(s.getUserAvatarPath(uid, fileExtension))
|
||||
}
|
||||
|
||||
func (s *ServiceUsingStorage) getUserAvatarPath(uid int64, fileExtension string) string {
|
||||
return fmt.Sprintf("%d.%s", uid, fileExtension)
|
||||
}
|
||||
|
||||
+103
-3
@@ -3,7 +3,10 @@ package services
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm"
|
||||
@@ -12,9 +15,11 @@ import (
|
||||
"github.com/mayswind/ezbookkeeping/pkg/datastore"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/locales"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/log"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/mail"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/storage"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/templates"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/uuid"
|
||||
@@ -28,6 +33,7 @@ type UserService struct {
|
||||
ServiceUsingConfig
|
||||
ServiceUsingMailer
|
||||
ServiceUsingUuid
|
||||
ServiceUsingStorage
|
||||
}
|
||||
|
||||
// Initialize a user service singleton instance
|
||||
@@ -45,6 +51,9 @@ var (
|
||||
ServiceUsingUuid: ServiceUsingUuid{
|
||||
container: uuid.Container,
|
||||
},
|
||||
ServiceUsingStorage: ServiceUsingStorage{
|
||||
container: storage.Container,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -126,6 +135,50 @@ func (s *UserService) GetUserByEmail(c *core.Context, email string) (*models.Use
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// GetUserAvatar returns the user avatar image data and image file extension according to user uid
|
||||
func (s *UserService) GetUserAvatar(c *core.Context, uid int64, fileExtension string) ([]byte, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
user := &models.User{}
|
||||
has, err := s.UserDB().NewSession(c).ID(uid).Cols("uid", "deleted", "custom_avatar_type").Where("deleted=?", false).Get(user)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, errs.ErrUserNotFound
|
||||
}
|
||||
|
||||
if user.CustomAvatarType == "" {
|
||||
return nil, errs.ErrUserAvatarNotSet
|
||||
}
|
||||
|
||||
if user.CustomAvatarType != fileExtension {
|
||||
return nil, errs.ErrUserAvatarExtensionInvalid
|
||||
}
|
||||
|
||||
avatarFile, err := s.ReadAvatar(user.Uid, user.CustomAvatarType)
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
return nil, errs.ErrUserAvatarNoExists
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer avatarFile.Close()
|
||||
|
||||
avatarData, err := io.ReadAll(avatarFile)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return avatarData, nil
|
||||
}
|
||||
|
||||
// CreateUser saves a new user model to database
|
||||
func (s *UserService) CreateUser(c *core.Context, user *models.User) error {
|
||||
exists, err := s.ExistsUsername(c, user.Username)
|
||||
@@ -294,16 +347,63 @@ func (s *UserService) UpdateUser(c *core.Context, user *models.User, modifyUserL
|
||||
return keyProfileUpdated, emailSetToUnverified, nil
|
||||
}
|
||||
|
||||
// UpdateUserAvatar updated the custom avatar type of specified user
|
||||
func (s *UserService) UpdateUserAvatar(c *core.Context, uid int64, customAvatarType string) error {
|
||||
// UpdateUserAvatar updates the custom avatar type of specified user
|
||||
func (s *UserService) UpdateUserAvatar(c *core.Context, uid int64, avatarFile multipart.File, fileExtension string, oldFileExtension string) error {
|
||||
if uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
defer avatarFile.Close()
|
||||
|
||||
err := s.SaveAvatar(uid, avatarFile, fileExtension)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
now := time.Now().Unix()
|
||||
|
||||
updateModel := &models.User{
|
||||
CustomAvatarType: customAvatarType,
|
||||
CustomAvatarType: fileExtension,
|
||||
UpdatedUnixTime: now,
|
||||
}
|
||||
|
||||
err = s.UserDB().DoTransaction(c, func(sess *xorm.Session) error {
|
||||
_, err := sess.ID(uid).Cols("custom_avatar_type", "updated_unix_time").Where("deleted=?", false).Update(updateModel)
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fileExtension != oldFileExtension && oldFileExtension != "" {
|
||||
err = s.DeleteAvatar(uid, oldFileExtension)
|
||||
|
||||
if err != nil {
|
||||
log.WarnfWithRequestId(c, "[users.UpdateUserAvatar] failed to delete old avatar with extension \"%s\" for user \"uid:%d\", because %s", oldFileExtension, uid, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveUserAvatar removes the custom avatar type of specified user
|
||||
func (s *UserService) RemoveUserAvatar(c *core.Context, uid int64, fileExtension string) error {
|
||||
if uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
err := s.DeleteAvatar(uid, fileExtension)
|
||||
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
now := time.Now().Unix()
|
||||
|
||||
updateModel := &models.User{
|
||||
CustomAvatarType: "",
|
||||
UpdatedUnixTime: now,
|
||||
}
|
||||
|
||||
|
||||
+6
-11
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/locales"
|
||||
)
|
||||
@@ -74,12 +75,6 @@ const (
|
||||
InMemoryDuplicateCheckerType string = "in_memory"
|
||||
)
|
||||
|
||||
// User avatar provider types
|
||||
const (
|
||||
InternalAvatarProvider string = "internal"
|
||||
GravatarProvider string = "gravatar"
|
||||
)
|
||||
|
||||
// Map provider types
|
||||
const (
|
||||
OpenStreetMapProvider string = "openstreetmap"
|
||||
@@ -276,7 +271,7 @@ type Config struct {
|
||||
EnableUserForceVerifyEmail bool
|
||||
EnableUserForgetPassword bool
|
||||
ForgetPasswordRequireVerifyEmail bool
|
||||
AvatarProvider string
|
||||
AvatarProvider core.UserAvatarProviderType
|
||||
|
||||
// Data
|
||||
EnableDataExport bool
|
||||
@@ -744,10 +739,10 @@ func loadUserConfiguration(config *Config, configFile *ini.File, sectionName str
|
||||
config.EnableUserForgetPassword = getConfigItemBoolValue(configFile, sectionName, "enable_forget_password", false)
|
||||
config.ForgetPasswordRequireVerifyEmail = getConfigItemBoolValue(configFile, sectionName, "forget_password_require_email_verify", false)
|
||||
|
||||
if getConfigItemStringValue(configFile, sectionName, "avatar_provider") == InternalAvatarProvider {
|
||||
config.AvatarProvider = InternalAvatarProvider
|
||||
} else if getConfigItemStringValue(configFile, sectionName, "avatar_provider") == GravatarProvider {
|
||||
config.AvatarProvider = GravatarProvider
|
||||
if getConfigItemStringValue(configFile, sectionName, "avatar_provider") == string(core.USER_AVATAR_PROVIDER_INTERNAL) {
|
||||
config.AvatarProvider = core.USER_AVATAR_PROVIDER_INTERNAL
|
||||
} else if getConfigItemStringValue(configFile, sectionName, "avatar_provider") == string(core.USER_AVATAR_PROVIDER_GRAVATAR) {
|
||||
config.AvatarProvider = core.USER_AVATAR_PROVIDER_GRAVATAR
|
||||
} else if getConfigItemStringValue(configFile, sectionName, "avatar_provider") == "" {
|
||||
config.AvatarProvider = ""
|
||||
} else {
|
||||
|
||||
@@ -16,60 +16,3 @@ var (
|
||||
func SetCurrentConfig(config *Config) {
|
||||
Container.Current = config
|
||||
}
|
||||
|
||||
// GetAfterRegisterNotificationContent returns the notification content displayed each time users register
|
||||
func (c *ConfigContainer) GetAfterRegisterNotificationContent(userLanguage string, clientLanguage string) string {
|
||||
language := userLanguage
|
||||
|
||||
if language == "" {
|
||||
language = clientLanguage
|
||||
}
|
||||
|
||||
if !c.Current.AfterRegisterNotification.Enabled {
|
||||
return ""
|
||||
}
|
||||
|
||||
if multiLanguageContent, exists := c.Current.AfterRegisterNotification.MultiLanguageContent[language]; exists {
|
||||
return multiLanguageContent
|
||||
}
|
||||
|
||||
return c.Current.AfterRegisterNotification.DefaultContent
|
||||
}
|
||||
|
||||
// GetAfterLoginNotificationContent returns the notification content displayed each time users log in
|
||||
func (c *ConfigContainer) GetAfterLoginNotificationContent(userLanguage string, clientLanguage string) string {
|
||||
language := userLanguage
|
||||
|
||||
if language == "" {
|
||||
language = clientLanguage
|
||||
}
|
||||
|
||||
if !c.Current.AfterLoginNotification.Enabled {
|
||||
return ""
|
||||
}
|
||||
|
||||
if multiLanguageContent, exists := c.Current.AfterLoginNotification.MultiLanguageContent[language]; exists {
|
||||
return multiLanguageContent
|
||||
}
|
||||
|
||||
return c.Current.AfterLoginNotification.DefaultContent
|
||||
}
|
||||
|
||||
// GetAfterOpenNotificationContent returns the notification content displayed each time users open the app
|
||||
func (c *ConfigContainer) GetAfterOpenNotificationContent(userLanguage string, clientLanguage string) string {
|
||||
language := userLanguage
|
||||
|
||||
if language == "" {
|
||||
language = clientLanguage
|
||||
}
|
||||
|
||||
if !c.Current.AfterOpenNotification.Enabled {
|
||||
return ""
|
||||
}
|
||||
|
||||
if multiLanguageContent, exists := c.Current.AfterOpenNotification.MultiLanguageContent[language]; exists {
|
||||
return multiLanguageContent
|
||||
}
|
||||
|
||||
return c.Current.AfterOpenNotification.DefaultContent
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
)
|
||||
@@ -36,26 +34,22 @@ func InitializeStorageContainer(config *settings.Config) error {
|
||||
return errs.ErrInvalidStorageType
|
||||
}
|
||||
|
||||
// ExistsAvatar returns whether the user avatar exists from the current object storage
|
||||
func (s *StorageContainer) ExistsAvatar(uid int64, fileExtension string) (bool, error) {
|
||||
return s.AvatarCurrentStorage.Exists(s.getUserAvatarPath(uid, fileExtension))
|
||||
// ExistsAvatar returns whether the avatar file exists from the current avatar object storage
|
||||
func (s *StorageContainer) ExistsAvatar(path string) (bool, error) {
|
||||
return s.AvatarCurrentStorage.Exists(path)
|
||||
}
|
||||
|
||||
// ReadAvatar returns the user avatar from the current object storage
|
||||
func (s *StorageContainer) ReadAvatar(uid int64, fileExtension string) (ObjectInStorage, error) {
|
||||
return s.AvatarCurrentStorage.Read(s.getUserAvatarPath(uid, fileExtension))
|
||||
// ReadAvatar returns the avatar file from the current avatar object storage
|
||||
func (s *StorageContainer) ReadAvatar(path string) (ObjectInStorage, error) {
|
||||
return s.AvatarCurrentStorage.Read(path)
|
||||
}
|
||||
|
||||
// SaveAvatar returns whether save the user avatar into the current object storage successfully
|
||||
func (s *StorageContainer) SaveAvatar(uid int64, object ObjectInStorage, fileExtension string) error {
|
||||
return s.AvatarCurrentStorage.Save(s.getUserAvatarPath(uid, fileExtension), object)
|
||||
// SaveAvatar returns whether save the avatar file into the current avatar object storage successfully
|
||||
func (s *StorageContainer) SaveAvatar(path string, object ObjectInStorage) error {
|
||||
return s.AvatarCurrentStorage.Save(path, object)
|
||||
}
|
||||
|
||||
// DeleteAvatar returns whether delete the user avatar from the current object storage successfully
|
||||
func (s *StorageContainer) DeleteAvatar(uid int64, fileExtension string) error {
|
||||
return s.AvatarCurrentStorage.Delete(s.getUserAvatarPath(uid, fileExtension))
|
||||
}
|
||||
|
||||
func (s *StorageContainer) getUserAvatarPath(uid int64, fileExtension string) string {
|
||||
return fmt.Sprintf("%d.%s", uid, fileExtension)
|
||||
// DeleteAvatar returns whether delete the avatar file from the current avatar object storage successfully
|
||||
func (s *StorageContainer) DeleteAvatar(path string) error {
|
||||
return s.AvatarCurrentStorage.Delete(path)
|
||||
}
|
||||
|
||||
@@ -967,6 +967,8 @@
|
||||
"no user avatar": "There is no user avatar file",
|
||||
"user avatar is empty": "User avatar file is empty",
|
||||
"user avatar not exists": "User avatar does not exist",
|
||||
"user avatar not set": "User avatar is not set",
|
||||
"user avatar file extension invalid": "User avatar file extension is invalid",
|
||||
"unauthorized access": "Unauthorized access",
|
||||
"current token is invalid": "Current token is invalid",
|
||||
"current token is expired": "Current token is expired",
|
||||
|
||||
@@ -967,6 +967,8 @@
|
||||
"no user avatar": "没有用户头像文件",
|
||||
"user avatar is empty": "用户头像文件为空",
|
||||
"user avatar not exists": "用户头像不存在",
|
||||
"user avatar not set": "用户没有设置头像",
|
||||
"user avatar file extension invalid": "用户头像文件扩展名无效",
|
||||
"unauthorized access": "未授权的登录",
|
||||
"current token is invalid": "当前认证令牌无效",
|
||||
"current token is expired": "当前认证令牌已过期",
|
||||
|
||||
Reference in New Issue
Block a user