mirror of
				https://github.com/usememos/memos.git
				synced 2025-10-25 13:56:27 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			174 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package v1
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"net/http"
 | |
| 
 | |
| 	"github.com/labstack/echo/v4"
 | |
| 	"github.com/pkg/errors"
 | |
| 	"golang.org/x/exp/slices"
 | |
| 
 | |
| 	"github.com/usememos/memos/store"
 | |
| )
 | |
| 
 | |
| type UserSettingKey string
 | |
| 
 | |
| const (
 | |
| 	// UserSettingLocaleKey is the key type for user locale.
 | |
| 	UserSettingLocaleKey UserSettingKey = "locale"
 | |
| 	// UserSettingAppearanceKey is the key type for user appearance.
 | |
| 	UserSettingAppearanceKey UserSettingKey = "appearance"
 | |
| 	// UserSettingMemoVisibilityKey is the key type for user preference memo default visibility.
 | |
| 	UserSettingMemoVisibilityKey UserSettingKey = "memo-visibility"
 | |
| 	// UserSettingTelegramUserIDKey is the key type for telegram UserID of memos user.
 | |
| 	UserSettingTelegramUserIDKey UserSettingKey = "telegram-user-id"
 | |
| )
 | |
| 
 | |
| // String returns the string format of UserSettingKey type.
 | |
| func (key UserSettingKey) String() string {
 | |
| 	switch key {
 | |
| 	case UserSettingLocaleKey:
 | |
| 		return "locale"
 | |
| 	case UserSettingAppearanceKey:
 | |
| 		return "appearance"
 | |
| 	case UserSettingMemoVisibilityKey:
 | |
| 		return "memo-visibility"
 | |
| 	case UserSettingTelegramUserIDKey:
 | |
| 		return "telegram-user-id"
 | |
| 	}
 | |
| 	return ""
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	UserSettingLocaleValue = []string{
 | |
| 		"ar",
 | |
| 		"de",
 | |
| 		"en",
 | |
| 		"es",
 | |
| 		"fr",
 | |
| 		"hi",
 | |
| 		"hr",
 | |
| 		"it",
 | |
| 		"ja",
 | |
| 		"ko",
 | |
| 		"nl",
 | |
| 		"pl",
 | |
| 		"pt-BR",
 | |
| 		"ru",
 | |
| 		"sl",
 | |
| 		"sv",
 | |
| 		"tr",
 | |
| 		"uk",
 | |
| 		"vi",
 | |
| 		"zh-Hans",
 | |
| 		"zh-Hant",
 | |
| 	}
 | |
| 	UserSettingAppearanceValue     = []string{"system", "light", "dark"}
 | |
| 	UserSettingMemoVisibilityValue = []Visibility{Private, Protected, Public}
 | |
| )
 | |
| 
 | |
| type UserSetting struct {
 | |
| 	UserID int32          `json:"userId"`
 | |
| 	Key    UserSettingKey `json:"key"`
 | |
| 	Value  string         `json:"value"`
 | |
| }
 | |
| 
 | |
| type UpsertUserSettingRequest struct {
 | |
| 	UserID int32          `json:"-"`
 | |
| 	Key    UserSettingKey `json:"key"`
 | |
| 	Value  string         `json:"value"`
 | |
| }
 | |
| 
 | |
| func (s *APIV1Service) registerUserSettingRoutes(g *echo.Group) {
 | |
| 	g.POST("/user/setting", s.UpsertUserSetting)
 | |
| }
 | |
| 
 | |
| // UpsertUserSetting godoc
 | |
| //
 | |
| //	@Summary	Upsert user setting
 | |
| //	@Tags		user-setting
 | |
| //	@Accept		json
 | |
| //	@Produce	json
 | |
| //	@Param		body	body		UpsertUserSettingRequest	true	"Request object."
 | |
| //	@Success	200		{object}	store.UserSetting			"Created user setting"
 | |
| //	@Failure	400		{object}	nil							"Malformatted post user setting upsert request | Invalid user setting format"
 | |
| //	@Failure	401		{object}	nil							"Missing auth session"
 | |
| //	@Failure	500		{object}	nil							"Failed to upsert user setting"
 | |
| //	@Router		/api/v1/user/setting [POST]
 | |
| func (s *APIV1Service) UpsertUserSetting(c echo.Context) error {
 | |
| 	ctx := c.Request().Context()
 | |
| 	userID, ok := c.Get(userIDContextKey).(int32)
 | |
| 	if !ok {
 | |
| 		return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
 | |
| 	}
 | |
| 
 | |
| 	userSettingUpsert := &UpsertUserSettingRequest{}
 | |
| 	if err := json.NewDecoder(c.Request().Body).Decode(userSettingUpsert); err != nil {
 | |
| 		return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user setting upsert request").SetInternal(err)
 | |
| 	}
 | |
| 	if err := userSettingUpsert.Validate(); err != nil {
 | |
| 		return echo.NewHTTPError(http.StatusBadRequest, "Invalid user setting format").SetInternal(err)
 | |
| 	}
 | |
| 
 | |
| 	userSettingUpsert.UserID = userID
 | |
| 	userSetting, err := s.Store.UpsertUserSetting(ctx, &store.UserSetting{
 | |
| 		UserID: userID,
 | |
| 		Key:    userSettingUpsert.Key.String(),
 | |
| 		Value:  userSettingUpsert.Value,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert user setting").SetInternal(err)
 | |
| 	}
 | |
| 
 | |
| 	userSettingMessage := convertUserSettingFromStore(userSetting)
 | |
| 	return c.JSON(http.StatusOK, userSettingMessage)
 | |
| }
 | |
| 
 | |
| func (upsert UpsertUserSettingRequest) Validate() error {
 | |
| 	if upsert.Key == UserSettingLocaleKey {
 | |
| 		localeValue := "en"
 | |
| 		err := json.Unmarshal([]byte(upsert.Value), &localeValue)
 | |
| 		if err != nil {
 | |
| 			return errors.New("failed to unmarshal user setting locale value")
 | |
| 		}
 | |
| 		if !slices.Contains(UserSettingLocaleValue, localeValue) {
 | |
| 			return errors.New("invalid user setting locale value")
 | |
| 		}
 | |
| 	} else if upsert.Key == UserSettingAppearanceKey {
 | |
| 		appearanceValue := "system"
 | |
| 		err := json.Unmarshal([]byte(upsert.Value), &appearanceValue)
 | |
| 		if err != nil {
 | |
| 			return errors.New("failed to unmarshal user setting appearance value")
 | |
| 		}
 | |
| 		if !slices.Contains(UserSettingAppearanceValue, appearanceValue) {
 | |
| 			return errors.New("invalid user setting appearance value")
 | |
| 		}
 | |
| 	} else if upsert.Key == UserSettingMemoVisibilityKey {
 | |
| 		memoVisibilityValue := Private
 | |
| 		err := json.Unmarshal([]byte(upsert.Value), &memoVisibilityValue)
 | |
| 		if err != nil {
 | |
| 			return errors.New("failed to unmarshal user setting memo visibility value")
 | |
| 		}
 | |
| 		if !slices.Contains(UserSettingMemoVisibilityValue, memoVisibilityValue) {
 | |
| 			return errors.New("invalid user setting memo visibility value")
 | |
| 		}
 | |
| 	} else if upsert.Key == UserSettingTelegramUserIDKey {
 | |
| 		var key string
 | |
| 		err := json.Unmarshal([]byte(upsert.Value), &key)
 | |
| 		if err != nil {
 | |
| 			return errors.New("invalid user setting telegram user id value")
 | |
| 		}
 | |
| 	} else {
 | |
| 		return errors.New("invalid user setting key")
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func convertUserSettingFromStore(userSetting *store.UserSetting) *UserSetting {
 | |
| 	return &UserSetting{
 | |
| 		UserID: userSetting.UserID,
 | |
| 		Key:    UserSettingKey(userSetting.Key),
 | |
| 		Value:  userSetting.Value,
 | |
| 	}
 | |
| }
 |