From 7fc7b19d647b1b04a459b6d8b8ff93c5ad1dc172 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 8 Dec 2023 22:41:47 +0800 Subject: [PATCH] chore: deprecate user setting legacy api --- api/v1/memo.go | 23 +-- api/v1/user.go | 35 +--- api/v1/user_setting.go | 174 ------------------ api/v1/v1.go | 1 - api/v2/user_service.go | 2 +- cmd/copydb.go | 6 +- server/integration/telegram.go | 15 +- store/cache.go | 4 - store/db/mysql/user_setting.go | 50 +---- store/db/postgres/user_setting.go | 71 +------ .../migration/prod/0.18/00__webhook.sql | 12 ++ .../migration/prod/0.18/01__user_setting.sql | 4 + store/db/sqlite/user_setting.go | 63 +------ store/driver.go | 6 +- store/user_setting.go | 63 +------ test/store/user_setting_test.go | 19 +- 16 files changed, 54 insertions(+), 494 deletions(-) delete mode 100644 api/v1/user_setting.go create mode 100644 store/db/sqlite/migration/prod/0.18/00__webhook.sql create mode 100644 store/db/sqlite/migration/prod/0.18/01__user_setting.sql diff --git a/api/v1/memo.go b/api/v1/memo.go index 6f1e6324..96c3ed07 100644 --- a/api/v1/memo.go +++ b/api/v1/memo.go @@ -265,20 +265,15 @@ func (s *APIV1Service) CreateMemo(c echo.Context) error { } if createMemoRequest.Visibility == "" { - userMemoVisibilitySetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{ + userMemoVisibilitySetting, err := s.Store.GetUserSettingV1(ctx, &store.FindUserSetting{ UserID: &userID, - Key: UserSettingMemoVisibilityKey.String(), + Key: storepb.UserSettingKey_USER_SETTING_MEMO_VISIBILITY, }) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user setting").SetInternal(err) } if userMemoVisibilitySetting != nil { - memoVisibility := Private - err := json.Unmarshal([]byte(userMemoVisibilitySetting.Value), &memoVisibility) - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal user setting value").SetInternal(err) - } - createMemoRequest.Visibility = memoVisibility + createMemoRequest.Visibility = Visibility(userMemoVisibilitySetting.GetMemoVisibility()) } else { // Private is the default memo visibility. createMemoRequest.Visibility = Private @@ -394,20 +389,12 @@ func (s *APIV1Service) CreateMemo(c echo.Context) error { // Send notification to telegram if memo is not private. if memoResponse.Visibility != Private { // fetch all telegram UserID - userSettings, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{Key: UserSettingTelegramUserIDKey.String()}) + userSettings, err := s.Store.ListUserSettingsV1(ctx, &store.FindUserSetting{Key: storepb.UserSettingKey_USER_SETTING_TELEGRAM_USER_ID}) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to ListUserSettings").SetInternal(err) } for _, userSetting := range userSettings { - // parse telegram UserID setting value into a int64 - var tgUserIDStr string - err := json.Unmarshal([]byte(userSetting.Value), &tgUserIDStr) - if err != nil { - log.Error("failed to parse Telegram UserID", zap.Error(err)) - continue - } - - tgUserID, err := strconv.ParseInt(tgUserIDStr, 10, 64) + tgUserID, err := strconv.ParseInt(userSetting.GetTelegramUserId(), 10, 64) if err != nil { log.Error("failed to parse Telegram UserID", zap.Error(err)) continue diff --git a/api/v1/user.go b/api/v1/user.go index 5412284a..4b5344a4 100644 --- a/api/v1/user.go +++ b/api/v1/user.go @@ -41,13 +41,12 @@ type User struct { UpdatedTs int64 `json:"updatedTs"` // Domain specific fields - Username string `json:"username"` - Role Role `json:"role"` - Email string `json:"email"` - Nickname string `json:"nickname"` - PasswordHash string `json:"-"` - AvatarURL string `json:"avatarUrl"` - UserSettingList []*UserSetting `json:"userSettingList"` + Username string `json:"username"` + Role Role `json:"role"` + Email string `json:"email"` + Nickname string `json:"nickname"` + PasswordHash string `json:"-"` + AvatarURL string `json:"avatarUrl"` } type CreateUserRequest struct { @@ -212,18 +211,7 @@ func (s *APIV1Service) GetCurrentUser(c echo.Context) error { return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session") } - list, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{ - UserID: &userID, - }) - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find userSettingList").SetInternal(err) - } - userSettingList := []*UserSetting{} - for _, userSetting := range list { - userSettingList = append(userSettingList, convertUserSettingFromStore(userSetting)) - } userMessage := convertUserFromStore(user) - userMessage.UserSettingList = userSettingList return c.JSON(http.StatusOK, userMessage) } @@ -415,18 +403,7 @@ func (s *APIV1Service) UpdateUser(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch user").SetInternal(err) } - list, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{ - UserID: &userID, - }) - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find userSettingList").SetInternal(err) - } - userSettingList := []*UserSetting{} - for _, userSetting := range list { - userSettingList = append(userSettingList, convertUserSettingFromStore(userSetting)) - } userMessage := convertUserFromStore(user) - userMessage.UserSettingList = userSettingList return c.JSON(http.StatusOK, userMessage) } diff --git a/api/v1/user_setting.go b/api/v1/user_setting.go deleted file mode 100644 index 52ae4580..00000000 --- a/api/v1/user_setting.go +++ /dev/null @@ -1,174 +0,0 @@ -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, - } -} diff --git a/api/v1/v1.go b/api/v1/v1.go index 78d6b1ac..50d0054c 100644 --- a/api/v1/v1.go +++ b/api/v1/v1.go @@ -72,7 +72,6 @@ func (s *APIV1Service) Register(rootGroup *echo.Group) { s.registerAuthRoutes(apiV1Group) s.registerIdentityProviderRoutes(apiV1Group) s.registerUserRoutes(apiV1Group) - s.registerUserSettingRoutes(apiV1Group) s.registerTagRoutes(apiV1Group) s.registerStorageRoutes(apiV1Group) s.registerResourceRoutes(apiV1Group) diff --git a/api/v2/user_service.go b/api/v2/user_service.go index f945f86c..250c1c13 100644 --- a/api/v2/user_service.go +++ b/api/v2/user_service.go @@ -201,7 +201,7 @@ func (s *APIV2Service) GetUserSetting(ctx context.Context, _ *apiv2pb.GetUserSet return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err) } - userSettings, err := s.Store.ListUserSettingsV1(ctx, &store.FindUserSettingV1{ + userSettings, err := s.Store.ListUserSettingsV1(ctx, &store.FindUserSetting{ UserID: &user.ID, }) if err != nil { diff --git a/cmd/copydb.go b/cmd/copydb.go index 0c857228..5ec22e21 100644 --- a/cmd/copydb.go +++ b/cmd/copydb.go @@ -375,11 +375,7 @@ func copyUserSettings(ctx context.Context, fromDriver, toDriver store.Driver) er fmt.Printf("\tTotal %d records\n", len(list)) for _, item := range list { - _, err := toDriver.UpsertUserSetting(ctx, &store.UserSetting{ - Key: item.Key, - Value: item.Value, - UserID: item.UserID, - }) + _, err := toDriver.UpsertUserSetting(ctx, item) if err != nil { return err } diff --git a/server/integration/telegram.go b/server/integration/telegram.go index 902935b1..4f036ccf 100644 --- a/server/integration/telegram.go +++ b/server/integration/telegram.go @@ -3,7 +3,6 @@ package integration import ( "bytes" "context" - "encoding/json" "fmt" "strconv" "unicode/utf16" @@ -12,6 +11,7 @@ import ( apiv1 "github.com/usememos/memos/api/v1" "github.com/usememos/memos/plugin/telegram" + storepb "github.com/usememos/memos/proto/gen/store" "github.com/usememos/memos/store" ) @@ -39,20 +39,15 @@ func (t *TelegramHandler) MessageHandle(ctx context.Context, bot *telegram.Bot, } var creatorID int32 - userSettingList, err := t.store.ListUserSettings(ctx, &store.FindUserSetting{ - Key: apiv1.UserSettingTelegramUserIDKey.String(), + userSettingList, err := t.store.ListUserSettingsV1(ctx, &store.FindUserSetting{ + Key: storepb.UserSettingKey_USER_SETTING_TELEGRAM_USER_ID, }) if err != nil { return errors.Wrap(err, "Failed to find userSettingList") } for _, userSetting := range userSettingList { - var value string - if err := json.Unmarshal([]byte(userSetting.Value), &value); err != nil { - continue - } - - if value == strconv.FormatInt(message.From.ID, 10) { - creatorID = userSetting.UserID + if userSetting.GetTelegramUserId() == strconv.FormatInt(message.From.ID, 10) { + creatorID = userSetting.UserId } } diff --git a/store/cache.go b/store/cache.go index 671a6a61..34c9c9d8 100644 --- a/store/cache.go +++ b/store/cache.go @@ -4,10 +4,6 @@ import ( "fmt" ) -func getUserSettingCacheKey(userID int32, key string) string { - return fmt.Sprintf("%d-%s", userID, key) -} - func getUserSettingV1CacheKey(userID int32, key string) string { return fmt.Sprintf("%d-%s-v1", userID, key) } diff --git a/store/db/mysql/user_setting.go b/store/db/mysql/user_setting.go index 6b127342..8a2114de 100644 --- a/store/db/mysql/user_setting.go +++ b/store/db/mysql/user_setting.go @@ -12,53 +12,7 @@ import ( "github.com/usememos/memos/store" ) -func (d *DB) UpsertUserSetting(ctx context.Context, upsert *store.UserSetting) (*store.UserSetting, error) { - stmt := "INSERT INTO `user_setting` (`user_id`, `key`, `value`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `value` = ?" - if _, err := d.db.ExecContext(ctx, stmt, upsert.UserID, upsert.Key, upsert.Value, upsert.Value); err != nil { - return nil, err - } - - return upsert, nil -} - -func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*store.UserSetting, error) { - where, args := []string{"1 = 1"}, []any{} - - if v := find.Key; v != "" { - where, args = append(where, "`key` = ?"), append(args, v) - } - if v := find.UserID; v != nil { - where, args = append(where, "`user_id` = ?"), append(args, *find.UserID) - } - - query := "SELECT `user_id`, `key`, `value` FROM `user_setting` WHERE " + strings.Join(where, " AND ") - rows, err := d.db.QueryContext(ctx, query, args...) - if err != nil { - return nil, err - } - defer rows.Close() - - userSettingList := make([]*store.UserSetting, 0) - for rows.Next() { - var userSetting store.UserSetting - if err := rows.Scan( - &userSetting.UserID, - &userSetting.Key, - &userSetting.Value, - ); err != nil { - return nil, err - } - userSettingList = append(userSettingList, &userSetting) - } - - if err := rows.Err(); err != nil { - return nil, err - } - - return userSettingList, nil -} - -func (d *DB) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) { +func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) { stmt := "INSERT INTO `user_setting` (`user_id`, `key`, `value`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `value` = ?" var valueString string if upsert.Key == storepb.UserSettingKey_USER_SETTING_ACCESS_TOKENS { @@ -86,7 +40,7 @@ func (d *DB) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSettin return upsert, nil } -func (d *DB) ListUserSettingsV1(ctx context.Context, find *store.FindUserSettingV1) ([]*storepb.UserSetting, error) { +func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*storepb.UserSetting, error) { where, args := []string{"1 = 1"}, []any{} if v := find.Key; v != storepb.UserSettingKey_USER_SETTING_KEY_UNSPECIFIED { diff --git a/store/db/postgres/user_setting.go b/store/db/postgres/user_setting.go index 0d8088b7..d53ae3cb 100644 --- a/store/db/postgres/user_setting.go +++ b/store/db/postgres/user_setting.go @@ -13,74 +13,7 @@ import ( "github.com/usememos/memos/store" ) -func (d *DB) UpsertUserSetting(ctx context.Context, upsert *store.UserSetting) (*store.UserSetting, error) { - // Construct the query using Squirrel - query, args, err := squirrel. - Insert("user_setting"). - Columns("user_id", "key", "value"). - Values(upsert.UserID, upsert.Key, upsert.Value). - PlaceholderFormat(squirrel.Dollar). - // no need to specify ON CONFLICT clause, as the primary key is (user_id, key) - ToSql() - if err != nil { - return nil, err - } - - // Execute the query - if _, err := d.db.ExecContext(ctx, query, args...); err != nil { - return nil, err - } - - return upsert, nil -} - -func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*store.UserSetting, error) { - // Start building the query - qb := squirrel.Select("user_id", "key", "value").From("user_setting").Where("1 = 1").PlaceholderFormat(squirrel.Dollar) - - // Add conditions based on the provided find parameters - if v := find.Key; v != "" { - qb = qb.Where(squirrel.Eq{"key": v}) - } - if v := find.UserID; v != nil { - qb = qb.Where(squirrel.Eq{"user_id": *v}) - } - - // Finalize the query - query, args, err := qb.ToSql() - if err != nil { - return nil, err - } - - // Execute the query - rows, err := d.db.QueryContext(ctx, query, args...) - if err != nil { - return nil, err - } - defer rows.Close() - - // Process the rows - userSettingList := make([]*store.UserSetting, 0) - for rows.Next() { - var userSetting store.UserSetting - if err := rows.Scan( - &userSetting.UserID, - &userSetting.Key, - &userSetting.Value, - ); err != nil { - return nil, err - } - userSettingList = append(userSettingList, &userSetting) - } - - if err := rows.Err(); err != nil { - return nil, err - } - - return userSettingList, nil -} - -func (d *DB) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) { +func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) { var valueString string if upsert.Key == storepb.UserSettingKey_USER_SETTING_ACCESS_TOKENS { valueBytes, err := protojson.Marshal(upsert.GetAccessTokens()) @@ -120,7 +53,7 @@ func (d *DB) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSettin return upsert, nil } -func (d *DB) ListUserSettingsV1(ctx context.Context, find *store.FindUserSettingV1) ([]*storepb.UserSetting, error) { +func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*storepb.UserSetting, error) { // Start building the query using Squirrel qb := squirrel.Select("user_id", "key", "value").From("user_setting").PlaceholderFormat(squirrel.Dollar) diff --git a/store/db/sqlite/migration/prod/0.18/00__webhook.sql b/store/db/sqlite/migration/prod/0.18/00__webhook.sql new file mode 100644 index 00000000..426ce9c2 --- /dev/null +++ b/store/db/sqlite/migration/prod/0.18/00__webhook.sql @@ -0,0 +1,12 @@ +-- webhook +CREATE TABLE webhook ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL', + creator_id INTEGER NOT NULL, + name TEXT NOT NULL, + url TEXT NOT NULL +); + +CREATE INDEX idx_webhook_creator_id ON webhook (creator_id); diff --git a/store/db/sqlite/migration/prod/0.18/01__user_setting.sql b/store/db/sqlite/migration/prod/0.18/01__user_setting.sql new file mode 100644 index 00000000..0d2769a5 --- /dev/null +++ b/store/db/sqlite/migration/prod/0.18/01__user_setting.sql @@ -0,0 +1,4 @@ +UPDATE user_setting SET key = 'USER_SETTING_LOCALE' WHERE key = 'locale'; +UPDATE user_setting SET key = 'USER_SETTING_APPEARANCE' WHERE key = 'appearance'; +UPDATE user_setting SET key = 'USER_SETTING_MEMO_VISIBILITY' WHERE key = 'memo-visibility'; +UPDATE user_setting SET key = 'USER_SETTING_TELEGRAM_USER_ID' WHERE key = 'telegram-user-id'; diff --git a/store/db/sqlite/user_setting.go b/store/db/sqlite/user_setting.go index 2cbcef5a..833072dd 100644 --- a/store/db/sqlite/user_setting.go +++ b/store/db/sqlite/user_setting.go @@ -12,66 +12,7 @@ import ( "github.com/usememos/memos/store" ) -func (d *DB) UpsertUserSetting(ctx context.Context, upsert *store.UserSetting) (*store.UserSetting, error) { - stmt := ` - INSERT INTO user_setting ( - user_id, key, value - ) - VALUES (?, ?, ?) - ON CONFLICT(user_id, key) DO UPDATE - SET value = EXCLUDED.value - ` - if _, err := d.db.ExecContext(ctx, stmt, upsert.UserID, upsert.Key, upsert.Value); err != nil { - return nil, err - } - - return upsert, nil -} - -func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*store.UserSetting, error) { - where, args := []string{"1 = 1"}, []any{} - - if v := find.Key; v != "" { - where, args = append(where, "key = ?"), append(args, v) - } - if v := find.UserID; v != nil { - where, args = append(where, "user_id = ?"), append(args, *find.UserID) - } - - query := ` - SELECT - user_id, - key, - value - FROM user_setting - WHERE ` + strings.Join(where, " AND ") - rows, err := d.db.QueryContext(ctx, query, args...) - if err != nil { - return nil, err - } - defer rows.Close() - - userSettingList := make([]*store.UserSetting, 0) - for rows.Next() { - var userSetting store.UserSetting - if err := rows.Scan( - &userSetting.UserID, - &userSetting.Key, - &userSetting.Value, - ); err != nil { - return nil, err - } - userSettingList = append(userSettingList, &userSetting) - } - - if err := rows.Err(); err != nil { - return nil, err - } - - return userSettingList, nil -} - -func (d *DB) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) { +func (d *DB) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) { stmt := ` INSERT INTO user_setting ( user_id, key, value @@ -106,7 +47,7 @@ func (d *DB) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSettin return upsert, nil } -func (d *DB) ListUserSettingsV1(ctx context.Context, find *store.FindUserSettingV1) ([]*storepb.UserSetting, error) { +func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*storepb.UserSetting, error) { where, args := []string{"1 = 1"}, []any{} if v := find.Key; v != storepb.UserSettingKey_USER_SETTING_KEY_UNSPECIFIED { diff --git a/store/driver.go b/store/driver.go index f5fcec49..5252e254 100644 --- a/store/driver.go +++ b/store/driver.go @@ -62,10 +62,8 @@ type Driver interface { DeleteUser(ctx context.Context, delete *DeleteUser) error // UserSetting model related methods. - UpsertUserSetting(ctx context.Context, upsert *UserSetting) (*UserSetting, error) - ListUserSettings(ctx context.Context, find *FindUserSetting) ([]*UserSetting, error) - UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) - ListUserSettingsV1(ctx context.Context, find *FindUserSettingV1) ([]*storepb.UserSetting, error) + UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) + ListUserSettings(ctx context.Context, find *FindUserSetting) ([]*storepb.UserSetting, error) // IdentityProvider model related methods. CreateIdentityProvider(ctx context.Context, create *IdentityProvider) (*IdentityProvider, error) diff --git a/store/user_setting.go b/store/user_setting.go index 7408ad4a..530f8500 100644 --- a/store/user_setting.go +++ b/store/user_setting.go @@ -6,66 +6,13 @@ import ( storepb "github.com/usememos/memos/proto/gen/store" ) -type UserSetting struct { - UserID int32 - Key string - Value string -} - type FindUserSetting struct { - UserID *int32 - Key string -} - -func (s *Store) UpsertUserSetting(ctx context.Context, upsert *UserSetting) (*UserSetting, error) { - userSetting, err := s.driver.UpsertUserSetting(ctx, upsert) - if err != nil { - return nil, err - } - - s.userSettingCache.Store(getUserSettingCacheKey(userSetting.UserID, userSetting.Key), userSetting) - return userSetting, nil -} - -func (s *Store) ListUserSettings(ctx context.Context, find *FindUserSetting) ([]*UserSetting, error) { - userSettingList, err := s.driver.ListUserSettings(ctx, find) - if err != nil { - return nil, err - } - - for _, userSetting := range userSettingList { - s.userSettingCache.Store(getUserSettingCacheKey(userSetting.UserID, userSetting.Key), userSetting) - } - return userSettingList, nil -} - -func (s *Store) GetUserSetting(ctx context.Context, find *FindUserSetting) (*UserSetting, error) { - if find.UserID != nil { - if cache, ok := s.userSettingCache.Load(getUserSettingCacheKey(*find.UserID, find.Key)); ok { - return cache.(*UserSetting), nil - } - } - - list, err := s.ListUserSettings(ctx, find) - if err != nil { - return nil, err - } - - if len(list) == 0 { - return nil, nil - } - - userSetting := list[0] - return userSetting, nil -} - -type FindUserSettingV1 struct { UserID *int32 Key storepb.UserSettingKey } func (s *Store) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) { - userSettingMessage, err := s.driver.UpsertUserSettingV1(ctx, upsert) + userSettingMessage, err := s.driver.UpsertUserSetting(ctx, upsert) if err != nil { return nil, err } @@ -74,8 +21,8 @@ func (s *Store) UpsertUserSettingV1(ctx context.Context, upsert *storepb.UserSet return userSettingMessage, nil } -func (s *Store) ListUserSettingsV1(ctx context.Context, find *FindUserSettingV1) ([]*storepb.UserSetting, error) { - userSettingList, err := s.driver.ListUserSettingsV1(ctx, find) +func (s *Store) ListUserSettingsV1(ctx context.Context, find *FindUserSetting) ([]*storepb.UserSetting, error) { + userSettingList, err := s.driver.ListUserSettings(ctx, find) if err != nil { return nil, err } @@ -86,7 +33,7 @@ func (s *Store) ListUserSettingsV1(ctx context.Context, find *FindUserSettingV1) return userSettingList, nil } -func (s *Store) GetUserSettingV1(ctx context.Context, find *FindUserSettingV1) (*storepb.UserSetting, error) { +func (s *Store) GetUserSettingV1(ctx context.Context, find *FindUserSetting) (*storepb.UserSetting, error) { if find.UserID != nil { if cache, ok := s.userSettingCache.Load(getUserSettingV1CacheKey(*find.UserID, find.Key.String())); ok { return cache.(*storepb.UserSetting), nil @@ -109,7 +56,7 @@ func (s *Store) GetUserSettingV1(ctx context.Context, find *FindUserSettingV1) ( // GetUserAccessTokens returns the access tokens of the user. func (s *Store) GetUserAccessTokens(ctx context.Context, userID int32) ([]*storepb.AccessTokensUserSetting_AccessToken, error) { - userSetting, err := s.GetUserSettingV1(ctx, &FindUserSettingV1{ + userSetting, err := s.GetUserSettingV1(ctx, &FindUserSetting{ UserID: &userID, Key: storepb.UserSettingKey_USER_SETTING_ACCESS_TOKENS, }) diff --git a/test/store/user_setting_test.go b/test/store/user_setting_test.go index c9341def..b06dc3fb 100644 --- a/test/store/user_setting_test.go +++ b/test/store/user_setting_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/require" + storepb "github.com/usememos/memos/proto/gen/store" "github.com/usememos/memos/store" ) @@ -14,19 +15,13 @@ func TestUserSettingStore(t *testing.T) { ts := NewTestingStore(ctx, t) user, err := createTestingHostUser(ctx, ts) require.NoError(t, err) - _, err = ts.UpsertUserSetting(ctx, &store.UserSetting{ - UserID: user.ID, - Key: "test_key", - Value: "test_value", + _, err = ts.UpsertUserSettingV1(ctx, &storepb.UserSetting{ + UserId: user.ID, + Key: storepb.UserSettingKey_USER_SETTING_LOCALE, + Value: &storepb.UserSetting_Locale{Locale: "en"}, }) require.NoError(t, err) - _, err = ts.UpsertUserSetting(ctx, &store.UserSetting{ - UserID: user.ID, - Key: "locale", - Value: "zh", - }) + list, err := ts.ListUserSettingsV1(ctx, &store.FindUserSetting{}) require.NoError(t, err) - list, err := ts.ListUserSettings(ctx, &store.FindUserSetting{}) - require.NoError(t, err) - require.Equal(t, 2, len(list)) + require.Equal(t, 1, len(list)) }