Commit e6e46049 authored by Johnny's avatar Johnny

refactor: general user setting

parent 9b159368
This diff is collapsed.
......@@ -6,53 +6,38 @@ import "google/protobuf/timestamp.proto";
option go_package = "gen/store";
enum UserSettingKey {
USER_SETTING_KEY_UNSPECIFIED = 0;
message UserSetting {
enum Key {
KEY_UNSPECIFIED = 0;
// General user settings.
GENERAL = 1;
// User authentication sessions.
SESSIONS = 2;
// Access tokens for the user.
ACCESS_TOKENS = 1;
// The locale of the user.
LOCALE = 2;
// The appearance of the user.
APPEARANCE = 3;
// The visibility of the memo.
MEMO_VISIBILITY = 4;
ACCESS_TOKENS = 3;
// The shortcuts of the user.
SHORTCUTS = 5;
// User authentication sessions.
SESSIONS = 6;
}
SHORTCUTS = 4;
}
message UserSetting {
int32 user_id = 1;
UserSettingKey key = 2;
oneof value {
AccessTokensUserSetting access_tokens = 3;
string locale = 4;
string appearance = 5;
string memo_visibility = 6;
ShortcutsUserSetting shortcuts = 7;
SessionsUserSetting sessions = 8;
}
}
message AccessTokensUserSetting {
message AccessToken {
// The access token is a JWT token.
// Including expiration time, issuer, etc.
string access_token = 1;
// A description for the access token.
string description = 2;
Key key = 2;
oneof value {
GeneralUserSetting general = 3;
SessionsUserSetting sessions = 4;
AccessTokensUserSetting access_tokens = 5;
ShortcutsUserSetting shortcuts = 6;
}
repeated AccessToken access_tokens = 1;
}
message ShortcutsUserSetting {
message Shortcut {
string id = 1;
string title = 2;
string filter = 3;
}
repeated Shortcut shortcuts = 1;
message GeneralUserSetting {
// The user's locale.
string locale = 1;
// The user's appearance setting.
string appearance = 2;
// The user's memo visibility setting.
string memo_visibility = 3;
}
message SessionsUserSetting {
......@@ -84,3 +69,23 @@ message SessionsUserSetting {
repeated Session sessions = 1;
}
message AccessTokensUserSetting {
message AccessToken {
// The access token is a JWT token.
// Including expiration time, issuer, etc.
string access_token = 1;
// A description for the access token.
string description = 2;
}
repeated AccessToken access_tokens = 1;
}
message ShortcutsUserSetting {
message Shortcut {
string id = 1;
string title = 2;
string filter = 3;
}
repeated Shortcut shortcuts = 1;
}
......@@ -59,7 +59,7 @@ func (s *APIV1Service) ListShortcuts(ctx context.Context, request *v1pb.ListShor
userSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storepb.UserSettingKey_SHORTCUTS,
Key: storepb.UserSetting_SHORTCUTS,
})
if err != nil {
return nil, err
......@@ -101,7 +101,7 @@ func (s *APIV1Service) GetShortcut(ctx context.Context, request *v1pb.GetShortcu
userSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storepb.UserSettingKey_SHORTCUTS,
Key: storepb.UserSetting_SHORTCUTS,
})
if err != nil {
return nil, err
......@@ -159,7 +159,7 @@ func (s *APIV1Service) CreateShortcut(ctx context.Context, request *v1pb.CreateS
userSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storepb.UserSettingKey_SHORTCUTS,
Key: storepb.UserSetting_SHORTCUTS,
})
if err != nil {
return nil, err
......@@ -167,7 +167,7 @@ func (s *APIV1Service) CreateShortcut(ctx context.Context, request *v1pb.CreateS
if userSetting == nil {
userSetting = &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_SHORTCUTS,
Key: storepb.UserSetting_SHORTCUTS,
Value: &storepb.UserSetting_Shortcuts{
Shortcuts: &storepb.ShortcutsUserSetting{
Shortcuts: []*storepb.ShortcutsUserSetting_Shortcut{},
......@@ -215,7 +215,7 @@ func (s *APIV1Service) UpdateShortcut(ctx context.Context, request *v1pb.UpdateS
userSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storepb.UserSettingKey_SHORTCUTS,
Key: storepb.UserSetting_SHORTCUTS,
})
if err != nil {
return nil, err
......@@ -284,7 +284,7 @@ func (s *APIV1Service) DeleteShortcut(ctx context.Context, request *v1pb.DeleteS
userSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storepb.UserSettingKey_SHORTCUTS,
Key: storepb.UserSetting_SHORTCUTS,
})
if err != nil {
return nil, err
......
......@@ -364,12 +364,13 @@ func (s *APIV1Service) GetUserSetting(ctx context.Context, request *v1pb.GetUser
userSettingMessage.Name = fmt.Sprintf("users/%d", userID)
for _, setting := range userSettings {
if setting.Key == storepb.UserSettingKey_LOCALE {
userSettingMessage.Locale = setting.GetLocale()
} else if setting.Key == storepb.UserSettingKey_APPEARANCE {
userSettingMessage.Appearance = setting.GetAppearance()
} else if setting.Key == storepb.UserSettingKey_MEMO_VISIBILITY {
userSettingMessage.MemoVisibility = setting.GetMemoVisibility()
if setting.Key == storepb.UserSetting_GENERAL {
general := setting.GetGeneral()
if general != nil {
userSettingMessage.Locale = general.Locale
userSettingMessage.Appearance = general.Appearance
userSettingMessage.MemoVisibility = general.MemoVisibility
}
}
}
return userSettingMessage, nil
......@@ -396,41 +397,54 @@ func (s *APIV1Service) UpdateUserSetting(ctx context.Context, request *v1pb.Upda
return nil, status.Errorf(codes.InvalidArgument, "update mask is empty")
}
// Get the current general setting
existingGeneralSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storepb.UserSetting_GENERAL,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get existing general setting: %v", err)
}
// Create or update the general setting
generalSetting := &storepb.GeneralUserSetting{
Locale: "en",
Appearance: "system",
MemoVisibility: "PRIVATE",
}
// If there's an existing setting, use its values as defaults
if existingGeneralSetting != nil && existingGeneralSetting.GetGeneral() != nil {
existing := existingGeneralSetting.GetGeneral()
generalSetting.Locale = existing.Locale
generalSetting.Appearance = existing.Appearance
generalSetting.MemoVisibility = existing.MemoVisibility
}
// Apply updates based on the update mask
for _, field := range request.UpdateMask.Paths {
if field == "locale" {
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_LOCALE,
Value: &storepb.UserSetting_Locale{
Locale: request.Setting.Locale,
},
}); err != nil {
return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err)
switch field {
case "locale":
generalSetting.Locale = request.Setting.Locale
case "appearance":
generalSetting.Appearance = request.Setting.Appearance
case "memo_visibility":
generalSetting.MemoVisibility = request.Setting.MemoVisibility
default:
return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field)
}
} else if field == "appearance" {
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_APPEARANCE,
Value: &storepb.UserSetting_Appearance{
Appearance: request.Setting.Appearance,
},
}); err != nil {
return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err)
}
} else if field == "memo_visibility" {
// Upsert the general setting
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_MEMO_VISIBILITY,
Value: &storepb.UserSetting_MemoVisibility{
MemoVisibility: request.Setting.MemoVisibility,
Key: storepb.UserSetting_GENERAL,
Value: &storepb.UserSetting_General{
General: generalSetting,
},
}); err != nil {
return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err)
}
} else {
return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field)
}
}
return s.GetUserSetting(ctx, &v1pb.GetUserSettingRequest{Name: request.Setting.Name})
}
......@@ -595,7 +609,7 @@ func (s *APIV1Service) DeleteUserAccessToken(ctx context.Context, request *v1pb.
}
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: currentUser.ID,
Key: storepb.UserSettingKey_ACCESS_TOKENS,
Key: storepb.UserSetting_ACCESS_TOKENS,
Value: &storepb.UserSetting_AccessTokens{
AccessTokens: &storepb.AccessTokensUserSetting{
AccessTokens: updatedUserAccessTokens,
......@@ -722,7 +736,7 @@ func (s *APIV1Service) UpsertAccessTokenToStore(ctx context.Context, user *store
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: user.ID,
Key: storepb.UserSettingKey_ACCESS_TOKENS,
Key: storepb.UserSetting_ACCESS_TOKENS,
Value: &storepb.UserSetting_AccessTokens{
AccessTokens: &storepb.AccessTokensUserSetting{
AccessTokens: userAccessTokens,
......
......@@ -19,7 +19,7 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *store.UserSetting) (
func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*store.UserSetting, error) {
where, args := []string{"1 = 1"}, []any{}
if v := find.Key; v != storepb.UserSettingKey_USER_SETTING_KEY_UNSPECIFIED {
if v := find.Key; v != storepb.UserSetting_KEY_UNSPECIFIED {
where, args = append(where, "`key` = ?"), append(args, v.String())
}
if v := find.UserID; v != nil {
......@@ -44,7 +44,7 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
); err != nil {
return nil, err
}
userSetting.Key = storepb.UserSettingKey(storepb.UserSettingKey_value[keyString])
userSetting.Key = storepb.UserSetting_Key(storepb.UserSetting_Key_value[keyString])
userSettingList = append(userSettingList, userSetting)
}
......
......@@ -26,7 +26,7 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *store.UserSetting) (
func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*store.UserSetting, error) {
where, args := []string{"1 = 1"}, []any{}
if v := find.Key; v != storepb.UserSettingKey_USER_SETTING_KEY_UNSPECIFIED {
if v := find.Key; v != storepb.UserSetting_KEY_UNSPECIFIED {
where, args = append(where, "key = "+placeholder(len(args)+1)), append(args, v.String())
}
if v := find.UserID; v != nil {
......@@ -57,7 +57,7 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
); err != nil {
return nil, err
}
userSetting.Key = storepb.UserSettingKey(storepb.UserSettingKey_value[keyString])
userSetting.Key = storepb.UserSetting_Key(storepb.UserSetting_Key_value[keyString])
userSettingList = append(userSettingList, userSetting)
}
......
......@@ -26,7 +26,7 @@ func (d *DB) UpsertUserSetting(ctx context.Context, upsert *store.UserSetting) (
func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting) ([]*store.UserSetting, error) {
where, args := []string{"1 = 1"}, []any{}
if v := find.Key; v != storepb.UserSettingKey_USER_SETTING_KEY_UNSPECIFIED {
if v := find.Key; v != storepb.UserSetting_KEY_UNSPECIFIED {
where, args = append(where, "key = ?"), append(args, v.String())
}
if v := find.UserID; v != nil {
......@@ -57,7 +57,7 @@ func (d *DB) ListUserSettings(ctx context.Context, find *store.FindUserSetting)
); err != nil {
return nil, err
}
userSetting.Key = storepb.UserSettingKey(storepb.UserSettingKey_value[keyString])
userSetting.Key = storepb.UserSetting_Key(storepb.UserSetting_Key_value[keyString])
userSettingList = append(userSettingList, userSetting)
}
if err := rows.Err(); err != nil {
......
......@@ -17,8 +17,8 @@ func TestUserSettingStore(t *testing.T) {
require.NoError(t, err)
_, err = ts.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: user.ID,
Key: storepb.UserSettingKey_LOCALE,
Value: &storepb.UserSetting_Locale{Locale: "en"},
Key: storepb.UserSetting_GENERAL,
Value: &storepb.UserSetting_General{General: &storepb.GeneralUserSetting{Locale: "en"}},
})
require.NoError(t, err)
list, err := ts.ListUserSettings(ctx, &store.FindUserSetting{})
......
......@@ -12,13 +12,13 @@ import (
type UserSetting struct {
UserID int32
Key storepb.UserSettingKey
Key storepb.UserSetting_Key
Value string
}
type FindUserSetting struct {
UserID *int32
Key storepb.UserSettingKey
Key storepb.UserSetting_Key
}
func (s *Store) UpsertUserSetting(ctx context.Context, upsert *storepb.UserSetting) (*storepb.UserSetting, error) {
......@@ -93,7 +93,7 @@ func (s *Store) GetUserSetting(ctx context.Context, find *FindUserSetting) (*sto
func (s *Store) GetUserAccessTokens(ctx context.Context, userID int32) ([]*storepb.AccessTokensUserSetting_AccessToken, error) {
userSetting, err := s.GetUserSetting(ctx, &FindUserSetting{
UserID: &userID,
Key: storepb.UserSettingKey_ACCESS_TOKENS,
Key: storepb.UserSetting_ACCESS_TOKENS,
})
if err != nil {
return nil, err
......@@ -122,7 +122,7 @@ func (s *Store) RemoveUserAccessToken(ctx context.Context, userID int32, token s
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_ACCESS_TOKENS,
Key: storepb.UserSetting_ACCESS_TOKENS,
Value: &storepb.UserSetting_AccessTokens{
AccessTokens: &storepb.AccessTokensUserSetting{
AccessTokens: newAccessTokens,
......@@ -137,7 +137,7 @@ func (s *Store) RemoveUserAccessToken(ctx context.Context, userID int32, token s
func (s *Store) GetUserSessions(ctx context.Context, userID int32) ([]*storepb.SessionsUserSetting_Session, error) {
userSetting, err := s.GetUserSetting(ctx, &FindUserSetting{
UserID: &userID,
Key: storepb.UserSettingKey_SESSIONS,
Key: storepb.UserSetting_SESSIONS,
})
if err != nil {
return nil, err
......@@ -166,7 +166,7 @@ func (s *Store) RemoveUserSession(ctx context.Context, userID int32, sessionID s
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_SESSIONS,
Key: storepb.UserSetting_SESSIONS,
Value: &storepb.UserSetting_Sessions{
Sessions: &storepb.SessionsUserSetting{
Sessions: newSessions,
......@@ -203,7 +203,7 @@ func (s *Store) AddUserSession(ctx context.Context, userID int32, session *store
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_SESSIONS,
Key: storepb.UserSetting_SESSIONS,
Value: &storepb.UserSetting_Sessions{
Sessions: &storepb.SessionsUserSetting{
Sessions: updatedSessions,
......@@ -230,7 +230,7 @@ func (s *Store) UpdateUserSessionLastAccessed(ctx context.Context, userID int32,
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_SESSIONS,
Key: storepb.UserSetting_SESSIONS,
Value: &storepb.UserSetting_Sessions{
Sessions: &storepb.SessionsUserSetting{
Sessions: sessions,
......@@ -248,30 +248,30 @@ func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) {
}
switch raw.Key {
case storepb.UserSettingKey_ACCESS_TOKENS:
case storepb.UserSetting_ACCESS_TOKENS:
accessTokensUserSetting := &storepb.AccessTokensUserSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(raw.Value), accessTokensUserSetting); err != nil {
return nil, err
}
userSetting.Value = &storepb.UserSetting_AccessTokens{AccessTokens: accessTokensUserSetting}
case storepb.UserSettingKey_SESSIONS:
case storepb.UserSetting_SESSIONS:
sessionsUserSetting := &storepb.SessionsUserSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(raw.Value), sessionsUserSetting); err != nil {
return nil, err
}
userSetting.Value = &storepb.UserSetting_Sessions{Sessions: sessionsUserSetting}
case storepb.UserSettingKey_SHORTCUTS:
case storepb.UserSetting_SHORTCUTS:
shortcutsUserSetting := &storepb.ShortcutsUserSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(raw.Value), shortcutsUserSetting); err != nil {
return nil, err
}
userSetting.Value = &storepb.UserSetting_Shortcuts{Shortcuts: shortcutsUserSetting}
case storepb.UserSettingKey_LOCALE:
userSetting.Value = &storepb.UserSetting_Locale{Locale: raw.Value}
case storepb.UserSettingKey_APPEARANCE:
userSetting.Value = &storepb.UserSetting_Appearance{Appearance: raw.Value}
case storepb.UserSettingKey_MEMO_VISIBILITY:
userSetting.Value = &storepb.UserSetting_MemoVisibility{MemoVisibility: raw.Value}
case storepb.UserSetting_GENERAL:
generalUserSetting := &storepb.GeneralUserSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(raw.Value), generalUserSetting); err != nil {
return nil, err
}
userSetting.Value = &storepb.UserSetting_General{General: generalUserSetting}
default:
return nil, nil
}
......@@ -285,33 +285,34 @@ func convertUserSettingToRaw(userSetting *storepb.UserSetting) (*UserSetting, er
}
switch userSetting.Key {
case storepb.UserSettingKey_ACCESS_TOKENS:
case storepb.UserSetting_ACCESS_TOKENS:
accessTokensUserSetting := userSetting.GetAccessTokens()
value, err := protojson.Marshal(accessTokensUserSetting)
if err != nil {
return nil, err
}
raw.Value = string(value)
case storepb.UserSettingKey_SESSIONS:
case storepb.UserSetting_SESSIONS:
sessionsUserSetting := userSetting.GetSessions()
value, err := protojson.Marshal(sessionsUserSetting)
if err != nil {
return nil, err
}
raw.Value = string(value)
case storepb.UserSettingKey_SHORTCUTS:
case storepb.UserSetting_SHORTCUTS:
shortcutsUserSetting := userSetting.GetShortcuts()
value, err := protojson.Marshal(shortcutsUserSetting)
if err != nil {
return nil, err
}
raw.Value = string(value)
case storepb.UserSettingKey_LOCALE:
raw.Value = userSetting.GetLocale()
case storepb.UserSettingKey_APPEARANCE:
raw.Value = userSetting.GetAppearance()
case storepb.UserSettingKey_MEMO_VISIBILITY:
raw.Value = userSetting.GetMemoVisibility()
case storepb.UserSetting_GENERAL:
generalUserSetting := userSetting.GetGeneral()
value, err := protojson.Marshal(generalUserSetting)
if err != nil {
return nil, err
}
raw.Value = string(value)
default:
return nil, errors.Errorf("unsupported user setting key: %v", userSetting.Key)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment