From d050a6fd4602d08573288cbb45b0856fe692b302 Mon Sep 17 00:00:00 2001 From: johnnyjoy Date: Sat, 11 Jan 2025 20:12:02 +0800 Subject: [PATCH] chore: update user stats --- proto/api/v1/user_service.proto | 29 +- proto/gen/api/v1/user_service.pb.go | 643 +++++++++++++---------- proto/gen/api/v1/user_service.pb.gw.go | 117 ++++- proto/gen/api/v1/user_service_grpc.pb.go | 72 ++- proto/gen/apidocs.swagger.yaml | 53 +- server/router/api/v1/user_service.go | 145 ++--- 6 files changed, 651 insertions(+), 408 deletions(-) diff --git a/proto/api/v1/user_service.proto b/proto/api/v1/user_service.proto index ef74ee4b..b5b21df3 100644 --- a/proto/api/v1/user_service.proto +++ b/proto/api/v1/user_service.proto @@ -53,9 +53,12 @@ service UserService { option (google.api.http) = {delete: "/api/v1/{name=users/*}"}; option (google.api.method_signature) = "name"; } - // ListUserStats returns the stats of a user. - // Use `users/-` to list all users. - rpc ListUserStats(ListUserStatsRequest) returns (ListUserStatsResponse) { + // ListAllUserStats returns all user stats. + rpc ListAllUserStats(ListAllUserStatsRequest) returns (ListAllUserStatsResponse) { + option (google.api.http) = {post: "/api/v1/users/-/stats"}; + } + // GetUserStats returns the stats of a user. + rpc GetUserStats(GetUserStatsRequest) returns (UserStats) { option (google.api.http) = {get: "/api/v1/{name=users/*}/stats"}; option (google.api.method_signature) = "name"; } @@ -194,16 +197,26 @@ message UserStats { } } -message ListUserStatsRequest { - // The name of the user. - // Format: users/{user}. Use "-" to list all users. - string name = 1; +message ListAllUserStatsRequest { + // Filter is used to filter memos to calculate stats. + // Same as `ListMemosRequest.filter`. + string filter = 1; } -message ListUserStatsResponse { +message ListAllUserStatsResponse { repeated UserStats user_stats = 1; } +message GetUserStatsRequest { + // The name of the user. + // Format: users/{user}. + string name = 1; + + // Filter is used to filter memos to calculate stats. + // Same as `ListMemosRequest.filter`. + string filter = 2; +} + message UserSetting { // The name of the user. // Format: users/{user} diff --git a/proto/gen/api/v1/user_service.pb.go b/proto/gen/api/v1/user_service.pb.go index 5ae7c60d..8f6be34a 100644 --- a/proto/gen/api/v1/user_service.pb.go +++ b/proto/gen/api/v1/user_service.pb.go @@ -691,29 +691,29 @@ func (x *UserStats) GetTagCount() map[string]int32 { return nil } -type ListUserStatsRequest struct { +type ListAllUserStatsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - // The name of the user. - // Format: users/{user}. Use "-" to list all users. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Filter is used to filter memos to calculate stats. + // Same as `ListMemosRequest.filter`. + Filter string `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ListUserStatsRequest) Reset() { - *x = ListUserStatsRequest{} +func (x *ListAllUserStatsRequest) Reset() { + *x = ListAllUserStatsRequest{} mi := &file_api_v1_user_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ListUserStatsRequest) String() string { +func (x *ListAllUserStatsRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ListUserStatsRequest) ProtoMessage() {} +func (*ListAllUserStatsRequest) ProtoMessage() {} -func (x *ListUserStatsRequest) ProtoReflect() protoreflect.Message { +func (x *ListAllUserStatsRequest) ProtoReflect() protoreflect.Message { mi := &file_api_v1_user_service_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -725,39 +725,39 @@ func (x *ListUserStatsRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ListUserStatsRequest.ProtoReflect.Descriptor instead. -func (*ListUserStatsRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use ListAllUserStatsRequest.ProtoReflect.Descriptor instead. +func (*ListAllUserStatsRequest) Descriptor() ([]byte, []int) { return file_api_v1_user_service_proto_rawDescGZIP(), []int{11} } -func (x *ListUserStatsRequest) GetName() string { +func (x *ListAllUserStatsRequest) GetFilter() string { if x != nil { - return x.Name + return x.Filter } return "" } -type ListUserStatsResponse struct { +type ListAllUserStatsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` UserStats []*UserStats `protobuf:"bytes,1,rep,name=user_stats,json=userStats,proto3" json:"user_stats,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ListUserStatsResponse) Reset() { - *x = ListUserStatsResponse{} +func (x *ListAllUserStatsResponse) Reset() { + *x = ListAllUserStatsResponse{} mi := &file_api_v1_user_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ListUserStatsResponse) String() string { +func (x *ListAllUserStatsResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ListUserStatsResponse) ProtoMessage() {} +func (*ListAllUserStatsResponse) ProtoMessage() {} -func (x *ListUserStatsResponse) ProtoReflect() protoreflect.Message { +func (x *ListAllUserStatsResponse) ProtoReflect() protoreflect.Message { mi := &file_api_v1_user_service_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -769,18 +769,74 @@ func (x *ListUserStatsResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ListUserStatsResponse.ProtoReflect.Descriptor instead. -func (*ListUserStatsResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use ListAllUserStatsResponse.ProtoReflect.Descriptor instead. +func (*ListAllUserStatsResponse) Descriptor() ([]byte, []int) { return file_api_v1_user_service_proto_rawDescGZIP(), []int{12} } -func (x *ListUserStatsResponse) GetUserStats() []*UserStats { +func (x *ListAllUserStatsResponse) GetUserStats() []*UserStats { if x != nil { return x.UserStats } return nil } +type GetUserStatsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The name of the user. + // Format: users/{user}. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Filter is used to filter memos to calculate stats. + // Same as `ListMemosRequest.filter`. + Filter string `protobuf:"bytes,2,opt,name=filter,proto3" json:"filter,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetUserStatsRequest) Reset() { + *x = GetUserStatsRequest{} + mi := &file_api_v1_user_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUserStatsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserStatsRequest) ProtoMessage() {} + +func (x *GetUserStatsRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_user_service_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserStatsRequest.ProtoReflect.Descriptor instead. +func (*GetUserStatsRequest) Descriptor() ([]byte, []int) { + return file_api_v1_user_service_proto_rawDescGZIP(), []int{13} +} + +func (x *GetUserStatsRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GetUserStatsRequest) GetFilter() string { + if x != nil { + return x.Filter + } + return "" +} + type UserSetting struct { state protoimpl.MessageState `protogen:"open.v1"` // The name of the user. @@ -798,7 +854,7 @@ type UserSetting struct { func (x *UserSetting) Reset() { *x = UserSetting{} - mi := &file_api_v1_user_service_proto_msgTypes[13] + mi := &file_api_v1_user_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -810,7 +866,7 @@ func (x *UserSetting) String() string { func (*UserSetting) ProtoMessage() {} func (x *UserSetting) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[13] + mi := &file_api_v1_user_service_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -823,7 +879,7 @@ func (x *UserSetting) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSetting.ProtoReflect.Descriptor instead. func (*UserSetting) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{13} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{14} } func (x *UserSetting) GetName() string { @@ -865,7 +921,7 @@ type GetUserSettingRequest struct { func (x *GetUserSettingRequest) Reset() { *x = GetUserSettingRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[14] + mi := &file_api_v1_user_service_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -877,7 +933,7 @@ func (x *GetUserSettingRequest) String() string { func (*GetUserSettingRequest) ProtoMessage() {} func (x *GetUserSettingRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[14] + mi := &file_api_v1_user_service_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -890,7 +946,7 @@ func (x *GetUserSettingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserSettingRequest.ProtoReflect.Descriptor instead. func (*GetUserSettingRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{14} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{15} } func (x *GetUserSettingRequest) GetName() string { @@ -910,7 +966,7 @@ type UpdateUserSettingRequest struct { func (x *UpdateUserSettingRequest) Reset() { *x = UpdateUserSettingRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[15] + mi := &file_api_v1_user_service_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -922,7 +978,7 @@ func (x *UpdateUserSettingRequest) String() string { func (*UpdateUserSettingRequest) ProtoMessage() {} func (x *UpdateUserSettingRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[15] + mi := &file_api_v1_user_service_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -935,7 +991,7 @@ func (x *UpdateUserSettingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserSettingRequest.ProtoReflect.Descriptor instead. func (*UpdateUserSettingRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{15} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{16} } func (x *UpdateUserSettingRequest) GetSetting() *UserSetting { @@ -964,7 +1020,7 @@ type UserAccessToken struct { func (x *UserAccessToken) Reset() { *x = UserAccessToken{} - mi := &file_api_v1_user_service_proto_msgTypes[16] + mi := &file_api_v1_user_service_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -976,7 +1032,7 @@ func (x *UserAccessToken) String() string { func (*UserAccessToken) ProtoMessage() {} func (x *UserAccessToken) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[16] + mi := &file_api_v1_user_service_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -989,7 +1045,7 @@ func (x *UserAccessToken) ProtoReflect() protoreflect.Message { // Deprecated: Use UserAccessToken.ProtoReflect.Descriptor instead. func (*UserAccessToken) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{16} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{17} } func (x *UserAccessToken) GetAccessToken() string { @@ -1031,7 +1087,7 @@ type ListUserAccessTokensRequest struct { func (x *ListUserAccessTokensRequest) Reset() { *x = ListUserAccessTokensRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[17] + mi := &file_api_v1_user_service_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1043,7 +1099,7 @@ func (x *ListUserAccessTokensRequest) String() string { func (*ListUserAccessTokensRequest) ProtoMessage() {} func (x *ListUserAccessTokensRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[17] + mi := &file_api_v1_user_service_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1056,7 +1112,7 @@ func (x *ListUserAccessTokensRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserAccessTokensRequest.ProtoReflect.Descriptor instead. func (*ListUserAccessTokensRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{17} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{18} } func (x *ListUserAccessTokensRequest) GetName() string { @@ -1075,7 +1131,7 @@ type ListUserAccessTokensResponse struct { func (x *ListUserAccessTokensResponse) Reset() { *x = ListUserAccessTokensResponse{} - mi := &file_api_v1_user_service_proto_msgTypes[18] + mi := &file_api_v1_user_service_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1087,7 +1143,7 @@ func (x *ListUserAccessTokensResponse) String() string { func (*ListUserAccessTokensResponse) ProtoMessage() {} func (x *ListUserAccessTokensResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[18] + mi := &file_api_v1_user_service_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1100,7 +1156,7 @@ func (x *ListUserAccessTokensResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserAccessTokensResponse.ProtoReflect.Descriptor instead. func (*ListUserAccessTokensResponse) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{18} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{19} } func (x *ListUserAccessTokensResponse) GetAccessTokens() []*UserAccessToken { @@ -1123,7 +1179,7 @@ type CreateUserAccessTokenRequest struct { func (x *CreateUserAccessTokenRequest) Reset() { *x = CreateUserAccessTokenRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[19] + mi := &file_api_v1_user_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1135,7 +1191,7 @@ func (x *CreateUserAccessTokenRequest) String() string { func (*CreateUserAccessTokenRequest) ProtoMessage() {} func (x *CreateUserAccessTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[19] + mi := &file_api_v1_user_service_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1148,7 +1204,7 @@ func (x *CreateUserAccessTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateUserAccessTokenRequest.ProtoReflect.Descriptor instead. func (*CreateUserAccessTokenRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{19} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{20} } func (x *CreateUserAccessTokenRequest) GetName() string { @@ -1185,7 +1241,7 @@ type DeleteUserAccessTokenRequest struct { func (x *DeleteUserAccessTokenRequest) Reset() { *x = DeleteUserAccessTokenRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[20] + mi := &file_api_v1_user_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1197,7 +1253,7 @@ func (x *DeleteUserAccessTokenRequest) String() string { func (*DeleteUserAccessTokenRequest) ProtoMessage() {} func (x *DeleteUserAccessTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[20] + mi := &file_api_v1_user_service_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1210,7 +1266,7 @@ func (x *DeleteUserAccessTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteUserAccessTokenRequest.ProtoReflect.Descriptor instead. func (*DeleteUserAccessTokenRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{20} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{21} } func (x *DeleteUserAccessTokenRequest) GetName() string { @@ -1238,7 +1294,7 @@ type UserStats_MemoTypeStats struct { func (x *UserStats_MemoTypeStats) Reset() { *x = UserStats_MemoTypeStats{} - mi := &file_api_v1_user_service_proto_msgTypes[22] + mi := &file_api_v1_user_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1250,7 +1306,7 @@ func (x *UserStats_MemoTypeStats) String() string { func (*UserStats_MemoTypeStats) ProtoMessage() {} func (x *UserStats_MemoTypeStats) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[22] + mi := &file_api_v1_user_service_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1399,193 +1455,205 @@ var file_api_v1_user_service_proto_rawDesc = []byte{ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6f, 0x64, 0x65, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x2a, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x31, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, + 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x52, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x73, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x41, 0x0a, 0x13, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 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, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, + 0x82, 0x01, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, + 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x6d, + 0x65, 0x6d, 0x6f, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x6f, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x22, 0x2b, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 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, 0x4f, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x1e, - 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x27, - 0x0a, 0x0f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x6f, 0x56, 0x69, 0x73, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x2b, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 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, 0x92, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x39, 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x04, 0xe2, - 0x41, 0x01, 0x02, 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x3b, 0x0a, 0x0b, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0xca, 0x01, 0x0a, 0x0f, 0x55, 0x73, - 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x21, 0x0a, - 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x65, 0x22, 0x92, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, + 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x02, + 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0xca, 0x01, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x20, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x37, 0x0a, 0x09, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, + 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x73, 0x41, 0x74, 0x22, 0x31, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 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, 0x62, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0c, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x1c, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 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, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x3e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x08, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, - 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x22, 0x31, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 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, 0x62, 0x0a, 0x1c, 0x4c, 0x69, 0x73, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, - 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0xa3, 0x01, - 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 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, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, - 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, - 0x74, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, - 0x5f, 0x61, 0x74, 0x22, 0x55, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 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, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xc4, 0x0d, 0x0a, 0x0b, 0x55, - 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, - 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, - 0x12, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, - 0x70, 0x0a, 0x0b, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x20, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3a, 0x73, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x12, 0x62, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6d, - 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x25, - 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, - 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x28, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x2a, 0xda, - 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x66, - 0x69, 0x6c, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, - 0x2a, 0x7d, 0x2f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x65, 0x0a, 0x0a, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x22, 0xda, 0x41, - 0x04, 0x75, 0x73, 0x65, 0x72, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x04, 0x75, 0x73, 0x65, - 0x72, 0x22, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, - 0x12, 0x7f, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x22, 0x3c, 0xda, 0x41, 0x10, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x3a, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x32, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, - 0x7d, 0x12, 0x6c, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x25, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, - 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x12, - 0x85, 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x73, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0xda, 0x41, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, - 0x7d, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x12, 0x7f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, + 0x70, 0x48, 0x00, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x88, 0x01, + 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, + 0x22, 0x55, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 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, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xb8, 0x0e, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x70, 0x0a, 0x0b, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, + 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x62, + 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x2d, 0xda, 0x41, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, - 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0xa5, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x26, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x22, 0x4d, 0xda, 0x41, 0x13, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2c, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x3a, - 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x32, 0x26, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x7d, - 0x12, 0xa2, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x33, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, - 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, - 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x9a, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x36, 0xda, 0x41, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, - 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x73, 0x12, 0xac, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2a, 0x2e, 0x6d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x25, 0xda, 0x41, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, + 0x2a, 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x76, + 0x61, 0x74, 0x61, 0x72, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x2a, 0xda, 0x41, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x66, 0x69, 0x6c, 0x65, + 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, + 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x65, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x22, 0xda, 0x41, 0x04, 0x75, 0x73, + 0x65, 0x72, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x0d, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x7f, 0x0a, + 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x22, 0x3c, 0xda, 0x41, 0x10, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x3a, 0x04, 0x75, 0x73, 0x65, + 0x72, 0x32, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x6c, + 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x4f, 0xda, 0x41, 0x11, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x2a, 0x33, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, - 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x73, 0x2f, 0x7b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x7d, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 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, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, - 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, - 0x31, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, - 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 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, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x25, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, + 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x80, 0x01, 0x0a, + 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x55, + 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2d, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x12, + 0x77, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, + 0x21, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x2b, 0xda, 0x41, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, + 0x2a, 0x7d, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x12, 0x7f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x19, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x2d, 0xda, 0x41, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, + 0x7d, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0xa5, 0x01, 0x0a, 0x11, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, + 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x22, 0x4d, 0xda, 0x41, 0x13, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2c, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, + 0x3a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x32, 0x26, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6e, 0x61, 0x6d, 0x65, + 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x7d, 0x12, 0xa2, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x33, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, + 0x12, 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, + 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x9a, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x36, 0xda, 0x41, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, + 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x73, 0x12, 0xac, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, + 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2a, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x4f, 0xda, 0x41, 0x11, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x2a, 0x33, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, + 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x73, 0x2f, 0x7b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x7d, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 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, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, + 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, + 0x56, 0x31, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, + 0x31, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, + 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, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1601,7 +1669,7 @@ func file_api_v1_user_service_proto_rawDescGZIP() []byte { } var file_api_v1_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_api_v1_user_service_proto_goTypes = []any{ (User_Role)(0), // 0: memos.api.v1.User.Role (*User)(nil), // 1: memos.api.v1.User @@ -1615,45 +1683,46 @@ var file_api_v1_user_service_proto_goTypes = []any{ (*UpdateUserRequest)(nil), // 9: memos.api.v1.UpdateUserRequest (*DeleteUserRequest)(nil), // 10: memos.api.v1.DeleteUserRequest (*UserStats)(nil), // 11: memos.api.v1.UserStats - (*ListUserStatsRequest)(nil), // 12: memos.api.v1.ListUserStatsRequest - (*ListUserStatsResponse)(nil), // 13: memos.api.v1.ListUserStatsResponse - (*UserSetting)(nil), // 14: memos.api.v1.UserSetting - (*GetUserSettingRequest)(nil), // 15: memos.api.v1.GetUserSettingRequest - (*UpdateUserSettingRequest)(nil), // 16: memos.api.v1.UpdateUserSettingRequest - (*UserAccessToken)(nil), // 17: memos.api.v1.UserAccessToken - (*ListUserAccessTokensRequest)(nil), // 18: memos.api.v1.ListUserAccessTokensRequest - (*ListUserAccessTokensResponse)(nil), // 19: memos.api.v1.ListUserAccessTokensResponse - (*CreateUserAccessTokenRequest)(nil), // 20: memos.api.v1.CreateUserAccessTokenRequest - (*DeleteUserAccessTokenRequest)(nil), // 21: memos.api.v1.DeleteUserAccessTokenRequest - nil, // 22: memos.api.v1.UserStats.TagCountEntry - (*UserStats_MemoTypeStats)(nil), // 23: memos.api.v1.UserStats.MemoTypeStats - (State)(0), // 24: memos.api.v1.State - (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp - (*httpbody.HttpBody)(nil), // 26: google.api.HttpBody - (*fieldmaskpb.FieldMask)(nil), // 27: google.protobuf.FieldMask - (*emptypb.Empty)(nil), // 28: google.protobuf.Empty + (*ListAllUserStatsRequest)(nil), // 12: memos.api.v1.ListAllUserStatsRequest + (*ListAllUserStatsResponse)(nil), // 13: memos.api.v1.ListAllUserStatsResponse + (*GetUserStatsRequest)(nil), // 14: memos.api.v1.GetUserStatsRequest + (*UserSetting)(nil), // 15: memos.api.v1.UserSetting + (*GetUserSettingRequest)(nil), // 16: memos.api.v1.GetUserSettingRequest + (*UpdateUserSettingRequest)(nil), // 17: memos.api.v1.UpdateUserSettingRequest + (*UserAccessToken)(nil), // 18: memos.api.v1.UserAccessToken + (*ListUserAccessTokensRequest)(nil), // 19: memos.api.v1.ListUserAccessTokensRequest + (*ListUserAccessTokensResponse)(nil), // 20: memos.api.v1.ListUserAccessTokensResponse + (*CreateUserAccessTokenRequest)(nil), // 21: memos.api.v1.CreateUserAccessTokenRequest + (*DeleteUserAccessTokenRequest)(nil), // 22: memos.api.v1.DeleteUserAccessTokenRequest + nil, // 23: memos.api.v1.UserStats.TagCountEntry + (*UserStats_MemoTypeStats)(nil), // 24: memos.api.v1.UserStats.MemoTypeStats + (State)(0), // 25: memos.api.v1.State + (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp + (*httpbody.HttpBody)(nil), // 27: google.api.HttpBody + (*fieldmaskpb.FieldMask)(nil), // 28: google.protobuf.FieldMask + (*emptypb.Empty)(nil), // 29: google.protobuf.Empty } var file_api_v1_user_service_proto_depIdxs = []int32{ 0, // 0: memos.api.v1.User.role:type_name -> memos.api.v1.User.Role - 24, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State - 25, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp - 25, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp + 25, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State + 26, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp + 26, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp 1, // 4: memos.api.v1.ListUsersResponse.users:type_name -> memos.api.v1.User 1, // 5: memos.api.v1.SearchUsersResponse.users:type_name -> memos.api.v1.User - 26, // 6: memos.api.v1.GetUserAvatarBinaryRequest.http_body:type_name -> google.api.HttpBody + 27, // 6: memos.api.v1.GetUserAvatarBinaryRequest.http_body:type_name -> google.api.HttpBody 1, // 7: memos.api.v1.CreateUserRequest.user:type_name -> memos.api.v1.User 1, // 8: memos.api.v1.UpdateUserRequest.user:type_name -> memos.api.v1.User - 27, // 9: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask - 25, // 10: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp - 23, // 11: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats - 22, // 12: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry - 11, // 13: memos.api.v1.ListUserStatsResponse.user_stats:type_name -> memos.api.v1.UserStats - 14, // 14: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting - 27, // 15: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask - 25, // 16: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp - 25, // 17: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp - 17, // 18: memos.api.v1.ListUserAccessTokensResponse.access_tokens:type_name -> memos.api.v1.UserAccessToken - 25, // 19: memos.api.v1.CreateUserAccessTokenRequest.expires_at:type_name -> google.protobuf.Timestamp + 28, // 9: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask + 26, // 10: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp + 24, // 11: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats + 23, // 12: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry + 11, // 13: memos.api.v1.ListAllUserStatsResponse.user_stats:type_name -> memos.api.v1.UserStats + 15, // 14: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting + 28, // 15: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask + 26, // 16: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp + 26, // 17: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp + 18, // 18: memos.api.v1.ListUserAccessTokensResponse.access_tokens:type_name -> memos.api.v1.UserAccessToken + 26, // 19: memos.api.v1.CreateUserAccessTokenRequest.expires_at:type_name -> google.protobuf.Timestamp 2, // 20: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest 4, // 21: memos.api.v1.UserService.SearchUsers:input_type -> memos.api.v1.SearchUsersRequest 6, // 22: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest @@ -1661,27 +1730,29 @@ var file_api_v1_user_service_proto_depIdxs = []int32{ 8, // 24: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest 9, // 25: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest 10, // 26: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest - 12, // 27: memos.api.v1.UserService.ListUserStats:input_type -> memos.api.v1.ListUserStatsRequest - 15, // 28: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest - 16, // 29: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest - 18, // 30: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest - 20, // 31: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest - 21, // 32: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest - 3, // 33: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse - 5, // 34: memos.api.v1.UserService.SearchUsers:output_type -> memos.api.v1.SearchUsersResponse - 1, // 35: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User - 26, // 36: memos.api.v1.UserService.GetUserAvatarBinary:output_type -> google.api.HttpBody - 1, // 37: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User - 1, // 38: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User - 28, // 39: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty - 13, // 40: memos.api.v1.UserService.ListUserStats:output_type -> memos.api.v1.ListUserStatsResponse - 14, // 41: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting - 14, // 42: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting - 19, // 43: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse - 17, // 44: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken - 28, // 45: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty - 33, // [33:46] is the sub-list for method output_type - 20, // [20:33] is the sub-list for method input_type + 12, // 27: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest + 14, // 28: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest + 16, // 29: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest + 17, // 30: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest + 19, // 31: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest + 21, // 32: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest + 22, // 33: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest + 3, // 34: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse + 5, // 35: memos.api.v1.UserService.SearchUsers:output_type -> memos.api.v1.SearchUsersResponse + 1, // 36: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User + 27, // 37: memos.api.v1.UserService.GetUserAvatarBinary:output_type -> google.api.HttpBody + 1, // 38: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User + 1, // 39: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User + 29, // 40: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty + 13, // 41: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse + 11, // 42: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats + 15, // 43: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting + 15, // 44: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting + 20, // 45: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse + 18, // 46: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken + 29, // 47: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty + 34, // [34:48] is the sub-list for method output_type + 20, // [20:34] is the sub-list for method input_type 20, // [20:20] is the sub-list for extension type_name 20, // [20:20] is the sub-list for extension extendee 0, // [0:20] is the sub-list for field type_name @@ -1693,14 +1764,14 @@ func file_api_v1_user_service_proto_init() { return } file_api_v1_common_proto_init() - file_api_v1_user_service_proto_msgTypes[19].OneofWrappers = []any{} + file_api_v1_user_service_proto_msgTypes[20].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_v1_user_service_proto_rawDesc, NumEnums: 1, - NumMessages: 23, + NumMessages: 24, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/api/v1/user_service.pb.gw.go b/proto/gen/api/v1/user_service.pb.gw.go index 795bdaca..d41843b1 100644 --- a/proto/gen/api/v1/user_service.pb.gw.go +++ b/proto/gen/api/v1/user_service.pb.gw.go @@ -309,9 +309,43 @@ func local_request_UserService_DeleteUser_0(ctx context.Context, marshaler runti return msg, metadata, err } -func request_UserService_ListUserStats_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { +var filter_UserService_ListAllUserStats_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + +func request_UserService_ListAllUserStats_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ListAllUserStatsRequest + metadata runtime.ServerMetadata + ) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_ListAllUserStats_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.ListAllUserStats(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_UserService_ListAllUserStats_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ListAllUserStatsRequest + metadata runtime.ServerMetadata + ) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_ListAllUserStats_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.ListAllUserStats(ctx, &protoReq) + return msg, metadata, err +} + +var filter_UserService_GetUserStats_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} + +func request_UserService_GetUserStats_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( - protoReq ListUserStatsRequest + protoReq GetUserStatsRequest metadata runtime.ServerMetadata err error ) @@ -323,13 +357,19 @@ func request_UserService_ListUserStats_0(ctx context.Context, marshaler runtime. if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) } - msg, err := client.ListUserStats(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_GetUserStats_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.GetUserStats(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_UserService_ListUserStats_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { +func local_request_UserService_GetUserStats_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( - protoReq ListUserStatsRequest + protoReq GetUserStatsRequest metadata runtime.ServerMetadata err error ) @@ -341,7 +381,13 @@ func local_request_UserService_ListUserStats_0(ctx context.Context, marshaler ru if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) } - msg, err := server.ListUserStats(ctx, &protoReq) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_GetUserStats_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetUserStats(ctx, &protoReq) return msg, metadata, err } @@ -735,25 +781,45 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux } forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle(http.MethodGet, pattern_UserService_ListUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_UserService_ListAllUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/ListUserStats", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}/stats")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/ListAllUserStats", runtime.WithHTTPPathPattern("/api/v1/users/-/stats")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_UserService_ListUserStats_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_UserService_ListAllUserStats_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_UserService_ListUserStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_UserService_ListAllUserStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_UserService_GetUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/GetUserStats", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}/stats")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_UserService_GetUserStats_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_UserService_GetUserStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) mux.Handle(http.MethodGet, pattern_UserService_GetUserSetting_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) @@ -1014,22 +1080,39 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux } forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle(http.MethodGet, pattern_UserService_ListUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_UserService_ListAllUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/ListAllUserStats", runtime.WithHTTPPathPattern("/api/v1/users/-/stats")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_UserService_ListAllUserStats_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_UserService_ListAllUserStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_UserService_GetUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/ListUserStats", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}/stats")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/GetUserStats", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}/stats")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_UserService_ListUserStats_0(annotatedContext, inboundMarshaler, client, req, pathParams) + resp, md, err := request_UserService_GetUserStats_0(annotatedContext, inboundMarshaler, client, req, pathParams) annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_UserService_ListUserStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_UserService_GetUserStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) mux.Handle(http.MethodGet, pattern_UserService_GetUserSetting_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) @@ -1127,7 +1210,8 @@ var ( pattern_UserService_CreateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, "")) pattern_UserService_UpdateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "user.name"}, "")) pattern_UserService_DeleteUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, "")) - pattern_UserService_ListUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "name", "stats"}, "")) + pattern_UserService_ListAllUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"api", "v1", "users", "-", "stats"}, "")) + pattern_UserService_GetUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "name", "stats"}, "")) pattern_UserService_GetUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "name", "setting"}, "")) pattern_UserService_UpdateUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 4, 3, 5, 4}, []string{"api", "v1", "users", "setting", "setting.name"}, "")) pattern_UserService_ListUserAccessTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "name", "access_tokens"}, "")) @@ -1143,7 +1227,8 @@ var ( forward_UserService_CreateUser_0 = runtime.ForwardResponseMessage forward_UserService_UpdateUser_0 = runtime.ForwardResponseMessage forward_UserService_DeleteUser_0 = runtime.ForwardResponseMessage - forward_UserService_ListUserStats_0 = runtime.ForwardResponseMessage + forward_UserService_ListAllUserStats_0 = runtime.ForwardResponseMessage + forward_UserService_GetUserStats_0 = runtime.ForwardResponseMessage forward_UserService_GetUserSetting_0 = runtime.ForwardResponseMessage forward_UserService_UpdateUserSetting_0 = runtime.ForwardResponseMessage forward_UserService_ListUserAccessTokens_0 = runtime.ForwardResponseMessage diff --git a/proto/gen/api/v1/user_service_grpc.pb.go b/proto/gen/api/v1/user_service_grpc.pb.go index e2ee3aaf..bbb38b7c 100644 --- a/proto/gen/api/v1/user_service_grpc.pb.go +++ b/proto/gen/api/v1/user_service_grpc.pb.go @@ -28,7 +28,8 @@ const ( UserService_CreateUser_FullMethodName = "/memos.api.v1.UserService/CreateUser" UserService_UpdateUser_FullMethodName = "/memos.api.v1.UserService/UpdateUser" UserService_DeleteUser_FullMethodName = "/memos.api.v1.UserService/DeleteUser" - UserService_ListUserStats_FullMethodName = "/memos.api.v1.UserService/ListUserStats" + UserService_ListAllUserStats_FullMethodName = "/memos.api.v1.UserService/ListAllUserStats" + UserService_GetUserStats_FullMethodName = "/memos.api.v1.UserService/GetUserStats" UserService_GetUserSetting_FullMethodName = "/memos.api.v1.UserService/GetUserSetting" UserService_UpdateUserSetting_FullMethodName = "/memos.api.v1.UserService/UpdateUserSetting" UserService_ListUserAccessTokens_FullMethodName = "/memos.api.v1.UserService/ListUserAccessTokens" @@ -54,7 +55,10 @@ type UserServiceClient interface { UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error) // DeleteUser deletes a user. DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) - ListUserStats(ctx context.Context, in *ListUserStatsRequest, opts ...grpc.CallOption) (*ListUserStatsResponse, error) + // ListAllUserStats returns all user stats. + ListAllUserStats(ctx context.Context, in *ListAllUserStatsRequest, opts ...grpc.CallOption) (*ListAllUserStatsResponse, error) + // GetUserStats returns the stats of a user. + GetUserStats(ctx context.Context, in *GetUserStatsRequest, opts ...grpc.CallOption) (*UserStats, error) // GetUserSetting gets the setting of a user. GetUserSetting(ctx context.Context, in *GetUserSettingRequest, opts ...grpc.CallOption) (*UserSetting, error) // UpdateUserSetting updates the setting of a user. @@ -145,10 +149,20 @@ func (c *userServiceClient) DeleteUser(ctx context.Context, in *DeleteUserReques return out, nil } -func (c *userServiceClient) ListUserStats(ctx context.Context, in *ListUserStatsRequest, opts ...grpc.CallOption) (*ListUserStatsResponse, error) { +func (c *userServiceClient) ListAllUserStats(ctx context.Context, in *ListAllUserStatsRequest, opts ...grpc.CallOption) (*ListAllUserStatsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ListUserStatsResponse) - err := c.cc.Invoke(ctx, UserService_ListUserStats_FullMethodName, in, out, cOpts...) + out := new(ListAllUserStatsResponse) + err := c.cc.Invoke(ctx, UserService_ListAllUserStats_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *userServiceClient) GetUserStats(ctx context.Context, in *GetUserStatsRequest, opts ...grpc.CallOption) (*UserStats, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UserStats) + err := c.cc.Invoke(ctx, UserService_GetUserStats_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -223,7 +237,10 @@ type UserServiceServer interface { UpdateUser(context.Context, *UpdateUserRequest) (*User, error) // DeleteUser deletes a user. DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) - ListUserStats(context.Context, *ListUserStatsRequest) (*ListUserStatsResponse, error) + // ListAllUserStats returns all user stats. + ListAllUserStats(context.Context, *ListAllUserStatsRequest) (*ListAllUserStatsResponse, error) + // GetUserStats returns the stats of a user. + GetUserStats(context.Context, *GetUserStatsRequest) (*UserStats, error) // GetUserSetting gets the setting of a user. GetUserSetting(context.Context, *GetUserSettingRequest) (*UserSetting, error) // UpdateUserSetting updates the setting of a user. @@ -265,8 +282,11 @@ func (UnimplementedUserServiceServer) UpdateUser(context.Context, *UpdateUserReq func (UnimplementedUserServiceServer) DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented") } -func (UnimplementedUserServiceServer) ListUserStats(context.Context, *ListUserStatsRequest) (*ListUserStatsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListUserStats not implemented") +func (UnimplementedUserServiceServer) ListAllUserStats(context.Context, *ListAllUserStatsRequest) (*ListAllUserStatsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListAllUserStats not implemented") +} +func (UnimplementedUserServiceServer) GetUserStats(context.Context, *GetUserStatsRequest) (*UserStats, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetUserStats not implemented") } func (UnimplementedUserServiceServer) GetUserSetting(context.Context, *GetUserSettingRequest) (*UserSetting, error) { return nil, status.Errorf(codes.Unimplemented, "method GetUserSetting not implemented") @@ -430,20 +450,38 @@ func _UserService_DeleteUser_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } -func _UserService_ListUserStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListUserStatsRequest) +func _UserService_ListAllUserStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListAllUserStatsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(UserServiceServer).ListUserStats(ctx, in) + return srv.(UserServiceServer).ListAllUserStats(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: UserService_ListUserStats_FullMethodName, + FullMethod: UserService_ListAllUserStats_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UserServiceServer).ListUserStats(ctx, req.(*ListUserStatsRequest)) + return srv.(UserServiceServer).ListAllUserStats(ctx, req.(*ListAllUserStatsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _UserService_GetUserStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetUserStatsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServiceServer).GetUserStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserService_GetUserStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServiceServer).GetUserStats(ctx, req.(*GetUserStatsRequest)) } return interceptor(ctx, in, info, handler) } @@ -574,8 +612,12 @@ var UserService_ServiceDesc = grpc.ServiceDesc{ Handler: _UserService_DeleteUser_Handler, }, { - MethodName: "ListUserStats", - Handler: _UserService_ListUserStats_Handler, + MethodName: "ListAllUserStats", + Handler: _UserService_ListAllUserStats_Handler, + }, + { + MethodName: "GetUserStats", + Handler: _UserService_GetUserStats_Handler, }, { MethodName: "GetUserSetting", diff --git a/proto/gen/apidocs.swagger.yaml b/proto/gen/apidocs.swagger.yaml index 8936aab0..5f180fff 100644 --- a/proto/gen/apidocs.swagger.yaml +++ b/proto/gen/apidocs.swagger.yaml @@ -494,6 +494,29 @@ paths: $ref: '#/definitions/v1User' tags: - UserService + /api/v1/users/-/stats: + post: + summary: ListAllUserStats returns all user stats. + operationId: UserService_ListAllUserStats + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1ListAllUserStatsResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: filter + description: |- + Filter is used to filter memos to calculate stats. + Same as `ListMemosRequest.filter`. + in: query + required: false + type: string + tags: + - UserService /api/v1/users:search: get: summary: SearchUsers searches users by filter. @@ -1466,12 +1489,13 @@ paths: - UserService /api/v1/{name}/stats: get: - operationId: UserService_ListUserStats + summary: GetUserStats returns the stats of a user. + operationId: UserService_GetUserStats responses: "200": description: A successful response. schema: - $ref: '#/definitions/v1ListUserStatsResponse' + $ref: '#/definitions/v1UserStats' default: description: An unexpected error response. schema: @@ -1480,11 +1504,18 @@ paths: - name: name description: |- The name of the user. - Format: users/{user}. Use "-" to list all users. + Format: users/{user}. in: path required: true type: string pattern: users/[^/]+ + - name: filter + description: |- + Filter is used to filter memos to calculate stats. + Same as `ListMemosRequest.filter`. + in: query + required: false + type: string tags: - UserService /api/v1/{parent}/tags/{tag}: @@ -2575,6 +2606,14 @@ definitions: type: string url: type: string + v1ListAllUserStatsResponse: + type: object + properties: + userStats: + type: array + items: + type: object + $ref: '#/definitions/v1UserStats' v1ListIdentityProvidersResponse: type: object properties: @@ -2670,14 +2709,6 @@ definitions: items: type: object $ref: '#/definitions/v1UserAccessToken' - v1ListUserStatsResponse: - type: object - properties: - userStats: - type: array - items: - type: object - $ref: '#/definitions/v1UserStats' v1ListUsersResponse: type: object properties: diff --git a/server/router/api/v1/user_service.go b/server/router/api/v1/user_service.go index 7fa9b3fb..d635e015 100644 --- a/server/router/api/v1/user_service.go +++ b/server/router/api/v1/user_service.go @@ -275,41 +275,49 @@ func (s *APIV1Service) DeleteUser(ctx context.Context, request *v1pb.DeleteUserR return &emptypb.Empty{}, nil } -func (s *APIV1Service) ListUserStats(ctx context.Context, request *v1pb.ListUserStatsRequest) (*v1pb.ListUserStatsResponse, error) { - currentUser, err := s.GetCurrentUser(ctx) +func (s *APIV1Service) ListAllUserStats(ctx context.Context, request *v1pb.ListAllUserStatsRequest) (*v1pb.ListAllUserStatsResponse, error) { + users, err := s.Store.ListUsers(ctx, &store.FindUser{}) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list users: %v", err) + } + userStatsList := []*v1pb.UserStats{} + for _, user := range users { + userStats, err := s.GetUserStats(ctx, &v1pb.GetUserStatsRequest{ + Name: fmt.Sprintf("%s%d", UserNamePrefix, user.ID), + Filter: request.Filter, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user stats: %v", err) + } + userStatsList = append(userStatsList, userStats) + } + return &v1pb.ListAllUserStatsResponse{ + UserStats: userStatsList, + }, nil +} + +func (s *APIV1Service) GetUserStats(ctx context.Context, request *v1pb.GetUserStatsRequest) (*v1pb.UserStats, error) { + userID, err := ExtractUserIDFromName(request.Name) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err) + } + user, err := s.Store.GetUser(ctx, &store.FindUser{ID: &userID}) if err != nil { return nil, status.Errorf(codes.Internal, "failed to get user: %v", err) } + currentUser, err := s.GetCurrentUser(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user: %v", err) + } // For unauthenticated users, only public memos are visible. - defaultVisibilities := []store.Visibility{store.Public} + visibilities := []store.Visibility{store.Public} if currentUser != nil { // For authenticated users, protected memos are also visible. - defaultVisibilities = append(defaultVisibilities, store.Protected) - } - - users := []*store.User{} - if request.Name == "users/-" { - users, err = s.Store.ListUsers(ctx, &store.FindUser{}) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to list users: %v", err) - } - } else { - userID, err := ExtractUserIDFromName(request.Name) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err) - } - if userID == currentUser.ID { - users = append(users, currentUser) - } else { - user, err := s.Store.GetUser(ctx, &store.FindUser{ID: &userID}) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to get user: %v", err) - } - if user == nil { - return nil, status.Errorf(codes.NotFound, "user not found") - } - users = append(users, user) + visibilities = append(visibilities, store.Protected) + if currentUser.ID == user.ID { + // For the current user, show all memos including private ones. + visibilities = []store.Visibility{store.Public, store.Protected, store.Private} } } @@ -317,55 +325,48 @@ func (s *APIV1Service) ListUserStats(ctx context.Context, request *v1pb.ListUser if err != nil { return nil, errors.Wrap(err, "failed to get workspace memo related setting") } - userStatsList := []*v1pb.UserStats{} - for _, user := range users { - userStats := &v1pb.UserStats{ - Name: fmt.Sprintf("%s%d", UserNamePrefix, user.ID), - MemoDisplayTimestamps: []*timestamppb.Timestamp{}, - MemoTypeStats: &v1pb.UserStats_MemoTypeStats{}, - TagCount: map[string]int32{}, + userStats := &v1pb.UserStats{ + Name: fmt.Sprintf("%s%d", UserNamePrefix, user.ID), + MemoDisplayTimestamps: []*timestamppb.Timestamp{}, + MemoTypeStats: &v1pb.UserStats_MemoTypeStats{}, + TagCount: map[string]int32{}, + } + memoFind := &store.FindMemo{ + // Exclude comments by default. + ExcludeComments: true, + ExcludeContent: true, + } + if err := s.buildMemoFindWithFilter(ctx, memoFind, request.Filter); err != nil { + return nil, status.Errorf(codes.InvalidArgument, "failed to build find memos with filter: %v", err) + } + // Override the creator ID and visibility list. + memoFind.CreatorID = &user.ID + memoFind.VisibilityList = visibilities + memos, err := s.Store.ListMemos(ctx, memoFind) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list memos: %v", err) + } + for _, memo := range memos { + displayTs := memo.CreatedTs + if workspaceMemoRelatedSetting.DisplayWithUpdateTime { + displayTs = memo.UpdatedTs } - var visibilities []store.Visibility = defaultVisibilities - // For the current user, show all memos including private ones. - if user.ID == currentUser.ID { - visibilities = []store.Visibility{store.Public, store.Protected, store.Private} + userStats.MemoDisplayTimestamps = append(userStats.MemoDisplayTimestamps, timestamppb.New(time.Unix(displayTs, 0))) + // Handle duplicated tags. + for _, tag := range memo.Payload.Tags { + userStats.TagCount[tag]++ } - memos, err := s.Store.ListMemos(ctx, &store.FindMemo{ - // Exclude comments by default. - ExcludeComments: true, - ExcludeContent: true, - CreatorID: &user.ID, - VisibilityList: visibilities, - }) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to list memos: %v", err) + if memo.Payload.Property.GetHasLink() { + userStats.MemoTypeStats.LinkCount++ } - for _, memo := range memos { - displayTs := memo.CreatedTs - if workspaceMemoRelatedSetting.DisplayWithUpdateTime { - displayTs = memo.UpdatedTs - } - userStats.MemoDisplayTimestamps = append(userStats.MemoDisplayTimestamps, timestamppb.New(time.Unix(displayTs, 0))) - // Handle duplicated tags. - for _, tag := range memo.Payload.Tags { - userStats.TagCount[tag]++ - } - if memo.Payload.Property.GetHasLink() { - userStats.MemoTypeStats.LinkCount++ - } - if memo.Payload.Property.GetHasTaskList() { - userStats.MemoTypeStats.TaskCount++ - } - if memo.Payload.Property.GetHasCode() { - userStats.MemoTypeStats.CodeCount++ - } + if memo.Payload.Property.GetHasTaskList() { + userStats.MemoTypeStats.TaskCount++ + } + if memo.Payload.Property.GetHasCode() { + userStats.MemoTypeStats.CodeCount++ } - userStatsList = append(userStatsList, userStats) } - - return &v1pb.ListUserStatsResponse{ - UserStats: userStatsList, - }, nil + return userStats, nil } func getDefaultUserSetting(workspaceMemoRelatedSetting *storepb.WorkspaceMemoRelatedSetting) *v1pb.UserSetting {