From 9ef0f8a901d2799722002844772f4467a16b4be9 Mon Sep 17 00:00:00 2001 From: boojack Date: Sun, 30 Jul 2023 09:53:24 +0800 Subject: [PATCH] feat: add user setting field (#2054) --- api/v2/user_service.go | 57 +++- proto/api/v2/user_service.proto | 42 +++ proto/gen/api/v2/README.md | 67 +++++ proto/gen/api/v2/user_service.pb.go | 452 ++++++++++++++++++++++++---- server/backup.go | 18 +- server/server.go | 13 +- 6 files changed, 581 insertions(+), 68 deletions(-) diff --git a/api/v2/user_service.go b/api/v2/user_service.go index 37e8db91..f62e3748 100644 --- a/api/v2/user_service.go +++ b/api/v2/user_service.go @@ -23,7 +23,6 @@ func NewUserService(store *store.Store) *UserService { } func (s *UserService) GetUser(ctx context.Context, request *apiv2pb.GetUserRequest) (*apiv2pb.GetUserResponse, error) { - println("GetUser", request.Name) user, err := s.Store.GetUser(ctx, &store.FindUser{ Username: &request.Name, }) @@ -38,6 +37,18 @@ func (s *UserService) GetUser(ctx context.Context, request *apiv2pb.GetUserReque // Data desensitization. userMessage.OpenId = "" + userUID := int(userMessage.Id) + userSettings, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{ + UserID: &userUID, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list user settings: %v", err) + } + // TODO: check the access permission for user settings. + for _, userSetting := range userSettings { + userMessage.Settings = append(userMessage.Settings, convertUserSettingFromStore(userSetting)) + } + response := &apiv2pb.GetUserResponse{ User: userMessage, } @@ -56,6 +67,7 @@ func convertUserFromStore(user *store.User) *apiv2pb.User { Nickname: user.Nickname, OpenId: user.OpenID, AvatarUrl: user.AvatarURL, + Settings: []*apiv2pb.UserSetting{}, } } @@ -71,3 +83,46 @@ func convertUserRoleFromStore(role store.Role) apiv2pb.Role { return apiv2pb.Role_ROLE_UNSPECIFIED } } + +func convertUserSettingFromStore(userSetting *store.UserSetting) *apiv2pb.UserSetting { + userSettingKey := apiv2pb.UserSetting_KEY_UNSPECIFIED + userSettingValue := &apiv2pb.UserSettingValue{} + switch userSetting.Key { + case "locale": + userSettingKey = apiv2pb.UserSetting_LOCALE + userSettingValue.Value = &apiv2pb.UserSettingValue_StringValue{ + StringValue: userSetting.Value, + } + case "appearance": + userSettingKey = apiv2pb.UserSetting_APPEARANCE + userSettingValue.Value = &apiv2pb.UserSettingValue_StringValue{ + StringValue: userSetting.Value, + } + case "memo-visibility": + userSettingKey = apiv2pb.UserSetting_MEMO_VISIBILITY + userSettingValue.Value = &apiv2pb.UserSettingValue_VisibilityValue{ + VisibilityValue: convertVisibilityFromString(userSetting.Value), + } + case "telegram-user-id": + userSettingKey = apiv2pb.UserSetting_TELEGRAM_USER_ID + userSettingValue.Value = &apiv2pb.UserSettingValue_StringValue{ + StringValue: userSetting.Value, + } + } + return &apiv2pb.UserSetting{ + UserId: int32(userSetting.UserID), + Key: userSettingKey, + Value: userSettingValue, + } +} + +func convertVisibilityFromString(visibility string) apiv2pb.Visibility { + switch visibility { + case "public": + return apiv2pb.Visibility_PUBLIC + case "private": + return apiv2pb.Visibility_PRIVATE + default: + return apiv2pb.Visibility_VISIBILITY_UNSPECIFIED + } +} diff --git a/proto/api/v2/user_service.proto b/proto/api/v2/user_service.proto index b2e22cb7..5777aaf9 100644 --- a/proto/api/v2/user_service.proto +++ b/proto/api/v2/user_service.proto @@ -35,6 +35,8 @@ message User { string open_id = 9; string avatar_url = 10; + + repeated UserSetting settings = 11; } enum Role { @@ -54,3 +56,43 @@ message GetUserRequest { message GetUserResponse { User user = 1; } + +message UserSetting { + // The user id of the setting. + int32 user_id = 1; + + enum Key { + KEY_UNSPECIFIED = 0; + // The preferred locale. + LOCALE = 1; + // The preferred appearance. + APPEARANCE = 2; + // The default visibility of the memo when creating a new memo. + MEMO_VISIBILITY = 3; + // User's telegram id + TELEGRAM_USER_ID = 4; + } + // The key of the setting. + Key key = 2; + + // The value of the setting. + UserSettingValue value = 3; +} + +message UserSettingValue { + oneof value { + // Default value as a string. + string string_value = 1; + Visibility visibility_value = 2; + } +} + +enum Visibility { + VISIBILITY_UNSPECIFIED = 0; + + PRIVATE = 1; + + PROTECTED = 2; + + PUBLIC = 3; +} diff --git a/proto/gen/api/v2/README.md b/proto/gen/api/v2/README.md index cc858285..cad494d6 100644 --- a/proto/gen/api/v2/README.md +++ b/proto/gen/api/v2/README.md @@ -17,8 +17,12 @@ - [GetUserRequest](#memos-api-v2-GetUserRequest) - [GetUserResponse](#memos-api-v2-GetUserResponse) - [User](#memos-api-v2-User) + - [UserSetting](#memos-api-v2-UserSetting) + - [UserSettingValue](#memos-api-v2-UserSettingValue) - [Role](#memos-api-v2-Role) + - [UserSetting.Key](#memos-api-v2-UserSetting-Key) + - [Visibility](#memos-api-v2-Visibility) - [UserService](#memos-api-v2-UserService) @@ -182,6 +186,40 @@ | nickname | [string](#string) | | | | open_id | [string](#string) | | | | avatar_url | [string](#string) | | | +| settings | [UserSetting](#memos-api-v2-UserSetting) | repeated | | + + + + + + + + +### UserSetting + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| user_id | [int32](#int32) | | The user id of the setting. | +| key | [UserSetting.Key](#memos-api-v2-UserSetting-Key) | | The key of the setting. | +| value | [UserSettingValue](#memos-api-v2-UserSettingValue) | | The value of the setting. | + + + + + + + + +### UserSettingValue + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| string_value | [string](#string) | | Default value as a string. | +| visibility_value | [Visibility](#memos-api-v2-Visibility) | | | @@ -203,6 +241,35 @@ | USER | 3 | | + + + +### UserSetting.Key + + +| Name | Number | Description | +| ---- | ------ | ----------- | +| KEY_UNSPECIFIED | 0 | | +| LOCALE | 1 | The preferred locale. | +| APPEARANCE | 2 | The preferred appearance. | +| MEMO_VISIBILITY | 3 | The default visibility of the memo when creating a new memo. | +| TELEGRAM_USER_ID | 4 | User's telegram id | + + + + + +### Visibility + + +| Name | Number | Description | +| ---- | ------ | ----------- | +| VISIBILITY_UNSPECIFIED | 0 | | +| PRIVATE | 1 | | +| PROTECTED | 2 | | +| PUBLIC | 3 | | + + diff --git a/proto/gen/api/v2/user_service.pb.go b/proto/gen/api/v2/user_service.pb.go index 87c02870..164afc5e 100644 --- a/proto/gen/api/v2/user_service.pb.go +++ b/proto/gen/api/v2/user_service.pb.go @@ -73,21 +73,133 @@ func (Role) EnumDescriptor() ([]byte, []int) { return file_api_v2_user_service_proto_rawDescGZIP(), []int{0} } +type Visibility int32 + +const ( + Visibility_VISIBILITY_UNSPECIFIED Visibility = 0 + Visibility_PRIVATE Visibility = 1 + Visibility_PROTECTED Visibility = 2 + Visibility_PUBLIC Visibility = 3 +) + +// Enum value maps for Visibility. +var ( + Visibility_name = map[int32]string{ + 0: "VISIBILITY_UNSPECIFIED", + 1: "PRIVATE", + 2: "PROTECTED", + 3: "PUBLIC", + } + Visibility_value = map[string]int32{ + "VISIBILITY_UNSPECIFIED": 0, + "PRIVATE": 1, + "PROTECTED": 2, + "PUBLIC": 3, + } +) + +func (x Visibility) Enum() *Visibility { + p := new(Visibility) + *p = x + return p +} + +func (x Visibility) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Visibility) Descriptor() protoreflect.EnumDescriptor { + return file_api_v2_user_service_proto_enumTypes[1].Descriptor() +} + +func (Visibility) Type() protoreflect.EnumType { + return &file_api_v2_user_service_proto_enumTypes[1] +} + +func (x Visibility) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Visibility.Descriptor instead. +func (Visibility) EnumDescriptor() ([]byte, []int) { + return file_api_v2_user_service_proto_rawDescGZIP(), []int{1} +} + +type UserSetting_Key int32 + +const ( + UserSetting_KEY_UNSPECIFIED UserSetting_Key = 0 + // The preferred locale. + UserSetting_LOCALE UserSetting_Key = 1 + // The preferred appearance. + UserSetting_APPEARANCE UserSetting_Key = 2 + // The default visibility of the memo when creating a new memo. + UserSetting_MEMO_VISIBILITY UserSetting_Key = 3 + // User's telegram id + UserSetting_TELEGRAM_USER_ID UserSetting_Key = 4 +) + +// Enum value maps for UserSetting_Key. +var ( + UserSetting_Key_name = map[int32]string{ + 0: "KEY_UNSPECIFIED", + 1: "LOCALE", + 2: "APPEARANCE", + 3: "MEMO_VISIBILITY", + 4: "TELEGRAM_USER_ID", + } + UserSetting_Key_value = map[string]int32{ + "KEY_UNSPECIFIED": 0, + "LOCALE": 1, + "APPEARANCE": 2, + "MEMO_VISIBILITY": 3, + "TELEGRAM_USER_ID": 4, + } +) + +func (x UserSetting_Key) Enum() *UserSetting_Key { + p := new(UserSetting_Key) + *p = x + return p +} + +func (x UserSetting_Key) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UserSetting_Key) Descriptor() protoreflect.EnumDescriptor { + return file_api_v2_user_service_proto_enumTypes[2].Descriptor() +} + +func (UserSetting_Key) Type() protoreflect.EnumType { + return &file_api_v2_user_service_proto_enumTypes[2] +} + +func (x UserSetting_Key) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UserSetting_Key.Descriptor instead. +func (UserSetting_Key) EnumDescriptor() ([]byte, []int) { + return file_api_v2_user_service_proto_rawDescGZIP(), []int{3, 0} +} + type User struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - RowStatus RowStatus `protobuf:"varint,2,opt,name=row_status,json=rowStatus,proto3,enum=memos.api.v2.RowStatus" json:"row_status,omitempty"` - CreatedTs int64 `protobuf:"varint,3,opt,name=created_ts,json=createdTs,proto3" json:"created_ts,omitempty"` - UpdatedTs int64 `protobuf:"varint,4,opt,name=updated_ts,json=updatedTs,proto3" json:"updated_ts,omitempty"` - Username string `protobuf:"bytes,5,opt,name=username,proto3" json:"username,omitempty"` - Role Role `protobuf:"varint,6,opt,name=role,proto3,enum=memos.api.v2.Role" json:"role,omitempty"` - Email string `protobuf:"bytes,7,opt,name=email,proto3" json:"email,omitempty"` - Nickname string `protobuf:"bytes,8,opt,name=nickname,proto3" json:"nickname,omitempty"` - OpenId string `protobuf:"bytes,9,opt,name=open_id,json=openId,proto3" json:"open_id,omitempty"` - AvatarUrl string `protobuf:"bytes,10,opt,name=avatar_url,json=avatarUrl,proto3" json:"avatar_url,omitempty"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + RowStatus RowStatus `protobuf:"varint,2,opt,name=row_status,json=rowStatus,proto3,enum=memos.api.v2.RowStatus" json:"row_status,omitempty"` + CreatedTs int64 `protobuf:"varint,3,opt,name=created_ts,json=createdTs,proto3" json:"created_ts,omitempty"` + UpdatedTs int64 `protobuf:"varint,4,opt,name=updated_ts,json=updatedTs,proto3" json:"updated_ts,omitempty"` + Username string `protobuf:"bytes,5,opt,name=username,proto3" json:"username,omitempty"` + Role Role `protobuf:"varint,6,opt,name=role,proto3,enum=memos.api.v2.Role" json:"role,omitempty"` + Email string `protobuf:"bytes,7,opt,name=email,proto3" json:"email,omitempty"` + Nickname string `protobuf:"bytes,8,opt,name=nickname,proto3" json:"nickname,omitempty"` + OpenId string `protobuf:"bytes,9,opt,name=open_id,json=openId,proto3" json:"open_id,omitempty"` + AvatarUrl string `protobuf:"bytes,10,opt,name=avatar_url,json=avatarUrl,proto3" json:"avatar_url,omitempty"` + Settings []*UserSetting `protobuf:"bytes,11,rep,name=settings,proto3" json:"settings,omitempty"` } func (x *User) Reset() { @@ -192,6 +304,13 @@ func (x *User) GetAvatarUrl() string { return "" } +func (x *User) GetSettings() []*UserSetting { + if x != nil { + return x.Settings + } + return nil +} + type GetUserRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -286,6 +405,154 @@ func (x *GetUserResponse) GetUser() *User { return nil } +type UserSetting struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The user id of the setting. + UserId int32 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + // The key of the setting. + Key UserSetting_Key `protobuf:"varint,2,opt,name=key,proto3,enum=memos.api.v2.UserSetting_Key" json:"key,omitempty"` + // The value of the setting. + Value *UserSettingValue `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *UserSetting) Reset() { + *x = UserSetting{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_user_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserSetting) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserSetting) ProtoMessage() {} + +func (x *UserSetting) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_user_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserSetting.ProtoReflect.Descriptor instead. +func (*UserSetting) Descriptor() ([]byte, []int) { + return file_api_v2_user_service_proto_rawDescGZIP(), []int{3} +} + +func (x *UserSetting) GetUserId() int32 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *UserSetting) GetKey() UserSetting_Key { + if x != nil { + return x.Key + } + return UserSetting_KEY_UNSPECIFIED +} + +func (x *UserSetting) GetValue() *UserSettingValue { + if x != nil { + return x.Value + } + return nil +} + +type UserSettingValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Value: + // + // *UserSettingValue_StringValue + // *UserSettingValue_VisibilityValue + Value isUserSettingValue_Value `protobuf_oneof:"value"` +} + +func (x *UserSettingValue) Reset() { + *x = UserSettingValue{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_user_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserSettingValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserSettingValue) ProtoMessage() {} + +func (x *UserSettingValue) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_user_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserSettingValue.ProtoReflect.Descriptor instead. +func (*UserSettingValue) Descriptor() ([]byte, []int) { + return file_api_v2_user_service_proto_rawDescGZIP(), []int{4} +} + +func (m *UserSettingValue) GetValue() isUserSettingValue_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *UserSettingValue) GetStringValue() string { + if x, ok := x.GetValue().(*UserSettingValue_StringValue); ok { + return x.StringValue + } + return "" +} + +func (x *UserSettingValue) GetVisibilityValue() Visibility { + if x, ok := x.GetValue().(*UserSettingValue_VisibilityValue); ok { + return x.VisibilityValue + } + return Visibility_VISIBILITY_UNSPECIFIED +} + +type isUserSettingValue_Value interface { + isUserSettingValue_Value() +} + +type UserSettingValue_StringValue struct { + // Default value as a string. + StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof"` +} + +type UserSettingValue_VisibilityValue struct { + VisibilityValue Visibility `protobuf:"varint,2,opt,name=visibility_value,json=visibilityValue,proto3,enum=memos.api.v2.Visibility,oneof"` +} + +func (*UserSettingValue_StringValue) isUserSettingValue_Value() {} + +func (*UserSettingValue_VisibilityValue) isUserSettingValue_Value() {} + var File_api_v2_user_service_proto protoreflect.FileDescriptor var file_api_v2_user_service_proto_rawDesc = []byte{ @@ -296,7 +563,7 @@ var file_api_v2_user_service_proto_rawDesc = []byte{ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xba, 0x02, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x02, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x72, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, @@ -316,35 +583,68 @@ var file_api_v2_user_service_proto_rawDesc = []byte{ 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x70, 0x65, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, - 0x72, 0x6c, 0x22, 0x24, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x2a, 0x3b, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x52, - 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, - 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x03, - 0x32, 0x7a, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x6b, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x42, 0xa8, 0x01, 0x0a, - 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x32, 0x42, 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, - 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, - 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, - 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, - 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6c, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x0b, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, + 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x24, 0x0a, 0x0e, 0x47, 0x65, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x39, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0xf0, 0x01, 0x0a, 0x0b, 0x55, + 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4b, 0x65, 0x79, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x61, 0x0a, 0x03, 0x4b, 0x65, + 0x79, 0x12, 0x13, 0x0a, 0x0f, 0x4b, 0x45, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x45, + 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x50, 0x50, 0x45, 0x41, 0x52, 0x41, 0x4e, 0x43, 0x45, + 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, + 0x49, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x45, 0x4c, 0x45, 0x47, + 0x52, 0x41, 0x4d, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x49, 0x44, 0x10, 0x04, 0x22, 0x87, 0x01, + 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x76, 0x69, 0x73, 0x69, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, + 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x48, 0x00, 0x52, 0x0f, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x3b, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, + 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, + 0x09, 0x0a, 0x05, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, + 0x45, 0x52, 0x10, 0x03, 0x2a, 0x50, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, + 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x50, + 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, + 0x42, 0x4c, 0x49, 0x43, 0x10, 0x03, 0x32, 0x7a, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0xda, + 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, + 0x65, 0x7d, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, + 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, + 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, + 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, + 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -359,26 +659,34 @@ func file_api_v2_user_service_proto_rawDescGZIP() []byte { return file_api_v2_user_service_proto_rawDescData } -var file_api_v2_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_api_v2_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_api_v2_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_api_v2_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_api_v2_user_service_proto_goTypes = []interface{}{ - (Role)(0), // 0: memos.api.v2.Role - (*User)(nil), // 1: memos.api.v2.User - (*GetUserRequest)(nil), // 2: memos.api.v2.GetUserRequest - (*GetUserResponse)(nil), // 3: memos.api.v2.GetUserResponse - (RowStatus)(0), // 4: memos.api.v2.RowStatus + (Role)(0), // 0: memos.api.v2.Role + (Visibility)(0), // 1: memos.api.v2.Visibility + (UserSetting_Key)(0), // 2: memos.api.v2.UserSetting.Key + (*User)(nil), // 3: memos.api.v2.User + (*GetUserRequest)(nil), // 4: memos.api.v2.GetUserRequest + (*GetUserResponse)(nil), // 5: memos.api.v2.GetUserResponse + (*UserSetting)(nil), // 6: memos.api.v2.UserSetting + (*UserSettingValue)(nil), // 7: memos.api.v2.UserSettingValue + (RowStatus)(0), // 8: memos.api.v2.RowStatus } var file_api_v2_user_service_proto_depIdxs = []int32{ - 4, // 0: memos.api.v2.User.row_status:type_name -> memos.api.v2.RowStatus + 8, // 0: memos.api.v2.User.row_status:type_name -> memos.api.v2.RowStatus 0, // 1: memos.api.v2.User.role:type_name -> memos.api.v2.Role - 1, // 2: memos.api.v2.GetUserResponse.user:type_name -> memos.api.v2.User - 2, // 3: memos.api.v2.UserService.GetUser:input_type -> memos.api.v2.GetUserRequest - 3, // 4: memos.api.v2.UserService.GetUser:output_type -> memos.api.v2.GetUserResponse - 4, // [4:5] is the sub-list for method output_type - 3, // [3:4] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 6, // 2: memos.api.v2.User.settings:type_name -> memos.api.v2.UserSetting + 3, // 3: memos.api.v2.GetUserResponse.user:type_name -> memos.api.v2.User + 2, // 4: memos.api.v2.UserSetting.key:type_name -> memos.api.v2.UserSetting.Key + 7, // 5: memos.api.v2.UserSetting.value:type_name -> memos.api.v2.UserSettingValue + 1, // 6: memos.api.v2.UserSettingValue.visibility_value:type_name -> memos.api.v2.Visibility + 4, // 7: memos.api.v2.UserService.GetUser:input_type -> memos.api.v2.GetUserRequest + 5, // 8: memos.api.v2.UserService.GetUser:output_type -> memos.api.v2.GetUserResponse + 8, // [8:9] is the sub-list for method output_type + 7, // [7:8] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_api_v2_user_service_proto_init() } @@ -424,14 +732,42 @@ func file_api_v2_user_service_proto_init() { return nil } } + file_api_v2_user_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserSetting); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v2_user_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserSettingValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_api_v2_user_service_proto_msgTypes[4].OneofWrappers = []interface{}{ + (*UserSettingValue_StringValue)(nil), + (*UserSettingValue_VisibilityValue)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_v2_user_service_proto_rawDesc, - NumEnums: 1, - NumMessages: 3, + NumEnums: 3, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, diff --git a/server/backup.go b/server/backup.go index c7ab5ec1..25780a6f 100644 --- a/server/backup.go +++ b/server/backup.go @@ -12,8 +12,18 @@ import ( "go.uber.org/zap" ) -func autoBackup(ctx context.Context, s *store.Store) { - intervalStr := s.GetSystemSettingValueWithDefault(&ctx, apiv1.SystemSettingAutoBackupIntervalName.String(), "") +type BackupRunner struct { + Store *store.Store +} + +func NewBackupRunner(store *store.Store) *BackupRunner { + return &BackupRunner{ + Store: store, + } +} + +func (r *BackupRunner) Run(ctx context.Context) { + intervalStr := r.Store.GetSystemSettingValueWithDefault(&ctx, apiv1.SystemSettingAutoBackupIntervalName.String(), "") if intervalStr == "" { log.Info("no SystemSettingAutoBackupIntervalName setting, disable auto backup") return @@ -38,9 +48,9 @@ func autoBackup(ctx context.Context, s *store.Store) { case t = <-ticker.C: } - filename := s.Profile.DSN + t.Format("-20060102-150405.bak") + filename := r.Store.Profile.DSN + t.Format("-20060102-150405.bak") log.Info(fmt.Sprintf("create backup to %s", filename)) - err := s.BackupTo(ctx, filename) + err := r.Store.BackupTo(ctx, filename) if err != nil { log.Error("fail to create backup", zap.Error(err)) } diff --git a/server/server.go b/server/server.go index c67601ff..d1d93293 100644 --- a/server/server.go +++ b/server/server.go @@ -32,7 +32,9 @@ type Server struct { Profile *profile.Profile Store *store.Store - telegramBot *telegram.Bot + // Asynchronous runners. + backupRunner *BackupRunner + telegramBot *telegram.Bot } func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store) (*Server, error) { @@ -45,10 +47,11 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store e: e, Store: store, Profile: profile, - } - telegramBotHandler := newTelegramHandler(store) - s.telegramBot = telegram.NewBotWithHandler(telegramBotHandler) + // Asynchronous runners. + backupRunner: NewBackupRunner(store), + telegramBot: telegram.NewBotWithHandler(newTelegramHandler(store)), + } e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ Format: `{"time":"${time_rfc3339}",` + @@ -116,7 +119,7 @@ func (s *Server) Start(ctx context.Context) error { } go s.telegramBot.Start(ctx) - go autoBackup(ctx, s.Store) + go s.backupRunner.Run(ctx) // Start gRPC server. listen, err := net.Listen("tcp", fmt.Sprintf(":%d", s.Profile.Port+1))