|
|
|
@ -249,7 +249,8 @@ func (s *APIV1Service) UpdateUser(ctx context.Context, request *v1pb.UpdateUserR
|
|
|
|
|
return nil, status.Errorf(codes.Internal, "failed to get workspace general setting: %v", err)
|
|
|
|
|
}
|
|
|
|
|
for _, field := range request.UpdateMask.Paths {
|
|
|
|
|
if field == "username" {
|
|
|
|
|
switch field {
|
|
|
|
|
case "username":
|
|
|
|
|
if workspaceGeneralSetting.DisallowChangeUsername {
|
|
|
|
|
return nil, status.Errorf(codes.PermissionDenied, "permission denied: disallow change username")
|
|
|
|
|
}
|
|
|
|
@ -257,35 +258,35 @@ func (s *APIV1Service) UpdateUser(ctx context.Context, request *v1pb.UpdateUserR
|
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "invalid username: %s", request.User.Username)
|
|
|
|
|
}
|
|
|
|
|
update.Username = &request.User.Username
|
|
|
|
|
} else if field == "display_name" {
|
|
|
|
|
case "display_name":
|
|
|
|
|
if workspaceGeneralSetting.DisallowChangeNickname {
|
|
|
|
|
return nil, status.Errorf(codes.PermissionDenied, "permission denied: disallow change nickname")
|
|
|
|
|
}
|
|
|
|
|
update.Nickname = &request.User.DisplayName
|
|
|
|
|
} else if field == "email" {
|
|
|
|
|
case "email":
|
|
|
|
|
update.Email = &request.User.Email
|
|
|
|
|
} else if field == "avatar_url" {
|
|
|
|
|
case "avatar_url":
|
|
|
|
|
update.AvatarURL = &request.User.AvatarUrl
|
|
|
|
|
} else if field == "description" {
|
|
|
|
|
case "description":
|
|
|
|
|
update.Description = &request.User.Description
|
|
|
|
|
} else if field == "role" {
|
|
|
|
|
case "role":
|
|
|
|
|
// Only allow admin to update role.
|
|
|
|
|
if currentUser.Role != store.RoleAdmin && currentUser.Role != store.RoleHost {
|
|
|
|
|
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
|
|
|
|
}
|
|
|
|
|
role := convertUserRoleToStore(request.User.Role)
|
|
|
|
|
update.Role = &role
|
|
|
|
|
} else if field == "password" {
|
|
|
|
|
case "password":
|
|
|
|
|
passwordHash, err := bcrypt.GenerateFromPassword([]byte(request.User.Password), bcrypt.DefaultCost)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, echo.NewHTTPError(http.StatusInternalServerError, "failed to generate password hash").SetInternal(err)
|
|
|
|
|
}
|
|
|
|
|
passwordHashStr := string(passwordHash)
|
|
|
|
|
update.PasswordHash = &passwordHashStr
|
|
|
|
|
} else if field == "state" {
|
|
|
|
|
case "state":
|
|
|
|
|
rowStatus := convertStateToStore(request.User.State)
|
|
|
|
|
update.RowStatus = &rowStatus
|
|
|
|
|
} else {
|
|
|
|
|
default:
|
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -334,6 +335,7 @@ func getDefaultUserSetting() *v1pb.UserSetting {
|
|
|
|
|
Locale: "en",
|
|
|
|
|
Appearance: "system",
|
|
|
|
|
MemoVisibility: "PRIVATE",
|
|
|
|
|
Theme: "",
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -370,9 +372,24 @@ func (s *APIV1Service) GetUserSetting(ctx context.Context, request *v1pb.GetUser
|
|
|
|
|
userSettingMessage.Locale = general.Locale
|
|
|
|
|
userSettingMessage.Appearance = general.Appearance
|
|
|
|
|
userSettingMessage.MemoVisibility = general.MemoVisibility
|
|
|
|
|
userSettingMessage.Theme = general.Theme
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Backfill theme if empty: use workspace theme or default to "default"
|
|
|
|
|
if userSettingMessage.Theme == "" {
|
|
|
|
|
workspaceGeneralSetting, err := s.Store.GetWorkspaceGeneralSetting(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, status.Errorf(codes.Internal, "failed to get workspace general setting: %v", err)
|
|
|
|
|
}
|
|
|
|
|
workspaceTheme := workspaceGeneralSetting.Theme
|
|
|
|
|
if workspaceTheme == "" {
|
|
|
|
|
workspaceTheme = "default"
|
|
|
|
|
}
|
|
|
|
|
userSettingMessage.Theme = workspaceTheme
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return userSettingMessage, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -411,6 +428,7 @@ func (s *APIV1Service) UpdateUserSetting(ctx context.Context, request *v1pb.Upda
|
|
|
|
|
Locale: "en",
|
|
|
|
|
Appearance: "system",
|
|
|
|
|
MemoVisibility: "PRIVATE",
|
|
|
|
|
Theme: "",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there's an existing setting, use its values as defaults
|
|
|
|
@ -419,6 +437,7 @@ func (s *APIV1Service) UpdateUserSetting(ctx context.Context, request *v1pb.Upda
|
|
|
|
|
generalSetting.Locale = existing.Locale
|
|
|
|
|
generalSetting.Appearance = existing.Appearance
|
|
|
|
|
generalSetting.MemoVisibility = existing.MemoVisibility
|
|
|
|
|
generalSetting.Theme = existing.Theme
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply updates based on the update mask
|
|
|
|
@ -430,6 +449,8 @@ func (s *APIV1Service) UpdateUserSetting(ctx context.Context, request *v1pb.Upda
|
|
|
|
|
generalSetting.Appearance = request.Setting.Appearance
|
|
|
|
|
case "memo_visibility":
|
|
|
|
|
generalSetting.MemoVisibility = request.Setting.MemoVisibility
|
|
|
|
|
case "theme":
|
|
|
|
|
generalSetting.Theme = request.Setting.Theme
|
|
|
|
|
default:
|
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field)
|
|
|
|
|
}
|
|
|
|
|