123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- 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{
- "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,
- }
- }
|