diff --git a/proto/api/v1/memo_service.proto b/proto/api/v1/memo_service.proto index d1ac3d177872c..f7a91266940bf 100644 --- a/proto/api/v1/memo_service.proto +++ b/proto/api/v1/memo_service.proto @@ -176,6 +176,9 @@ message Memo { // The location of the memo. optional Location location = 20; + + // The nest of the memo. + string nest = 21; } message MemoProperty { @@ -202,6 +205,8 @@ message CreateMemoRequest { repeated MemoRelation relations = 4; optional Location location = 5; + + string nest = 6; } enum MemoView { diff --git a/proto/api/v1/nest_service.proto b/proto/api/v1/nest_service.proto new file mode 100644 index 0000000000000..4b8ecba5e8fce --- /dev/null +++ b/proto/api/v1/nest_service.proto @@ -0,0 +1,99 @@ +syntax = "proto3"; + +package memos.api.v1; + +import "google/api/annotations.proto"; +import "google/api/client.proto"; +import "google/api/field_behavior.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "gen/api/v1"; + +service NestService { + // CreateNest creates a new nest. + rpc CreateNest(CreateNestRequest) returns (Nest) { + option (google.api.http) = { + post: "/api/v1/nests" + body: "name" + }; + } + // ListNests lists all nests. + rpc ListNests(ListNestsRequest) returns (ListNestsResponse) { + option (google.api.http) = {get: "/api/v1/nests"}; + } + // GetNest returns a nest by id. + rpc GetNest(GetNestRequest) returns (Nest) { + option (google.api.http) = {get: "/api/v1/{id=nests/*}"}; + option (google.api.method_signature) = "id"; + } + // GetNestByName returns a nest by name. + rpc GetNestByName(GetNestByNameRequest) returns (Nest) { + option (google.api.http) = {get: "/api/v1/nests:by-name/{name}"}; + option (google.api.method_signature) = "name"; + } + // UpdateNest updates a nest. + rpc UpdateNest(UpdateNestRequest) returns (Nest) { + option (google.api.http) = { + patch: "/api/v1/{nest.id=nests/*}" + body: "nest" + }; + option (google.api.method_signature) = "nest,update_mask"; + } + // DeleteNest deletes a nest by id. + rpc DeleteNest(DeleteNestRequest) returns (google.protobuf.Empty) { + option (google.api.http) = {delete: "/api/v1/{id=nests/*}/moveto/{move_to=nests/*}"}; + option (google.api.method_signature) = "id,moveto"; + } +} + +message Nest { + // The id of the nest. + // Format: nests/{id} + // id is the system generated unique identifier. + string id = 1; + + // The user defined name of the nest. + string name = 2; + + google.protobuf.Timestamp create_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY]; +} + +message CreateNestRequest { + string name = 1; +} + +message ListNestsRequest {} + +message ListNestsResponse { + repeated Nest nests = 1; +} + +message GetNestRequest { + // The id of the nest. + // Format: nest/{id} + // id is the system generated unique identifier. + string id = 1; +} + +message GetNestByNameRequest { + // The name of the nest. + string name = 1; +} + +message UpdateNestRequest { + Nest nest = 1; + + google.protobuf.FieldMask update_mask = 2; +} + +message DeleteNestRequest { + // The id of the nest. + // Format: nests/{id} + // id is the system generated unique identifier. + string id = 1; + + // The nest id where to move the memos of the nest being deleted. + string move_to = 2; +} diff --git a/proto/api/v1/user_service.proto b/proto/api/v1/user_service.proto index 80fdf98a513a5..a12a5770b7035 100644 --- a/proto/api/v1/user_service.proto +++ b/proto/api/v1/user_service.proto @@ -178,6 +178,8 @@ message UserSetting { string appearance = 3; // The default visibility of the memo. string memo_visibility = 4; + // The default nest of the user. + string nest = 5; } message GetUserSettingRequest { diff --git a/proto/gen/api/v1/memo_service.pb.go b/proto/gen/api/v1/memo_service.pb.go index b42a6ad33a3ab..fd0730d2ec5ff 100644 --- a/proto/gen/api/v1/memo_service.pb.go +++ b/proto/gen/api/v1/memo_service.pb.go @@ -161,6 +161,8 @@ type Memo struct { Snippet string `protobuf:"bytes,19,opt,name=snippet,proto3" json:"snippet,omitempty"` // The location of the memo. Location *Location `protobuf:"bytes,20,opt,name=location,proto3,oneof" json:"location,omitempty"` + // The nest of the memo. + Nest string `protobuf:"bytes,21,opt,name=nest,proto3" json:"nest,omitempty"` } func (x *Memo) Reset() { @@ -326,6 +328,13 @@ func (x *Memo) GetLocation() *Location { return nil } +func (x *Memo) GetNest() string { + if x != nil { + return x.Nest + } + return "" +} + type MemoProperty struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -474,6 +483,7 @@ type CreateMemoRequest struct { Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"` Relations []*MemoRelation `protobuf:"bytes,4,rep,name=relations,proto3" json:"relations,omitempty"` Location *Location `protobuf:"bytes,5,opt,name=location,proto3,oneof" json:"location,omitempty"` + Nest string `protobuf:"bytes,6,opt,name=nest,proto3" json:"nest,omitempty"` } func (x *CreateMemoRequest) Reset() { @@ -541,6 +551,13 @@ func (x *CreateMemoRequest) GetLocation() *Location { return nil } +func (x *CreateMemoRequest) GetNest() string { + if x != nil { + return x.Nest + } + return "" +} + type ListMemosRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1649,7 +1666,7 @@ var file_api_v1_memo_service_proto_rawDesc = []byte{ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe5, 0x06, 0x0a, 0x04, 0x4d, 0x65, 0x6d, 0x6f, + 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf9, 0x06, 0x0a, 0x04, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x72, 0x6f, 0x77, 0x5f, 0x73, 0x74, @@ -1702,310 +1719,312 @@ var file_api_v1_memo_service_proto_rawDesc = []byte{ 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0xae, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, - 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, - 0x74, 0x61, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, - 0x22, 0x0a, 0x0d, 0x68, 0x61, 0x73, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x6c, 0x69, 0x73, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x68, 0x61, 0x73, 0x54, 0x61, 0x73, 0x6b, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x30, - 0x0a, 0x14, 0x68, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x68, 0x61, - 0x73, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x73, - 0x22, 0x66, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, - 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x1a, - 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, - 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, - 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x6c, - 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x22, 0x9d, 0x02, 0x0a, 0x11, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, - 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x08, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x92, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, - 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, - 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x12, 0x2a, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x65, 0x6d, 0x6f, 0x56, 0x69, 0x65, 0x77, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x22, 0x65, 0x0a, - 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x26, 0x0a, 0x0f, - 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x24, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x27, 0x0a, 0x13, 0x47, 0x65, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x42, 0x79, 0x55, 0x69, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x75, 0x69, 0x64, 0x22, 0x78, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, - 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, 0x27, 0x0a, - 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x60, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x6c, 0x64, 0x5f, 0x74, 0x61, - 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x6c, 0x64, 0x54, 0x61, 0x67, 0x12, - 0x17, 0x0a, 0x07, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x6e, 0x65, 0x77, 0x54, 0x61, 0x67, 0x22, 0x72, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x22, 0x63, 0x0a, 0x17, - 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x34, 0x0a, 0x09, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x22, 0x2e, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x51, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, - 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x22, 0x67, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 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, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x2e, 0x0a, - 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 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, 0x55, 0x0a, - 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, - 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x69, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, - 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 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, 0x39, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, - 0x2d, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, - 0x6e, 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, 0x22, 0x44, - 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d, 0x65, + 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x65, 0x73, 0x74, 0x18, + 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x65, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x5f, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0xae, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x70, + 0x65, 0x72, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, + 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x4c, + 0x69, 0x6e, 0x6b, 0x12, 0x22, 0x0a, 0x0d, 0x68, 0x61, 0x73, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, + 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x68, 0x61, 0x73, 0x54, + 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x12, 0x68, 0x61, 0x73, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x54, + 0x61, 0x73, 0x6b, 0x73, 0x22, 0x66, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, + 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x22, 0xb1, 0x02, 0x0a, + 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0a, + 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x09, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x48, 0x00, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x65, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x65, 0x73, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x92, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x04, 0x76, 0x69, 0x65, + 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x56, 0x69, 0x65, 0x77, 0x52, + 0x04, 0x76, 0x69, 0x65, 0x77, 0x22, 0x65, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, + 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x05, 0x6d, - 0x65, 0x6d, 0x6f, 0x73, 0x22, 0x2e, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, - 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 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, 0x51, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, - 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x63, 0x0a, 0x19, 0x55, 0x70, 0x73, 0x65, 0x72, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 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, 0x32, 0x0a, 0x08, 0x72, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3c, 0x0a, 0x19, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, - 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x2a, 0x50, 0x0a, 0x0a, 0x56, 0x69, - 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, - 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, - 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, - 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x08, - 0x4d, 0x65, 0x6d, 0x6f, 0x56, 0x69, 0x65, 0x77, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x4f, - 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x56, 0x49, 0x45, 0x57, - 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, - 0x56, 0x49, 0x45, 0x57, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x4f, 0x4e, - 0x4c, 0x59, 0x10, 0x02, 0x32, 0x9d, 0x11, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, - 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, - 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x1e, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x62, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, - 0x6f, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x65, 0x6d, 0x6f, 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, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x6f, 0x0a, 0x0c, 0x47, 0x65, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x42, 0x79, 0x55, 0x69, 0x64, 0x12, 0x21, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, - 0x6f, 0x42, 0x79, 0x55, 0x69, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, - 0x6f, 0x22, 0x28, 0xda, 0x41, 0x03, 0x75, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, - 0x1a, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x62, - 0x79, 0x2d, 0x75, 0x69, 0x64, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x12, 0x7f, 0x0a, 0x0a, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, - 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x22, 0x3c, - 0xda, 0x41, 0x10, 0x6d, 0x65, 0x6d, 0x6f, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, - 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x3a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x32, - 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6d, 0x65, 0x6d, 0x6f, 0x2e, 0x6e, - 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x6c, 0x0a, 0x0a, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x4d, 0x65, 0x6d, 0x6f, 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, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x7c, 0x0a, 0x0d, 0x52, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 0x12, 0x22, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 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, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, - 0x01, 0x2a, 0x32, 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x74, 0x61, 0x67, - 0x73, 0x3a, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x78, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, - 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, + 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x24, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x27, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x42, 0x79, 0x55, + 0x69, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x78, 0x0a, 0x11, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 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, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x2a, 0x23, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x6d, - 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x74, 0x61, 0x67, 0x73, 0x2f, 0x7b, 0x74, 0x61, - 0x67, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 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, 0x32, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x32, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x11, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x27, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, + 0x65, 0x6d, 0x6f, 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, 0x60, + 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x17, + 0x0a, 0x07, 0x6f, 0x6c, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x6f, 0x6c, 0x64, 0x54, 0x61, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x65, 0x77, 0x5f, 0x74, + 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x65, 0x77, 0x54, 0x61, 0x67, + 0x22, 0x72, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, + 0x61, 0x67, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x12, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4d, + 0x65, 0x6d, 0x6f, 0x73, 0x22, 0x63, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x2e, 0x0a, 0x18, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x51, 0x0a, 0x19, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x67, 0x0a, 0x17, + 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 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, 0x12, 0x38, 0x0a, 0x09, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x2e, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, + 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 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, 0x55, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, + 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x69, 0x0a, 0x18, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 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, 0x39, 0x0a, 0x07, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x2d, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 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, 0x22, 0x44, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x22, 0x2e, 0x0a, 0x18, + 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 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, 0x51, 0x0a, 0x19, + 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0x63, 0x0a, 0x19, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, + 0x63, 0x74, 0x69, 0x6f, 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, 0x32, 0x0a, 0x08, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3c, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x2a, 0x50, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x4f, + 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, + 0x49, 0x43, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x08, 0x4d, 0x65, 0x6d, 0x6f, 0x56, 0x69, 0x65, 0x77, + 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4d, + 0x45, 0x4d, 0x4f, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x10, 0x01, 0x12, + 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x4d, 0x45, 0x54, + 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x32, 0x9d, 0x11, 0x0a, + 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0a, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x22, + 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x62, + 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, + 0x2a, 0x7d, 0x12, 0x6f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x42, 0x79, 0x55, + 0x69, 0x64, 0x12, 0x21, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x42, 0x79, 0x55, 0x69, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x22, 0x28, 0xda, 0x41, 0x03, 0x75, 0x69, + 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, + 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x62, 0x79, 0x2d, 0x75, 0x69, 0x64, 0x2f, 0x7b, 0x75, + 0x69, 0x64, 0x7d, 0x12, 0x7f, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, + 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x22, 0x3c, 0xda, 0x41, 0x10, 0x6d, 0x65, 0x6d, 0x6f, 0x2c, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x23, 0x3a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x32, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, + 0x2f, 0x7b, 0x6d, 0x65, 0x6d, 0x6f, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x6c, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, + 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 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, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, + 0x2a, 0x7d, 0x12, 0x7c, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x65, 0x6d, 0x6f, + 0x54, 0x61, 0x67, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, + 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, + 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x32, 0x24, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x74, 0x61, 0x67, 0x73, 0x3a, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x78, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, + 0x67, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x54, 0x61, 0x67, 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, 0x2b, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x2a, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, + 0x74, 0x61, 0x67, 0x73, 0x2f, 0x7b, 0x74, 0x61, 0x67, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x10, 0x53, + 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, + 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 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, 0x32, + 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, + 0x32, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0xda, 0x41, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, + 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x10, 0x53, + 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0x32, + 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, + 0x32, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x2f, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, - 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0x32, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x32, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0xda, 0x41, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, - 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x11, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x11, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, - 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x2f, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, - 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, - 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, - 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x65, 0x6d, 0x6f, 0x22, 0x37, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x2a, 0x3a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x1f, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x91, 0x01, - 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 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, 0x4d, 0x65, 0x6d, - 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x2e, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, - 0x12, 0x1f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x95, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, - 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x22, 0x37, 0xda, 0x41, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x3a, 0x07, 0x63, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x1f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, + 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x91, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 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, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0xda, 0x41, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, + 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x11, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, - 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, - 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x89, 0x01, 0x0a, 0x12, 0x55, 0x70, - 0x73, 0x65, 0x72, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x22, 0x32, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, - 0x3a, 0x01, 0x2a, 0x22, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, - 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x6d, - 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 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, 0x35, 0xda, - 0x41, 0x0b, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x21, 0x2a, 0x1f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x7d, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x10, 0x4d, 0x65, 0x6d, 0x6f, 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, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, + 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2f, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, + 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x89, 0x01, 0x0a, 0x12, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x65, 0x6d, 0x6f, + 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x32, 0xda, 0x41, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x22, 0x20, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2f, 0x2a, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x8c, 0x01, + 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, + 0x61, 0x63, 0x74, 0x69, 0x6f, 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, 0x35, 0xda, 0x41, 0x0b, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x2a, 0x1f, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, + 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x42, 0xa8, 0x01, 0x0a, + 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x42, 0x10, 0x4d, 0x65, 0x6d, 0x6f, 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 ( diff --git a/proto/gen/api/v1/nest_service.pb.go b/proto/gen/api/v1/nest_service.pb.go new file mode 100644 index 0000000000000..c7e04bd1d8a2b --- /dev/null +++ b/proto/gen/api/v1/nest_service.pb.go @@ -0,0 +1,600 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.35.1 +// protoc (unknown) +// source: api/v1/nest_service.proto + +package apiv1 + +import ( + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Nest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The id of the nest. + // Format: nests/{id} + // id is the system generated unique identifier. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // The user defined name of the nest. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + CreateTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"` +} + +func (x *Nest) Reset() { + *x = Nest{} + mi := &file_api_v1_nest_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Nest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Nest) ProtoMessage() {} + +func (x *Nest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[0] + 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 Nest.ProtoReflect.Descriptor instead. +func (*Nest) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{0} +} + +func (x *Nest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Nest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Nest) GetCreateTime() *timestamppb.Timestamp { + if x != nil { + return x.CreateTime + } + return nil +} + +type CreateNestRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *CreateNestRequest) Reset() { + *x = CreateNestRequest{} + mi := &file_api_v1_nest_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateNestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateNestRequest) ProtoMessage() {} + +func (x *CreateNestRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[1] + 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 CreateNestRequest.ProtoReflect.Descriptor instead. +func (*CreateNestRequest) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateNestRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type ListNestsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListNestsRequest) Reset() { + *x = ListNestsRequest{} + mi := &file_api_v1_nest_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListNestsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListNestsRequest) ProtoMessage() {} + +func (x *ListNestsRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[2] + 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 ListNestsRequest.ProtoReflect.Descriptor instead. +func (*ListNestsRequest) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{2} +} + +type ListNestsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Nests []*Nest `protobuf:"bytes,1,rep,name=nests,proto3" json:"nests,omitempty"` +} + +func (x *ListNestsResponse) Reset() { + *x = ListNestsResponse{} + mi := &file_api_v1_nest_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListNestsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListNestsResponse) ProtoMessage() {} + +func (x *ListNestsResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[3] + 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 ListNestsResponse.ProtoReflect.Descriptor instead. +func (*ListNestsResponse) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{3} +} + +func (x *ListNestsResponse) GetNests() []*Nest { + if x != nil { + return x.Nests + } + return nil +} + +type GetNestRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The id of the nest. + // Format: nest/{id} + // id is the system generated unique identifier. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetNestRequest) Reset() { + *x = GetNestRequest{} + mi := &file_api_v1_nest_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetNestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNestRequest) ProtoMessage() {} + +func (x *GetNestRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[4] + 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 GetNestRequest.ProtoReflect.Descriptor instead. +func (*GetNestRequest) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{4} +} + +func (x *GetNestRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type GetNestByNameRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the nest. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetNestByNameRequest) Reset() { + *x = GetNestByNameRequest{} + mi := &file_api_v1_nest_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetNestByNameRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNestByNameRequest) ProtoMessage() {} + +func (x *GetNestByNameRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[5] + 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 GetNestByNameRequest.ProtoReflect.Descriptor instead. +func (*GetNestByNameRequest) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{5} +} + +func (x *GetNestByNameRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UpdateNestRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Nest *Nest `protobuf:"bytes,1,opt,name=nest,proto3" json:"nest,omitempty"` + UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` +} + +func (x *UpdateNestRequest) Reset() { + *x = UpdateNestRequest{} + mi := &file_api_v1_nest_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateNestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateNestRequest) ProtoMessage() {} + +func (x *UpdateNestRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[6] + 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 UpdateNestRequest.ProtoReflect.Descriptor instead. +func (*UpdateNestRequest) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{6} +} + +func (x *UpdateNestRequest) GetNest() *Nest { + if x != nil { + return x.Nest + } + return nil +} + +func (x *UpdateNestRequest) GetUpdateMask() *fieldmaskpb.FieldMask { + if x != nil { + return x.UpdateMask + } + return nil +} + +type DeleteNestRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The id of the nest. + // Format: nests/{id} + // id is the system generated unique identifier. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // The nest id where to move the memos of the nest being deleted. + MoveTo string `protobuf:"bytes,2,opt,name=move_to,json=moveTo,proto3" json:"move_to,omitempty"` +} + +func (x *DeleteNestRequest) Reset() { + *x = DeleteNestRequest{} + mi := &file_api_v1_nest_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteNestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteNestRequest) ProtoMessage() {} + +func (x *DeleteNestRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_nest_service_proto_msgTypes[7] + 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 DeleteNestRequest.ProtoReflect.Descriptor instead. +func (*DeleteNestRequest) Descriptor() ([]byte, []int) { + return file_api_v1_nest_service_proto_rawDescGZIP(), []int{7} +} + +func (x *DeleteNestRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *DeleteNestRequest) GetMoveTo() string { + if x != nil { + return x.MoveTo + } + return "" +} + +var File_api_v1_nest_service_proto protoreflect.FileDescriptor + +var file_api_v1_nest_service_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x6d, 0x0a, 0x04, 0x4e, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, + 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 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, 0x42, 0x04, + 0xe2, 0x41, 0x01, 0x03, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x22, 0x27, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x73, 0x74, 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, 0x12, 0x0a, 0x10, 0x4c, 0x69, 0x73, + 0x74, 0x4e, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3d, 0x0a, + 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x52, 0x05, 0x6e, 0x65, 0x73, 0x74, 0x73, 0x22, 0x20, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2a, + 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 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, 0x78, 0x0a, 0x11, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x26, 0x0a, 0x04, 0x6e, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x73, + 0x74, 0x52, 0x04, 0x6e, 0x65, 0x73, 0x74, 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, 0x3c, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x65, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x6f, 0x76, + 0x65, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x76, 0x65, + 0x54, 0x6f, 0x32, 0xb2, 0x05, 0x0a, 0x0b, 0x4e, 0x65, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x5e, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x73, 0x74, + 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x22, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x65, 0x73, + 0x74, 0x73, 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x73, 0x12, + 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x4e, 0x65, 0x73, 0x74, 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, 0x4e, 0x65, 0x73, 0x74, 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, 0x6e, 0x65, 0x73, 0x74, 0x73, 0x12, 0x5e, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, 0x65, + 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x65, 0x73, 0x74, 0x22, 0x21, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x16, 0x12, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x69, 0x64, 0x3d, 0x6e, + 0x65, 0x73, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x74, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x65, + 0x73, 0x74, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x42, + 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x73, 0x74, + 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, 0x6e, 0x65, 0x73, 0x74, 0x73, 0x3a, 0x62, + 0x79, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x7d, 0x0a, + 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4e, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x73, 0x74, + 0x22, 0x3a, 0xda, 0x41, 0x10, 0x6e, 0x65, 0x73, 0x74, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x04, 0x6e, 0x65, 0x73, + 0x74, 0x32, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x65, 0x73, 0x74, + 0x2e, 0x69, 0x64, 0x3d, 0x6e, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x88, 0x01, 0x0a, + 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4e, 0x65, 0x73, 0x74, 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, 0x41, 0xda, 0x41, 0x09, 0x69, 0x64, 0x2c, 0x6d, 0x6f, 0x76, 0x65, + 0x74, 0x6f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x2a, 0x2d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x31, 0x2f, 0x7b, 0x69, 0x64, 0x3d, 0x6e, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x6d, + 0x6f, 0x76, 0x65, 0x74, 0x6f, 0x2f, 0x7b, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x74, 0x6f, 0x3d, 0x6e, + 0x65, 0x73, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x10, 0x4e, 0x65, + 0x73, 0x74, 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 ( + file_api_v1_nest_service_proto_rawDescOnce sync.Once + file_api_v1_nest_service_proto_rawDescData = file_api_v1_nest_service_proto_rawDesc +) + +func file_api_v1_nest_service_proto_rawDescGZIP() []byte { + file_api_v1_nest_service_proto_rawDescOnce.Do(func() { + file_api_v1_nest_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_v1_nest_service_proto_rawDescData) + }) + return file_api_v1_nest_service_proto_rawDescData +} + +var file_api_v1_nest_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_api_v1_nest_service_proto_goTypes = []any{ + (*Nest)(nil), // 0: memos.api.v1.Nest + (*CreateNestRequest)(nil), // 1: memos.api.v1.CreateNestRequest + (*ListNestsRequest)(nil), // 2: memos.api.v1.ListNestsRequest + (*ListNestsResponse)(nil), // 3: memos.api.v1.ListNestsResponse + (*GetNestRequest)(nil), // 4: memos.api.v1.GetNestRequest + (*GetNestByNameRequest)(nil), // 5: memos.api.v1.GetNestByNameRequest + (*UpdateNestRequest)(nil), // 6: memos.api.v1.UpdateNestRequest + (*DeleteNestRequest)(nil), // 7: memos.api.v1.DeleteNestRequest + (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp + (*fieldmaskpb.FieldMask)(nil), // 9: google.protobuf.FieldMask + (*emptypb.Empty)(nil), // 10: google.protobuf.Empty +} +var file_api_v1_nest_service_proto_depIdxs = []int32{ + 8, // 0: memos.api.v1.Nest.create_time:type_name -> google.protobuf.Timestamp + 0, // 1: memos.api.v1.ListNestsResponse.nests:type_name -> memos.api.v1.Nest + 0, // 2: memos.api.v1.UpdateNestRequest.nest:type_name -> memos.api.v1.Nest + 9, // 3: memos.api.v1.UpdateNestRequest.update_mask:type_name -> google.protobuf.FieldMask + 1, // 4: memos.api.v1.NestService.CreateNest:input_type -> memos.api.v1.CreateNestRequest + 2, // 5: memos.api.v1.NestService.ListNests:input_type -> memos.api.v1.ListNestsRequest + 4, // 6: memos.api.v1.NestService.GetNest:input_type -> memos.api.v1.GetNestRequest + 5, // 7: memos.api.v1.NestService.GetNestByName:input_type -> memos.api.v1.GetNestByNameRequest + 6, // 8: memos.api.v1.NestService.UpdateNest:input_type -> memos.api.v1.UpdateNestRequest + 7, // 9: memos.api.v1.NestService.DeleteNest:input_type -> memos.api.v1.DeleteNestRequest + 0, // 10: memos.api.v1.NestService.CreateNest:output_type -> memos.api.v1.Nest + 3, // 11: memos.api.v1.NestService.ListNests:output_type -> memos.api.v1.ListNestsResponse + 0, // 12: memos.api.v1.NestService.GetNest:output_type -> memos.api.v1.Nest + 0, // 13: memos.api.v1.NestService.GetNestByName:output_type -> memos.api.v1.Nest + 0, // 14: memos.api.v1.NestService.UpdateNest:output_type -> memos.api.v1.Nest + 10, // 15: memos.api.v1.NestService.DeleteNest:output_type -> google.protobuf.Empty + 10, // [10:16] is the sub-list for method output_type + 4, // [4:10] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_api_v1_nest_service_proto_init() } +func file_api_v1_nest_service_proto_init() { + if File_api_v1_nest_service_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_v1_nest_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_api_v1_nest_service_proto_goTypes, + DependencyIndexes: file_api_v1_nest_service_proto_depIdxs, + MessageInfos: file_api_v1_nest_service_proto_msgTypes, + }.Build() + File_api_v1_nest_service_proto = out.File + file_api_v1_nest_service_proto_rawDesc = nil + file_api_v1_nest_service_proto_goTypes = nil + file_api_v1_nest_service_proto_depIdxs = nil +} diff --git a/proto/gen/api/v1/nest_service.pb.gw.go b/proto/gen/api/v1/nest_service.pb.gw.go new file mode 100644 index 0000000000000..b6cd77a241e9d --- /dev/null +++ b/proto/gen/api/v1/nest_service.pb.gw.go @@ -0,0 +1,713 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: api/v1/nest_service.proto + +/* +Package apiv1 is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package apiv1 + +import ( + "context" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = metadata.Join + +func request_NestService_CreateNest_0(ctx context.Context, marshaler runtime.Marshaler, client NestServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CreateNestRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Name); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.CreateNest(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_NestService_CreateNest_0(ctx context.Context, marshaler runtime.Marshaler, server NestServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CreateNestRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Name); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.CreateNest(ctx, &protoReq) + return msg, metadata, err + +} + +func request_NestService_ListNests_0(ctx context.Context, marshaler runtime.Marshaler, client NestServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListNestsRequest + var metadata runtime.ServerMetadata + + msg, err := client.ListNests(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_NestService_ListNests_0(ctx context.Context, marshaler runtime.Marshaler, server NestServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListNestsRequest + var metadata runtime.ServerMetadata + + msg, err := server.ListNests(ctx, &protoReq) + return msg, metadata, err + +} + +func request_NestService_GetNest_0(ctx context.Context, marshaler runtime.Marshaler, client NestServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetNestRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.GetNest(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_NestService_GetNest_0(ctx context.Context, marshaler runtime.Marshaler, server NestServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetNestRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.GetNest(ctx, &protoReq) + return msg, metadata, err + +} + +func request_NestService_GetNestByName_0(ctx context.Context, marshaler runtime.Marshaler, client NestServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetNestByNameRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") + } + + protoReq.Name, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) + } + + msg, err := client.GetNestByName(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_NestService_GetNestByName_0(ctx context.Context, marshaler runtime.Marshaler, server NestServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetNestByNameRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") + } + + protoReq.Name, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) + } + + msg, err := server.GetNestByName(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_NestService_UpdateNest_0 = &utilities.DoubleArray{Encoding: map[string]int{"nest": 0, "id": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}} +) + +func request_NestService_UpdateNest_0(ctx context.Context, marshaler runtime.Marshaler, client NestServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq UpdateNestRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Nest); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 { + if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Nest); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } else { + protoReq.UpdateMask = fieldMask + } + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["nest.id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "nest.id") + } + + err = runtime.PopulateFieldFromPath(&protoReq, "nest.id", val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "nest.id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NestService_UpdateNest_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.UpdateNest(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_NestService_UpdateNest_0(ctx context.Context, marshaler runtime.Marshaler, server NestServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq UpdateNestRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Nest); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 { + if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Nest); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } else { + protoReq.UpdateMask = fieldMask + } + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["nest.id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "nest.id") + } + + err = runtime.PopulateFieldFromPath(&protoReq, "nest.id", val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "nest.id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NestService_UpdateNest_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.UpdateNest(ctx, &protoReq) + return msg, metadata, err + +} + +func request_NestService_DeleteNest_0(ctx context.Context, marshaler runtime.Marshaler, client NestServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq DeleteNestRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + val, ok = pathParams["move_to"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "move_to") + } + + protoReq.MoveTo, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "move_to", err) + } + + msg, err := client.DeleteNest(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_NestService_DeleteNest_0(ctx context.Context, marshaler runtime.Marshaler, server NestServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq DeleteNestRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + val, ok = pathParams["move_to"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "move_to") + } + + protoReq.MoveTo, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "move_to", err) + } + + msg, err := server.DeleteNest(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterNestServiceHandlerServer registers the http handlers for service NestService to "mux". +// UnaryRPC :call NestServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterNestServiceHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. +func RegisterNestServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server NestServiceServer) error { + + mux.Handle("POST", pattern_NestService_CreateNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.NestService/CreateNest", runtime.WithHTTPPathPattern("/api/v1/nests")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_NestService_CreateNest_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_NestService_CreateNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_NestService_ListNests_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.NestService/ListNests", runtime.WithHTTPPathPattern("/api/v1/nests")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_NestService_ListNests_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_NestService_ListNests_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_NestService_GetNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.NestService/GetNest", runtime.WithHTTPPathPattern("/api/v1/{id=nests/*}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_NestService_GetNest_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_NestService_GetNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_NestService_GetNestByName_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.NestService/GetNestByName", runtime.WithHTTPPathPattern("/api/v1/nests:by-name/{name}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_NestService_GetNestByName_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_NestService_GetNestByName_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PATCH", pattern_NestService_UpdateNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.NestService/UpdateNest", runtime.WithHTTPPathPattern("/api/v1/{nest.id=nests/*}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_NestService_UpdateNest_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_NestService_UpdateNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("DELETE", pattern_NestService_DeleteNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.NestService/DeleteNest", runtime.WithHTTPPathPattern("/api/v1/{id=nests/*}/moveto/{move_to=nests/*}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_NestService_DeleteNest_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_NestService_DeleteNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterNestServiceHandlerFromEndpoint is same as RegisterNestServiceHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterNestServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.NewClient(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterNestServiceHandler(ctx, mux, conn) +} + +// RegisterNestServiceHandler registers the http handlers for service NestService to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterNestServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterNestServiceHandlerClient(ctx, mux, NewNestServiceClient(conn)) +} + +// RegisterNestServiceHandlerClient registers the http handlers for service NestService +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "NestServiceClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "NestServiceClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "NestServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. +func RegisterNestServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client NestServiceClient) error { + + mux.Handle("POST", pattern_NestService_CreateNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.NestService/CreateNest", runtime.WithHTTPPathPattern("/api/v1/nests")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_NestService_CreateNest_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NestService_CreateNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_NestService_ListNests_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.NestService/ListNests", runtime.WithHTTPPathPattern("/api/v1/nests")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_NestService_ListNests_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NestService_ListNests_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_NestService_GetNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.NestService/GetNest", runtime.WithHTTPPathPattern("/api/v1/{id=nests/*}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_NestService_GetNest_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NestService_GetNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_NestService_GetNestByName_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.NestService/GetNestByName", runtime.WithHTTPPathPattern("/api/v1/nests:by-name/{name}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_NestService_GetNestByName_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NestService_GetNestByName_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PATCH", pattern_NestService_UpdateNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.NestService/UpdateNest", runtime.WithHTTPPathPattern("/api/v1/{nest.id=nests/*}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_NestService_UpdateNest_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NestService_UpdateNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("DELETE", pattern_NestService_DeleteNest_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.NestService/DeleteNest", runtime.WithHTTPPathPattern("/api/v1/{id=nests/*}/moveto/{move_to=nests/*}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_NestService_DeleteNest_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NestService_DeleteNest_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_NestService_CreateNest_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "nests"}, "")) + + pattern_NestService_ListNests_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "nests"}, "")) + + pattern_NestService_GetNest_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "nests", "id"}, "")) + + pattern_NestService_GetNestByName_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "nests:by-name", "name"}, "")) + + pattern_NestService_UpdateNest_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "nests", "nest.id"}, "")) + + pattern_NestService_DeleteNest_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4, 2, 2, 1, 0, 4, 2, 5, 5}, []string{"api", "v1", "nests", "id", "moveto", "move_to"}, "")) +) + +var ( + forward_NestService_CreateNest_0 = runtime.ForwardResponseMessage + + forward_NestService_ListNests_0 = runtime.ForwardResponseMessage + + forward_NestService_GetNest_0 = runtime.ForwardResponseMessage + + forward_NestService_GetNestByName_0 = runtime.ForwardResponseMessage + + forward_NestService_UpdateNest_0 = runtime.ForwardResponseMessage + + forward_NestService_DeleteNest_0 = runtime.ForwardResponseMessage +) diff --git a/proto/gen/api/v1/nest_service_grpc.pb.go b/proto/gen/api/v1/nest_service_grpc.pb.go new file mode 100644 index 0000000000000..242498c15e7ac --- /dev/null +++ b/proto/gen/api/v1/nest_service_grpc.pb.go @@ -0,0 +1,324 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc (unknown) +// source: api/v1/nest_service.proto + +package apiv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + NestService_CreateNest_FullMethodName = "/memos.api.v1.NestService/CreateNest" + NestService_ListNests_FullMethodName = "/memos.api.v1.NestService/ListNests" + NestService_GetNest_FullMethodName = "/memos.api.v1.NestService/GetNest" + NestService_GetNestByName_FullMethodName = "/memos.api.v1.NestService/GetNestByName" + NestService_UpdateNest_FullMethodName = "/memos.api.v1.NestService/UpdateNest" + NestService_DeleteNest_FullMethodName = "/memos.api.v1.NestService/DeleteNest" +) + +// NestServiceClient is the client API for NestService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type NestServiceClient interface { + // CreateNest creates a new nest. + CreateNest(ctx context.Context, in *CreateNestRequest, opts ...grpc.CallOption) (*Nest, error) + // ListNests lists all nests. + ListNests(ctx context.Context, in *ListNestsRequest, opts ...grpc.CallOption) (*ListNestsResponse, error) + // GetNest returns a nest by id. + GetNest(ctx context.Context, in *GetNestRequest, opts ...grpc.CallOption) (*Nest, error) + // GetNestByName returns a nest by name. + GetNestByName(ctx context.Context, in *GetNestByNameRequest, opts ...grpc.CallOption) (*Nest, error) + // UpdateNest updates a nest. + UpdateNest(ctx context.Context, in *UpdateNestRequest, opts ...grpc.CallOption) (*Nest, error) + // DeleteNest deletes a nest by id. + DeleteNest(ctx context.Context, in *DeleteNestRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) +} + +type nestServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewNestServiceClient(cc grpc.ClientConnInterface) NestServiceClient { + return &nestServiceClient{cc} +} + +func (c *nestServiceClient) CreateNest(ctx context.Context, in *CreateNestRequest, opts ...grpc.CallOption) (*Nest, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Nest) + err := c.cc.Invoke(ctx, NestService_CreateNest_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nestServiceClient) ListNests(ctx context.Context, in *ListNestsRequest, opts ...grpc.CallOption) (*ListNestsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListNestsResponse) + err := c.cc.Invoke(ctx, NestService_ListNests_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nestServiceClient) GetNest(ctx context.Context, in *GetNestRequest, opts ...grpc.CallOption) (*Nest, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Nest) + err := c.cc.Invoke(ctx, NestService_GetNest_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nestServiceClient) GetNestByName(ctx context.Context, in *GetNestByNameRequest, opts ...grpc.CallOption) (*Nest, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Nest) + err := c.cc.Invoke(ctx, NestService_GetNestByName_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nestServiceClient) UpdateNest(ctx context.Context, in *UpdateNestRequest, opts ...grpc.CallOption) (*Nest, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Nest) + err := c.cc.Invoke(ctx, NestService_UpdateNest_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nestServiceClient) DeleteNest(ctx context.Context, in *DeleteNestRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, NestService_DeleteNest_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// NestServiceServer is the server API for NestService service. +// All implementations must embed UnimplementedNestServiceServer +// for forward compatibility. +type NestServiceServer interface { + // CreateNest creates a new nest. + CreateNest(context.Context, *CreateNestRequest) (*Nest, error) + // ListNests lists all nests. + ListNests(context.Context, *ListNestsRequest) (*ListNestsResponse, error) + // GetNest returns a nest by id. + GetNest(context.Context, *GetNestRequest) (*Nest, error) + // GetNestByName returns a nest by name. + GetNestByName(context.Context, *GetNestByNameRequest) (*Nest, error) + // UpdateNest updates a nest. + UpdateNest(context.Context, *UpdateNestRequest) (*Nest, error) + // DeleteNest deletes a nest by id. + DeleteNest(context.Context, *DeleteNestRequest) (*emptypb.Empty, error) + mustEmbedUnimplementedNestServiceServer() +} + +// UnimplementedNestServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedNestServiceServer struct{} + +func (UnimplementedNestServiceServer) CreateNest(context.Context, *CreateNestRequest) (*Nest, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateNest not implemented") +} +func (UnimplementedNestServiceServer) ListNests(context.Context, *ListNestsRequest) (*ListNestsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListNests not implemented") +} +func (UnimplementedNestServiceServer) GetNest(context.Context, *GetNestRequest) (*Nest, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNest not implemented") +} +func (UnimplementedNestServiceServer) GetNestByName(context.Context, *GetNestByNameRequest) (*Nest, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNestByName not implemented") +} +func (UnimplementedNestServiceServer) UpdateNest(context.Context, *UpdateNestRequest) (*Nest, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateNest not implemented") +} +func (UnimplementedNestServiceServer) DeleteNest(context.Context, *DeleteNestRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteNest not implemented") +} +func (UnimplementedNestServiceServer) mustEmbedUnimplementedNestServiceServer() {} +func (UnimplementedNestServiceServer) testEmbeddedByValue() {} + +// UnsafeNestServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to NestServiceServer will +// result in compilation errors. +type UnsafeNestServiceServer interface { + mustEmbedUnimplementedNestServiceServer() +} + +func RegisterNestServiceServer(s grpc.ServiceRegistrar, srv NestServiceServer) { + // If the following call pancis, it indicates UnimplementedNestServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&NestService_ServiceDesc, srv) +} + +func _NestService_CreateNest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateNestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NestServiceServer).CreateNest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NestService_CreateNest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NestServiceServer).CreateNest(ctx, req.(*CreateNestRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NestService_ListNests_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListNestsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NestServiceServer).ListNests(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NestService_ListNests_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NestServiceServer).ListNests(ctx, req.(*ListNestsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NestService_GetNest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NestServiceServer).GetNest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NestService_GetNest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NestServiceServer).GetNest(ctx, req.(*GetNestRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NestService_GetNestByName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNestByNameRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NestServiceServer).GetNestByName(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NestService_GetNestByName_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NestServiceServer).GetNestByName(ctx, req.(*GetNestByNameRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NestService_UpdateNest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateNestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NestServiceServer).UpdateNest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NestService_UpdateNest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NestServiceServer).UpdateNest(ctx, req.(*UpdateNestRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NestService_DeleteNest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteNestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NestServiceServer).DeleteNest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NestService_DeleteNest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NestServiceServer).DeleteNest(ctx, req.(*DeleteNestRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// NestService_ServiceDesc is the grpc.ServiceDesc for NestService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var NestService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "memos.api.v1.NestService", + HandlerType: (*NestServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateNest", + Handler: _NestService_CreateNest_Handler, + }, + { + MethodName: "ListNests", + Handler: _NestService_ListNests_Handler, + }, + { + MethodName: "GetNest", + Handler: _NestService_GetNest_Handler, + }, + { + MethodName: "GetNestByName", + Handler: _NestService_GetNestByName_Handler, + }, + { + MethodName: "UpdateNest", + Handler: _NestService_UpdateNest_Handler, + }, + { + MethodName: "DeleteNest", + Handler: _NestService_DeleteNest_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api/v1/nest_service.proto", +} diff --git a/proto/gen/api/v1/user_service.pb.go b/proto/gen/api/v1/user_service.pb.go index f007908d5fcf5..d65b4432308b4 100644 --- a/proto/gen/api/v1/user_service.pb.go +++ b/proto/gen/api/v1/user_service.pb.go @@ -648,6 +648,8 @@ type UserSetting struct { Appearance string `protobuf:"bytes,3,opt,name=appearance,proto3" json:"appearance,omitempty"` // The default visibility of the memo. MemoVisibility string `protobuf:"bytes,4,opt,name=memo_visibility,json=memoVisibility,proto3" json:"memo_visibility,omitempty"` + // The default nest of the user. + Nest string `protobuf:"bytes,5,opt,name=nest,proto3" json:"nest,omitempty"` } func (x *UserSetting) Reset() { @@ -708,6 +710,13 @@ func (x *UserSetting) GetMemoVisibility() string { return "" } +func (x *UserSetting) GetNest() string { + if x != nil { + return x.Nest + } + return "" +} + type GetUserSettingRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1174,7 +1183,7 @@ var file_api_v1_user_service_proto_rawDesc = []byte{ 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x27, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x82, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x96, 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, @@ -1183,168 +1192,169 @@ var file_api_v1_user_service_proto_rawDesc = []byte{ 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, 0x03, 0x20, 0x01, 0x28, + 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x65, 0x73, 0x74, 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, 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, 0xbc, 0x0c, 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, 0x7f, 0x0a, 0x0e, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x2e, + 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, 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, 0xbc, 0x0c, 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, 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, + 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, + 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, 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, + 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 ( diff --git a/proto/gen/apidocs.swagger.yaml b/proto/gen/apidocs.swagger.yaml index e2fade861c5ce..f29c4dc6e2ef2 100644 --- a/proto/gen/apidocs.swagger.yaml +++ b/proto/gen/apidocs.swagger.yaml @@ -11,6 +11,7 @@ tags: - name: MarkdownService - name: ResourceService - name: MemoService + - name: NestService - name: WebhookService - name: WorkspaceService - name: WorkspaceSettingService @@ -381,6 +382,62 @@ paths: type: string tags: - MemoService + /api/v1/nests: + get: + summary: ListNests lists all nests. + operationId: NestService_ListNests + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1ListNestsResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + tags: + - NestService + post: + summary: CreateNest creates a new nest. + operationId: NestService_CreateNest + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1Nest' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: name + in: body + required: true + schema: + type: string + tags: + - NestService + /api/v1/nests:by-name/{name}: + get: + summary: GetNestByName returns a nest by name. + operationId: NestService_GetNestByName + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1Nest' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: name + description: The name of the nest. + in: path + required: true + type: string + tags: + - NestService /api/v1/reactions/{reactionId}: delete: summary: DeleteMemoReaction deletes a reaction for a memo. @@ -759,6 +816,63 @@ paths: title: The identityProvider to update. tags: - IdentityProviderService + /api/v1/{id}: + get: + summary: GetNest returns a nest by id. + operationId: NestService_GetNest + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1Nest' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: id + description: |- + The id of the nest. + Format: nest/{id} + id is the system generated unique identifier. + in: path + required: true + type: string + pattern: nests/[^/]+ + tags: + - NestService + /api/v1/{id}/moveto/{moveTo}: + delete: + summary: DeleteNest deletes a nest by id. + operationId: NestService_DeleteNest + responses: + "200": + description: A successful response. + schema: + type: object + properties: {} + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: id + description: |- + The id of the nest. + Format: nests/{id} + id is the system generated unique identifier. + in: path + required: true + type: string + pattern: nests/[^/]+ + - name: moveTo + description: The nest id where to move the memos of the nest being deleted. + in: path + required: true + type: string + pattern: nests/[^/]+ + tags: + - NestService /api/v1/{inbox.name}: patch: summary: UpdateInbox updates an inbox. @@ -901,6 +1015,9 @@ paths: location: $ref: '#/definitions/apiv1Location' description: The location of the memo. + nest: + type: string + description: The nest of the memo. tags: - MemoService /api/v1/{name_1}: @@ -1461,6 +1578,44 @@ paths: pattern: users/[^/]+ tags: - UserService + /api/v1/{nest.id}: + patch: + summary: UpdateNest updates a nest. + operationId: NestService_UpdateNest + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1Nest' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: nest.id + description: |- + The id of the nest. + Format: nests/{id} + id is the system generated unique identifier. + in: path + required: true + type: string + pattern: nests/[^/]+ + - name: nest + in: body + required: true + schema: + type: object + properties: + name: + type: string + description: The user defined name of the nest. + createTime: + type: string + format: date-time + readOnly: true + tags: + - NestService /api/v1/{parent}/tags/{tag}: delete: summary: DeleteMemoTag deletes a tag for a memo. @@ -1616,6 +1771,9 @@ paths: memoVisibility: type: string description: The default visibility of the memo. + nest: + type: string + description: The default nest of the user. required: - setting tags: @@ -2033,6 +2191,9 @@ definitions: location: $ref: '#/definitions/apiv1Location' description: The location of the memo. + nest: + type: string + description: The nest of the memo. apiv1OAuth2Config: type: object properties: @@ -2069,6 +2230,9 @@ definitions: memoVisibility: type: string description: The default visibility of the memo. + nest: + type: string + description: The default nest of the user. apiv1WorkspaceCustomProfile: type: object properties: @@ -2419,6 +2583,8 @@ definitions: $ref: '#/definitions/v1MemoRelation' location: $ref: '#/definitions/apiv1Location' + nest: + type: string v1CreateWebhookRequest: type: object properties: @@ -2604,6 +2770,14 @@ definitions: description: |- A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages. + v1ListNestsResponse: + type: object + properties: + nests: + type: array + items: + type: object + $ref: '#/definitions/v1Nest' v1ListNode: type: object properties: @@ -2720,6 +2894,22 @@ definitions: description: |2- - MEMO_VIEW_FULL: The full view of the memo. Includes all fields. - MEMO_VIEW_METADATA_ONLY: The metadata only view of the memo. Excludes the content/snippet fields. + v1Nest: + type: object + properties: + id: + type: string + description: |- + The id of the nest. + Format: nests/{id} + id is the system generated unique identifier. + name: + type: string + description: The user defined name of the nest. + createTime: + type: string + format: date-time + readOnly: true v1Node: type: object properties: diff --git a/proto/gen/store/user_setting.pb.go b/proto/gen/store/user_setting.pb.go index d8954f6621222..15df2b116f40e 100644 --- a/proto/gen/store/user_setting.pb.go +++ b/proto/gen/store/user_setting.pb.go @@ -32,6 +32,8 @@ const ( UserSettingKey_APPEARANCE UserSettingKey = 3 // The visibility of the memo. UserSettingKey_MEMO_VISIBILITY UserSettingKey = 4 + // The default nest of the user. + UserSettingKey_NEST UserSettingKey = 5 ) // Enum value maps for UserSettingKey. @@ -42,6 +44,7 @@ var ( 2: "LOCALE", 3: "APPEARANCE", 4: "MEMO_VISIBILITY", + 5: "NEST", } UserSettingKey_value = map[string]int32{ "USER_SETTING_KEY_UNSPECIFIED": 0, @@ -49,6 +52,7 @@ var ( "LOCALE": 2, "APPEARANCE": 3, "MEMO_VISIBILITY": 4, + "NEST": 5, } ) @@ -92,6 +96,7 @@ type UserSetting struct { // *UserSetting_Locale // *UserSetting_Appearance // *UserSetting_MemoVisibility + // *UserSetting_Nest Value isUserSetting_Value `protobuf_oneof:"value"` } @@ -174,6 +179,13 @@ func (x *UserSetting) GetMemoVisibility() string { return "" } +func (x *UserSetting) GetNest() string { + if x, ok := x.GetValue().(*UserSetting_Nest); ok { + return x.Nest + } + return "" +} + type isUserSetting_Value interface { isUserSetting_Value() } @@ -194,6 +206,10 @@ type UserSetting_MemoVisibility struct { MemoVisibility string `protobuf:"bytes,6,opt,name=memo_visibility,json=memoVisibility,proto3,oneof"` } +type UserSetting_Nest struct { + Nest string `protobuf:"bytes,7,opt,name=nest,proto3,oneof"` +} + func (*UserSetting_AccessTokens) isUserSetting_Value() {} func (*UserSetting_Locale) isUserSetting_Value() {} @@ -202,6 +218,8 @@ func (*UserSetting_Appearance) isUserSetting_Value() {} func (*UserSetting_MemoVisibility) isUserSetting_Value() {} +func (*UserSetting_Nest) isUserSetting_Value() {} + type AccessTokensUserSetting struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -308,7 +326,7 @@ var File_store_user_setting_proto protoreflect.FileDescriptor var file_store_user_setting_proto_rawDesc = []byte{ 0x0a, 0x18, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x92, 0x02, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, + 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0xa8, 0x02, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, @@ -325,38 +343,40 @@ var file_store_user_setting_proto_rawDesc = []byte{ 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x0f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x6f, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc4, 0x01, 0x0a, - 0x17, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x55, 0x73, 0x65, - 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x55, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x30, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 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, 0x1a, - 0x52, 0x0a, 0x0b, 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, 0x2a, 0x76, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x1c, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x45, - 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x43, 0x43, 0x45, 0x53, - 0x53, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x53, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, - 0x43, 0x41, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x50, 0x50, 0x45, 0x41, 0x52, - 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x56, - 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x04, 0x42, 0x9b, 0x01, 0x0a, 0x0f, - 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, - 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x29, 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, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xa2, 0x02, - 0x03, 0x4d, 0x53, 0x58, 0xaa, 0x02, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0xca, 0x02, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, - 0xe2, 0x02, 0x17, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x4d, 0x65, 0x6d, - 0x6f, 0x73, 0x3a, 0x3a, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x04, 0x6e, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x65, 0x73, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0xc4, 0x01, 0x0a, 0x17, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x55, + 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, + 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 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, 0x1a, 0x52, 0x0a, 0x0b, 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, 0x2a, 0x80, 0x01, 0x0a, 0x0e, 0x55, 0x73, + 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x1c, + 0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x4b, 0x45, 0x59, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, + 0x0a, 0x0d, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x53, 0x10, + 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, + 0x0a, 0x41, 0x50, 0x50, 0x45, 0x41, 0x52, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, + 0x0f, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, + 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x45, 0x53, 0x54, 0x10, 0x05, 0x42, 0x9b, 0x01, 0x0a, + 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x42, 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x29, 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, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xa2, + 0x02, 0x03, 0x4d, 0x53, 0x58, 0xaa, 0x02, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, + 0x6f, 0x72, 0x65, 0xca, 0x02, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, + 0x65, 0xe2, 0x02, 0x17, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x4d, 0x65, + 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -400,6 +420,7 @@ func file_store_user_setting_proto_init() { (*UserSetting_Locale)(nil), (*UserSetting_Appearance)(nil), (*UserSetting_MemoVisibility)(nil), + (*UserSetting_Nest)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/proto/store/user_setting.proto b/proto/store/user_setting.proto index 345e8dacdb7bd..c63bbf4ff9462 100644 --- a/proto/store/user_setting.proto +++ b/proto/store/user_setting.proto @@ -14,6 +14,8 @@ enum UserSettingKey { APPEARANCE = 3; // The visibility of the memo. MEMO_VISIBILITY = 4; + // The default nest of the user. + NEST = 5; } message UserSetting { @@ -24,6 +26,7 @@ message UserSetting { string locale = 4; string appearance = 5; string memo_visibility = 6; + string nest = 7; } } diff --git a/server/router/api/v1/auth_service.go b/server/router/api/v1/auth_service.go index bb7f03390b02a..b3b814353a2eb 100644 --- a/server/router/api/v1/auth_service.go +++ b/server/router/api/v1/auth_service.go @@ -221,6 +221,25 @@ func (s *APIV1Service) SignUp(ctx context.Context, request *v1pb.SignUpRequest) return nil, status.Errorf(codes.Internal, "failed to create user, error: %v", err) } + nest, err := s.Store.CreateNest(ctx, &store.Nest{ + Name: "Personal", + CreatorID: user.ID, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to create default nest: %v", err) + } + + _, err = s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{ + UserId: user.ID, + Key: storepb.UserSettingKey_NEST, + Value: &storepb.UserSetting_Nest{ + Nest: fmt.Sprintf("%d", nest.ID), + }, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err) + } + if err := s.doSignIn(ctx, user, time.Now().Add(AccessTokenDuration)); err != nil { return nil, status.Errorf(codes.Internal, "failed to sign in, error: %v", err) } diff --git a/server/router/api/v1/memo_service.go b/server/router/api/v1/memo_service.go index 328b97cc609c4..b2669d45aa996 100644 --- a/server/router/api/v1/memo_service.go +++ b/server/router/api/v1/memo_service.go @@ -40,9 +40,15 @@ func (s *APIV1Service) CreateMemo(ctx context.Context, request *v1pb.CreateMemoR return nil, status.Errorf(codes.Internal, "failed to get user") } + nestID, err := ExtractNestIDFromName(request.Nest) + if err != nil { + return nil, errors.Wrap(err, "invalid nest") + } + create := &store.Memo{ UID: shortuuid.New(), CreatorID: user.ID, + NestID: nestID, Content: request.Content, Visibility: convertVisibilityToStore(request.Visibility), } @@ -830,6 +836,13 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store. } find.CreatorID = &user.ID } + if filter.Nest != nil { + nestID, err := ExtractNestIDFromName(*filter.Nest) + if err != nil { + return errors.Wrap(err, "invalid nest") + } + find.NestID = &nestID + } if filter.RowStatus != nil { find.RowStatus = filter.RowStatus } @@ -901,6 +914,7 @@ var MemoFilterCELAttributes = []cel.EnvOption{ cel.Variable("display_time_before", cel.IntType), cel.Variable("display_time_after", cel.IntType), cel.Variable("creator", cel.StringType), + cel.Variable("nest", cel.StringType), cel.Variable("uid", cel.StringType), cel.Variable("row_status", cel.StringType), cel.Variable("random", cel.BoolType), @@ -921,6 +935,7 @@ type MemoFilter struct { DisplayTimeBefore *int64 DisplayTimeAfter *int64 Creator *string + Nest *string RowStatus *store.RowStatus Random bool Limit *int @@ -990,6 +1005,9 @@ func findMemoField(callExpr *expr.Expr_Call, filter *MemoFilter) { } else if idExpr.Name == "creator" { creator := callExpr.Args[1].GetConstExpr().GetStringValue() filter.Creator = &creator + } else if idExpr.Name == "nest" { + nest := callExpr.Args[1].GetConstExpr().GetStringValue() + filter.Nest = &nest } else if idExpr.Name == "row_status" { rowStatus := store.RowStatus(callExpr.Args[1].GetConstExpr().GetStringValue()) filter.RowStatus = &rowStatus diff --git a/server/router/api/v1/nest_service.go b/server/router/api/v1/nest_service.go new file mode 100644 index 0000000000000..65c34bde98362 --- /dev/null +++ b/server/router/api/v1/nest_service.go @@ -0,0 +1,280 @@ +package v1 + +import ( + "context" + "fmt" + "time" + + "github.com/pkg/errors" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/emptypb" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/usememos/memos/internal/util" + v1pb "github.com/usememos/memos/proto/gen/api/v1" + "github.com/usememos/memos/store" +) + +func (s *APIV1Service) CreateNest(ctx context.Context, request *v1pb.CreateNestRequest) (*v1pb.Nest, error) { + user, err := s.GetCurrentUser(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user") + } + + if user == nil { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + create := &store.Nest{ + CreatorID: user.ID, + Name: request.Name, + } + + nest, err := s.Store.CreateNest(ctx, create) + if err != nil { + return nil, err + } + + nestMessage, err := convertNestFromStore(nest) + if err != nil { + return nil, errors.Wrap(err, "failed to convert nest") + } + + return nestMessage, nil +} + +func (s *APIV1Service) ListNests(ctx context.Context, _ *v1pb.ListNestsRequest) (*v1pb.ListNestsResponse, error) { + user, err := s.GetCurrentUser(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user") + } + + if user == nil { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + nestFind := &store.FindNest{ + CreatorID: &user.ID, + } + + nests, err := s.Store.ListNests(ctx, nestFind) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list nests: %v", err) + } + + nestMessages := []*v1pb.Nest{} + for _, nest := range nests { + nestMessage, err := convertNestFromStore(nest) + if err != nil { + return nil, errors.Wrap(err, "failed to convert nest") + } + nestMessages = append(nestMessages, nestMessage) + } + + response := &v1pb.ListNestsResponse{ + Nests: nestMessages, + } + return response, nil +} + +func (s *APIV1Service) GetNest(ctx context.Context, request *v1pb.GetNestRequest) (*v1pb.Nest, error) { + user, err := s.GetCurrentUser(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user") + } + + if user == nil { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + id, err := ExtractNestIDFromName(request.Id) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid nest name: %v", err) + } + nest, err := s.Store.GetNest(ctx, &store.FindNest{ + CreatorID: &user.ID, + ID: &id, + }) + if err != nil { + return nil, err + } + if nest == nil { + return nil, status.Errorf(codes.NotFound, "nest not found") + } + + nestMessage, err := convertNestFromStore(nest) + if err != nil { + return nil, errors.Wrap(err, "failed to convert nest") + } + return nestMessage, nil +} + +//nolint:all +func (s *APIV1Service) GetNestByName(ctx context.Context, request *v1pb.GetNestByNameRequest) (*v1pb.Nest, error) { + user, err := s.GetCurrentUser(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user") + } + + if user == nil { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + nest, err := s.Store.GetNest(ctx, &store.FindNest{ + Name: &request.Name, + CreatorID: &user.ID, + }) + if err != nil { + return nil, err + } + if nest == nil { + return nil, status.Errorf(codes.NotFound, "nest not found") + } + + nestMessage, err := convertNestFromStore(nest) + if err != nil { + return nil, errors.Wrap(err, "failed to convert nest") + } + return nestMessage, nil +} + +func (s *APIV1Service) UpdateNest(ctx context.Context, request *v1pb.UpdateNestRequest) (*v1pb.Nest, error) { + user, err := s.GetCurrentUser(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user") + } + + if user == nil { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + id, err := ExtractNestIDFromName(request.Nest.Id) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid nest name: %v", err) + } + if request.UpdateMask == nil || len(request.UpdateMask.Paths) == 0 { + return nil, status.Errorf(codes.InvalidArgument, "update mask is required") + } + + nest, err := s.Store.GetNest(ctx, &store.FindNest{ + ID: &id, + }) + if err != nil { + return nil, err + } + if nest == nil { + return nil, status.Errorf(codes.NotFound, "nest not found") + } + + // Only the creator or admin can update the nest. + if nest.CreatorID != user.ID && !isSuperUser(user) { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + update := &store.UpdateNest{ + ID: id, + } + for _, path := range request.UpdateMask.Paths { + if path == "name" { + update.Name = &request.Nest.Name + if !util.UIDMatcher.MatchString(*update.Name) { + return nil, status.Errorf(codes.InvalidArgument, "invalid resource name") + } + } + } + + if err = s.Store.UpdateNest(ctx, update); err != nil { + return nil, status.Errorf(codes.Internal, "failed to update nest") + } + + nest, err = s.Store.GetNest(ctx, &store.FindNest{ + ID: &id, + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get nest") + } + nestMessage, err := convertNestFromStore(nest) + if err != nil { + return nil, errors.Wrap(err, "failed to convert nest") + } + + return nestMessage, nil +} + +func (s *APIV1Service) DeleteNest(ctx context.Context, request *v1pb.DeleteNestRequest) (*emptypb.Empty, error) { + user, err := s.GetCurrentUser(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get user") + } + + if user == nil { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + nestID, err := ExtractNestIDFromName(request.Id) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid nest name: %v", err) + } + nest, err := s.Store.GetNest(ctx, &store.FindNest{ + ID: &nestID, + }) + if err != nil { + return nil, err + } + if nest == nil { + return nil, status.Errorf(codes.NotFound, "nest not found") + } + + newNestID, err := ExtractNestIDFromName(request.MoveTo) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid target nest name: %v", err) + } + newNest, err := s.Store.GetNest(ctx, &store.FindNest{ + ID: &newNestID, + }) + if err != nil { + return nil, err + } + if newNest == nil { + return nil, status.Errorf(codes.NotFound, "target nest not found") + } + + // Only the creator or admin can update the nest. + if (nest.CreatorID != user.ID || newNest.CreatorID != user.ID) && !isSuperUser(user) { + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + + memos, err := s.Store.ListMemos(ctx, &store.FindMemo{ + CreatorID: &user.ID, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get nest memos") + } + for _, memo := range memos { + err := s.Store.UpdateMemo(ctx, &store.UpdateMemo{ + ID: memo.ID, + Nest: &newNestID, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to move memo") + } + } + + if err = s.Store.DeleteNest(ctx, &store.DeleteNest{ID: nestID}); err != nil { + return nil, status.Errorf(codes.Internal, "failed to delete nest") + } + + return &emptypb.Empty{}, nil +} + +func convertNestFromStore(nest *store.Nest) (*v1pb.Nest, error) { + id := fmt.Sprintf("%s%d", NestNamePrefix, nest.ID) + nestMessage := &v1pb.Nest{ + Id: id, + Name: nest.Name, + CreateTime: timestamppb.New(time.Unix(nest.CreatedTs, 0)), + } + + return nestMessage, nil +} diff --git a/server/router/api/v1/resource_name.go b/server/router/api/v1/resource_name.go index 94b41836ef3a6..b80a756d70a35 100644 --- a/server/router/api/v1/resource_name.go +++ b/server/router/api/v1/resource_name.go @@ -13,6 +13,7 @@ const ( WorkspaceSettingNamePrefix = "settings/" UserNamePrefix = "users/" MemoNamePrefix = "memos/" + NestNamePrefix = "nests/" ResourceNamePrefix = "resources/" InboxNamePrefix = "inboxes/" StorageNamePrefix = "storages/" @@ -74,6 +75,19 @@ func ExtractMemoIDFromName(name string) (int32, error) { return id, nil } +// ExtractNestIDFromName returns the nest ID from a resource name. +func ExtractNestIDFromName(name string) (int32, error) { + tokens, err := GetNameParentTokens(name, NestNamePrefix) + if err != nil { + return 0, err + } + id, err := util.ConvertStringToInt32(tokens[0]) + if err != nil { + return 0, errors.Errorf("invalid nest ID %q", tokens[0]) + } + return id, nil +} + // ExtractResourceIDFromName returns the resource ID from a resource name. func ExtractResourceIDFromName(name string) (int32, error) { tokens, err := GetNameParentTokens(name, ResourceNamePrefix) diff --git a/server/router/api/v1/user_service.go b/server/router/api/v1/user_service.go index 8a501376044d8..30e77f13282ee 100644 --- a/server/router/api/v1/user_service.go +++ b/server/router/api/v1/user_service.go @@ -162,6 +162,25 @@ func (s *APIV1Service) CreateUser(ctx context.Context, request *v1pb.CreateUserR return nil, status.Errorf(codes.Internal, "failed to create user: %v", err) } + nest, err := s.Store.CreateNest(ctx, &store.Nest{ + Name: "Personal", + CreatorID: user.ID, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to create default nest: %v", err) + } + + _, err = s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{ + UserId: user.ID, + Key: storepb.UserSettingKey_NEST, + Value: &storepb.UserSetting_Nest{ + Nest: fmt.Sprintf("%d", nest.ID), + }, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err) + } + return convertUserFromStore(user), nil } @@ -284,6 +303,7 @@ func getDefaultUserSetting(workspaceMemoRelatedSetting *storepb.WorkspaceMemoRel Locale: "en", Appearance: "system", MemoVisibility: defaultVisibility, + Nest: "nests/0", } } @@ -313,6 +333,8 @@ func (s *APIV1Service) GetUserSetting(ctx context.Context, _ *v1pb.GetUserSettin userSettingMessage.Appearance = setting.GetAppearance() } else if setting.Key == storepb.UserSettingKey_MEMO_VISIBILITY { userSettingMessage.MemoVisibility = setting.GetMemoVisibility() + } else if setting.Key == storepb.UserSettingKey_NEST { + userSettingMessage.Nest = fmt.Sprintf("%s%s", NestNamePrefix, setting.GetNest()) } } return userSettingMessage, nil @@ -359,6 +381,20 @@ func (s *APIV1Service) UpdateUserSetting(ctx context.Context, request *v1pb.Upda }); err != nil { return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err) } + } else if field == "nest" { + nest, err := ExtractNestIDFromName(request.Setting.Nest) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid nest: %s", request.Setting.Nest) + } + if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{ + UserId: user.ID, + Key: storepb.UserSettingKey_NEST, + Value: &storepb.UserSetting_Nest{ + Nest: fmt.Sprintf("%d", nest), + }, + }); err != nil { + return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err) + } } else { return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field) } diff --git a/server/router/api/v1/v1.go b/server/router/api/v1/v1.go index a8ba11fd0ad63..654fe12e56d79 100644 --- a/server/router/api/v1/v1.go +++ b/server/router/api/v1/v1.go @@ -24,6 +24,7 @@ type APIV1Service struct { v1pb.UnimplementedAuthServiceServer v1pb.UnimplementedUserServiceServer v1pb.UnimplementedMemoServiceServer + v1pb.UnimplementedNestServiceServer v1pb.UnimplementedResourceServiceServer v1pb.UnimplementedInboxServiceServer v1pb.UnimplementedActivityServiceServer @@ -51,6 +52,7 @@ func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store v1pb.RegisterAuthServiceServer(grpcServer, apiv1Service) v1pb.RegisterUserServiceServer(grpcServer, apiv1Service) v1pb.RegisterMemoServiceServer(grpcServer, apiv1Service) + v1pb.RegisterNestServiceServer(grpcServer, apiv1Service) v1pb.RegisterResourceServiceServer(grpcServer, apiv1Service) v1pb.RegisterInboxServiceServer(grpcServer, apiv1Service) v1pb.RegisterActivityServiceServer(grpcServer, apiv1Service) @@ -88,6 +90,9 @@ func (s *APIV1Service) RegisterGateway(ctx context.Context, echoServer *echo.Ech if err := v1pb.RegisterMemoServiceHandler(ctx, gwMux, conn); err != nil { return err } + if err := v1pb.RegisterNestServiceHandler(ctx, gwMux, conn); err != nil { + return err + } if err := v1pb.RegisterResourceServiceHandler(ctx, gwMux, conn); err != nil { return err } diff --git a/store/db/mysql/memo.go b/store/db/mysql/memo.go index db9ccba3505fb..4a1a1331c0e0d 100644 --- a/store/db/mysql/memo.go +++ b/store/db/mysql/memo.go @@ -13,8 +13,8 @@ import ( ) func (d *DB) CreateMemo(ctx context.Context, create *store.Memo) (*store.Memo, error) { - fields := []string{"`uid`", "`creator_id`", "`content`", "`visibility`", "`tags`", "`payload`"} - placeholder := []string{"?", "?", "?", "?", "?", "?"} + fields := []string{"`uid`", "`creator_id`", "`nest`", "`content`", "`visibility`", "`tags`", "`payload`"} + placeholder := []string{"?", "?", "?", "?", "?", "?", "?"} payload := "{}" if create.Payload != nil { payloadBytes, err := protojson.Marshal(create.Payload) @@ -23,7 +23,7 @@ func (d *DB) CreateMemo(ctx context.Context, create *store.Memo) (*store.Memo, e } payload = string(payloadBytes) } - args := []any{create.UID, create.CreatorID, create.Content, create.Visibility, "[]", payload} + args := []any{create.UID, create.CreatorID, create.NestID, create.Content, create.Visibility, "[]", payload} stmt := "INSERT INTO `memo` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ")" result, err := d.db.ExecContext(ctx, stmt, args...) @@ -58,6 +58,9 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo if v := find.CreatorID; v != nil { where, args = append(where, "`memo`.`creator_id` = ?"), append(args, *v) } + if v := find.NestID; v != nil { + where, args = append(where, "`memo`.`nest` = ?"), append(args, *v) + } if v := find.RowStatus; v != nil { where, args = append(where, "`memo`.`row_status` = ?"), append(args, *v) } @@ -235,6 +238,9 @@ func (d *DB) UpdateMemo(ctx context.Context, update *store.UpdateMemo) error { if v := update.Visibility; v != nil { set, args = append(set, "`visibility` = ?"), append(args, *v) } + if v := update.Nest; v != nil { + set, args = append(set, "`nest` = ?"), append(args, *v) + } if v := update.Payload; v != nil { payloadBytes, err := protojson.Marshal(v) if err != nil { diff --git a/store/db/mysql/nest.go b/store/db/mysql/nest.go new file mode 100644 index 0000000000000..5f7f931dcc983 --- /dev/null +++ b/store/db/mysql/nest.go @@ -0,0 +1,142 @@ +package mysql + +import ( + "context" + "strings" + + "github.com/pkg/errors" + + "github.com/usememos/memos/store" +) + +func (d *DB) CreateNest(ctx context.Context, create *store.Nest) (*store.Nest, error) { + fields := []string{"`name`", "`creator_id`"} + placeholder := []string{"?", "?"} + args := []any{create.Name, create.CreatorID} + + stmt := "INSERT INTO `nest` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ")" + result, err := d.db.ExecContext(ctx, stmt, args...) + if err != nil { + return nil, err + } + + rawID, err := result.LastInsertId() + if err != nil { + return nil, err + } + id := int32(rawID) + nest, err := d.GetNest(ctx, &store.FindNest{ID: &id}) + if err != nil { + return nil, err + } + if nest == nil { + return nil, errors.Errorf("failed to create nest") + } + return nest, nil +} + +func (d *DB) ListNests(ctx context.Context, find *store.FindNest) ([]*store.Nest, error) { + where, having, args := []string{"1 = 1"}, []string{"1 = 1"}, []any{} + + if v := find.ID; v != nil { + where, args = append(where, "`nest`.`id` = ?"), append(args, *v) + } + if v := find.Name; v != nil { + where, args = append(where, "`nest`.`name` = ?"), append(args, *v) + } + if v := find.CreatorID; v != nil { + where, args = append(where, "`nest`.`creator_id` = ?"), append(args, *v) + } + if v := find.RowStatus; v != nil { + where, args = append(where, "`nest`.`row_status` = ?"), append(args, *v) + } + + orders := []string{} + order := "DESC" + orders = append(orders, "`created_ts` "+order) + orders = append(orders, "`id` "+order) + + fields := []string{ + "`nest`.`id` AS `id`", + "`nest`.`name` AS `name`", + "`nest`.`creator_id` AS `creator_id`", + "UNIX_TIMESTAMP(`nest`.`created_ts`) AS `created_ts`", + "`nest`.`row_status` AS `row_status`", + } + + query := "SELECT " + strings.Join(fields, ", ") + " FROM `nest`" + " " + + "WHERE " + strings.Join(where, " AND ") + " " + + "HAVING " + strings.Join(having, " AND ") + " " + + "ORDER BY " + strings.Join(orders, ", ") + + rows, err := d.db.QueryContext(ctx, query, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + list := make([]*store.Nest, 0) + for rows.Next() { + var nest store.Nest + dests := []any{ + &nest.ID, + &nest.Name, + &nest.CreatorID, + &nest.CreatedTs, + &nest.RowStatus, + } + if err := rows.Scan(dests...); err != nil { + return nil, err + } + list = append(list, &nest) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return list, nil +} + +func (d *DB) GetNest(ctx context.Context, find *store.FindNest) (*store.Nest, error) { + list, err := d.ListNests(ctx, find) + if err != nil { + return nil, err + } + if len(list) == 0 { + return nil, nil + } + + nest := list[0] + return nest, nil +} + +func (d *DB) UpdateNest(ctx context.Context, update *store.UpdateNest) error { + set, args := []string{}, []any{} + if v := update.Name; v != nil { + set, args = append(set, "`name` = ?"), append(args, *v) + } + if v := update.RowStatus; v != nil { + set, args = append(set, "`row_status` = ?"), append(args, *v) + } + args = append(args, update.ID) + + stmt := "UPDATE `nest` SET " + strings.Join(set, ", ") + " WHERE `id` = ?" + if _, err := d.db.ExecContext(ctx, stmt, args...); err != nil { + return err + } + return nil +} + +func (d *DB) DeleteNest(ctx context.Context, delete *store.DeleteNest) error { + where, args := []string{"`id` = ?"}, []any{delete.ID} + stmt := "DELETE FROM `nest` WHERE " + strings.Join(where, " AND ") + result, err := d.db.ExecContext(ctx, stmt, args...) + if err != nil { + return err + } + if _, err := result.RowsAffected(); err != nil { + return err + } + return nil +} diff --git a/store/db/postgres/memo.go b/store/db/postgres/memo.go index c9ff66a867d6e..810abcdd73e0d 100644 --- a/store/db/postgres/memo.go +++ b/store/db/postgres/memo.go @@ -13,7 +13,7 @@ import ( ) func (d *DB) CreateMemo(ctx context.Context, create *store.Memo) (*store.Memo, error) { - fields := []string{"uid", "creator_id", "content", "visibility", "payload"} + fields := []string{"uid", "creator_id", "nest", "content", "visibility", "payload"} payload := "{}" if create.Payload != nil { payloadBytes, err := protojson.Marshal(create.Payload) @@ -22,7 +22,7 @@ func (d *DB) CreateMemo(ctx context.Context, create *store.Memo) (*store.Memo, e } payload = string(payloadBytes) } - args := []any{create.UID, create.CreatorID, create.Content, create.Visibility, payload} + args := []any{create.UID, create.CreatorID, create.NestID, create.Content, create.Visibility, payload} stmt := "INSERT INTO memo (" + strings.Join(fields, ", ") + ") VALUES (" + placeholders(len(args)) + ") RETURNING id, created_ts, updated_ts, row_status" if err := d.db.QueryRowContext(ctx, stmt, args...).Scan( @@ -49,6 +49,9 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo if v := find.CreatorID; v != nil { where, args = append(where, "memo.creator_id = "+placeholder(len(args)+1)), append(args, *v) } + if v := find.NestID; v != nil { + where, args = append(where, "memo.nest = "+placeholder(len(args)+1)), append(args, *v) + } if v := find.RowStatus; v != nil { where, args = append(where, "memo.row_status = "+placeholder(len(args)+1)), append(args, *v) } @@ -226,6 +229,9 @@ func (d *DB) UpdateMemo(ctx context.Context, update *store.UpdateMemo) error { if v := update.Visibility; v != nil { set, args = append(set, "visibility = "+placeholder(len(args)+1)), append(args, *v) } + if v := update.Nest; v != nil { + set, args = append(set, "nest = "+placeholder(len(args)+1)), append(args, *v) + } if v := update.Payload; v != nil { payloadBytes, err := protojson.Marshal(v) if err != nil { diff --git a/store/db/postgres/nest.go b/store/db/postgres/nest.go new file mode 100644 index 0000000000000..f4e4103f25eb3 --- /dev/null +++ b/store/db/postgres/nest.go @@ -0,0 +1,132 @@ +package postgres + +import ( + "context" + "strings" + + "github.com/pkg/errors" + + "github.com/usememos/memos/store" +) + +func (d *DB) CreateNest(ctx context.Context, create *store.Nest) (*store.Nest, error) { + fields := []string{"name", "creator_id"} + args := []any{create.Name, create.CreatorID} + + stmt := "INSERT INTO nest (" + strings.Join(fields, ", ") + ") VALUES (" + placeholders(len(args)) + ") RETURNING id, created_ts, row_status" + if err := d.db.QueryRowContext(ctx, stmt, args...).Scan( + &create.ID, + &create.CreatedTs, + &create.RowStatus, + ); err != nil { + return nil, err + } + + return create, nil +} + +func (d *DB) ListNests(ctx context.Context, find *store.FindNest) ([]*store.Nest, error) { + where, args := []string{"1 = 1"}, []any{} + + if v := find.ID; v != nil { + where, args = append(where, "nest.id = "+placeholder(len(args)+1)), append(args, *v) + } + if v := find.Name; v != nil { + where, args = append(where, "nest.name = "+placeholder(len(args)+1)), append(args, *v) + } + if v := find.CreatorID; v != nil { + where, args = append(where, "nest.creator_id = "+placeholder(len(args)+1)), append(args, *v) + } + if v := find.RowStatus; v != nil { + where, args = append(where, "nest.row_status = "+placeholder(len(args)+1)), append(args, *v) + } + + orders := []string{} + order := "DESC" + orders = append(orders, "created_ts "+order) + orders = append(orders, "id "+order) + + fields := []string{ + `nest.id AS id`, + `nest.name AS name`, + `nest.creator_id AS creator_id`, + `nest.created_ts AS created_ts`, + `nest.row_status AS row_status`, + } + + query := `SELECT ` + strings.Join(fields, ", ") + ` + FROM nest + WHERE ` + strings.Join(where, " AND ") + ` + ORDER BY ` + strings.Join(orders, ", ") + + rows, err := d.db.QueryContext(ctx, query, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + list := make([]*store.Nest, 0) + for rows.Next() { + var nest store.Nest + dests := []any{ + &nest.ID, + &nest.Name, + &nest.CreatorID, + &nest.CreatedTs, + &nest.RowStatus, + } + if err := rows.Scan(dests...); err != nil { + return nil, err + } + list = append(list, &nest) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return list, nil +} + +func (d *DB) GetNest(ctx context.Context, find *store.FindNest) (*store.Nest, error) { + list, err := d.ListNests(ctx, find) + if err != nil { + return nil, err + } + if len(list) == 0 { + return nil, nil + } + + nest := list[0] + return nest, nil +} + +func (d *DB) UpdateNest(ctx context.Context, update *store.UpdateNest) error { + set, args := []string{}, []any{} + if v := update.Name; v != nil { + set, args = append(set, "name = "+placeholder(len(args)+1)), append(args, *v) + } + if v := update.RowStatus; v != nil { + set, args = append(set, "row_status = "+placeholder(len(args)+1)), append(args, *v) + } + + stmt := `UPDATE nest SET ` + strings.Join(set, ", ") + ` WHERE id = ` + placeholder(len(args)+1) + args = append(args, update.ID) + if _, err := d.db.ExecContext(ctx, stmt, args...); err != nil { + return err + } + return nil +} + +func (d *DB) DeleteNest(ctx context.Context, delete *store.DeleteNest) error { + where, args := []string{"id = " + placeholder(1)}, []any{delete.ID} + stmt := `DELETE FROM nest WHERE ` + strings.Join(where, " AND ") + result, err := d.db.ExecContext(ctx, stmt, args...) + if err != nil { + return errors.Wrap(err, "failed to delete nest") + } + if _, err := result.RowsAffected(); err != nil { + return err + } + return nil +} diff --git a/store/db/sqlite/memo.go b/store/db/sqlite/memo.go index cbde004c91078..4365a6e830a2f 100644 --- a/store/db/sqlite/memo.go +++ b/store/db/sqlite/memo.go @@ -13,8 +13,8 @@ import ( ) func (d *DB) CreateMemo(ctx context.Context, create *store.Memo) (*store.Memo, error) { - fields := []string{"`uid`", "`creator_id`", "`content`", "`visibility`", "`payload`"} - placeholder := []string{"?", "?", "?", "?", "?"} + fields := []string{"`uid`", "`creator_id`", "`nest`", "`content`", "`visibility`", "`payload`"} + placeholder := []string{"?", "?", "?", "?", "?", "?"} payload := "{}" if create.Payload != nil { payloadBytes, err := protojson.Marshal(create.Payload) @@ -23,7 +23,7 @@ func (d *DB) CreateMemo(ctx context.Context, create *store.Memo) (*store.Memo, e } payload = string(payloadBytes) } - args := []any{create.UID, create.CreatorID, create.Content, create.Visibility, payload} + args := []any{create.UID, create.CreatorID, create.NestID, create.Content, create.Visibility, payload} stmt := "INSERT INTO `memo` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ") RETURNING `id`, `created_ts`, `updated_ts`, `row_status`" if err := d.db.QueryRowContext(ctx, stmt, args...).Scan( @@ -50,6 +50,9 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo if v := find.CreatorID; v != nil { where, args = append(where, "`memo`.`creator_id` = ?"), append(args, *v) } + if v := find.NestID; v != nil { + where, args = append(where, "`memo`.`nest` = ?"), append(args, *v) + } if v := find.RowStatus; v != nil { where, args = append(where, "`memo`.`row_status` = ?"), append(args, *v) } @@ -207,6 +210,9 @@ func (d *DB) UpdateMemo(ctx context.Context, update *store.UpdateMemo) error { if v := update.RowStatus; v != nil { set, args = append(set, "`row_status` = ?"), append(args, *v) } + if v := update.Nest; v != nil { + set, args = append(set, "`nest` = ?"), append(args, *v) + } if v := update.Content; v != nil { set, args = append(set, "`content` = ?"), append(args, *v) } diff --git a/store/db/sqlite/nest.go b/store/db/sqlite/nest.go new file mode 100644 index 0000000000000..4dafbb7c79de9 --- /dev/null +++ b/store/db/sqlite/nest.go @@ -0,0 +1,117 @@ +package sqlite + +import ( + "context" + "strings" + + "github.com/usememos/memos/store" +) + +func (d *DB) CreateNest(ctx context.Context, create *store.Nest) (*store.Nest, error) { + fields := []string{"`name`", "`creator_id`"} + placeholder := []string{"?", "?"} + args := []any{create.Name, create.CreatorID} + + stmt := "INSERT INTO `nest` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ") RETURNING `id`, `created_ts`, `row_status`" + if err := d.db.QueryRowContext(ctx, stmt, args...).Scan( + &create.ID, + &create.CreatedTs, + &create.RowStatus, + ); err != nil { + return nil, err + } + + return create, nil +} + +func (d *DB) ListNests(ctx context.Context, find *store.FindNest) ([]*store.Nest, error) { + where, args := []string{"1 = 1"}, []any{} + + if v := find.ID; v != nil { + where, args = append(where, "`nest`.`id` = ?"), append(args, *v) + } + if v := find.Name; v != nil { + where, args = append(where, "`nest`.`name` = ?"), append(args, *v) + } + if v := find.CreatorID; v != nil { + where, args = append(where, "`nest`.`creator_id` = ?"), append(args, *v) + } + if v := find.RowStatus; v != nil { + where, args = append(where, "`nest`.`row_status` = ?"), append(args, *v) + } + + orderBy := []string{} + order := "DESC" + orderBy = append(orderBy, "`created_ts` "+order) + orderBy = append(orderBy, "`id` "+order) + + fields := []string{ + "`nest`.`id` AS `id`", + "`nest`.`name` AS `name`", + "`nest`.`creator_id` AS `creator_id`", + "`nest`.`created_ts` AS `created_ts`", + "`nest`.`row_status` AS `row_status`", + } + + query := "SELECT " + strings.Join(fields, ", ") + "FROM `nest` " + + "WHERE " + strings.Join(where, " AND ") + " " + + "ORDER BY " + strings.Join(orderBy, ", ") + + rows, err := d.db.QueryContext(ctx, query, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + list := make([]*store.Nest, 0) + for rows.Next() { + var nest store.Nest + dests := []any{ + &nest.ID, + &nest.Name, + &nest.CreatorID, + &nest.CreatedTs, + &nest.RowStatus, + } + if err := rows.Scan(dests...); err != nil { + return nil, err + } + list = append(list, &nest) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return list, nil +} + +func (d *DB) UpdateNest(ctx context.Context, update *store.UpdateNest) error { + set, args := []string{}, []any{} + if v := update.Name; v != nil { + set, args = append(set, "`name` = ?"), append(args, *v) + } + if v := update.RowStatus; v != nil { + set, args = append(set, "`row_status` = ?"), append(args, *v) + } + args = append(args, update.ID) + + stmt := "UPDATE `nest` SET " + strings.Join(set, ", ") + " WHERE `id` = ?" + if _, err := d.db.ExecContext(ctx, stmt, args...); err != nil { + return err + } + return nil +} + +func (d *DB) DeleteNest(ctx context.Context, delete *store.DeleteNest) error { + where, args := []string{"`id` = ?"}, []any{delete.ID} + stmt := "DELETE FROM `nest` WHERE " + strings.Join(where, " AND ") + result, err := d.db.ExecContext(ctx, stmt, args...) + if err != nil { + return err + } + if _, err := result.RowsAffected(); err != nil { + return err + } + return nil +} diff --git a/store/driver.go b/store/driver.go index c152a9372627d..7dc6ececebdd4 100644 --- a/store/driver.go +++ b/store/driver.go @@ -31,6 +31,12 @@ type Driver interface { UpdateMemo(ctx context.Context, update *UpdateMemo) error DeleteMemo(ctx context.Context, delete *DeleteMemo) error + // Nest model related methods. + CreateNest(ctx context.Context, create *Nest) (*Nest, error) + ListNests(ctx context.Context, find *FindNest) ([]*Nest, error) + UpdateNest(ctx context.Context, update *UpdateNest) error + DeleteNest(ctx context.Context, delete *DeleteNest) error + // MemoRelation model related methods. UpsertMemoRelation(ctx context.Context, create *MemoRelation) (*MemoRelation, error) ListMemoRelations(ctx context.Context, find *FindMemoRelation) ([]*MemoRelation, error) diff --git a/store/memo.go b/store/memo.go index e8513fa4d2188..701fa90eedeb1 100644 --- a/store/memo.go +++ b/store/memo.go @@ -48,6 +48,7 @@ type Memo struct { // Domain specific fields Content string Visibility Visibility + NestID int32 Payload *storepb.MemoPayload // Composed fields @@ -70,6 +71,7 @@ type FindMemo struct { // Domain specific fields ContentSearch []string VisibilityList []Visibility + NestID *int32 PayloadFind *FindMemoPayload ExcludeContent bool ExcludeComments bool @@ -102,6 +104,7 @@ type UpdateMemo struct { RowStatus *RowStatus Content *string Visibility *Visibility + Nest *int32 Payload *storepb.MemoPayload } diff --git a/store/migration/mysql/dev/LATEST.sql b/store/migration/mysql/dev/LATEST.sql index 3a3fb7d009179..2ca1faa6298b4 100644 --- a/store/migration/mysql/dev/LATEST.sql +++ b/store/migration/mysql/dev/LATEST.sql @@ -41,6 +41,7 @@ CREATE TABLE `memo` ( `creator_id` INT NOT NULL, `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `nest` INT NOT NULL DEFAULT 0, `row_status` VARCHAR(256) NOT NULL DEFAULT 'NORMAL', `content` TEXT NOT NULL, `visibility` VARCHAR(256) NOT NULL DEFAULT 'PRIVATE', @@ -48,6 +49,15 @@ CREATE TABLE `memo` ( `payload` JSON NOT NULL ); +-- nest +CREATE TABLE nest ( + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(256) NOT NULL, + `creator_id` INT NOT NULL, + `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `row_status` VARCHAR(256) NOT NULL DEFAULT 'NORMAL' +); + -- memo_organizer CREATE TABLE `memo_organizer` ( `memo_id` INT NOT NULL, @@ -128,5 +138,5 @@ CREATE TABLE `reaction` ( `creator_id` INT NOT NULL, `content_id` VARCHAR(256) NOT NULL, `reaction_type` VARCHAR(256) NOT NULL, - UNIQUE(`creator_id`,`content_id`,`reaction_type`) + UNIQUE(`creator_id`,`content_id`,`reaction_type`) ); diff --git a/store/migration/mysql/prod/0.23/01__nests.sql b/store/migration/mysql/prod/0.23/01__nests.sql new file mode 100644 index 0000000000000..49b23000f818b --- /dev/null +++ b/store/migration/mysql/prod/0.23/01__nests.sql @@ -0,0 +1,40 @@ +ALTER TABLE + memo +ADD + COLUMN nest INT NOT NULL DEFAULT 0; + +CREATE TABLE nest ( + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(256) NOT NULL, + `creator_id` INT NOT NULL, + `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `row_status` VARCHAR(256) NOT NULL DEFAULT 'NORMAL' +); + +INSERT INTO + nest (name, creator_id) +SELECT + 'Personal', id +FROM + user; + +UPDATE + memo +SET + nest = ( + SELECT id + FROM nest + WHERE creator_id = memo.creator_id + LIMIT 1 + ) +WHERE + nest = 0; + +INSERT INTO + user_setting (user_id, key, value) +SELECT + creator_id AS user_id, + 'NEST' AS key, + id AS value +FROM + nest; \ No newline at end of file diff --git a/store/migration/mysql/prod/LATEST.sql b/store/migration/mysql/prod/LATEST.sql index 3a3fb7d009179..2ca1faa6298b4 100644 --- a/store/migration/mysql/prod/LATEST.sql +++ b/store/migration/mysql/prod/LATEST.sql @@ -41,6 +41,7 @@ CREATE TABLE `memo` ( `creator_id` INT NOT NULL, `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `nest` INT NOT NULL DEFAULT 0, `row_status` VARCHAR(256) NOT NULL DEFAULT 'NORMAL', `content` TEXT NOT NULL, `visibility` VARCHAR(256) NOT NULL DEFAULT 'PRIVATE', @@ -48,6 +49,15 @@ CREATE TABLE `memo` ( `payload` JSON NOT NULL ); +-- nest +CREATE TABLE nest ( + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(256) NOT NULL, + `creator_id` INT NOT NULL, + `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `row_status` VARCHAR(256) NOT NULL DEFAULT 'NORMAL' +); + -- memo_organizer CREATE TABLE `memo_organizer` ( `memo_id` INT NOT NULL, @@ -128,5 +138,5 @@ CREATE TABLE `reaction` ( `creator_id` INT NOT NULL, `content_id` VARCHAR(256) NOT NULL, `reaction_type` VARCHAR(256) NOT NULL, - UNIQUE(`creator_id`,`content_id`,`reaction_type`) + UNIQUE(`creator_id`,`content_id`,`reaction_type`) ); diff --git a/store/migration/postgres/dev/LATEST.sql b/store/migration/postgres/dev/LATEST.sql index 957eaced5c7cb..9f0ee410d6deb 100644 --- a/store/migration/postgres/dev/LATEST.sql +++ b/store/migration/postgres/dev/LATEST.sql @@ -41,6 +41,7 @@ CREATE TABLE memo ( creator_id INTEGER NOT NULL, created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + nest INTEGER NOT NULL DEFAULT 0, row_status TEXT NOT NULL DEFAULT 'NORMAL', content TEXT NOT NULL, visibility TEXT NOT NULL DEFAULT 'PRIVATE', @@ -48,6 +49,15 @@ CREATE TABLE memo ( payload JSONB NOT NULL DEFAULT '{}' ); +-- nest +CREATE TABLE nest ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + creator_id INTEGER NOT NULL, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + row_status TEXT NOT NULL DEFAULT 'NORMAL' +); + -- memo_organizer CREATE TABLE memo_organizer ( memo_id INTEGER NOT NULL, diff --git a/store/migration/postgres/prod/0.23/01__nests.sql b/store/migration/postgres/prod/0.23/01__nests.sql new file mode 100644 index 0000000000000..c0b092068f367 --- /dev/null +++ b/store/migration/postgres/prod/0.23/01__nests.sql @@ -0,0 +1,39 @@ +ALTER TABLE + memo +ADD + COLUMN nest INTEGER NOT NULL DEFAULT 0; + +CREATE TABLE nest ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + creator_id INTEGER NOT NULL, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + row_status TEXT NOT NULL DEFAULT 'NORMAL' +); + +INSERT INTO + nest (name, creator_id) +SELECT + 'Personal', id +FROM + "user"; + +UPDATE + memo +SET + nest = ( + SELECT id + FROM nest + WHERE creator_id = memo.creator_id + ) +WHERE + nest = 0; + +INSERT INTO + user_setting (user_id, key, value) +SELECT + creator_id AS user_id, + 'NEST' AS key, + id::text AS value +FROM + nest; \ No newline at end of file diff --git a/store/migration/postgres/prod/LATEST.sql b/store/migration/postgres/prod/LATEST.sql index 957eaced5c7cb..9f0ee410d6deb 100644 --- a/store/migration/postgres/prod/LATEST.sql +++ b/store/migration/postgres/prod/LATEST.sql @@ -41,6 +41,7 @@ CREATE TABLE memo ( creator_id INTEGER NOT NULL, created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + nest INTEGER NOT NULL DEFAULT 0, row_status TEXT NOT NULL DEFAULT 'NORMAL', content TEXT NOT NULL, visibility TEXT NOT NULL DEFAULT 'PRIVATE', @@ -48,6 +49,15 @@ CREATE TABLE memo ( payload JSONB NOT NULL DEFAULT '{}' ); +-- nest +CREATE TABLE nest ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + creator_id INTEGER NOT NULL, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + row_status TEXT NOT NULL DEFAULT 'NORMAL' +); + -- memo_organizer CREATE TABLE memo_organizer ( memo_id INTEGER NOT NULL, diff --git a/store/migration/sqlite/dev/LATEST.sql b/store/migration/sqlite/dev/LATEST.sql index bcaeefc04d948..2cb25e0b746fc 100644 --- a/store/migration/sqlite/dev/LATEST.sql +++ b/store/migration/sqlite/dev/LATEST.sql @@ -44,6 +44,7 @@ CREATE TABLE memo ( creator_id INTEGER NOT NULL, created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + nest INTEGER NOT NULL DEFAULT 0, row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL', content TEXT NOT NULL DEFAULT '', visibility TEXT NOT NULL CHECK (visibility IN ('PUBLIC', 'PROTECTED', 'PRIVATE')) DEFAULT 'PRIVATE', @@ -51,6 +52,15 @@ CREATE TABLE memo ( payload TEXT NOT NULL DEFAULT '{}' ); +-- nest +CREATE TABLE nest ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + creator_id INTEGER NOT NULL, + created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL' +); + CREATE INDEX idx_memo_creator_id ON memo (creator_id); CREATE INDEX idx_memo_content ON memo (content); CREATE INDEX idx_memo_visibility ON memo (visibility); diff --git a/store/migration/sqlite/prod/0.23/01__nests.sql b/store/migration/sqlite/prod/0.23/01__nests.sql new file mode 100644 index 0000000000000..840e76a46ff2e --- /dev/null +++ b/store/migration/sqlite/prod/0.23/01__nests.sql @@ -0,0 +1,39 @@ +ALTER TABLE + memo +ADD + COLUMN nest INTEGER NOT NULL DEFAULT 0; + +CREATE TABLE nest ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + creator_id INTEGER NOT NULL, + created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL' +); + +INSERT INTO + nest (name, creator_id) +SELECT + 'Personal', id +FROM + user; + +UPDATE + memo +SET + nest = ( + SELECT id + FROM nest + WHERE creator_id = memo.creator_id + ) +WHERE + nest = 0; + +INSERT INTO + user_setting (user_id, key, value) +SELECT + creator_id AS user_id, + 'NEST' AS key, + id AS value +FROM + nest; diff --git a/store/migration/sqlite/prod/LATEST.sql b/store/migration/sqlite/prod/LATEST.sql index 8052de8c8e0aa..72fc4293464b7 100644 --- a/store/migration/sqlite/prod/LATEST.sql +++ b/store/migration/sqlite/prod/LATEST.sql @@ -44,6 +44,7 @@ CREATE TABLE memo ( creator_id INTEGER NOT NULL, created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + nest INTEGER NOT NULL DEFAULT 0, row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL', content TEXT NOT NULL DEFAULT '', visibility TEXT NOT NULL CHECK (visibility IN ('PUBLIC', 'PROTECTED', 'PRIVATE')) DEFAULT 'PRIVATE', @@ -51,6 +52,15 @@ CREATE TABLE memo ( payload TEXT NOT NULL DEFAULT '{}' ); +-- nest +CREATE TABLE nest ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + creator_id INTEGER NOT NULL, + created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL' +); + CREATE INDEX idx_memo_creator_id ON memo (creator_id); CREATE INDEX idx_memo_content ON memo (content); CREATE INDEX idx_memo_visibility ON memo (visibility); diff --git a/store/nest.go b/store/nest.go new file mode 100644 index 0000000000000..d3cf8b5518dc2 --- /dev/null +++ b/store/nest.go @@ -0,0 +1,74 @@ +package store + +import ( + "context" + "errors" + + "github.com/usememos/memos/internal/util" +) + +type Nest struct { + // ID is the system generated unique identifier for the memo. + ID int32 + // Name is the user defined name for this nest. + Name string + + // Standard fields + RowStatus RowStatus + CreatorID int32 + CreatedTs int64 +} + +type FindNest struct { + ID *int32 + Name *string + + // Standard fields + RowStatus *RowStatus + CreatorID *int32 +} + +type UpdateNest struct { + ID int32 + Name *string + RowStatus *RowStatus +} + +type DeleteNest struct { + ID int32 +} + +func (s *Store) CreateNest(ctx context.Context, create *Nest) (*Nest, error) { + if !util.UIDMatcher.MatchString(create.Name) { + return nil, errors.New("invalid name") + } + return s.driver.CreateNest(ctx, create) +} + +func (s *Store) ListNests(ctx context.Context, find *FindNest) ([]*Nest, error) { + return s.driver.ListNests(ctx, find) +} + +func (s *Store) GetNest(ctx context.Context, find *FindNest) (*Nest, error) { + list, err := s.ListNests(ctx, find) + if err != nil { + return nil, err + } + if len(list) == 0 { + return nil, nil + } + + memo := list[0] + return memo, nil +} + +func (s *Store) UpdateNest(ctx context.Context, update *UpdateNest) error { + if update.Name != nil && !util.UIDMatcher.MatchString(*update.Name) { + return errors.New("invalid uid") + } + return s.driver.UpdateNest(ctx, update) +} + +func (s *Store) DeleteNest(ctx context.Context, delete *DeleteNest) error { + return s.driver.DeleteNest(ctx, delete) +} diff --git a/store/seed/sqlite/00__reset.sql b/store/seed/sqlite/00__reset.sql index 4112901ca3cd7..692a4d5b5bdd7 100644 --- a/store/seed/sqlite/00__reset.sql +++ b/store/seed/sqlite/00__reset.sql @@ -2,6 +2,7 @@ DELETE FROM system_setting; DELETE FROM user; DELETE FROM user_setting; DELETE FROM memo; +DELETE FROM nest; DELETE FROM memo_organizer; DELETE FROM memo_relation; DELETE FROM resource; diff --git a/store/user_setting.go b/store/user_setting.go index 8ef1bb117cf72..2dfd0297f6f90 100644 --- a/store/user_setting.go +++ b/store/user_setting.go @@ -151,6 +151,8 @@ func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) { userSetting.Value = &storepb.UserSetting_Appearance{Appearance: raw.Value} case storepb.UserSettingKey_MEMO_VISIBILITY: userSetting.Value = &storepb.UserSetting_MemoVisibility{MemoVisibility: raw.Value} + case storepb.UserSettingKey_NEST: + userSetting.Value = &storepb.UserSetting_Nest{Nest: raw.Value} default: return nil, nil } @@ -177,6 +179,8 @@ func convertUserSettingToRaw(userSetting *storepb.UserSetting) (*UserSetting, er raw.Value = userSetting.GetAppearance() case storepb.UserSettingKey_MEMO_VISIBILITY: raw.Value = userSetting.GetMemoVisibility() + case storepb.UserSettingKey_NEST: + raw.Value = userSetting.GetNest() default: return nil, errors.Errorf("unsupported user setting key: %v", userSetting.Key) } diff --git a/web/src/App.tsx b/web/src/App.tsx index 6aac053da91f8..5b73339b339a0 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -114,6 +114,7 @@ const App = () => { commonContext.setLocale(userSetting.locale); commonContext.setAppearance(userSetting.appearance); + commonContext.setNest(userSetting.nest); }, [userSetting?.locale, userSetting?.appearance]); return ; diff --git a/web/src/components/AddNestPopover.tsx b/web/src/components/AddNestPopover.tsx new file mode 100644 index 0000000000000..b782894de49f9 --- /dev/null +++ b/web/src/components/AddNestPopover.tsx @@ -0,0 +1,56 @@ +import { Input } from "@mui/joy"; +import { Button } from "@usememos/mui"; +import { PlusIcon } from "lucide-react"; +import { useState } from "react"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/Popover"; +import { useCommonContext } from "@/layouts/CommonContextProvider"; +import { useNestStore } from "@/store/v1"; +import { useTranslate } from "@/utils/i18n"; + +const AddNestPopover = () => { + const t = useTranslate(); + const nestStore = useNestStore(); + const [popoverOpen, setPopoverOpen] = useState(false); + const [nestName, setNestName] = useState(""); + const commonContext = useCommonContext(); + + const addNest = async () => { + const nest = await nestStore.createNest({ + name: nestName, + }); + if (nest) { + await nestStore.fetchNests(); + commonContext.setNest(nest.id); + } + setPopoverOpen(false); + setNestName(""); + }; + + return ( + + + + + + + + + setNestName(e.target.value.trim())} + /> + + + {t("common.add")} + + + + + + ); +}; + +export default AddNestPopover; diff --git a/web/src/components/DeleteNestPopover.tsx b/web/src/components/DeleteNestPopover.tsx new file mode 100644 index 0000000000000..ea7d479b234ad --- /dev/null +++ b/web/src/components/DeleteNestPopover.tsx @@ -0,0 +1,81 @@ +import { Select, Option } from "@mui/joy"; +import { Button } from "@usememos/mui"; +import { TrashIcon } from "lucide-react"; +import { useState } from "react"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/Popover"; +import { useCommonContext } from "@/layouts/CommonContextProvider"; +import { useNestList, useNestStore, useUserStore } from "@/store/v1"; +import { useTranslate } from "@/utils/i18n"; +import NestIcon from "./NestIcon"; + +interface Props { + nest: string; +} + +const DeleteNestPopover = (props: Props) => { + const { nest } = props; + const t = useTranslate(); + const nestStore = useNestStore(); + const [popoverOpen, setPopoverOpen] = useState(false); + const [newNestID, setNewNestID] = useState(""); + const commonContext = useCommonContext(); + const nests = useNestList(); + const userStore = useUserStore(); + + const deleteNest = async () => { + if (nest == userStore.userSetting?.nest) { + await userStore.updateUserSetting( + { + nest: newNestID, + }, + ["nest"], + ); + } + await nestStore.deleteNest({ + id: nest, + moveTo: newNestID, + }); + await nestStore.fetchNests(); + commonContext.setNest(newNestID); + }; + + return ( + + + + + + + + + {t("nest.delete-nest-move-to-nest")} + } + onChange={(_, nest) => { + if (nest) { + setNewNestID(nest); + } + }} + > + {nests + .filter((v) => v.id !== nest) + .map((v) => ( + + {v.name} + + ))} + + + + + {t("common.delete")} + + + + + ); +}; + +export default DeleteNestPopover; diff --git a/web/src/components/ExploreSidebar/ExploreSidebar.tsx b/web/src/components/ExploreSidebar/ExploreSidebar.tsx index a550d5db8d644..56c0a1af95deb 100644 --- a/web/src/components/ExploreSidebar/ExploreSidebar.tsx +++ b/web/src/components/ExploreSidebar/ExploreSidebar.tsx @@ -2,6 +2,7 @@ import clsx from "clsx"; import { useLocation } from "react-router-dom"; import useDebounce from "react-use/lib/useDebounce"; import SearchBar from "@/components/SearchBar"; +import useCurrentNest from "@/hooks/useCurrentNest"; import { useMemoList, useMemoMetadataStore } from "@/store/v1"; import TagsSection from "../HomeSidebar/TagsSection"; @@ -13,14 +14,15 @@ const ExploreSidebar = (props: Props) => { const location = useLocation(); const memoList = useMemoList(); const memoMetadataStore = useMemoMetadataStore(); + const nest = useCurrentNest(); useDebounce( async () => { if (memoList.size() === 0) return; - await memoMetadataStore.fetchMemoMetadata({ location }); + await memoMetadataStore.fetchMemoMetadata({ location, nest }); }, 300, - [memoList.size(), location.pathname], + [memoList.size(), location.pathname, nest], ); return ( diff --git a/web/src/components/HomeSidebar/HomeSidebar.tsx b/web/src/components/HomeSidebar/HomeSidebar.tsx index 11a9d29285e0b..0a68c06a322fb 100644 --- a/web/src/components/HomeSidebar/HomeSidebar.tsx +++ b/web/src/components/HomeSidebar/HomeSidebar.tsx @@ -3,6 +3,7 @@ import { useLocation } from "react-router-dom"; import useDebounce from "react-use/lib/useDebounce"; import SearchBar from "@/components/SearchBar"; import UserStatisticsView from "@/components/UserStatisticsView"; +import useCurrentNest from "@/hooks/useCurrentNest"; import useCurrentUser from "@/hooks/useCurrentUser"; import { useMemoList, useMemoMetadataStore } from "@/store/v1"; import TagsSection from "./TagsSection"; @@ -16,13 +17,14 @@ const HomeSidebar = (props: Props) => { const user = useCurrentUser(); const memoList = useMemoList(); const memoMetadataStore = useMemoMetadataStore(); + const nest = useCurrentNest(); useDebounce( async () => { - await memoMetadataStore.fetchMemoMetadata({ user, location }); + await memoMetadataStore.fetchMemoMetadata({ user, location, nest }); }, 300, - [memoList.size(), user, location.pathname], + [memoList.size(), user, location.pathname, nest], ); return ( diff --git a/web/src/components/HomeSidebar/TagsSection.tsx b/web/src/components/HomeSidebar/TagsSection.tsx index 7a078cf91cb03..91392eabbfb1c 100644 --- a/web/src/components/HomeSidebar/TagsSection.tsx +++ b/web/src/components/HomeSidebar/TagsSection.tsx @@ -5,6 +5,7 @@ import toast from "react-hot-toast"; import { useLocation } from "react-router-dom"; import useLocalStorage from "react-use/lib/useLocalStorage"; import { memoServiceClient } from "@/grpcweb"; +import useCurrentNest from "@/hooks/useCurrentNest"; import useCurrentUser from "@/hooks/useCurrentUser"; import { useMemoFilterStore, useMemoMetadataStore, useMemoTagList } from "@/store/v1"; import { useTranslate } from "@/utils/i18n"; @@ -26,6 +27,7 @@ const TagsSection = (props: Props) => { const tags = Object.entries(useMemoTagList()) .sort((a, b) => a[0].localeCompare(b[0])) .sort((a, b) => b[1] - a[1]); + const nest = useCurrentNest(); const handleTagClick = (tag: string) => { const isActive = memoFilterStore.getFiltersByFactor("tagSearch").some((filter) => filter.value === tag); @@ -46,7 +48,7 @@ const TagsSection = (props: Props) => { parent: "memos/-", tag: tag, }); - await memoMetadataStore.fetchMemoMetadata({ user, location }); + await memoMetadataStore.fetchMemoMetadata({ user, location, nest }); toast.success(t("message.deleted-successfully")); } }; diff --git a/web/src/components/MemoEditor/ActionButton/AddMemoRelationPopover.tsx b/web/src/components/MemoEditor/ActionButton/AddMemoRelationPopover.tsx index ead9cc3d76a02..9c1abe8156412 100644 --- a/web/src/components/MemoEditor/ActionButton/AddMemoRelationPopover.tsx +++ b/web/src/components/MemoEditor/ActionButton/AddMemoRelationPopover.tsx @@ -8,6 +8,7 @@ import useDebounce from "react-use/lib/useDebounce"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/Popover"; import { memoServiceClient } from "@/grpcweb"; import { DEFAULT_LIST_MEMOS_PAGE_SIZE } from "@/helpers/consts"; +import useCurrentNest from "@/hooks/useCurrentNest"; import useCurrentUser from "@/hooks/useCurrentUser"; import { MemoRelation_Memo, MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service"; import { Memo, MemoView } from "@/types/proto/api/v1/memo_service"; @@ -30,6 +31,7 @@ const AddMemoRelationPopover = (props: Props) => { const [selectedMemos, setSelectedMemos] = useState([]); const [embedded, setEmbedded] = useState(false); const [popoverOpen, setPopoverOpen] = useState(false); + const nest = useCurrentNest(); const filteredMemos = fetchedMemos.filter( (memo) => @@ -45,6 +47,7 @@ const AddMemoRelationPopover = (props: Props) => { setIsFetching(true); try { const filters = [`creator == "${user.name}"`, `row_status == "NORMAL"`]; + filters.push(`nest == "${nest}"`); if (searchText) { filters.push(`content_search == [${JSON.stringify(searchText)}]`); } diff --git a/web/src/components/MemoEditor/index.tsx b/web/src/components/MemoEditor/index.tsx index 6caeb2a6c2c4e..5f2be5d1c75c8 100644 --- a/web/src/components/MemoEditor/index.tsx +++ b/web/src/components/MemoEditor/index.tsx @@ -12,6 +12,7 @@ import { memoServiceClient } from "@/grpcweb"; import { TAB_SPACE_WIDTH } from "@/helpers/consts"; import { isValidUrl } from "@/helpers/utils"; import useAsyncEffect from "@/hooks/useAsyncEffect"; +import useCurrentNest from "@/hooks/useCurrentNest"; import useCurrentUser from "@/hooks/useCurrentUser"; import { useMemoStore, useResourceStore, useUserStore, useWorkspaceSettingStore } from "@/store/v1"; import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service"; @@ -90,6 +91,7 @@ const MemoEditor = (props: Props) => { const workspaceMemoRelatedSetting = workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.MEMO_RELATED)?.memoRelatedSetting || WorkspaceMemoRelatedSetting.fromPartial({}); + const nest = useCurrentNest(); useEffect(() => { editorRef.current?.setContent(contentCache || ""); @@ -338,6 +340,7 @@ const MemoEditor = (props: Props) => { resources: state.resourceList, relations: state.relationList, location: state.location, + nest: nest, }) : memoServiceClient .createMemoComment({ diff --git a/web/src/components/Navigation.tsx b/web/src/components/Navigation.tsx index 7b1fe4d9fbe79..47e4a79d9bf74 100644 --- a/web/src/components/Navigation.tsx +++ b/web/src/components/Navigation.tsx @@ -8,6 +8,7 @@ import { Routes } from "@/router"; import { useInboxStore } from "@/store/v1"; import { Inbox_Status } from "@/types/proto/api/v1/inbox_service"; import { useTranslate } from "@/utils/i18n"; +import NestBanner from "./NestBanner"; import UserBanner from "./UserBanner"; interface NavLinkItem { @@ -119,6 +120,7 @@ const Navigation = (props: Props) => { className={clsx("w-full h-full overflow-auto flex flex-col justify-start items-start py-4 md:pt-6 z-30 hide-scrollbar", className)} > + {user ? : null} {navLinks.map((navLink) => ( { + const { collapsed } = props; + const user = useCurrentUser(); + const nests = useNestList(); + const nestStore = useNestStore(); + const commonContext = useCommonContext(); + + const handleNestChange = (nest: string) => { + commonContext.setNest(nest); + }; + + return ( + + + + + + {!collapsed && ( + + {nestStore.getNestById(commonContext.nest)?.name} + + )} + + + + {nests.map((nest) => ( + handleNestChange(nest.id)} key={nest.id}> + {nest.name} + + ))} + + + + {nests.length > 1 && } + + ); +}; + +export default NestBanner; diff --git a/web/src/components/NestIcon.tsx b/web/src/components/NestIcon.tsx new file mode 100644 index 0000000000000..314b6fce4abe3 --- /dev/null +++ b/web/src/components/NestIcon.tsx @@ -0,0 +1,8 @@ +import clsx from "clsx"; +import { BirdIcon } from "lucide-react"; + +const NestIcon = () => { + return ; +}; + +export default NestIcon; diff --git a/web/src/components/PasswordSignInForm.tsx b/web/src/components/PasswordSignInForm.tsx index aba46cba666b5..d8ef1c5bb71a5 100644 --- a/web/src/components/PasswordSignInForm.tsx +++ b/web/src/components/PasswordSignInForm.tsx @@ -7,7 +7,7 @@ import { authServiceClient } from "@/grpcweb"; import useLoading from "@/hooks/useLoading"; import useNavigateTo from "@/hooks/useNavigateTo"; import { useCommonContext } from "@/layouts/CommonContextProvider"; -import { useUserStore } from "@/store/v1"; +import { useNestStore, useUserStore } from "@/store/v1"; import { useTranslate } from "@/utils/i18n"; const PasswordSignInForm = () => { @@ -15,6 +15,7 @@ const PasswordSignInForm = () => { const navigateTo = useNavigateTo(); const commonContext = useCommonContext(); const userStore = useUserStore(); + const nestStore = useNestStore(); const actionBtnLoadingState = useLoading(false); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); @@ -55,6 +56,7 @@ const PasswordSignInForm = () => { actionBtnLoadingState.setLoading(); await authServiceClient.signIn({ username, password, neverExpire: remember }); await userStore.fetchCurrentUser(); + await nestStore.fetchNests(); navigateTo("/"); } catch (error: any) { console.error(error); diff --git a/web/src/components/RenameTagDialog.tsx b/web/src/components/RenameTagDialog.tsx index 3e14d95be2197..dff476e57ba82 100644 --- a/web/src/components/RenameTagDialog.tsx +++ b/web/src/components/RenameTagDialog.tsx @@ -4,6 +4,7 @@ import { XIcon } from "lucide-react"; import React, { useState } from "react"; import { toast } from "react-hot-toast"; import { memoServiceClient } from "@/grpcweb"; +import useCurrentNest from "@/hooks/useCurrentNest"; import useCurrentUser from "@/hooks/useCurrentUser"; import useLoading from "@/hooks/useLoading"; import { useMemoMetadataStore } from "@/store/v1"; @@ -21,6 +22,7 @@ const RenameTagDialog: React.FC = (props: Props) => { const [newName, setNewName] = useState(tag); const requestState = useLoading(false); const user = useCurrentUser(); + const nest = useCurrentNest(); const handleTagNameInputChange = (e: React.ChangeEvent) => { setNewName(e.target.value.trim()); @@ -43,7 +45,7 @@ const RenameTagDialog: React.FC = (props: Props) => { newTag: newName, }); toast.success("Rename tag successfully"); - memoMetadataStore.fetchMemoMetadata({ user }); + memoMetadataStore.fetchMemoMetadata({ user, nest }); } catch (error: any) { console.error(error); toast.error(error.details); diff --git a/web/src/components/Settings/PreferencesSection.tsx b/web/src/components/Settings/PreferencesSection.tsx index c4b9519b324b4..c7694eba2913b 100644 --- a/web/src/components/Settings/PreferencesSection.tsx +++ b/web/src/components/Settings/PreferencesSection.tsx @@ -1,12 +1,14 @@ import { Divider, Option, Select } from "@mui/joy"; import { useCommonContext } from "@/layouts/CommonContextProvider"; import { useUserStore } from "@/store/v1"; +import { useNestList } from "@/store/v1/nest"; import { Visibility } from "@/types/proto/api/v1/memo_service"; import { UserSetting } from "@/types/proto/api/v1/user_service"; import { useTranslate } from "@/utils/i18n"; import { convertVisibilityFromString, convertVisibilityToString } from "@/utils/memo"; import AppearanceSelect from "../AppearanceSelect"; import LocaleSelect from "../LocaleSelect"; +import NestIcon from "../NestIcon"; import VisibilityIcon from "../VisibilityIcon"; import WebhookSection from "./WebhookSection"; @@ -15,6 +17,7 @@ const PreferencesSection = () => { const commonContext = useCommonContext(); const userStore = useUserStore(); const setting = userStore.userSetting as UserSetting; + const nests = useNestList(); const handleLocaleSelectChange = async (locale: Locale) => { commonContext.setLocale(locale); @@ -45,6 +48,16 @@ const PreferencesSection = () => { ); }; + const handleDefaultNestChanged = async (nest: string) => { + commonContext.setNest(nest); + await userStore.updateUserSetting( + { + nest, + }, + ["nest"], + ); + }; + return ( {t("common.basic")} @@ -78,6 +91,25 @@ const PreferencesSection = () => { ))} + + {t("setting.preference-section.default-nest")} + } + onChange={(_, nest) => { + if (nest) { + handleDefaultNestChanged(nest); + } + }} + > + {nests.map((v) => ( + + {v.name} + + ))} + + diff --git a/web/src/grpcweb.ts b/web/src/grpcweb.ts index abecc81cbad83..a6f7715859848 100644 --- a/web/src/grpcweb.ts +++ b/web/src/grpcweb.ts @@ -5,6 +5,7 @@ import { IdentityProviderServiceDefinition } from "./types/proto/api/v1/idp_serv import { InboxServiceDefinition } from "./types/proto/api/v1/inbox_service"; import { MarkdownServiceDefinition } from "./types/proto/api/v1/markdown_service"; import { MemoServiceDefinition } from "./types/proto/api/v1/memo_service"; +import { NestServiceDefinition } from "./types/proto/api/v1/nest_service"; import { ResourceServiceDefinition } from "./types/proto/api/v1/resource_service"; import { UserServiceDefinition } from "./types/proto/api/v1/user_service"; import { WebhookServiceDefinition } from "./types/proto/api/v1/webhook_service"; @@ -41,3 +42,5 @@ export const webhookServiceClient = clientFactory.create(WebhookServiceDefinitio export const markdownServiceClient = clientFactory.create(MarkdownServiceDefinition, channel); export const identityProviderServiceClient = clientFactory.create(IdentityProviderServiceDefinition, channel); + +export const nestServiceClient = clientFactory.create(NestServiceDefinition, channel); diff --git a/web/src/hooks/index.ts b/web/src/hooks/index.ts index eec8f21436fb3..ee9992f58ab0f 100644 --- a/web/src/hooks/index.ts +++ b/web/src/hooks/index.ts @@ -3,3 +3,4 @@ export * from "./useCurrentUser"; export * from "./useNavigateTo"; export * from "./useAsyncEffect"; export * from "./useResponsiveWidth"; +export * from "./useCurrentNest"; diff --git a/web/src/hooks/useCurrentNest.ts b/web/src/hooks/useCurrentNest.ts new file mode 100644 index 0000000000000..e2a4b9a17caef --- /dev/null +++ b/web/src/hooks/useCurrentNest.ts @@ -0,0 +1,8 @@ +import { useCommonContext } from "@/layouts/CommonContextProvider"; + +const useCurrentNest = () => { + const commonContext = useCommonContext(); + return commonContext.nest; +}; + +export default useCurrentNest; diff --git a/web/src/layouts/CommonContextProvider.tsx b/web/src/layouts/CommonContextProvider.tsx index 36f7f088eace2..b641422a58d2b 100644 --- a/web/src/layouts/CommonContextProvider.tsx +++ b/web/src/layouts/CommonContextProvider.tsx @@ -2,6 +2,7 @@ import { createContext, useContext, useEffect, useState } from "react"; import useLocalStorage from "react-use/lib/useLocalStorage"; import { workspaceServiceClient } from "@/grpcweb"; import { useUserStore, useWorkspaceSettingStore } from "@/store/v1"; +import { useNestStore } from "@/store/v1/nest"; import { WorkspaceProfile } from "@/types/proto/api/v1/workspace_service"; import { WorkspaceGeneralSetting, WorkspaceSettingKey } from "@/types/proto/store/workspace_setting"; @@ -9,34 +10,40 @@ interface Context { locale: string; appearance: string; profile: WorkspaceProfile; + nest: string; setLocale: (locale: string) => void; setAppearance: (appearance: string) => void; + setNest: (nest: string) => void; } const CommonContext = createContext({ locale: "en", appearance: "system", profile: WorkspaceProfile.fromPartial({}), + nest: "none", setLocale: () => {}, setAppearance: () => {}, + setNest: () => {}, }); const CommonContextProvider = ({ children }: { children: React.ReactNode }) => { const workspaceSettingStore = useWorkspaceSettingStore(); const userStore = useUserStore(); + const nestStore = useNestStore(); const [initialized, setInitialized] = useState(false); - const [commonContext, setCommonContext] = useState>({ + const [commonContext, setCommonContext] = useState>({ locale: "en", appearance: "system", + nest: "none", profile: WorkspaceProfile.fromPartial({}), }); const [locale] = useLocalStorage("locale", "en"); const [appearance] = useLocalStorage("appearance", "system"); + const [nest] = useLocalStorage("nest", "none"); useEffect(() => { const initialWorkspace = async () => { const workspaceProfile = await workspaceServiceClient.getWorkspaceProfile({}); - // Initial fetch for workspace settings. (async () => { [WorkspaceSettingKey.GENERAL, WorkspaceSettingKey.MEMO_RELATED].forEach(async (key) => { await workspaceSettingStore.fetchWorkspaceSetting(key); @@ -49,6 +56,7 @@ const CommonContextProvider = ({ children }: { children: React.ReactNode }) => { setCommonContext({ locale: locale || workspaceGeneralSetting.customProfile?.locale || "en", appearance: appearance || workspaceGeneralSetting.customProfile?.appearance || "system", + nest: nest || "none", profile: workspaceProfile, }); }; @@ -56,6 +64,7 @@ const CommonContextProvider = ({ children }: { children: React.ReactNode }) => { const initialUser = async () => { try { await userStore.fetchCurrentUser(); + await nestStore.fetchNests(); } catch (error) { // Do nothing. } @@ -70,6 +79,7 @@ const CommonContextProvider = ({ children }: { children: React.ReactNode }) => { ...commonContext, setLocale: (locale: string) => setCommonContext({ ...commonContext, locale }), setAppearance: (appearance: string) => setCommonContext({ ...commonContext, appearance }), + setNest: (nest: string) => setCommonContext({ ...commonContext, nest }), }} > {!initialized ? null : <>{children}>} diff --git a/web/src/locales/en.json b/web/src/locales/en.json index 4301742bd7ea8..c3f38f3c4d3c8 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -143,6 +143,10 @@ "no-memos-found": "No memos found", "search-placeholder": "Search content" }, + "nest": { + "add-nest": "Add nest", + "delete-nest-move-to-nest": "Move to nest" + }, "resource": { "clear": "Clear", "copy-link": "Copy Link", @@ -212,6 +216,7 @@ "preference-section": { "default-memo-sort-option": "Memo display time", "default-memo-visibility": "Default memo visibility", + "default-nest": "Default nest", "theme": "Theme" }, "sso": "SSO", diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx index f98a71bed6c92..3c01d62180af3 100644 --- a/web/src/pages/Home.tsx +++ b/web/src/pages/Home.tsx @@ -7,6 +7,7 @@ import MemoFilters from "@/components/MemoFilters"; import MemoView from "@/components/MemoView"; import MobileHeader from "@/components/MobileHeader"; import PagedMemoList from "@/components/PagedMemoList"; +import useCurrentNest from "@/hooks/useCurrentNest"; import useCurrentUser from "@/hooks/useCurrentUser"; import useResponsiveWidth from "@/hooks/useResponsiveWidth"; import { useMemoFilterStore } from "@/store/v1"; @@ -17,9 +18,11 @@ const Home = () => { const { md } = useResponsiveWidth(); const user = useCurrentUser(); const memoFilterStore = useMemoFilterStore(); + const nest = useCurrentNest(); const memoListFilter = useMemo(() => { const filters = [`creator == "${user.name}"`, `row_status == "NORMAL"`, `order_by_pinned == true`]; + filters.push(`nest == "${nest}"`); const contentSearch: string[] = []; const tagSearch: string[] = []; for (const filter of memoFilterStore.filters) { @@ -51,7 +54,7 @@ const Home = () => { filters.push(`tag_search == [${tagSearch.join(", ")}]`); } return filters.join(" && "); - }, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc]); + }, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc, nest]); return ( diff --git a/web/src/pages/SignUp.tsx b/web/src/pages/SignUp.tsx index 14874213cf468..7677ff85e1b40 100644 --- a/web/src/pages/SignUp.tsx +++ b/web/src/pages/SignUp.tsx @@ -10,7 +10,7 @@ import { authServiceClient } from "@/grpcweb"; import useLoading from "@/hooks/useLoading"; import useNavigateTo from "@/hooks/useNavigateTo"; import { useCommonContext } from "@/layouts/CommonContextProvider"; -import { useUserStore, useWorkspaceSettingStore } from "@/store/v1"; +import { useNestStore, useUserStore, useWorkspaceSettingStore } from "@/store/v1"; import { WorkspaceGeneralSetting } from "@/types/proto/api/v1/workspace_setting_service"; import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting"; import { useTranslate } from "@/utils/i18n"; @@ -21,6 +21,7 @@ const SignUp = () => { const commonContext = useCommonContext(); const workspaceSettingStore = useWorkspaceSettingStore(); const userStore = useUserStore(); + const nestStore = useNestStore(); const actionBtnLoadingState = useLoading(false); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); @@ -63,6 +64,7 @@ const SignUp = () => { actionBtnLoadingState.setLoading(); await authServiceClient.signUp({ username, password }); await userStore.fetchCurrentUser(); + await nestStore.fetchNests(); navigateTo("/"); } catch (error: any) { console.error(error); diff --git a/web/src/store/v1/index.ts b/web/src/store/v1/index.ts index 9cc46daa2079e..a1e2c0af16762 100644 --- a/web/src/store/v1/index.ts +++ b/web/src/store/v1/index.ts @@ -6,3 +6,4 @@ export * from "./resource"; export * from "./workspaceSetting"; export * from "./memoFilter"; export * from "./memoMetadata"; +export * from "./nest"; diff --git a/web/src/store/v1/memoMetadata.ts b/web/src/store/v1/memoMetadata.ts index 2c92f3852d85a..79f2ee90024f6 100644 --- a/web/src/store/v1/memoMetadata.ts +++ b/web/src/store/v1/memoMetadata.ts @@ -14,11 +14,13 @@ interface State { // stateId is used to identify the store instance state. // It should be update when any state change. stateId: string; + nest: string; dataMapByName: Record; } const getDefaultState = (): State => ({ stateId: uniqueId(), + nest: "", dataMapByName: {}, }); @@ -26,11 +28,18 @@ export const useMemoMetadataStore = create( combine(getDefaultState(), (set, get) => ({ setState: (state: State) => set(state), getState: () => get(), - fetchMemoMetadata: async (params: { user?: User; location?: Location }) => { + fetchMemoMetadata: async (params: { user?: User; location?: Location; nest: string }) => { const filters = [`row_status == "NORMAL"`]; + + if (get().nest != params.nest) { + set({ nest: params.nest, dataMapByName: {} }); + } + if (params.user) { if (params.location?.pathname === Routes.EXPLORE) { filters.push(`visibilities == ["PUBLIC", "PROTECTED"]`); + } else { + filters.push(`nest == "${params.nest}"`); } filters.push(`creator == "${params.user.name}"`); } else { diff --git a/web/src/store/v1/nest.ts b/web/src/store/v1/nest.ts new file mode 100644 index 0000000000000..d40c8018f01f1 --- /dev/null +++ b/web/src/store/v1/nest.ts @@ -0,0 +1,55 @@ +import { create } from "zustand"; +import { combine } from "zustand/middleware"; +import { nestServiceClient } from "@/grpcweb"; +import { CreateNestRequest, DeleteNestRequest, Nest, UpdateNestRequest } from "@/types/proto/api/v1/nest_service"; +import { Empty } from "@/types/proto/google/protobuf/empty"; + +interface State { + nestMapByName: Record; +} + +const getDefaultState = (): State => ({ + nestMapByName: {}, +}); + +export const useNestStore = create( + combine(getDefaultState(), (set, get) => ({ + setState: (state: State) => set(state), + getState: () => get(), + fetchNests: async () => { + const { nests } = await nestServiceClient.listNests({}); + const nestMap = get().nestMapByName; + for (const nest of nests) { + nestMap[nest.id] = nest; + } + set({ nestMapByName: nestMap }); + return nestMap; + }, + getNestById: (id: string) => { + const nestMap = get().nestMapByName; + return Object.values(nestMap).find((r) => r.id === id); + }, + async createNest(create: CreateNestRequest): Promise { + const nest = await nestServiceClient.createNest(create); + const nestMap = get().nestMapByName; + nestMap[nest.id] = nest; + return nest; + }, + async updateNest(update: UpdateNestRequest): Promise { + const nest = await nestServiceClient.updateNest(update); + const nestMap = get().nestMapByName; + nestMap[nest.id] = nest; + return nest; + }, + async deleteNest(delreq: DeleteNestRequest): Promise { + return await nestServiceClient.deleteNest(delreq); + }, + })), +); + +export const useNestList = () => { + const nestStore = useNestStore(); + const nests = Object.values(nestStore.getState().nestMapByName); + + return nests; +}; diff --git a/web/src/store/v1/user.ts b/web/src/store/v1/user.ts index f65a878aa2e0e..9f1b9a00d33f5 100644 --- a/web/src/store/v1/user.ts +++ b/web/src/store/v1/user.ts @@ -21,6 +21,7 @@ const getDefaultUserSetting = () => { locale: "en", appearance: "auto", memoVisibility: "PRIVATE", + nest: "none", }); };
{t("common.basic")}