mirror of
https://github.com/mayswind/ezbookkeeping
synced 2026-04-21 21:47:54 +00:00
235 lines
9.5 KiB
Go
235 lines
9.5 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"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
|
|
users *services.UserService
|
|
}
|
|
|
|
// Initialize a user application cloud settings api singleton instance
|
|
var (
|
|
UserApplicationCloudSettings = &UserApplicationCloudSettingsApi{
|
|
userAppCloudSettings: services.UserApplicationCloudSettings,
|
|
users: services.Users,
|
|
}
|
|
)
|
|
|
|
// 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()
|
|
user, err := a.users.GetUserById(c, uid)
|
|
|
|
if err != nil {
|
|
if !errs.IsCustomError(err) {
|
|
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] failed to get user for user \"uid:%d\", because %s", uid, err.Error())
|
|
}
|
|
|
|
return false, errs.ErrUserNotFound
|
|
}
|
|
|
|
if user.FeatureRestriction.Contains(core.USER_FEATURE_RESTRICTION_TYPE_SYNC_APPLICATION_SETTINGS) {
|
|
return false, errs.ErrNotPermittedToPerformThisAction
|
|
}
|
|
|
|
var userApplicationCloudSettings *models.UserApplicationCloudSetting
|
|
|
|
// Retry up to 3 times
|
|
for i := 0; i < 3; i++ {
|
|
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\" (try count %d), because %s", uid, i+1, err.Error())
|
|
return false, errs.Or(err, errs.ErrOperationFailed)
|
|
}
|
|
|
|
oldApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
|
|
lastUpdateTime := int64(0)
|
|
|
|
if userApplicationCloudSettings != nil {
|
|
for _, setting := range userApplicationCloudSettings.Settings {
|
|
oldApplicationCloudSettingsMap[setting.SettingKey] = setting
|
|
}
|
|
|
|
lastUpdateTime = userApplicationCloudSettings.UpdatedUnixTime
|
|
}
|
|
|
|
// 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 (try count %d)", setting.SettingKey, i+1)
|
|
} 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 (try count %d)", setting.SettingKey, setting.SettingValue, i+1)
|
|
}
|
|
}
|
|
|
|
if !needUpdate {
|
|
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] no user application cloud settings need to update for user \"uid:%d\" (try count %d)", uid, i+1)
|
|
return true, 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 (try count %d)", uid, i+1)
|
|
} 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 (try count %d)", uid, i+1)
|
|
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 (try count %d)", settingKey, i+1)
|
|
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\" (try count %d)", settingKey, setting.SettingValue, i+1)
|
|
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\" (try count %d)", settingKey, setting.SettingValue, i+1)
|
|
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\" (try count %d), because %s", settingKey, setting.SettingValue, i+1, err.Error())
|
|
continue
|
|
}
|
|
} else {
|
|
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has unknown type \"%s\" (try count %d)", settingKey, settingType, i+1)
|
|
continue
|
|
}
|
|
|
|
newApplicationCloudSettingSlice = append(newApplicationCloudSettingSlice, setting)
|
|
}
|
|
|
|
err = a.userAppCloudSettings.UpdateUserApplicationCloudSettings(c, uid, newApplicationCloudSettingSlice, userAppCloudSettingUpdateReq.FullUpdate, lastUpdateTime)
|
|
|
|
if err == nil {
|
|
break
|
|
}
|
|
|
|
time.Sleep(100 * time.Millisecond) // Wait for 100 milliseconds before retrying
|
|
}
|
|
|
|
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()
|
|
user, err := a.users.GetUserById(c, uid)
|
|
|
|
if err != nil {
|
|
if !errs.IsCustomError(err) {
|
|
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsDisableHandler] failed to get user for user \"uid:%d\", because %s", uid, err.Error())
|
|
}
|
|
|
|
return false, errs.ErrUserNotFound
|
|
}
|
|
|
|
if user.FeatureRestriction.Contains(core.USER_FEATURE_RESTRICTION_TYPE_SYNC_APPLICATION_SETTINGS) {
|
|
return false, errs.ErrNotPermittedToPerformThisAction
|
|
}
|
|
|
|
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
|
|
}
|