mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 15:07:33 +08:00
sync application settings
This commit is contained in:
@@ -19,6 +19,7 @@ type AuthorizationsApi struct {
|
||||
ApiUsingDuplicateChecker
|
||||
ApiWithUserInfo
|
||||
users *services.UserService
|
||||
userAppCloudSettings *services.UserApplicationCloudSettingsService
|
||||
tokens *services.TokenService
|
||||
twoFactorAuthorizations *services.TwoFactorAuthorizationService
|
||||
}
|
||||
@@ -44,6 +45,7 @@ var (
|
||||
},
|
||||
},
|
||||
users: services.Users,
|
||||
userAppCloudSettings: services.UserApplicationCloudSettings,
|
||||
tokens: services.Tokens,
|
||||
twoFactorAuthorizations: services.TwoFactorAuthorizations,
|
||||
}
|
||||
@@ -140,9 +142,18 @@ func (a *AuthorizationsApi) AuthorizeHandler(c *core.WebContext) (any, *errs.Err
|
||||
|
||||
c.SetTokenClaims(claims)
|
||||
|
||||
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, user.Uid)
|
||||
var applicationCloudSettingSlice *models.ApplicationCloudSettingSlice = nil
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[authorizations.AuthorizeHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
} else if userApplicationCloudSettings != nil && len(userApplicationCloudSettings.Settings) > 0 {
|
||||
applicationCloudSettingSlice = &userApplicationCloudSettings.Settings
|
||||
}
|
||||
|
||||
log.Infof(c, "[authorizations.AuthorizeHandler] user \"uid:%d\" has logined, token type is %d, token will be expired at %d", user.Uid, claims.Type, claims.ExpiresAt)
|
||||
|
||||
authResp := a.getAuthResponse(c, token, twoFactorEnable, user)
|
||||
authResp := a.getAuthResponse(c, token, twoFactorEnable, user, applicationCloudSettingSlice)
|
||||
return authResp, nil
|
||||
}
|
||||
|
||||
@@ -218,9 +229,18 @@ func (a *AuthorizationsApi) TwoFactorAuthorizeHandler(c *core.WebContext) (any,
|
||||
c.SetTextualToken(token)
|
||||
c.SetTokenClaims(claims)
|
||||
|
||||
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, user.Uid)
|
||||
var applicationCloudSettingSlice *models.ApplicationCloudSettingSlice = nil
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[authorizations.TwoFactorAuthorizeHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
} else if userApplicationCloudSettings != nil && len(userApplicationCloudSettings.Settings) > 0 {
|
||||
applicationCloudSettingSlice = &userApplicationCloudSettings.Settings
|
||||
}
|
||||
|
||||
log.Infof(c, "[authorizations.TwoFactorAuthorizeHandler] user \"uid:%d\" has authorized two-factor via passcode, token will be expired at %d", user.Uid, claims.ExpiresAt)
|
||||
|
||||
authResp := a.getAuthResponse(c, token, false, user)
|
||||
authResp := a.getAuthResponse(c, token, false, user, applicationCloudSettingSlice)
|
||||
return authResp, nil
|
||||
}
|
||||
|
||||
@@ -303,17 +323,27 @@ func (a *AuthorizationsApi) TwoFactorAuthorizeByRecoveryCodeHandler(c *core.WebC
|
||||
c.SetTextualToken(token)
|
||||
c.SetTokenClaims(claims)
|
||||
|
||||
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, user.Uid)
|
||||
var applicationCloudSettingSlice *models.ApplicationCloudSettingSlice = nil
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[authorizations.TwoFactorAuthorizeByRecoveryCodeHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
} else if userApplicationCloudSettings != nil && len(userApplicationCloudSettings.Settings) > 0 {
|
||||
applicationCloudSettingSlice = &userApplicationCloudSettings.Settings
|
||||
}
|
||||
|
||||
log.Infof(c, "[authorizations.TwoFactorAuthorizeByRecoveryCodeHandler] user \"uid:%d\" has authorized two-factor via recovery code \"%s\", token will be expired at %d", user.Uid, credential.RecoveryCode, claims.ExpiresAt)
|
||||
|
||||
authResp := a.getAuthResponse(c, token, false, user)
|
||||
authResp := a.getAuthResponse(c, token, false, user, applicationCloudSettingSlice)
|
||||
return authResp, nil
|
||||
}
|
||||
|
||||
func (a *AuthorizationsApi) getAuthResponse(c *core.WebContext, token string, need2FA bool, user *models.User) *models.AuthResponse {
|
||||
func (a *AuthorizationsApi) getAuthResponse(c *core.WebContext, token string, need2FA bool, user *models.User, applicationCloudSettings *models.ApplicationCloudSettingSlice) *models.AuthResponse {
|
||||
return &models.AuthResponse{
|
||||
Token: token,
|
||||
Need2FA: need2FA,
|
||||
User: a.GetUserBasicInfo(user),
|
||||
NotificationContent: a.GetAfterLoginNotificationContent(user.Language, c.GetClientLocale()),
|
||||
Token: token,
|
||||
Need2FA: need2FA,
|
||||
User: a.GetUserBasicInfo(user),
|
||||
ApplicationCloudSettings: applicationCloudSettings,
|
||||
NotificationContent: a.GetAfterLoginNotificationContent(user.Language, c.GetClientLocale()),
|
||||
}
|
||||
}
|
||||
|
||||
+32
-10
@@ -18,8 +18,9 @@ import (
|
||||
type TokensApi struct {
|
||||
ApiUsingConfig
|
||||
ApiWithUserInfo
|
||||
tokens *services.TokenService
|
||||
users *services.UserService
|
||||
tokens *services.TokenService
|
||||
users *services.UserService
|
||||
userAppCloudSettings *services.UserApplicationCloudSettingsService
|
||||
}
|
||||
|
||||
// Initialize a token api singleton instance
|
||||
@@ -36,8 +37,9 @@ var (
|
||||
container: avatars.Container,
|
||||
},
|
||||
},
|
||||
tokens: services.Tokens,
|
||||
users: services.Users,
|
||||
tokens: services.Tokens,
|
||||
users: services.Users,
|
||||
userAppCloudSettings: services.UserApplicationCloudSettings,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -251,9 +253,19 @@ func (a *TokensApi) TokenRefreshHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
}
|
||||
}
|
||||
|
||||
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, user.Uid)
|
||||
var applicationCloudSettingSlice *models.ApplicationCloudSettingSlice = nil
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[tokens.TokenRefreshHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
} else if userApplicationCloudSettings != nil && len(userApplicationCloudSettings.Settings) > 0 {
|
||||
applicationCloudSettingSlice = &userApplicationCloudSettings.Settings
|
||||
}
|
||||
|
||||
refreshResp := &models.TokenRefreshResponse{
|
||||
User: a.GetUserBasicInfo(user),
|
||||
NotificationContent: a.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
ApplicationCloudSettings: applicationCloudSettingSlice,
|
||||
NotificationContent: a.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
}
|
||||
|
||||
return refreshResp, nil
|
||||
@@ -276,13 +288,23 @@ func (a *TokensApi) TokenRefreshHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
c.SetTextualToken(token)
|
||||
c.SetTokenClaims(claims)
|
||||
|
||||
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, user.Uid)
|
||||
var applicationCloudSettingSlice *models.ApplicationCloudSettingSlice = nil
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[tokens.TokenRefreshHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", user.Uid, err.Error())
|
||||
} else if userApplicationCloudSettings != nil && len(userApplicationCloudSettings.Settings) > 0 {
|
||||
applicationCloudSettingSlice = &userApplicationCloudSettings.Settings
|
||||
}
|
||||
|
||||
log.Infof(c, "[tokens.TokenRefreshHandler] user \"uid:%d\" token refreshed, new token will be expired at %d", user.Uid, claims.ExpiresAt)
|
||||
|
||||
refreshResp := &models.TokenRefreshResponse{
|
||||
NewToken: token,
|
||||
OldTokenId: a.tokens.GenerateTokenId(oldTokenRecord),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
NotificationContent: a.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
NewToken: token,
|
||||
OldTokenId: a.tokens.GenerateTokenId(oldTokenRecord),
|
||||
User: a.GetUserBasicInfo(user),
|
||||
ApplicationCloudSettings: applicationCloudSettingSlice,
|
||||
NotificationContent: a.GetAfterOpenNotificationContent(user.Language, c.GetClientLocale()),
|
||||
}
|
||||
|
||||
return refreshResp, nil
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/log"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/services"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
)
|
||||
|
||||
// UserApplicationCloudSettingsApi represents user application cloud settings api
|
||||
type UserApplicationCloudSettingsApi struct {
|
||||
userAppCloudSettings *services.UserApplicationCloudSettingsService
|
||||
}
|
||||
|
||||
// Initialize a user application cloud settings api singleton instance
|
||||
var (
|
||||
UserApplicationCloudSettings = &UserApplicationCloudSettingsApi{
|
||||
userAppCloudSettings: services.UserApplicationCloudSettings,
|
||||
}
|
||||
)
|
||||
|
||||
// ApplicationSettingsGetHandler returns application cloud settings of current user
|
||||
func (a *UserApplicationCloudSettingsApi) ApplicationSettingsGetHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
uid := c.GetCurrentUid()
|
||||
|
||||
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, uid)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsGetHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
if userApplicationCloudSettings == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
applicationCloudSettingSlice := userApplicationCloudSettings.Settings
|
||||
|
||||
if len(applicationCloudSettingSlice) < 1 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return applicationCloudSettingSlice, nil
|
||||
}
|
||||
|
||||
// ApplicationSettingsUpdateHandler updates user application cloud settings by request parameters for current user
|
||||
func (a *UserApplicationCloudSettingsApi) ApplicationSettingsUpdateHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
var userAppCloudSettingUpdateReq models.UserApplicationCloudSettingsUpdateRequest
|
||||
err := c.ShouldBindJSON(&userAppCloudSettingUpdateReq)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] parse request failed, because %s", err.Error())
|
||||
return false, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, uid)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return false, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
oldApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
|
||||
|
||||
if userApplicationCloudSettings != nil {
|
||||
for _, setting := range userApplicationCloudSettings.Settings {
|
||||
oldApplicationCloudSettingsMap[setting.SettingKey] = setting
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the full update settings are the same as the existing settings
|
||||
if userAppCloudSettingUpdateReq.FullUpdate {
|
||||
if len(userAppCloudSettingUpdateReq.Settings) == len(oldApplicationCloudSettingsMap) {
|
||||
needUpdate := false
|
||||
|
||||
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
||||
oldSetting, exists := oldApplicationCloudSettingsMap[setting.SettingKey]
|
||||
|
||||
if !exists || oldSetting.SettingValue != setting.SettingValue {
|
||||
needUpdate = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !needUpdate {
|
||||
return false, errs.ErrNothingWillBeUpdated
|
||||
}
|
||||
}
|
||||
} else { // Check if the partial update settings are the same as the existing settings or the settings to update are not set to sync
|
||||
needUpdate := true
|
||||
|
||||
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
||||
cloudSetting, exists := oldApplicationCloudSettingsMap[setting.SettingKey]
|
||||
|
||||
if !exists {
|
||||
needUpdate = false
|
||||
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not set to sync", setting.SettingKey)
|
||||
} else if cloudSetting.SettingValue == setting.SettingValue {
|
||||
needUpdate = false
|
||||
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" value \"%s\" is not changed, no need to update", setting.SettingKey, setting.SettingValue)
|
||||
}
|
||||
}
|
||||
|
||||
if !needUpdate {
|
||||
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] no user application cloud settings need to update for user \"uid:%d\"", uid)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
newApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
|
||||
var newApplicationCloudSettingSlice models.ApplicationCloudSettingSlice
|
||||
|
||||
if userAppCloudSettingUpdateReq.FullUpdate {
|
||||
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user \"uid:%d\" application cloud settings force update, will overwrite all existing settings", uid)
|
||||
} else {
|
||||
if len(oldApplicationCloudSettingsMap) > 0 {
|
||||
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user \"uid:%d\" application cloud settings exists, try to merge it with request settings", uid)
|
||||
newApplicationCloudSettingsMap = oldApplicationCloudSettingsMap
|
||||
}
|
||||
}
|
||||
|
||||
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
||||
newApplicationCloudSettingsMap[setting.SettingKey] = setting
|
||||
}
|
||||
|
||||
for settingKey, setting := range newApplicationCloudSettingsMap {
|
||||
settingType, exists := models.ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES[settingKey]
|
||||
|
||||
if !exists {
|
||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not supported to sync", settingKey)
|
||||
continue
|
||||
}
|
||||
|
||||
if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING {
|
||||
// Do Nothing
|
||||
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER {
|
||||
_, err := utils.StringToFloat64(setting.SettingValue)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid number value \"%s\"", settingKey, setting.SettingValue)
|
||||
continue
|
||||
}
|
||||
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN {
|
||||
if setting.SettingValue != "true" && setting.SettingValue != "false" {
|
||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid boolean value \"%s\"", settingKey, setting.SettingValue)
|
||||
continue
|
||||
}
|
||||
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING_BOOLEAN_MAP {
|
||||
var settingValueMap map[string]bool
|
||||
err := json.Unmarshal([]byte(setting.SettingValue), &settingValueMap)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid map value \"%s\", because %s", settingKey, setting.SettingValue, err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has unknown type \"%s\"", settingKey, settingType)
|
||||
continue
|
||||
}
|
||||
|
||||
newApplicationCloudSettingSlice = append(newApplicationCloudSettingSlice, setting)
|
||||
}
|
||||
|
||||
err = a.userAppCloudSettings.UpdateUserApplicationCloudSettings(c, uid, newApplicationCloudSettingSlice)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] failed to update user application cloud settings for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return false, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// ApplicationSettingsDisableHandler disabled user application cloud settings by request parameters for current user
|
||||
func (a *UserApplicationCloudSettingsApi) ApplicationSettingsDisableHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
uid := c.GetCurrentUid()
|
||||
|
||||
err := a.userAppCloudSettings.ClearUserApplicationCloudSettings(c, uid)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsDisableHandler] failed to clear user application cloud settings for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return false, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
Reference in New Issue
Block a user