diff --git a/proto/api/v1/attachment_service.proto b/proto/api/v1/attachment_service.proto index 12fc9c1a3..ad2631f45 100644 --- a/proto/api/v1/attachment_service.proto +++ b/proto/api/v1/attachment_service.proto @@ -5,7 +5,6 @@ package memos.api.v1; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; -import "google/api/httpbody.proto"; import "google/api/resource.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; @@ -31,11 +30,6 @@ service AttachmentService { option (google.api.http) = {get: "/api/v1/{name=attachments/*}"}; option (google.api.method_signature) = "name"; } - // GetAttachmentBinary returns a attachment binary by name. - rpc GetAttachmentBinary(GetAttachmentBinaryRequest) returns (google.api.HttpBody) { - option (google.api.http) = {get: "/file/{name=attachments/*}/{filename}"}; - option (google.api.method_signature) = "name,filename,thumbnail"; - } // UpdateAttachment updates a attachment. rpc UpdateAttachment(UpdateAttachmentRequest) returns (Attachment) { option (google.api.http) = { @@ -138,21 +132,6 @@ message GetAttachmentRequest { ]; } -message GetAttachmentBinaryRequest { - // Required. The attachment name of the attachment. - // Format: attachments/{attachment} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = {type: "memos.api.v1/Attachment"} - ]; - - // The filename of the attachment. Mainly used for downloading. - string filename = 2 [(google.api.field_behavior) = REQUIRED]; - - // Optional. A flag indicating if the thumbnail version of the attachment should be returned. - bool thumbnail = 3 [(google.api.field_behavior) = OPTIONAL]; -} - message UpdateAttachmentRequest { // Required. The attachment which replaces the attachment on the server. Attachment attachment = 1 [(google.api.field_behavior) = REQUIRED]; diff --git a/proto/api/v1/user_service.proto b/proto/api/v1/user_service.proto index 1c14f45f0..8eff1bebd 100644 --- a/proto/api/v1/user_service.proto +++ b/proto/api/v1/user_service.proto @@ -6,7 +6,6 @@ import "api/v1/common.proto"; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; -import "google/api/httpbody.proto"; import "google/api/resource.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; @@ -53,12 +52,6 @@ service UserService { option (google.api.method_signature) = "name"; } - // GetUserAvatar gets the avatar of a user. - rpc GetUserAvatar(GetUserAvatarRequest) returns (google.api.HttpBody) { - option (google.api.http) = {get: "/api/v1/{name=users/*}/avatar"}; - option (google.api.method_signature) = "name"; - } - // ListAllUserStats returns statistics for all users. rpc ListAllUserStats(ListAllUserStatsRequest) returns (ListAllUserStatsResponse) { option (google.api.http) = {get: "/api/v1/users:stats"}; @@ -324,15 +317,6 @@ message DeleteUserRequest { bool force = 2 [(google.api.field_behavior) = OPTIONAL]; } -message GetUserAvatarRequest { - // Required. The resource name of the user. - // Format: users/{user} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = {type: "memos.api.v1/User"} - ]; -} - // User statistics messages message UserStats { option (google.api.resource) = { diff --git a/proto/gen/api/v1/attachment_service.pb.go b/proto/gen/api/v1/attachment_service.pb.go index f471c3ebe..65bdf6eb5 100644 --- a/proto/gen/api/v1/attachment_service.pb.go +++ b/proto/gen/api/v1/attachment_service.pb.go @@ -8,7 +8,6 @@ package apiv1 import ( _ "google.golang.org/genproto/googleapis/api/annotations" - httpbody "google.golang.org/genproto/googleapis/api/httpbody" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" @@ -381,70 +380,6 @@ func (x *GetAttachmentRequest) GetName() string { return "" } -type GetAttachmentBinaryRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. The attachment name of the attachment. - // Format: attachments/{attachment} - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // The filename of the attachment. Mainly used for downloading. - Filename string `protobuf:"bytes,2,opt,name=filename,proto3" json:"filename,omitempty"` - // Optional. A flag indicating if the thumbnail version of the attachment should be returned. - Thumbnail bool `protobuf:"varint,3,opt,name=thumbnail,proto3" json:"thumbnail,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAttachmentBinaryRequest) Reset() { - *x = GetAttachmentBinaryRequest{} - mi := &file_api_v1_attachment_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAttachmentBinaryRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAttachmentBinaryRequest) ProtoMessage() {} - -func (x *GetAttachmentBinaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_attachment_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 GetAttachmentBinaryRequest.ProtoReflect.Descriptor instead. -func (*GetAttachmentBinaryRequest) Descriptor() ([]byte, []int) { - return file_api_v1_attachment_service_proto_rawDescGZIP(), []int{5} -} - -func (x *GetAttachmentBinaryRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *GetAttachmentBinaryRequest) GetFilename() string { - if x != nil { - return x.Filename - } - return "" -} - -func (x *GetAttachmentBinaryRequest) GetThumbnail() bool { - if x != nil { - return x.Thumbnail - } - return false -} - type UpdateAttachmentRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. The attachment which replaces the attachment on the server. @@ -457,7 +392,7 @@ type UpdateAttachmentRequest struct { func (x *UpdateAttachmentRequest) Reset() { *x = UpdateAttachmentRequest{} - mi := &file_api_v1_attachment_service_proto_msgTypes[6] + mi := &file_api_v1_attachment_service_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -469,7 +404,7 @@ func (x *UpdateAttachmentRequest) String() string { func (*UpdateAttachmentRequest) ProtoMessage() {} func (x *UpdateAttachmentRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_attachment_service_proto_msgTypes[6] + mi := &file_api_v1_attachment_service_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -482,7 +417,7 @@ func (x *UpdateAttachmentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAttachmentRequest.ProtoReflect.Descriptor instead. func (*UpdateAttachmentRequest) Descriptor() ([]byte, []int) { - return file_api_v1_attachment_service_proto_rawDescGZIP(), []int{6} + return file_api_v1_attachment_service_proto_rawDescGZIP(), []int{5} } func (x *UpdateAttachmentRequest) GetAttachment() *Attachment { @@ -510,7 +445,7 @@ type DeleteAttachmentRequest struct { func (x *DeleteAttachmentRequest) Reset() { *x = DeleteAttachmentRequest{} - mi := &file_api_v1_attachment_service_proto_msgTypes[7] + mi := &file_api_v1_attachment_service_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -522,7 +457,7 @@ func (x *DeleteAttachmentRequest) String() string { func (*DeleteAttachmentRequest) ProtoMessage() {} func (x *DeleteAttachmentRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_attachment_service_proto_msgTypes[7] + mi := &file_api_v1_attachment_service_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -535,7 +470,7 @@ func (x *DeleteAttachmentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteAttachmentRequest.ProtoReflect.Descriptor instead. func (*DeleteAttachmentRequest) Descriptor() ([]byte, []int) { - return file_api_v1_attachment_service_proto_rawDescGZIP(), []int{7} + return file_api_v1_attachment_service_proto_rawDescGZIP(), []int{6} } func (x *DeleteAttachmentRequest) GetName() string { @@ -549,7 +484,7 @@ var File_api_v1_attachment_service_proto protoreflect.FileDescriptor const file_api_v1_attachment_service_proto_rawDesc = "" + "\n" + - "\x1fapi/v1/attachment_service.proto\x12\fmemos.api.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/httpbody.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xfb\x02\n" + + "\x1fapi/v1/attachment_service.proto\x12\fmemos.api.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xfb\x02\n" + "\n" + "Attachment\x12\x17\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12@\n" + @@ -582,12 +517,7 @@ const file_api_v1_attachment_service_proto_rawDesc = "" + "total_size\x18\x03 \x01(\x05R\ttotalSize\"K\n" + "\x14GetAttachmentRequest\x123\n" + "\x04name\x18\x01 \x01(\tB\x1f\xe0A\x02\xfaA\x19\n" + - "\x17memos.api.v1/AttachmentR\x04name\"\x95\x01\n" + - "\x1aGetAttachmentBinaryRequest\x123\n" + - "\x04name\x18\x01 \x01(\tB\x1f\xe0A\x02\xfaA\x19\n" + - "\x17memos.api.v1/AttachmentR\x04name\x12\x1f\n" + - "\bfilename\x18\x02 \x01(\tB\x03\xe0A\x02R\bfilename\x12!\n" + - "\tthumbnail\x18\x03 \x01(\bB\x03\xe0A\x01R\tthumbnail\"\x9a\x01\n" + + "\x17memos.api.v1/AttachmentR\x04name\"\x9a\x01\n" + "\x17UpdateAttachmentRequest\x12=\n" + "\n" + "attachment\x18\x01 \x01(\v2\x18.memos.api.v1.AttachmentB\x03\xe0A\x02R\n" + @@ -596,14 +526,13 @@ const file_api_v1_attachment_service_proto_rawDesc = "" + "updateMask\"N\n" + "\x17DeleteAttachmentRequest\x123\n" + "\x04name\x18\x01 \x01(\tB\x1f\xe0A\x02\xfaA\x19\n" + - "\x17memos.api.v1/AttachmentR\x04name2\xe5\x06\n" + + "\x17memos.api.v1/AttachmentR\x04name2\xc4\x05\n" + "\x11AttachmentService\x12\x89\x01\n" + "\x10CreateAttachment\x12%.memos.api.v1.CreateAttachmentRequest\x1a\x18.memos.api.v1.Attachment\"4\xdaA\n" + "attachment\x82\xd3\xe4\x93\x02!:\n" + "attachment\"\x13/api/v1/attachments\x12{\n" + "\x0fListAttachments\x12$.memos.api.v1.ListAttachmentsRequest\x1a%.memos.api.v1.ListAttachmentsResponse\"\x1b\x82\xd3\xe4\x93\x02\x15\x12\x13/api/v1/attachments\x12z\n" + - "\rGetAttachment\x12\".memos.api.v1.GetAttachmentRequest\x1a\x18.memos.api.v1.Attachment\"+\xdaA\x04name\x82\xd3\xe4\x93\x02\x1e\x12\x1c/api/v1/{name=attachments/*}\x12\x9e\x01\n" + - "\x13GetAttachmentBinary\x12(.memos.api.v1.GetAttachmentBinaryRequest\x1a\x14.google.api.HttpBody\"G\xdaA\x17name,filename,thumbnail\x82\xd3\xe4\x93\x02'\x12%/file/{name=attachments/*}/{filename}\x12\xa9\x01\n" + + "\rGetAttachment\x12\".memos.api.v1.GetAttachmentRequest\x1a\x18.memos.api.v1.Attachment\"+\xdaA\x04name\x82\xd3\xe4\x93\x02\x1e\x12\x1c/api/v1/{name=attachments/*}\x12\xa9\x01\n" + "\x10UpdateAttachment\x12%.memos.api.v1.UpdateAttachmentRequest\x1a\x18.memos.api.v1.Attachment\"T\xdaA\x16attachment,update_mask\x82\xd3\xe4\x93\x025:\n" + "attachment2'/api/v1/{attachment.name=attachments/*}\x12~\n" + "\x10DeleteAttachment\x12%.memos.api.v1.DeleteAttachmentRequest\x1a\x16.google.protobuf.Empty\"+\xdaA\x04name\x82\xd3\xe4\x93\x02\x1e*\x1c/api/v1/{name=attachments/*}B\xae\x01\n" + @@ -621,41 +550,37 @@ func file_api_v1_attachment_service_proto_rawDescGZIP() []byte { return file_api_v1_attachment_service_proto_rawDescData } -var file_api_v1_attachment_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_api_v1_attachment_service_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_api_v1_attachment_service_proto_goTypes = []any{ - (*Attachment)(nil), // 0: memos.api.v1.Attachment - (*CreateAttachmentRequest)(nil), // 1: memos.api.v1.CreateAttachmentRequest - (*ListAttachmentsRequest)(nil), // 2: memos.api.v1.ListAttachmentsRequest - (*ListAttachmentsResponse)(nil), // 3: memos.api.v1.ListAttachmentsResponse - (*GetAttachmentRequest)(nil), // 4: memos.api.v1.GetAttachmentRequest - (*GetAttachmentBinaryRequest)(nil), // 5: memos.api.v1.GetAttachmentBinaryRequest - (*UpdateAttachmentRequest)(nil), // 6: memos.api.v1.UpdateAttachmentRequest - (*DeleteAttachmentRequest)(nil), // 7: memos.api.v1.DeleteAttachmentRequest - (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp - (*fieldmaskpb.FieldMask)(nil), // 9: google.protobuf.FieldMask - (*httpbody.HttpBody)(nil), // 10: google.api.HttpBody - (*emptypb.Empty)(nil), // 11: google.protobuf.Empty + (*Attachment)(nil), // 0: memos.api.v1.Attachment + (*CreateAttachmentRequest)(nil), // 1: memos.api.v1.CreateAttachmentRequest + (*ListAttachmentsRequest)(nil), // 2: memos.api.v1.ListAttachmentsRequest + (*ListAttachmentsResponse)(nil), // 3: memos.api.v1.ListAttachmentsResponse + (*GetAttachmentRequest)(nil), // 4: memos.api.v1.GetAttachmentRequest + (*UpdateAttachmentRequest)(nil), // 5: memos.api.v1.UpdateAttachmentRequest + (*DeleteAttachmentRequest)(nil), // 6: memos.api.v1.DeleteAttachmentRequest + (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp + (*fieldmaskpb.FieldMask)(nil), // 8: google.protobuf.FieldMask + (*emptypb.Empty)(nil), // 9: google.protobuf.Empty } var file_api_v1_attachment_service_proto_depIdxs = []int32{ - 8, // 0: memos.api.v1.Attachment.create_time:type_name -> google.protobuf.Timestamp + 7, // 0: memos.api.v1.Attachment.create_time:type_name -> google.protobuf.Timestamp 0, // 1: memos.api.v1.CreateAttachmentRequest.attachment:type_name -> memos.api.v1.Attachment 0, // 2: memos.api.v1.ListAttachmentsResponse.attachments:type_name -> memos.api.v1.Attachment 0, // 3: memos.api.v1.UpdateAttachmentRequest.attachment:type_name -> memos.api.v1.Attachment - 9, // 4: memos.api.v1.UpdateAttachmentRequest.update_mask:type_name -> google.protobuf.FieldMask + 8, // 4: memos.api.v1.UpdateAttachmentRequest.update_mask:type_name -> google.protobuf.FieldMask 1, // 5: memos.api.v1.AttachmentService.CreateAttachment:input_type -> memos.api.v1.CreateAttachmentRequest 2, // 6: memos.api.v1.AttachmentService.ListAttachments:input_type -> memos.api.v1.ListAttachmentsRequest 4, // 7: memos.api.v1.AttachmentService.GetAttachment:input_type -> memos.api.v1.GetAttachmentRequest - 5, // 8: memos.api.v1.AttachmentService.GetAttachmentBinary:input_type -> memos.api.v1.GetAttachmentBinaryRequest - 6, // 9: memos.api.v1.AttachmentService.UpdateAttachment:input_type -> memos.api.v1.UpdateAttachmentRequest - 7, // 10: memos.api.v1.AttachmentService.DeleteAttachment:input_type -> memos.api.v1.DeleteAttachmentRequest - 0, // 11: memos.api.v1.AttachmentService.CreateAttachment:output_type -> memos.api.v1.Attachment - 3, // 12: memos.api.v1.AttachmentService.ListAttachments:output_type -> memos.api.v1.ListAttachmentsResponse - 0, // 13: memos.api.v1.AttachmentService.GetAttachment:output_type -> memos.api.v1.Attachment - 10, // 14: memos.api.v1.AttachmentService.GetAttachmentBinary:output_type -> google.api.HttpBody - 0, // 15: memos.api.v1.AttachmentService.UpdateAttachment:output_type -> memos.api.v1.Attachment - 11, // 16: memos.api.v1.AttachmentService.DeleteAttachment:output_type -> google.protobuf.Empty - 11, // [11:17] is the sub-list for method output_type - 5, // [5:11] is the sub-list for method input_type + 5, // 8: memos.api.v1.AttachmentService.UpdateAttachment:input_type -> memos.api.v1.UpdateAttachmentRequest + 6, // 9: memos.api.v1.AttachmentService.DeleteAttachment:input_type -> memos.api.v1.DeleteAttachmentRequest + 0, // 10: memos.api.v1.AttachmentService.CreateAttachment:output_type -> memos.api.v1.Attachment + 3, // 11: memos.api.v1.AttachmentService.ListAttachments:output_type -> memos.api.v1.ListAttachmentsResponse + 0, // 12: memos.api.v1.AttachmentService.GetAttachment:output_type -> memos.api.v1.Attachment + 0, // 13: memos.api.v1.AttachmentService.UpdateAttachment:output_type -> memos.api.v1.Attachment + 9, // 14: memos.api.v1.AttachmentService.DeleteAttachment:output_type -> google.protobuf.Empty + 10, // [10:15] is the sub-list for method output_type + 5, // [5:10] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name @@ -673,7 +598,7 @@ func file_api_v1_attachment_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_attachment_service_proto_rawDesc), len(file_api_v1_attachment_service_proto_rawDesc)), NumEnums: 0, - NumMessages: 8, + NumMessages: 7, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/api/v1/attachment_service.pb.gw.go b/proto/gen/api/v1/attachment_service.pb.gw.go index d31cc5c93..9d6f6d8c4 100644 --- a/proto/gen/api/v1/attachment_service.pb.gw.go +++ b/proto/gen/api/v1/attachment_service.pb.gw.go @@ -150,75 +150,6 @@ func local_request_AttachmentService_GetAttachment_0(ctx context.Context, marsha return msg, metadata, err } -var filter_AttachmentService_GetAttachmentBinary_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0, "filename": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} - -func request_AttachmentService_GetAttachmentBinary_0(ctx context.Context, marshaler runtime.Marshaler, client AttachmentServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var ( - protoReq GetAttachmentBinaryRequest - metadata runtime.ServerMetadata - err error - ) - if req.Body != nil { - _, _ = io.Copy(io.Discard, req.Body) - } - 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) - } - val, ok = pathParams["filename"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "filename") - } - protoReq.Filename, err = runtime.String(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "filename", err) - } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AttachmentService_GetAttachmentBinary_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := client.GetAttachmentBinary(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err -} - -func local_request_AttachmentService_GetAttachmentBinary_0(ctx context.Context, marshaler runtime.Marshaler, server AttachmentServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var ( - protoReq GetAttachmentBinaryRequest - metadata runtime.ServerMetadata - err error - ) - 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) - } - val, ok = pathParams["filename"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "filename") - } - protoReq.Filename, err = runtime.String(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "filename", err) - } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AttachmentService_GetAttachmentBinary_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := server.GetAttachmentBinary(ctx, &protoReq) - return msg, metadata, err -} - var filter_AttachmentService_UpdateAttachment_0 = &utilities.DoubleArray{Encoding: map[string]int{"attachment": 0, "name": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}} func request_AttachmentService_UpdateAttachment_0(ctx context.Context, marshaler runtime.Marshaler, client AttachmentServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -405,26 +336,6 @@ func RegisterAttachmentServiceHandlerServer(ctx context.Context, mux *runtime.Se } forward_AttachmentService_GetAttachment_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle(http.MethodGet, pattern_AttachmentService_GetAttachmentBinary_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.AttachmentService/GetAttachmentBinary", runtime.WithHTTPPathPattern("/file/{name=attachments/*}/{filename}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_AttachmentService_GetAttachmentBinary_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_AttachmentService_GetAttachmentBinary_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) mux.Handle(http.MethodPatch, pattern_AttachmentService_UpdateAttachment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -556,23 +467,6 @@ func RegisterAttachmentServiceHandlerClient(ctx context.Context, mux *runtime.Se } forward_AttachmentService_GetAttachment_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle(http.MethodGet, pattern_AttachmentService_GetAttachmentBinary_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.AttachmentService/GetAttachmentBinary", runtime.WithHTTPPathPattern("/file/{name=attachments/*}/{filename}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_AttachmentService_GetAttachmentBinary_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - forward_AttachmentService_GetAttachmentBinary_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) mux.Handle(http.MethodPatch, pattern_AttachmentService_UpdateAttachment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -611,19 +505,17 @@ func RegisterAttachmentServiceHandlerClient(ctx context.Context, mux *runtime.Se } var ( - pattern_AttachmentService_CreateAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "attachments"}, "")) - pattern_AttachmentService_ListAttachments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "attachments"}, "")) - pattern_AttachmentService_GetAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "attachments", "name"}, "")) - pattern_AttachmentService_GetAttachmentBinary_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 2, 5, 2, 1, 0, 4, 1, 5, 3}, []string{"file", "attachments", "name", "filename"}, "")) - pattern_AttachmentService_UpdateAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "attachments", "attachment.name"}, "")) - pattern_AttachmentService_DeleteAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "attachments", "name"}, "")) + pattern_AttachmentService_CreateAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "attachments"}, "")) + pattern_AttachmentService_ListAttachments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "attachments"}, "")) + pattern_AttachmentService_GetAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "attachments", "name"}, "")) + pattern_AttachmentService_UpdateAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "attachments", "attachment.name"}, "")) + pattern_AttachmentService_DeleteAttachment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "attachments", "name"}, "")) ) var ( - forward_AttachmentService_CreateAttachment_0 = runtime.ForwardResponseMessage - forward_AttachmentService_ListAttachments_0 = runtime.ForwardResponseMessage - forward_AttachmentService_GetAttachment_0 = runtime.ForwardResponseMessage - forward_AttachmentService_GetAttachmentBinary_0 = runtime.ForwardResponseMessage - forward_AttachmentService_UpdateAttachment_0 = runtime.ForwardResponseMessage - forward_AttachmentService_DeleteAttachment_0 = runtime.ForwardResponseMessage + forward_AttachmentService_CreateAttachment_0 = runtime.ForwardResponseMessage + forward_AttachmentService_ListAttachments_0 = runtime.ForwardResponseMessage + forward_AttachmentService_GetAttachment_0 = runtime.ForwardResponseMessage + forward_AttachmentService_UpdateAttachment_0 = runtime.ForwardResponseMessage + forward_AttachmentService_DeleteAttachment_0 = runtime.ForwardResponseMessage ) diff --git a/proto/gen/api/v1/attachment_service_grpc.pb.go b/proto/gen/api/v1/attachment_service_grpc.pb.go index a453128ea..4a32b3c6f 100644 --- a/proto/gen/api/v1/attachment_service_grpc.pb.go +++ b/proto/gen/api/v1/attachment_service_grpc.pb.go @@ -8,7 +8,6 @@ package apiv1 import ( context "context" - httpbody "google.golang.org/genproto/googleapis/api/httpbody" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -21,12 +20,11 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - AttachmentService_CreateAttachment_FullMethodName = "/memos.api.v1.AttachmentService/CreateAttachment" - AttachmentService_ListAttachments_FullMethodName = "/memos.api.v1.AttachmentService/ListAttachments" - AttachmentService_GetAttachment_FullMethodName = "/memos.api.v1.AttachmentService/GetAttachment" - AttachmentService_GetAttachmentBinary_FullMethodName = "/memos.api.v1.AttachmentService/GetAttachmentBinary" - AttachmentService_UpdateAttachment_FullMethodName = "/memos.api.v1.AttachmentService/UpdateAttachment" - AttachmentService_DeleteAttachment_FullMethodName = "/memos.api.v1.AttachmentService/DeleteAttachment" + AttachmentService_CreateAttachment_FullMethodName = "/memos.api.v1.AttachmentService/CreateAttachment" + AttachmentService_ListAttachments_FullMethodName = "/memos.api.v1.AttachmentService/ListAttachments" + AttachmentService_GetAttachment_FullMethodName = "/memos.api.v1.AttachmentService/GetAttachment" + AttachmentService_UpdateAttachment_FullMethodName = "/memos.api.v1.AttachmentService/UpdateAttachment" + AttachmentService_DeleteAttachment_FullMethodName = "/memos.api.v1.AttachmentService/DeleteAttachment" ) // AttachmentServiceClient is the client API for AttachmentService service. @@ -39,8 +37,6 @@ type AttachmentServiceClient interface { ListAttachments(ctx context.Context, in *ListAttachmentsRequest, opts ...grpc.CallOption) (*ListAttachmentsResponse, error) // GetAttachment returns a attachment by name. GetAttachment(ctx context.Context, in *GetAttachmentRequest, opts ...grpc.CallOption) (*Attachment, error) - // GetAttachmentBinary returns a attachment binary by name. - GetAttachmentBinary(ctx context.Context, in *GetAttachmentBinaryRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) // UpdateAttachment updates a attachment. UpdateAttachment(ctx context.Context, in *UpdateAttachmentRequest, opts ...grpc.CallOption) (*Attachment, error) // DeleteAttachment deletes a attachment by name. @@ -85,16 +81,6 @@ func (c *attachmentServiceClient) GetAttachment(ctx context.Context, in *GetAtta return out, nil } -func (c *attachmentServiceClient) GetAttachmentBinary(ctx context.Context, in *GetAttachmentBinaryRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(httpbody.HttpBody) - err := c.cc.Invoke(ctx, AttachmentService_GetAttachmentBinary_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *attachmentServiceClient) UpdateAttachment(ctx context.Context, in *UpdateAttachmentRequest, opts ...grpc.CallOption) (*Attachment, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(Attachment) @@ -125,8 +111,6 @@ type AttachmentServiceServer interface { ListAttachments(context.Context, *ListAttachmentsRequest) (*ListAttachmentsResponse, error) // GetAttachment returns a attachment by name. GetAttachment(context.Context, *GetAttachmentRequest) (*Attachment, error) - // GetAttachmentBinary returns a attachment binary by name. - GetAttachmentBinary(context.Context, *GetAttachmentBinaryRequest) (*httpbody.HttpBody, error) // UpdateAttachment updates a attachment. UpdateAttachment(context.Context, *UpdateAttachmentRequest) (*Attachment, error) // DeleteAttachment deletes a attachment by name. @@ -150,9 +134,6 @@ func (UnimplementedAttachmentServiceServer) ListAttachments(context.Context, *Li func (UnimplementedAttachmentServiceServer) GetAttachment(context.Context, *GetAttachmentRequest) (*Attachment, error) { return nil, status.Error(codes.Unimplemented, "method GetAttachment not implemented") } -func (UnimplementedAttachmentServiceServer) GetAttachmentBinary(context.Context, *GetAttachmentBinaryRequest) (*httpbody.HttpBody, error) { - return nil, status.Error(codes.Unimplemented, "method GetAttachmentBinary not implemented") -} func (UnimplementedAttachmentServiceServer) UpdateAttachment(context.Context, *UpdateAttachmentRequest) (*Attachment, error) { return nil, status.Error(codes.Unimplemented, "method UpdateAttachment not implemented") } @@ -234,24 +215,6 @@ func _AttachmentService_GetAttachment_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } -func _AttachmentService_GetAttachmentBinary_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetAttachmentBinaryRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AttachmentServiceServer).GetAttachmentBinary(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: AttachmentService_GetAttachmentBinary_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AttachmentServiceServer).GetAttachmentBinary(ctx, req.(*GetAttachmentBinaryRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _AttachmentService_UpdateAttachment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(UpdateAttachmentRequest) if err := dec(in); err != nil { @@ -307,10 +270,6 @@ var AttachmentService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetAttachment", Handler: _AttachmentService_GetAttachment_Handler, }, - { - MethodName: "GetAttachmentBinary", - Handler: _AttachmentService_GetAttachmentBinary_Handler, - }, { MethodName: "UpdateAttachment", Handler: _AttachmentService_UpdateAttachment_Handler, diff --git a/proto/gen/api/v1/user_service.pb.go b/proto/gen/api/v1/user_service.pb.go index 7b62f212a..0f08bb699 100644 --- a/proto/gen/api/v1/user_service.pb.go +++ b/proto/gen/api/v1/user_service.pb.go @@ -8,7 +8,6 @@ package apiv1 import ( _ "google.golang.org/genproto/googleapis/api/annotations" - httpbody "google.golang.org/genproto/googleapis/api/httpbody" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" @@ -140,7 +139,7 @@ func (x UserSetting_Key) Number() protoreflect.EnumNumber { // Deprecated: Use UserSetting_Key.Descriptor instead. func (UserSetting_Key) EnumDescriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{12, 0} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{11, 0} } type UserNotification_Status int32 @@ -189,7 +188,7 @@ func (x UserNotification_Status) Number() protoreflect.EnumNumber { // Deprecated: Use UserNotification_Status.Descriptor instead. func (UserNotification_Status) EnumDescriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{32, 0} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{31, 0} } type UserNotification_Type int32 @@ -235,7 +234,7 @@ func (x UserNotification_Type) Number() protoreflect.EnumNumber { // Deprecated: Use UserNotification_Type.Descriptor instead. func (UserNotification_Type) EnumDescriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{32, 1} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{31, 1} } type User struct { @@ -770,52 +769,6 @@ func (x *DeleteUserRequest) GetForce() bool { return false } -type GetUserAvatarRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Required. The resource name of the user. - // Format: users/{user} - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetUserAvatarRequest) Reset() { - *x = GetUserAvatarRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetUserAvatarRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetUserAvatarRequest) ProtoMessage() {} - -func (x *GetUserAvatarRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_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 GetUserAvatarRequest.ProtoReflect.Descriptor instead. -func (*GetUserAvatarRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{7} -} - -func (x *GetUserAvatarRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - // User statistics messages type UserStats struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -838,7 +791,7 @@ type UserStats struct { func (x *UserStats) Reset() { *x = UserStats{} - mi := &file_api_v1_user_service_proto_msgTypes[8] + mi := &file_api_v1_user_service_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -850,7 +803,7 @@ func (x *UserStats) String() string { func (*UserStats) ProtoMessage() {} func (x *UserStats) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[8] + mi := &file_api_v1_user_service_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -863,7 +816,7 @@ func (x *UserStats) ProtoReflect() protoreflect.Message { // Deprecated: Use UserStats.ProtoReflect.Descriptor instead. func (*UserStats) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{8} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{7} } func (x *UserStats) GetName() string { @@ -919,7 +872,7 @@ type GetUserStatsRequest struct { func (x *GetUserStatsRequest) Reset() { *x = GetUserStatsRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[9] + mi := &file_api_v1_user_service_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -931,7 +884,7 @@ func (x *GetUserStatsRequest) String() string { func (*GetUserStatsRequest) ProtoMessage() {} func (x *GetUserStatsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[9] + mi := &file_api_v1_user_service_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -944,7 +897,7 @@ func (x *GetUserStatsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserStatsRequest.ProtoReflect.Descriptor instead. func (*GetUserStatsRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{9} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{8} } func (x *GetUserStatsRequest) GetName() string { @@ -962,7 +915,7 @@ type ListAllUserStatsRequest struct { func (x *ListAllUserStatsRequest) Reset() { *x = ListAllUserStatsRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[10] + mi := &file_api_v1_user_service_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -974,7 +927,7 @@ func (x *ListAllUserStatsRequest) String() string { func (*ListAllUserStatsRequest) ProtoMessage() {} func (x *ListAllUserStatsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[10] + mi := &file_api_v1_user_service_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -987,7 +940,7 @@ func (x *ListAllUserStatsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAllUserStatsRequest.ProtoReflect.Descriptor instead. func (*ListAllUserStatsRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{10} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{9} } type ListAllUserStatsResponse struct { @@ -1000,7 +953,7 @@ type ListAllUserStatsResponse struct { func (x *ListAllUserStatsResponse) Reset() { *x = ListAllUserStatsResponse{} - mi := &file_api_v1_user_service_proto_msgTypes[11] + mi := &file_api_v1_user_service_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1012,7 +965,7 @@ func (x *ListAllUserStatsResponse) String() string { func (*ListAllUserStatsResponse) ProtoMessage() {} func (x *ListAllUserStatsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[11] + mi := &file_api_v1_user_service_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1025,7 +978,7 @@ func (x *ListAllUserStatsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAllUserStatsResponse.ProtoReflect.Descriptor instead. func (*ListAllUserStatsResponse) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{11} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{10} } func (x *ListAllUserStatsResponse) GetStats() []*UserStats { @@ -1055,7 +1008,7 @@ type UserSetting struct { func (x *UserSetting) Reset() { *x = UserSetting{} - mi := &file_api_v1_user_service_proto_msgTypes[12] + mi := &file_api_v1_user_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1067,7 +1020,7 @@ func (x *UserSetting) String() string { func (*UserSetting) ProtoMessage() {} func (x *UserSetting) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[12] + mi := &file_api_v1_user_service_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1080,7 +1033,7 @@ func (x *UserSetting) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSetting.ProtoReflect.Descriptor instead. func (*UserSetting) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{12} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{11} } func (x *UserSetting) GetName() string { @@ -1172,7 +1125,7 @@ type GetUserSettingRequest struct { func (x *GetUserSettingRequest) Reset() { *x = GetUserSettingRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[13] + mi := &file_api_v1_user_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1184,7 +1137,7 @@ func (x *GetUserSettingRequest) String() string { func (*GetUserSettingRequest) ProtoMessage() {} func (x *GetUserSettingRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[13] + mi := &file_api_v1_user_service_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1197,7 +1150,7 @@ func (x *GetUserSettingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserSettingRequest.ProtoReflect.Descriptor instead. func (*GetUserSettingRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{13} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{12} } func (x *GetUserSettingRequest) GetName() string { @@ -1219,7 +1172,7 @@ type UpdateUserSettingRequest struct { func (x *UpdateUserSettingRequest) Reset() { *x = UpdateUserSettingRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[14] + mi := &file_api_v1_user_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1231,7 +1184,7 @@ func (x *UpdateUserSettingRequest) String() string { func (*UpdateUserSettingRequest) ProtoMessage() {} func (x *UpdateUserSettingRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[14] + mi := &file_api_v1_user_service_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1244,7 +1197,7 @@ func (x *UpdateUserSettingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserSettingRequest.ProtoReflect.Descriptor instead. func (*UpdateUserSettingRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{14} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{13} } func (x *UpdateUserSettingRequest) GetSetting() *UserSetting { @@ -1281,7 +1234,7 @@ type ListUserSettingsRequest struct { func (x *ListUserSettingsRequest) Reset() { *x = ListUserSettingsRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[15] + mi := &file_api_v1_user_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1293,7 +1246,7 @@ func (x *ListUserSettingsRequest) String() string { func (*ListUserSettingsRequest) ProtoMessage() {} func (x *ListUserSettingsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[15] + mi := &file_api_v1_user_service_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1306,7 +1259,7 @@ func (x *ListUserSettingsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserSettingsRequest.ProtoReflect.Descriptor instead. func (*ListUserSettingsRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{15} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{14} } func (x *ListUserSettingsRequest) GetParent() string { @@ -1346,7 +1299,7 @@ type ListUserSettingsResponse struct { func (x *ListUserSettingsResponse) Reset() { *x = ListUserSettingsResponse{} - mi := &file_api_v1_user_service_proto_msgTypes[16] + mi := &file_api_v1_user_service_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1358,7 +1311,7 @@ func (x *ListUserSettingsResponse) String() string { func (*ListUserSettingsResponse) ProtoMessage() {} func (x *ListUserSettingsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[16] + mi := &file_api_v1_user_service_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1371,7 +1324,7 @@ func (x *ListUserSettingsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserSettingsResponse.ProtoReflect.Descriptor instead. func (*ListUserSettingsResponse) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{16} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{15} } func (x *ListUserSettingsResponse) GetSettings() []*UserSetting { @@ -1415,7 +1368,7 @@ type UserAccessToken struct { func (x *UserAccessToken) Reset() { *x = UserAccessToken{} - mi := &file_api_v1_user_service_proto_msgTypes[17] + mi := &file_api_v1_user_service_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1427,7 +1380,7 @@ func (x *UserAccessToken) String() string { func (*UserAccessToken) ProtoMessage() {} func (x *UserAccessToken) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[17] + mi := &file_api_v1_user_service_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1440,7 +1393,7 @@ func (x *UserAccessToken) ProtoReflect() protoreflect.Message { // Deprecated: Use UserAccessToken.ProtoReflect.Descriptor instead. func (*UserAccessToken) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{17} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{16} } func (x *UserAccessToken) GetName() string { @@ -1493,7 +1446,7 @@ type ListUserAccessTokensRequest struct { func (x *ListUserAccessTokensRequest) Reset() { *x = ListUserAccessTokensRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[18] + mi := &file_api_v1_user_service_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1505,7 +1458,7 @@ func (x *ListUserAccessTokensRequest) String() string { func (*ListUserAccessTokensRequest) ProtoMessage() {} func (x *ListUserAccessTokensRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[18] + mi := &file_api_v1_user_service_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1518,7 +1471,7 @@ func (x *ListUserAccessTokensRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserAccessTokensRequest.ProtoReflect.Descriptor instead. func (*ListUserAccessTokensRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{18} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{17} } func (x *ListUserAccessTokensRequest) GetParent() string { @@ -1556,7 +1509,7 @@ type ListUserAccessTokensResponse struct { func (x *ListUserAccessTokensResponse) Reset() { *x = ListUserAccessTokensResponse{} - mi := &file_api_v1_user_service_proto_msgTypes[19] + mi := &file_api_v1_user_service_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1568,7 +1521,7 @@ func (x *ListUserAccessTokensResponse) String() string { func (*ListUserAccessTokensResponse) ProtoMessage() {} func (x *ListUserAccessTokensResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[19] + mi := &file_api_v1_user_service_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1581,7 +1534,7 @@ func (x *ListUserAccessTokensResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserAccessTokensResponse.ProtoReflect.Descriptor instead. func (*ListUserAccessTokensResponse) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{19} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{18} } func (x *ListUserAccessTokensResponse) GetAccessTokens() []*UserAccessToken { @@ -1620,7 +1573,7 @@ type CreateUserAccessTokenRequest struct { func (x *CreateUserAccessTokenRequest) Reset() { *x = CreateUserAccessTokenRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[20] + mi := &file_api_v1_user_service_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1632,7 +1585,7 @@ func (x *CreateUserAccessTokenRequest) String() string { func (*CreateUserAccessTokenRequest) ProtoMessage() {} func (x *CreateUserAccessTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[20] + mi := &file_api_v1_user_service_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1645,7 +1598,7 @@ func (x *CreateUserAccessTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateUserAccessTokenRequest.ProtoReflect.Descriptor instead. func (*CreateUserAccessTokenRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{20} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{19} } func (x *CreateUserAccessTokenRequest) GetParent() string { @@ -1680,7 +1633,7 @@ type DeleteUserAccessTokenRequest struct { func (x *DeleteUserAccessTokenRequest) Reset() { *x = DeleteUserAccessTokenRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[21] + mi := &file_api_v1_user_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1692,7 +1645,7 @@ func (x *DeleteUserAccessTokenRequest) String() string { func (*DeleteUserAccessTokenRequest) ProtoMessage() {} func (x *DeleteUserAccessTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[21] + mi := &file_api_v1_user_service_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1705,7 +1658,7 @@ func (x *DeleteUserAccessTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteUserAccessTokenRequest.ProtoReflect.Descriptor instead. func (*DeleteUserAccessTokenRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{21} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{20} } func (x *DeleteUserAccessTokenRequest) GetName() string { @@ -1735,7 +1688,7 @@ type UserSession struct { func (x *UserSession) Reset() { *x = UserSession{} - mi := &file_api_v1_user_service_proto_msgTypes[22] + mi := &file_api_v1_user_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1747,7 +1700,7 @@ func (x *UserSession) String() string { func (*UserSession) ProtoMessage() {} func (x *UserSession) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[22] + mi := &file_api_v1_user_service_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1760,7 +1713,7 @@ func (x *UserSession) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSession.ProtoReflect.Descriptor instead. func (*UserSession) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{22} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{21} } func (x *UserSession) GetName() string { @@ -1809,7 +1762,7 @@ type ListUserSessionsRequest struct { func (x *ListUserSessionsRequest) Reset() { *x = ListUserSessionsRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[23] + mi := &file_api_v1_user_service_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1821,7 +1774,7 @@ func (x *ListUserSessionsRequest) String() string { func (*ListUserSessionsRequest) ProtoMessage() {} func (x *ListUserSessionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[23] + mi := &file_api_v1_user_service_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1834,7 +1787,7 @@ func (x *ListUserSessionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserSessionsRequest.ProtoReflect.Descriptor instead. func (*ListUserSessionsRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{23} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{22} } func (x *ListUserSessionsRequest) GetParent() string { @@ -1854,7 +1807,7 @@ type ListUserSessionsResponse struct { func (x *ListUserSessionsResponse) Reset() { *x = ListUserSessionsResponse{} - mi := &file_api_v1_user_service_proto_msgTypes[24] + mi := &file_api_v1_user_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1866,7 +1819,7 @@ func (x *ListUserSessionsResponse) String() string { func (*ListUserSessionsResponse) ProtoMessage() {} func (x *ListUserSessionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[24] + mi := &file_api_v1_user_service_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1879,7 +1832,7 @@ func (x *ListUserSessionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserSessionsResponse.ProtoReflect.Descriptor instead. func (*ListUserSessionsResponse) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{24} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{23} } func (x *ListUserSessionsResponse) GetSessions() []*UserSession { @@ -1900,7 +1853,7 @@ type RevokeUserSessionRequest struct { func (x *RevokeUserSessionRequest) Reset() { *x = RevokeUserSessionRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[25] + mi := &file_api_v1_user_service_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1912,7 +1865,7 @@ func (x *RevokeUserSessionRequest) String() string { func (*RevokeUserSessionRequest) ProtoMessage() {} func (x *RevokeUserSessionRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[25] + mi := &file_api_v1_user_service_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1925,7 +1878,7 @@ func (x *RevokeUserSessionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokeUserSessionRequest.ProtoReflect.Descriptor instead. func (*RevokeUserSessionRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{25} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{24} } func (x *RevokeUserSessionRequest) GetName() string { @@ -1955,7 +1908,7 @@ type UserWebhook struct { func (x *UserWebhook) Reset() { *x = UserWebhook{} - mi := &file_api_v1_user_service_proto_msgTypes[26] + mi := &file_api_v1_user_service_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1967,7 +1920,7 @@ func (x *UserWebhook) String() string { func (*UserWebhook) ProtoMessage() {} func (x *UserWebhook) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[26] + mi := &file_api_v1_user_service_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1980,7 +1933,7 @@ func (x *UserWebhook) ProtoReflect() protoreflect.Message { // Deprecated: Use UserWebhook.ProtoReflect.Descriptor instead. func (*UserWebhook) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{26} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{25} } func (x *UserWebhook) GetName() string { @@ -2029,7 +1982,7 @@ type ListUserWebhooksRequest struct { func (x *ListUserWebhooksRequest) Reset() { *x = ListUserWebhooksRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[27] + mi := &file_api_v1_user_service_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2041,7 +1994,7 @@ func (x *ListUserWebhooksRequest) String() string { func (*ListUserWebhooksRequest) ProtoMessage() {} func (x *ListUserWebhooksRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[27] + mi := &file_api_v1_user_service_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2054,7 +2007,7 @@ func (x *ListUserWebhooksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserWebhooksRequest.ProtoReflect.Descriptor instead. func (*ListUserWebhooksRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{27} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{26} } func (x *ListUserWebhooksRequest) GetParent() string { @@ -2074,7 +2027,7 @@ type ListUserWebhooksResponse struct { func (x *ListUserWebhooksResponse) Reset() { *x = ListUserWebhooksResponse{} - mi := &file_api_v1_user_service_proto_msgTypes[28] + mi := &file_api_v1_user_service_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2086,7 +2039,7 @@ func (x *ListUserWebhooksResponse) String() string { func (*ListUserWebhooksResponse) ProtoMessage() {} func (x *ListUserWebhooksResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[28] + mi := &file_api_v1_user_service_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2099,7 +2052,7 @@ func (x *ListUserWebhooksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserWebhooksResponse.ProtoReflect.Descriptor instead. func (*ListUserWebhooksResponse) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{28} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{27} } func (x *ListUserWebhooksResponse) GetWebhooks() []*UserWebhook { @@ -2122,7 +2075,7 @@ type CreateUserWebhookRequest struct { func (x *CreateUserWebhookRequest) Reset() { *x = CreateUserWebhookRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[29] + mi := &file_api_v1_user_service_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2134,7 +2087,7 @@ func (x *CreateUserWebhookRequest) String() string { func (*CreateUserWebhookRequest) ProtoMessage() {} func (x *CreateUserWebhookRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[29] + mi := &file_api_v1_user_service_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2147,7 +2100,7 @@ func (x *CreateUserWebhookRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateUserWebhookRequest.ProtoReflect.Descriptor instead. func (*CreateUserWebhookRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{29} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{28} } func (x *CreateUserWebhookRequest) GetParent() string { @@ -2176,7 +2129,7 @@ type UpdateUserWebhookRequest struct { func (x *UpdateUserWebhookRequest) Reset() { *x = UpdateUserWebhookRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[30] + mi := &file_api_v1_user_service_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2188,7 +2141,7 @@ func (x *UpdateUserWebhookRequest) String() string { func (*UpdateUserWebhookRequest) ProtoMessage() {} func (x *UpdateUserWebhookRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[30] + mi := &file_api_v1_user_service_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2201,7 +2154,7 @@ func (x *UpdateUserWebhookRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserWebhookRequest.ProtoReflect.Descriptor instead. func (*UpdateUserWebhookRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{30} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{29} } func (x *UpdateUserWebhookRequest) GetWebhook() *UserWebhook { @@ -2229,7 +2182,7 @@ type DeleteUserWebhookRequest struct { func (x *DeleteUserWebhookRequest) Reset() { *x = DeleteUserWebhookRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[31] + mi := &file_api_v1_user_service_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2241,7 +2194,7 @@ func (x *DeleteUserWebhookRequest) String() string { func (*DeleteUserWebhookRequest) ProtoMessage() {} func (x *DeleteUserWebhookRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[31] + mi := &file_api_v1_user_service_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2254,7 +2207,7 @@ func (x *DeleteUserWebhookRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteUserWebhookRequest.ProtoReflect.Descriptor instead. func (*DeleteUserWebhookRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{31} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{30} } func (x *DeleteUserWebhookRequest) GetName() string { @@ -2286,7 +2239,7 @@ type UserNotification struct { func (x *UserNotification) Reset() { *x = UserNotification{} - mi := &file_api_v1_user_service_proto_msgTypes[32] + mi := &file_api_v1_user_service_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2298,7 +2251,7 @@ func (x *UserNotification) String() string { func (*UserNotification) ProtoMessage() {} func (x *UserNotification) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[32] + mi := &file_api_v1_user_service_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2311,7 +2264,7 @@ func (x *UserNotification) ProtoReflect() protoreflect.Message { // Deprecated: Use UserNotification.ProtoReflect.Descriptor instead. func (*UserNotification) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{32} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{31} } func (x *UserNotification) GetName() string { @@ -2370,7 +2323,7 @@ type ListUserNotificationsRequest struct { func (x *ListUserNotificationsRequest) Reset() { *x = ListUserNotificationsRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[33] + mi := &file_api_v1_user_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2382,7 +2335,7 @@ func (x *ListUserNotificationsRequest) String() string { func (*ListUserNotificationsRequest) ProtoMessage() {} func (x *ListUserNotificationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[33] + mi := &file_api_v1_user_service_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2395,7 +2348,7 @@ func (x *ListUserNotificationsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserNotificationsRequest.ProtoReflect.Descriptor instead. func (*ListUserNotificationsRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{33} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{32} } func (x *ListUserNotificationsRequest) GetParent() string { @@ -2436,7 +2389,7 @@ type ListUserNotificationsResponse struct { func (x *ListUserNotificationsResponse) Reset() { *x = ListUserNotificationsResponse{} - mi := &file_api_v1_user_service_proto_msgTypes[34] + mi := &file_api_v1_user_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2448,7 +2401,7 @@ func (x *ListUserNotificationsResponse) String() string { func (*ListUserNotificationsResponse) ProtoMessage() {} func (x *ListUserNotificationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[34] + mi := &file_api_v1_user_service_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2461,7 +2414,7 @@ func (x *ListUserNotificationsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserNotificationsResponse.ProtoReflect.Descriptor instead. func (*ListUserNotificationsResponse) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{34} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{33} } func (x *ListUserNotificationsResponse) GetNotifications() []*UserNotification { @@ -2488,7 +2441,7 @@ type UpdateUserNotificationRequest struct { func (x *UpdateUserNotificationRequest) Reset() { *x = UpdateUserNotificationRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[35] + mi := &file_api_v1_user_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2500,7 +2453,7 @@ func (x *UpdateUserNotificationRequest) String() string { func (*UpdateUserNotificationRequest) ProtoMessage() {} func (x *UpdateUserNotificationRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[35] + mi := &file_api_v1_user_service_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2513,7 +2466,7 @@ func (x *UpdateUserNotificationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserNotificationRequest.ProtoReflect.Descriptor instead. func (*UpdateUserNotificationRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{35} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{34} } func (x *UpdateUserNotificationRequest) GetNotification() *UserNotification { @@ -2540,7 +2493,7 @@ type DeleteUserNotificationRequest struct { func (x *DeleteUserNotificationRequest) Reset() { *x = DeleteUserNotificationRequest{} - mi := &file_api_v1_user_service_proto_msgTypes[36] + mi := &file_api_v1_user_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2552,7 +2505,7 @@ func (x *DeleteUserNotificationRequest) String() string { func (*DeleteUserNotificationRequest) ProtoMessage() {} func (x *DeleteUserNotificationRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[36] + mi := &file_api_v1_user_service_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2565,7 +2518,7 @@ func (x *DeleteUserNotificationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteUserNotificationRequest.ProtoReflect.Descriptor instead. func (*DeleteUserNotificationRequest) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{36} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{35} } func (x *DeleteUserNotificationRequest) GetName() string { @@ -2588,7 +2541,7 @@ type UserStats_MemoTypeStats struct { func (x *UserStats_MemoTypeStats) Reset() { *x = UserStats_MemoTypeStats{} - mi := &file_api_v1_user_service_proto_msgTypes[38] + mi := &file_api_v1_user_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2600,7 +2553,7 @@ func (x *UserStats_MemoTypeStats) String() string { func (*UserStats_MemoTypeStats) ProtoMessage() {} func (x *UserStats_MemoTypeStats) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[38] + mi := &file_api_v1_user_service_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2613,7 +2566,7 @@ func (x *UserStats_MemoTypeStats) ProtoReflect() protoreflect.Message { // Deprecated: Use UserStats_MemoTypeStats.ProtoReflect.Descriptor instead. func (*UserStats_MemoTypeStats) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{8, 1} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{7, 1} } func (x *UserStats_MemoTypeStats) GetLinkCount() int32 { @@ -2661,7 +2614,7 @@ type UserSetting_GeneralSetting struct { func (x *UserSetting_GeneralSetting) Reset() { *x = UserSetting_GeneralSetting{} - mi := &file_api_v1_user_service_proto_msgTypes[39] + mi := &file_api_v1_user_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2673,7 +2626,7 @@ func (x *UserSetting_GeneralSetting) String() string { func (*UserSetting_GeneralSetting) ProtoMessage() {} func (x *UserSetting_GeneralSetting) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[39] + mi := &file_api_v1_user_service_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2686,7 +2639,7 @@ func (x *UserSetting_GeneralSetting) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSetting_GeneralSetting.ProtoReflect.Descriptor instead. func (*UserSetting_GeneralSetting) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{12, 0} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{11, 0} } func (x *UserSetting_GeneralSetting) GetLocale() string { @@ -2721,7 +2674,7 @@ type UserSetting_SessionsSetting struct { func (x *UserSetting_SessionsSetting) Reset() { *x = UserSetting_SessionsSetting{} - mi := &file_api_v1_user_service_proto_msgTypes[40] + mi := &file_api_v1_user_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2733,7 +2686,7 @@ func (x *UserSetting_SessionsSetting) String() string { func (*UserSetting_SessionsSetting) ProtoMessage() {} func (x *UserSetting_SessionsSetting) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[40] + mi := &file_api_v1_user_service_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2746,7 +2699,7 @@ func (x *UserSetting_SessionsSetting) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSetting_SessionsSetting.ProtoReflect.Descriptor instead. func (*UserSetting_SessionsSetting) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{12, 1} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{11, 1} } func (x *UserSetting_SessionsSetting) GetSessions() []*UserSession { @@ -2767,7 +2720,7 @@ type UserSetting_AccessTokensSetting struct { func (x *UserSetting_AccessTokensSetting) Reset() { *x = UserSetting_AccessTokensSetting{} - mi := &file_api_v1_user_service_proto_msgTypes[41] + mi := &file_api_v1_user_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2779,7 +2732,7 @@ func (x *UserSetting_AccessTokensSetting) String() string { func (*UserSetting_AccessTokensSetting) ProtoMessage() {} func (x *UserSetting_AccessTokensSetting) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[41] + mi := &file_api_v1_user_service_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2792,7 +2745,7 @@ func (x *UserSetting_AccessTokensSetting) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSetting_AccessTokensSetting.ProtoReflect.Descriptor instead. func (*UserSetting_AccessTokensSetting) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{12, 2} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{11, 2} } func (x *UserSetting_AccessTokensSetting) GetAccessTokens() []*UserAccessToken { @@ -2813,7 +2766,7 @@ type UserSetting_WebhooksSetting struct { func (x *UserSetting_WebhooksSetting) Reset() { *x = UserSetting_WebhooksSetting{} - mi := &file_api_v1_user_service_proto_msgTypes[42] + mi := &file_api_v1_user_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2825,7 +2778,7 @@ func (x *UserSetting_WebhooksSetting) String() string { func (*UserSetting_WebhooksSetting) ProtoMessage() {} func (x *UserSetting_WebhooksSetting) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[42] + mi := &file_api_v1_user_service_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2838,7 +2791,7 @@ func (x *UserSetting_WebhooksSetting) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSetting_WebhooksSetting.ProtoReflect.Descriptor instead. func (*UserSetting_WebhooksSetting) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{12, 3} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{11, 3} } func (x *UserSetting_WebhooksSetting) GetWebhooks() []*UserWebhook { @@ -2866,7 +2819,7 @@ type UserSession_ClientInfo struct { func (x *UserSession_ClientInfo) Reset() { *x = UserSession_ClientInfo{} - mi := &file_api_v1_user_service_proto_msgTypes[43] + mi := &file_api_v1_user_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2878,7 +2831,7 @@ func (x *UserSession_ClientInfo) String() string { func (*UserSession_ClientInfo) ProtoMessage() {} func (x *UserSession_ClientInfo) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_user_service_proto_msgTypes[43] + mi := &file_api_v1_user_service_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2891,7 +2844,7 @@ func (x *UserSession_ClientInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSession_ClientInfo.ProtoReflect.Descriptor instead. func (*UserSession_ClientInfo) Descriptor() ([]byte, []int) { - return file_api_v1_user_service_proto_rawDescGZIP(), []int{22, 0} + return file_api_v1_user_service_proto_rawDescGZIP(), []int{21, 0} } func (x *UserSession_ClientInfo) GetUserAgent() string { @@ -2933,7 +2886,7 @@ var File_api_v1_user_service_proto protoreflect.FileDescriptor const file_api_v1_user_service_proto_rawDesc = "" + "\n" + - "\x19api/v1/user_service.proto\x12\fmemos.api.v1\x1a\x13api/v1/common.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/httpbody.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xcb\x04\n" + + "\x19api/v1/user_service.proto\x12\fmemos.api.v1\x1a\x13api/v1/common.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xcb\x04\n" + "\x04User\x12\x17\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x120\n" + "\x04role\x18\x02 \x01(\x0e2\x17.memos.api.v1.User.RoleB\x03\xe0A\x02R\x04role\x12\x1f\n" + @@ -2985,10 +2938,7 @@ const file_api_v1_user_service_proto_rawDesc = "" + "\x11DeleteUserRequest\x12-\n" + "\x04name\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" + "\x11memos.api.v1/UserR\x04name\x12\x19\n" + - "\x05force\x18\x02 \x01(\bB\x03\xe0A\x01R\x05force\"E\n" + - "\x14GetUserAvatarRequest\x12-\n" + - "\x04name\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" + - "\x11memos.api.v1/UserR\x04name\"\xe4\x04\n" + + "\x05force\x18\x02 \x01(\bB\x03\xe0A\x01R\x05force\"\xe4\x04\n" + "\tUserStats\x12\x17\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12R\n" + "\x17memo_display_timestamps\x18\x02 \x03(\v2\x1a.google.protobuf.TimestampR\x15memoDisplayTimestamps\x12M\n" + @@ -3168,7 +3118,7 @@ const file_api_v1_user_service_proto_rawDesc = "" + "updateMask\"Z\n" + "\x1dDeleteUserNotificationRequest\x129\n" + "\x04name\x18\x01 \x01(\tB%\xe0A\x02\xfaA\x1f\n" + - "\x1dmemos.api.v1/UserNotificationR\x04name2\xf7\x19\n" + + "\x1dmemos.api.v1/UserNotificationR\x04name2\xfe\x18\n" + "\vUserService\x12c\n" + "\tListUsers\x12\x1e.memos.api.v1.ListUsersRequest\x1a\x1f.memos.api.v1.ListUsersResponse\"\x15\x82\xd3\xe4\x93\x02\x0f\x12\r/api/v1/users\x12b\n" + "\aGetUser\x12\x1c.memos.api.v1.GetUserRequest\x1a\x12.memos.api.v1.User\"%\xdaA\x04name\x82\xd3\xe4\x93\x02\x18\x12\x16/api/v1/{name=users/*}\x12e\n" + @@ -3177,8 +3127,7 @@ const file_api_v1_user_service_proto_rawDesc = "" + "\n" + "UpdateUser\x12\x1f.memos.api.v1.UpdateUserRequest\x1a\x12.memos.api.v1.User\"<\xdaA\x10user,update_mask\x82\xd3\xe4\x93\x02#:\x04user2\x1b/api/v1/{user.name=users/*}\x12l\n" + "\n" + - "DeleteUser\x12\x1f.memos.api.v1.DeleteUserRequest\x1a\x16.google.protobuf.Empty\"%\xdaA\x04name\x82\xd3\xe4\x93\x02\x18*\x16/api/v1/{name=users/*}\x12w\n" + - "\rGetUserAvatar\x12\".memos.api.v1.GetUserAvatarRequest\x1a\x14.google.api.HttpBody\",\xdaA\x04name\x82\xd3\xe4\x93\x02\x1f\x12\x1d/api/v1/{name=users/*}/avatar\x12~\n" + + "DeleteUser\x12\x1f.memos.api.v1.DeleteUserRequest\x1a\x16.google.protobuf.Empty\"%\xdaA\x04name\x82\xd3\xe4\x93\x02\x18*\x16/api/v1/{name=users/*}\x12~\n" + "\x10ListAllUserStats\x12%.memos.api.v1.ListAllUserStatsRequest\x1a&.memos.api.v1.ListAllUserStatsResponse\"\x1b\x82\xd3\xe4\x93\x02\x15\x12\x13/api/v1/users:stats\x12z\n" + "\fGetUserStats\x12!.memos.api.v1.GetUserStatsRequest\x1a\x17.memos.api.v1.UserStats\".\xdaA\x04name\x82\xd3\xe4\x93\x02!\x12\x1f/api/v1/{name=users/*}:getStats\x12\x82\x01\n" + "\x0eGetUserSetting\x12#.memos.api.v1.GetUserSettingRequest\x1a\x19.memos.api.v1.UserSetting\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#\x12!/api/v1/{name=users/*/settings/*}\x12\xa8\x01\n" + @@ -3211,7 +3160,7 @@ func file_api_v1_user_service_proto_rawDescGZIP() []byte { } var file_api_v1_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 44) +var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 43) var file_api_v1_user_service_proto_goTypes = []any{ (User_Role)(0), // 0: memos.api.v1.User.Role (UserSetting_Key)(0), // 1: memos.api.v1.UserSetting.Key @@ -3224,141 +3173,137 @@ var file_api_v1_user_service_proto_goTypes = []any{ (*CreateUserRequest)(nil), // 8: memos.api.v1.CreateUserRequest (*UpdateUserRequest)(nil), // 9: memos.api.v1.UpdateUserRequest (*DeleteUserRequest)(nil), // 10: memos.api.v1.DeleteUserRequest - (*GetUserAvatarRequest)(nil), // 11: memos.api.v1.GetUserAvatarRequest - (*UserStats)(nil), // 12: memos.api.v1.UserStats - (*GetUserStatsRequest)(nil), // 13: memos.api.v1.GetUserStatsRequest - (*ListAllUserStatsRequest)(nil), // 14: memos.api.v1.ListAllUserStatsRequest - (*ListAllUserStatsResponse)(nil), // 15: memos.api.v1.ListAllUserStatsResponse - (*UserSetting)(nil), // 16: memos.api.v1.UserSetting - (*GetUserSettingRequest)(nil), // 17: memos.api.v1.GetUserSettingRequest - (*UpdateUserSettingRequest)(nil), // 18: memos.api.v1.UpdateUserSettingRequest - (*ListUserSettingsRequest)(nil), // 19: memos.api.v1.ListUserSettingsRequest - (*ListUserSettingsResponse)(nil), // 20: memos.api.v1.ListUserSettingsResponse - (*UserAccessToken)(nil), // 21: memos.api.v1.UserAccessToken - (*ListUserAccessTokensRequest)(nil), // 22: memos.api.v1.ListUserAccessTokensRequest - (*ListUserAccessTokensResponse)(nil), // 23: memos.api.v1.ListUserAccessTokensResponse - (*CreateUserAccessTokenRequest)(nil), // 24: memos.api.v1.CreateUserAccessTokenRequest - (*DeleteUserAccessTokenRequest)(nil), // 25: memos.api.v1.DeleteUserAccessTokenRequest - (*UserSession)(nil), // 26: memos.api.v1.UserSession - (*ListUserSessionsRequest)(nil), // 27: memos.api.v1.ListUserSessionsRequest - (*ListUserSessionsResponse)(nil), // 28: memos.api.v1.ListUserSessionsResponse - (*RevokeUserSessionRequest)(nil), // 29: memos.api.v1.RevokeUserSessionRequest - (*UserWebhook)(nil), // 30: memos.api.v1.UserWebhook - (*ListUserWebhooksRequest)(nil), // 31: memos.api.v1.ListUserWebhooksRequest - (*ListUserWebhooksResponse)(nil), // 32: memos.api.v1.ListUserWebhooksResponse - (*CreateUserWebhookRequest)(nil), // 33: memos.api.v1.CreateUserWebhookRequest - (*UpdateUserWebhookRequest)(nil), // 34: memos.api.v1.UpdateUserWebhookRequest - (*DeleteUserWebhookRequest)(nil), // 35: memos.api.v1.DeleteUserWebhookRequest - (*UserNotification)(nil), // 36: memos.api.v1.UserNotification - (*ListUserNotificationsRequest)(nil), // 37: memos.api.v1.ListUserNotificationsRequest - (*ListUserNotificationsResponse)(nil), // 38: memos.api.v1.ListUserNotificationsResponse - (*UpdateUserNotificationRequest)(nil), // 39: memos.api.v1.UpdateUserNotificationRequest - (*DeleteUserNotificationRequest)(nil), // 40: memos.api.v1.DeleteUserNotificationRequest - nil, // 41: memos.api.v1.UserStats.TagCountEntry - (*UserStats_MemoTypeStats)(nil), // 42: memos.api.v1.UserStats.MemoTypeStats - (*UserSetting_GeneralSetting)(nil), // 43: memos.api.v1.UserSetting.GeneralSetting - (*UserSetting_SessionsSetting)(nil), // 44: memos.api.v1.UserSetting.SessionsSetting - (*UserSetting_AccessTokensSetting)(nil), // 45: memos.api.v1.UserSetting.AccessTokensSetting - (*UserSetting_WebhooksSetting)(nil), // 46: memos.api.v1.UserSetting.WebhooksSetting - (*UserSession_ClientInfo)(nil), // 47: memos.api.v1.UserSession.ClientInfo - (State)(0), // 48: memos.api.v1.State - (*timestamppb.Timestamp)(nil), // 49: google.protobuf.Timestamp - (*fieldmaskpb.FieldMask)(nil), // 50: google.protobuf.FieldMask - (*emptypb.Empty)(nil), // 51: google.protobuf.Empty - (*httpbody.HttpBody)(nil), // 52: google.api.HttpBody + (*UserStats)(nil), // 11: memos.api.v1.UserStats + (*GetUserStatsRequest)(nil), // 12: memos.api.v1.GetUserStatsRequest + (*ListAllUserStatsRequest)(nil), // 13: memos.api.v1.ListAllUserStatsRequest + (*ListAllUserStatsResponse)(nil), // 14: memos.api.v1.ListAllUserStatsResponse + (*UserSetting)(nil), // 15: memos.api.v1.UserSetting + (*GetUserSettingRequest)(nil), // 16: memos.api.v1.GetUserSettingRequest + (*UpdateUserSettingRequest)(nil), // 17: memos.api.v1.UpdateUserSettingRequest + (*ListUserSettingsRequest)(nil), // 18: memos.api.v1.ListUserSettingsRequest + (*ListUserSettingsResponse)(nil), // 19: memos.api.v1.ListUserSettingsResponse + (*UserAccessToken)(nil), // 20: memos.api.v1.UserAccessToken + (*ListUserAccessTokensRequest)(nil), // 21: memos.api.v1.ListUserAccessTokensRequest + (*ListUserAccessTokensResponse)(nil), // 22: memos.api.v1.ListUserAccessTokensResponse + (*CreateUserAccessTokenRequest)(nil), // 23: memos.api.v1.CreateUserAccessTokenRequest + (*DeleteUserAccessTokenRequest)(nil), // 24: memos.api.v1.DeleteUserAccessTokenRequest + (*UserSession)(nil), // 25: memos.api.v1.UserSession + (*ListUserSessionsRequest)(nil), // 26: memos.api.v1.ListUserSessionsRequest + (*ListUserSessionsResponse)(nil), // 27: memos.api.v1.ListUserSessionsResponse + (*RevokeUserSessionRequest)(nil), // 28: memos.api.v1.RevokeUserSessionRequest + (*UserWebhook)(nil), // 29: memos.api.v1.UserWebhook + (*ListUserWebhooksRequest)(nil), // 30: memos.api.v1.ListUserWebhooksRequest + (*ListUserWebhooksResponse)(nil), // 31: memos.api.v1.ListUserWebhooksResponse + (*CreateUserWebhookRequest)(nil), // 32: memos.api.v1.CreateUserWebhookRequest + (*UpdateUserWebhookRequest)(nil), // 33: memos.api.v1.UpdateUserWebhookRequest + (*DeleteUserWebhookRequest)(nil), // 34: memos.api.v1.DeleteUserWebhookRequest + (*UserNotification)(nil), // 35: memos.api.v1.UserNotification + (*ListUserNotificationsRequest)(nil), // 36: memos.api.v1.ListUserNotificationsRequest + (*ListUserNotificationsResponse)(nil), // 37: memos.api.v1.ListUserNotificationsResponse + (*UpdateUserNotificationRequest)(nil), // 38: memos.api.v1.UpdateUserNotificationRequest + (*DeleteUserNotificationRequest)(nil), // 39: memos.api.v1.DeleteUserNotificationRequest + nil, // 40: memos.api.v1.UserStats.TagCountEntry + (*UserStats_MemoTypeStats)(nil), // 41: memos.api.v1.UserStats.MemoTypeStats + (*UserSetting_GeneralSetting)(nil), // 42: memos.api.v1.UserSetting.GeneralSetting + (*UserSetting_SessionsSetting)(nil), // 43: memos.api.v1.UserSetting.SessionsSetting + (*UserSetting_AccessTokensSetting)(nil), // 44: memos.api.v1.UserSetting.AccessTokensSetting + (*UserSetting_WebhooksSetting)(nil), // 45: memos.api.v1.UserSetting.WebhooksSetting + (*UserSession_ClientInfo)(nil), // 46: memos.api.v1.UserSession.ClientInfo + (State)(0), // 47: memos.api.v1.State + (*timestamppb.Timestamp)(nil), // 48: google.protobuf.Timestamp + (*fieldmaskpb.FieldMask)(nil), // 49: google.protobuf.FieldMask + (*emptypb.Empty)(nil), // 50: google.protobuf.Empty } var file_api_v1_user_service_proto_depIdxs = []int32{ 0, // 0: memos.api.v1.User.role:type_name -> memos.api.v1.User.Role - 48, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State - 49, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp - 49, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp + 47, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State + 48, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp + 48, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp 4, // 4: memos.api.v1.ListUsersResponse.users:type_name -> memos.api.v1.User - 50, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask + 49, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask 4, // 6: memos.api.v1.CreateUserRequest.user:type_name -> memos.api.v1.User 4, // 7: memos.api.v1.UpdateUserRequest.user:type_name -> memos.api.v1.User - 50, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask - 49, // 9: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp - 42, // 10: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats - 41, // 11: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry - 12, // 12: memos.api.v1.ListAllUserStatsResponse.stats:type_name -> memos.api.v1.UserStats - 43, // 13: memos.api.v1.UserSetting.general_setting:type_name -> memos.api.v1.UserSetting.GeneralSetting - 44, // 14: memos.api.v1.UserSetting.sessions_setting:type_name -> memos.api.v1.UserSetting.SessionsSetting - 45, // 15: memos.api.v1.UserSetting.access_tokens_setting:type_name -> memos.api.v1.UserSetting.AccessTokensSetting - 46, // 16: memos.api.v1.UserSetting.webhooks_setting:type_name -> memos.api.v1.UserSetting.WebhooksSetting - 16, // 17: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting - 50, // 18: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask - 16, // 19: memos.api.v1.ListUserSettingsResponse.settings:type_name -> memos.api.v1.UserSetting - 49, // 20: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp - 49, // 21: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp - 21, // 22: memos.api.v1.ListUserAccessTokensResponse.access_tokens:type_name -> memos.api.v1.UserAccessToken - 21, // 23: memos.api.v1.CreateUserAccessTokenRequest.access_token:type_name -> memos.api.v1.UserAccessToken - 49, // 24: memos.api.v1.UserSession.create_time:type_name -> google.protobuf.Timestamp - 49, // 25: memos.api.v1.UserSession.last_accessed_time:type_name -> google.protobuf.Timestamp - 47, // 26: memos.api.v1.UserSession.client_info:type_name -> memos.api.v1.UserSession.ClientInfo - 26, // 27: memos.api.v1.ListUserSessionsResponse.sessions:type_name -> memos.api.v1.UserSession - 49, // 28: memos.api.v1.UserWebhook.create_time:type_name -> google.protobuf.Timestamp - 49, // 29: memos.api.v1.UserWebhook.update_time:type_name -> google.protobuf.Timestamp - 30, // 30: memos.api.v1.ListUserWebhooksResponse.webhooks:type_name -> memos.api.v1.UserWebhook - 30, // 31: memos.api.v1.CreateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook - 30, // 32: memos.api.v1.UpdateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook - 50, // 33: memos.api.v1.UpdateUserWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask + 49, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask + 48, // 9: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp + 41, // 10: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats + 40, // 11: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry + 11, // 12: memos.api.v1.ListAllUserStatsResponse.stats:type_name -> memos.api.v1.UserStats + 42, // 13: memos.api.v1.UserSetting.general_setting:type_name -> memos.api.v1.UserSetting.GeneralSetting + 43, // 14: memos.api.v1.UserSetting.sessions_setting:type_name -> memos.api.v1.UserSetting.SessionsSetting + 44, // 15: memos.api.v1.UserSetting.access_tokens_setting:type_name -> memos.api.v1.UserSetting.AccessTokensSetting + 45, // 16: memos.api.v1.UserSetting.webhooks_setting:type_name -> memos.api.v1.UserSetting.WebhooksSetting + 15, // 17: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting + 49, // 18: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask + 15, // 19: memos.api.v1.ListUserSettingsResponse.settings:type_name -> memos.api.v1.UserSetting + 48, // 20: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp + 48, // 21: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp + 20, // 22: memos.api.v1.ListUserAccessTokensResponse.access_tokens:type_name -> memos.api.v1.UserAccessToken + 20, // 23: memos.api.v1.CreateUserAccessTokenRequest.access_token:type_name -> memos.api.v1.UserAccessToken + 48, // 24: memos.api.v1.UserSession.create_time:type_name -> google.protobuf.Timestamp + 48, // 25: memos.api.v1.UserSession.last_accessed_time:type_name -> google.protobuf.Timestamp + 46, // 26: memos.api.v1.UserSession.client_info:type_name -> memos.api.v1.UserSession.ClientInfo + 25, // 27: memos.api.v1.ListUserSessionsResponse.sessions:type_name -> memos.api.v1.UserSession + 48, // 28: memos.api.v1.UserWebhook.create_time:type_name -> google.protobuf.Timestamp + 48, // 29: memos.api.v1.UserWebhook.update_time:type_name -> google.protobuf.Timestamp + 29, // 30: memos.api.v1.ListUserWebhooksResponse.webhooks:type_name -> memos.api.v1.UserWebhook + 29, // 31: memos.api.v1.CreateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook + 29, // 32: memos.api.v1.UpdateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook + 49, // 33: memos.api.v1.UpdateUserWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask 2, // 34: memos.api.v1.UserNotification.status:type_name -> memos.api.v1.UserNotification.Status - 49, // 35: memos.api.v1.UserNotification.create_time:type_name -> google.protobuf.Timestamp + 48, // 35: memos.api.v1.UserNotification.create_time:type_name -> google.protobuf.Timestamp 3, // 36: memos.api.v1.UserNotification.type:type_name -> memos.api.v1.UserNotification.Type - 36, // 37: memos.api.v1.ListUserNotificationsResponse.notifications:type_name -> memos.api.v1.UserNotification - 36, // 38: memos.api.v1.UpdateUserNotificationRequest.notification:type_name -> memos.api.v1.UserNotification - 50, // 39: memos.api.v1.UpdateUserNotificationRequest.update_mask:type_name -> google.protobuf.FieldMask - 26, // 40: memos.api.v1.UserSetting.SessionsSetting.sessions:type_name -> memos.api.v1.UserSession - 21, // 41: memos.api.v1.UserSetting.AccessTokensSetting.access_tokens:type_name -> memos.api.v1.UserAccessToken - 30, // 42: memos.api.v1.UserSetting.WebhooksSetting.webhooks:type_name -> memos.api.v1.UserWebhook + 35, // 37: memos.api.v1.ListUserNotificationsResponse.notifications:type_name -> memos.api.v1.UserNotification + 35, // 38: memos.api.v1.UpdateUserNotificationRequest.notification:type_name -> memos.api.v1.UserNotification + 49, // 39: memos.api.v1.UpdateUserNotificationRequest.update_mask:type_name -> google.protobuf.FieldMask + 25, // 40: memos.api.v1.UserSetting.SessionsSetting.sessions:type_name -> memos.api.v1.UserSession + 20, // 41: memos.api.v1.UserSetting.AccessTokensSetting.access_tokens:type_name -> memos.api.v1.UserAccessToken + 29, // 42: memos.api.v1.UserSetting.WebhooksSetting.webhooks:type_name -> memos.api.v1.UserWebhook 5, // 43: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest 7, // 44: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest 8, // 45: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest 9, // 46: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest 10, // 47: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest - 11, // 48: memos.api.v1.UserService.GetUserAvatar:input_type -> memos.api.v1.GetUserAvatarRequest - 14, // 49: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest - 13, // 50: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest - 17, // 51: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest - 18, // 52: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest - 19, // 53: memos.api.v1.UserService.ListUserSettings:input_type -> memos.api.v1.ListUserSettingsRequest - 22, // 54: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest - 24, // 55: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest - 25, // 56: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest - 27, // 57: memos.api.v1.UserService.ListUserSessions:input_type -> memos.api.v1.ListUserSessionsRequest - 29, // 58: memos.api.v1.UserService.RevokeUserSession:input_type -> memos.api.v1.RevokeUserSessionRequest - 31, // 59: memos.api.v1.UserService.ListUserWebhooks:input_type -> memos.api.v1.ListUserWebhooksRequest - 33, // 60: memos.api.v1.UserService.CreateUserWebhook:input_type -> memos.api.v1.CreateUserWebhookRequest - 34, // 61: memos.api.v1.UserService.UpdateUserWebhook:input_type -> memos.api.v1.UpdateUserWebhookRequest - 35, // 62: memos.api.v1.UserService.DeleteUserWebhook:input_type -> memos.api.v1.DeleteUserWebhookRequest - 37, // 63: memos.api.v1.UserService.ListUserNotifications:input_type -> memos.api.v1.ListUserNotificationsRequest - 39, // 64: memos.api.v1.UserService.UpdateUserNotification:input_type -> memos.api.v1.UpdateUserNotificationRequest - 40, // 65: memos.api.v1.UserService.DeleteUserNotification:input_type -> memos.api.v1.DeleteUserNotificationRequest - 6, // 66: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse - 4, // 67: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User - 4, // 68: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User - 4, // 69: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User - 51, // 70: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty - 52, // 71: memos.api.v1.UserService.GetUserAvatar:output_type -> google.api.HttpBody - 15, // 72: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse - 12, // 73: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats - 16, // 74: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting - 16, // 75: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting - 20, // 76: memos.api.v1.UserService.ListUserSettings:output_type -> memos.api.v1.ListUserSettingsResponse - 23, // 77: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse - 21, // 78: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken - 51, // 79: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty - 28, // 80: memos.api.v1.UserService.ListUserSessions:output_type -> memos.api.v1.ListUserSessionsResponse - 51, // 81: memos.api.v1.UserService.RevokeUserSession:output_type -> google.protobuf.Empty - 32, // 82: memos.api.v1.UserService.ListUserWebhooks:output_type -> memos.api.v1.ListUserWebhooksResponse - 30, // 83: memos.api.v1.UserService.CreateUserWebhook:output_type -> memos.api.v1.UserWebhook - 30, // 84: memos.api.v1.UserService.UpdateUserWebhook:output_type -> memos.api.v1.UserWebhook - 51, // 85: memos.api.v1.UserService.DeleteUserWebhook:output_type -> google.protobuf.Empty - 38, // 86: memos.api.v1.UserService.ListUserNotifications:output_type -> memos.api.v1.ListUserNotificationsResponse - 36, // 87: memos.api.v1.UserService.UpdateUserNotification:output_type -> memos.api.v1.UserNotification - 51, // 88: memos.api.v1.UserService.DeleteUserNotification:output_type -> google.protobuf.Empty - 66, // [66:89] is the sub-list for method output_type - 43, // [43:66] is the sub-list for method input_type + 13, // 48: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest + 12, // 49: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest + 16, // 50: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest + 17, // 51: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest + 18, // 52: memos.api.v1.UserService.ListUserSettings:input_type -> memos.api.v1.ListUserSettingsRequest + 21, // 53: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest + 23, // 54: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest + 24, // 55: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest + 26, // 56: memos.api.v1.UserService.ListUserSessions:input_type -> memos.api.v1.ListUserSessionsRequest + 28, // 57: memos.api.v1.UserService.RevokeUserSession:input_type -> memos.api.v1.RevokeUserSessionRequest + 30, // 58: memos.api.v1.UserService.ListUserWebhooks:input_type -> memos.api.v1.ListUserWebhooksRequest + 32, // 59: memos.api.v1.UserService.CreateUserWebhook:input_type -> memos.api.v1.CreateUserWebhookRequest + 33, // 60: memos.api.v1.UserService.UpdateUserWebhook:input_type -> memos.api.v1.UpdateUserWebhookRequest + 34, // 61: memos.api.v1.UserService.DeleteUserWebhook:input_type -> memos.api.v1.DeleteUserWebhookRequest + 36, // 62: memos.api.v1.UserService.ListUserNotifications:input_type -> memos.api.v1.ListUserNotificationsRequest + 38, // 63: memos.api.v1.UserService.UpdateUserNotification:input_type -> memos.api.v1.UpdateUserNotificationRequest + 39, // 64: memos.api.v1.UserService.DeleteUserNotification:input_type -> memos.api.v1.DeleteUserNotificationRequest + 6, // 65: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse + 4, // 66: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User + 4, // 67: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User + 4, // 68: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User + 50, // 69: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty + 14, // 70: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse + 11, // 71: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats + 15, // 72: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting + 15, // 73: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting + 19, // 74: memos.api.v1.UserService.ListUserSettings:output_type -> memos.api.v1.ListUserSettingsResponse + 22, // 75: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse + 20, // 76: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken + 50, // 77: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty + 27, // 78: memos.api.v1.UserService.ListUserSessions:output_type -> memos.api.v1.ListUserSessionsResponse + 50, // 79: memos.api.v1.UserService.RevokeUserSession:output_type -> google.protobuf.Empty + 31, // 80: memos.api.v1.UserService.ListUserWebhooks:output_type -> memos.api.v1.ListUserWebhooksResponse + 29, // 81: memos.api.v1.UserService.CreateUserWebhook:output_type -> memos.api.v1.UserWebhook + 29, // 82: memos.api.v1.UserService.UpdateUserWebhook:output_type -> memos.api.v1.UserWebhook + 50, // 83: memos.api.v1.UserService.DeleteUserWebhook:output_type -> google.protobuf.Empty + 37, // 84: memos.api.v1.UserService.ListUserNotifications:output_type -> memos.api.v1.ListUserNotificationsResponse + 35, // 85: memos.api.v1.UserService.UpdateUserNotification:output_type -> memos.api.v1.UserNotification + 50, // 86: memos.api.v1.UserService.DeleteUserNotification:output_type -> google.protobuf.Empty + 65, // [65:87] is the sub-list for method output_type + 43, // [43:65] is the sub-list for method input_type 43, // [43:43] is the sub-list for extension type_name 43, // [43:43] is the sub-list for extension extendee 0, // [0:43] is the sub-list for field type_name @@ -3370,20 +3315,20 @@ func file_api_v1_user_service_proto_init() { return } file_api_v1_common_proto_init() - file_api_v1_user_service_proto_msgTypes[12].OneofWrappers = []any{ + file_api_v1_user_service_proto_msgTypes[11].OneofWrappers = []any{ (*UserSetting_GeneralSetting_)(nil), (*UserSetting_SessionsSetting_)(nil), (*UserSetting_AccessTokensSetting_)(nil), (*UserSetting_WebhooksSetting_)(nil), } - file_api_v1_user_service_proto_msgTypes[32].OneofWrappers = []any{} + file_api_v1_user_service_proto_msgTypes[31].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_user_service_proto_rawDesc), len(file_api_v1_user_service_proto_rawDesc)), NumEnums: 4, - NumMessages: 44, + NumMessages: 43, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/api/v1/user_service.pb.gw.go b/proto/gen/api/v1/user_service.pb.gw.go index bf4051c69..37b7dac70 100644 --- a/proto/gen/api/v1/user_service.pb.gw.go +++ b/proto/gen/api/v1/user_service.pb.gw.go @@ -298,45 +298,6 @@ func local_request_UserService_DeleteUser_0(ctx context.Context, marshaler runti return msg, metadata, err } -func request_UserService_GetUserAvatar_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var ( - protoReq GetUserAvatarRequest - metadata runtime.ServerMetadata - err error - ) - if req.Body != nil { - _, _ = io.Copy(io.Discard, req.Body) - } - 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.GetUserAvatar(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err -} - -func local_request_UserService_GetUserAvatar_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var ( - protoReq GetUserAvatarRequest - metadata runtime.ServerMetadata - err error - ) - 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.GetUserAvatar(ctx, &protoReq) - return msg, metadata, err -} - func request_UserService_ListAllUserStats_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( protoReq ListAllUserStatsRequest @@ -1282,26 +1243,6 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux } forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle(http.MethodGet, pattern_UserService_GetUserAvatar_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/GetUserAvatar", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}/avatar")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_UserService_GetUserAvatar_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - forward_UserService_GetUserAvatar_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) mux.Handle(http.MethodGet, pattern_UserService_ListAllUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1767,23 +1708,6 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux } forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle(http.MethodGet, pattern_UserService_GetUserAvatar_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/GetUserAvatar", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}/avatar")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_UserService_GetUserAvatar_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - forward_UserService_GetUserAvatar_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) mux.Handle(http.MethodGet, pattern_UserService_ListAllUserStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2082,7 +2006,6 @@ var ( pattern_UserService_CreateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, "")) pattern_UserService_UpdateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "user.name"}, "")) pattern_UserService_DeleteUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, "")) - pattern_UserService_GetUserAvatar_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "name", "avatar"}, "")) pattern_UserService_ListAllUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, "stats")) pattern_UserService_GetUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, "getStats")) pattern_UserService_GetUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "settings", "name"}, "")) @@ -2108,7 +2031,6 @@ var ( forward_UserService_CreateUser_0 = runtime.ForwardResponseMessage forward_UserService_UpdateUser_0 = runtime.ForwardResponseMessage forward_UserService_DeleteUser_0 = runtime.ForwardResponseMessage - forward_UserService_GetUserAvatar_0 = runtime.ForwardResponseMessage forward_UserService_ListAllUserStats_0 = runtime.ForwardResponseMessage forward_UserService_GetUserStats_0 = runtime.ForwardResponseMessage forward_UserService_GetUserSetting_0 = runtime.ForwardResponseMessage diff --git a/proto/gen/api/v1/user_service_grpc.pb.go b/proto/gen/api/v1/user_service_grpc.pb.go index 5f54cba22..b0deb0f93 100644 --- a/proto/gen/api/v1/user_service_grpc.pb.go +++ b/proto/gen/api/v1/user_service_grpc.pb.go @@ -8,7 +8,6 @@ package apiv1 import ( context "context" - httpbody "google.golang.org/genproto/googleapis/api/httpbody" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -26,7 +25,6 @@ const ( UserService_CreateUser_FullMethodName = "/memos.api.v1.UserService/CreateUser" UserService_UpdateUser_FullMethodName = "/memos.api.v1.UserService/UpdateUser" UserService_DeleteUser_FullMethodName = "/memos.api.v1.UserService/DeleteUser" - UserService_GetUserAvatar_FullMethodName = "/memos.api.v1.UserService/GetUserAvatar" UserService_ListAllUserStats_FullMethodName = "/memos.api.v1.UserService/ListAllUserStats" UserService_GetUserStats_FullMethodName = "/memos.api.v1.UserService/GetUserStats" UserService_GetUserSetting_FullMethodName = "/memos.api.v1.UserService/GetUserSetting" @@ -63,8 +61,6 @@ type UserServiceClient interface { UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error) // DeleteUser deletes a user. DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) - // GetUserAvatar gets the avatar of a user. - GetUserAvatar(ctx context.Context, in *GetUserAvatarRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) // ListAllUserStats returns statistics for all users. ListAllUserStats(ctx context.Context, in *ListAllUserStatsRequest, opts ...grpc.CallOption) (*ListAllUserStatsResponse, error) // GetUserStats returns statistics for a specific user. @@ -159,16 +155,6 @@ func (c *userServiceClient) DeleteUser(ctx context.Context, in *DeleteUserReques return out, nil } -func (c *userServiceClient) GetUserAvatar(ctx context.Context, in *GetUserAvatarRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(httpbody.HttpBody) - err := c.cc.Invoke(ctx, UserService_GetUserAvatar_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *userServiceClient) ListAllUserStats(ctx context.Context, in *ListAllUserStatsRequest, opts ...grpc.CallOption) (*ListAllUserStatsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListAllUserStatsResponse) @@ -356,8 +342,6 @@ type UserServiceServer interface { UpdateUser(context.Context, *UpdateUserRequest) (*User, error) // DeleteUser deletes a user. DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) - // GetUserAvatar gets the avatar of a user. - GetUserAvatar(context.Context, *GetUserAvatarRequest) (*httpbody.HttpBody, error) // ListAllUserStats returns statistics for all users. ListAllUserStats(context.Context, *ListAllUserStatsRequest) (*ListAllUserStatsResponse, error) // GetUserStats returns statistics for a specific user. @@ -417,9 +401,6 @@ func (UnimplementedUserServiceServer) UpdateUser(context.Context, *UpdateUserReq func (UnimplementedUserServiceServer) DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) { return nil, status.Error(codes.Unimplemented, "method DeleteUser not implemented") } -func (UnimplementedUserServiceServer) GetUserAvatar(context.Context, *GetUserAvatarRequest) (*httpbody.HttpBody, error) { - return nil, status.Error(codes.Unimplemented, "method GetUserAvatar not implemented") -} func (UnimplementedUserServiceServer) ListAllUserStats(context.Context, *ListAllUserStatsRequest) (*ListAllUserStatsResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListAllUserStats not implemented") } @@ -582,24 +563,6 @@ func _UserService_DeleteUser_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } -func _UserService_GetUserAvatar_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetUserAvatarRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(UserServiceServer).GetUserAvatar(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: UserService_GetUserAvatar_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UserServiceServer).GetUserAvatar(ctx, req.(*GetUserAvatarRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _UserService_ListAllUserStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListAllUserStatsRequest) if err := dec(in); err != nil { @@ -933,10 +896,6 @@ var UserService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteUser", Handler: _UserService_DeleteUser_Handler, }, - { - MethodName: "GetUserAvatar", - Handler: _UserService_GetUserAvatar_Handler, - }, { MethodName: "ListAllUserStats", Handler: _UserService_ListAllUserStats_Handler, diff --git a/proto/gen/openapi.yaml b/proto/gen/openapi.yaml index 0bd250136..412b0a8ee 100644 --- a/proto/gen/openapi.yaml +++ b/proto/gen/openapi.yaml @@ -1322,30 +1322,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Status' - /api/v1/users/{user}/avatar: - get: - tags: - - UserService - description: GetUserAvatar gets the avatar of a user. - operationId: UserService_GetUserAvatar - parameters: - - name: user - in: path - description: The user id. - required: true - schema: - type: string - responses: - "200": - description: OK - content: - '*/*': {} - default: - description: Default error response - content: - application/json: - schema: - $ref: '#/components/schemas/Status' /api/v1/users/{user}/notifications: get: tags: @@ -1968,41 +1944,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Status' - /file/attachments/{attachment}/{filename: - get: - tags: - - AttachmentService - description: GetAttachmentBinary returns a attachment binary by name. - operationId: AttachmentService_GetAttachmentBinary - parameters: - - name: filename - in: path - description: The filename of the attachment. Mainly used for downloading. - required: true - schema: - type: string - - name: attachment - in: path - description: The attachment id. - required: true - schema: - type: string - - name: thumbnail - in: query - description: Optional. A flag indicating if the thumbnail version of the attachment should be returned. - schema: - type: boolean - responses: - "200": - description: OK - content: - '*/*': {} - default: - description: Default error response - content: - application/json: - schema: - $ref: '#/components/schemas/Status' components: schemas: Activity: diff --git a/server/router/api/v1/attachment_service.go b/server/router/api/v1/attachment_service.go index e3768f8e9..1c82a5a84 100644 --- a/server/router/api/v1/attachment_service.go +++ b/server/router/api/v1/attachment_service.go @@ -6,21 +6,15 @@ import ( "encoding/binary" "fmt" "io" - "log/slog" "os" "path/filepath" "regexp" - "strconv" "strings" "time" - "github.com/disintegration/imaging" "github.com/lithammer/shortuuid/v4" "github.com/pkg/errors" - "google.golang.org/genproto/googleapis/api/httpbody" - "google.golang.org/grpc" "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" @@ -197,129 +191,6 @@ func (s *APIV1Service) GetAttachment(ctx context.Context, request *v1pb.GetAttac return convertAttachmentFromStore(attachment), nil } -func (s *APIV1Service) GetAttachmentBinary(ctx context.Context, request *v1pb.GetAttachmentBinaryRequest) (*httpbody.HttpBody, error) { - attachmentUID, err := ExtractAttachmentUIDFromName(request.Name) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "invalid attachment id: %v", err) - } - attachment, err := s.Store.GetAttachment(ctx, &store.FindAttachment{ - GetBlob: true, - UID: &attachmentUID, - }) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to get attachment: %v", err) - } - if attachment == nil { - return nil, status.Errorf(codes.NotFound, "attachment not found") - } - // Check the related memo visibility. - if attachment.MemoID != nil { - memo, err := s.Store.GetMemo(ctx, &store.FindMemo{ - ID: attachment.MemoID, - }) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to find memo by ID: %v", attachment.MemoID) - } - if memo != nil && memo.Visibility != store.Public { - user, err := s.GetCurrentUser(ctx) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err) - } - if user == nil { - return nil, status.Errorf(codes.Unauthenticated, "unauthorized access") - } - if memo.Visibility == store.Private && user.ID != attachment.CreatorID { - return nil, status.Errorf(codes.Unauthenticated, "unauthorized access") - } - } - } - - if request.Thumbnail && util.HasPrefixes(attachment.Type, SupportedThumbnailMimeTypes...) { - // Skip server-side thumbnail generation for S3 storage to reduce memory usage. - // S3 images use external links (presigned URLs) directly, which avoids: - // 1. Downloading large images from S3 into server memory - // 2. Decoding and resizing images on the server - // 3. High memory consumption when many thumbnails are requested at once - // The client will use the external link and can implement client-side thumbnail logic if needed. - if attachment.StorageType == storepb.AttachmentStorageType_S3 { - slog.Debug("skipping server-side thumbnail for S3-stored image to reduce memory usage") - // Fall through to return the full image via external link - } else { - // Generate thumbnails for local and database storage - thumbnailBlob, err := s.getOrGenerateThumbnail(ctx, attachment) - if err != nil { - // thumbnail failures are logged as warnings and not cosidered critical failures as - // a attachment image can be used in its place. - slog.Warn("failed to get attachment thumbnail image", slog.Any("error", err)) - } else { - return &httpbody.HttpBody{ - ContentType: attachment.Type, - Data: thumbnailBlob, - }, nil - } - } - } - - blob, err := s.GetAttachmentBlob(attachment) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to get attachment blob: %v", err) - } - - contentType := attachment.Type - if strings.HasPrefix(contentType, "text/") { - contentType += "; charset=utf-8" - } - // Prevent XSS attacks by serving potentially unsafe files with a content type that prevents script execution. - if strings.EqualFold(contentType, "image/svg+xml") || - strings.EqualFold(contentType, "text/html") || - strings.EqualFold(contentType, "application/xhtml+xml") { - contentType = "application/octet-stream" - } - - // Extract range header from gRPC metadata for iOS Safari video support - var rangeHeader string - if md, ok := metadata.FromIncomingContext(ctx); ok { - // Check for range header from gRPC-Gateway - if ranges := md.Get("grpcgateway-range"); len(ranges) > 0 { - rangeHeader = ranges[0] - } else if ranges := md.Get("range"); len(ranges) > 0 { - rangeHeader = ranges[0] - } - - // Log for debugging iOS Safari issues - if userAgents := md.Get("user-agent"); len(userAgents) > 0 { - userAgent := userAgents[0] - if strings.Contains(strings.ToLower(userAgent), "safari") && rangeHeader != "" { - slog.Debug("Safari range request detected", - slog.String("range", rangeHeader), - slog.String("user-agent", userAgent), - slog.String("content-type", contentType)) - } - } - } - - // Handle range requests for video/audio streaming (iOS Safari requirement) - if rangeHeader != "" && (strings.HasPrefix(contentType, "video/") || strings.HasPrefix(contentType, "audio/")) { - return s.handleRangeRequest(ctx, blob, rangeHeader, contentType) - } - - // Set headers for streaming support - if strings.HasPrefix(contentType, "video/") || strings.HasPrefix(contentType, "audio/") { - if err := setResponseHeaders(ctx, map[string]string{ - "accept-ranges": "bytes", - "content-length": fmt.Sprintf("%d", len(blob)), - "cache-control": "public, max-age=3600", // 1 hour cache - }); err != nil { - slog.Warn("failed to set streaming headers", slog.Any("error", err)) - } - } - - return &httpbody.HttpBody{ - ContentType: contentType, - Data: blob, - }, nil -} - func (s *APIV1Service) UpdateAttachment(ctx context.Context, request *v1pb.UpdateAttachmentRequest) (*v1pb.Attachment, error) { attachmentUID, err := ExtractAttachmentUIDFromName(request.Attachment.Name) if err != nil { @@ -541,113 +412,6 @@ func (s *APIV1Service) GetAttachmentBlob(attachment *store.Attachment) ([]byte, return attachment.Blob, nil } -const ( - // thumbnailMaxSize is the maximum size in pixels for the largest dimension of the thumbnail image. - thumbnailMaxSize = 600 -) - -// getOrGenerateThumbnail returns the thumbnail image of the attachment. -// Uses semaphore to limit concurrent thumbnail generation and prevent memory exhaustion. -func (s *APIV1Service) getOrGenerateThumbnail(ctx context.Context, attachment *store.Attachment) ([]byte, error) { - thumbnailCacheFolder := filepath.Join(s.Profile.Data, ThumbnailCacheFolder) - if err := os.MkdirAll(thumbnailCacheFolder, os.ModePerm); err != nil { - return nil, errors.Wrap(err, "failed to create thumbnail cache folder") - } - filePath := filepath.Join(thumbnailCacheFolder, fmt.Sprintf("%d%s", attachment.ID, filepath.Ext(attachment.Filename))) - - // Check if thumbnail already exists - if _, err := os.Stat(filePath); err == nil { - // Thumbnail exists, read and return it - thumbnailFile, err := os.Open(filePath) - if err != nil { - return nil, errors.Wrap(err, "failed to open thumbnail file") - } - defer thumbnailFile.Close() - blob, err := io.ReadAll(thumbnailFile) - if err != nil { - return nil, errors.Wrap(err, "failed to read thumbnail file") - } - return blob, nil - } else if !os.IsNotExist(err) { - return nil, errors.Wrap(err, "failed to check thumbnail image stat") - } - - // Thumbnail doesn't exist, acquire semaphore to limit concurrent generation - if err := s.thumbnailSemaphore.Acquire(ctx, 1); err != nil { - return nil, errors.Wrap(err, "failed to acquire thumbnail generation semaphore") - } - defer s.thumbnailSemaphore.Release(1) - - // Double-check if thumbnail was created while waiting for semaphore - if _, err := os.Stat(filePath); err == nil { - thumbnailFile, err := os.Open(filePath) - if err != nil { - return nil, errors.Wrap(err, "failed to open thumbnail file") - } - defer thumbnailFile.Close() - blob, err := io.ReadAll(thumbnailFile) - if err != nil { - return nil, errors.Wrap(err, "failed to read thumbnail file") - } - return blob, nil - } - - // Generate the thumbnail - blob, err := s.GetAttachmentBlob(attachment) - if err != nil { - return nil, errors.Wrap(err, "failed to get attachment blob") - } - - // Decode image - this is memory intensive - img, err := imaging.Decode(bytes.NewReader(blob), imaging.AutoOrientation(true)) - if err != nil { - return nil, errors.Wrap(err, "failed to decode thumbnail image") - } - - // The largest dimension is set to thumbnailMaxSize and the smaller dimension is scaled proportionally. - // Small images are not enlarged. - width := img.Bounds().Dx() - height := img.Bounds().Dy() - var thumbnailWidth, thumbnailHeight int - - // Only resize if the image is larger than thumbnailMaxSize - if max(width, height) > thumbnailMaxSize { - if width >= height { - // Landscape or square - constrain width, maintain aspect ratio for height - thumbnailWidth = thumbnailMaxSize - thumbnailHeight = 0 - } else { - // Portrait - constrain height, maintain aspect ratio for width - thumbnailWidth = 0 - thumbnailHeight = thumbnailMaxSize - } - } else { - // Keep original dimensions for small images - thumbnailWidth = width - thumbnailHeight = height - } - - // Resize the image to the calculated dimensions. - thumbnailImage := imaging.Resize(img, thumbnailWidth, thumbnailHeight, imaging.Lanczos) - - // Save thumbnail to disk - if err := imaging.Save(thumbnailImage, filePath); err != nil { - return nil, errors.Wrap(err, "failed to save thumbnail file") - } - - // Read the saved thumbnail and return it - thumbnailFile, err := os.Open(filePath) - if err != nil { - return nil, errors.Wrap(err, "failed to open thumbnail file") - } - defer thumbnailFile.Close() - thumbnailBlob, err := io.ReadAll(thumbnailFile) - if err != nil { - return nil, errors.Wrap(err, "failed to read thumbnail file") - } - return thumbnailBlob, nil -} - var fileKeyPattern = regexp.MustCompile(`\{[a-z]{1,9}\}`) func replaceFilenameWithPathTemplate(path, filename string) string { @@ -679,85 +443,6 @@ func replaceFilenameWithPathTemplate(path, filename string) string { return path } -// handleRangeRequest handles HTTP range requests for video/audio streaming (iOS Safari requirement). -func (*APIV1Service) handleRangeRequest(ctx context.Context, data []byte, rangeHeader, contentType string) (*httpbody.HttpBody, error) { - // Parse "bytes=start-end" - if !strings.HasPrefix(rangeHeader, "bytes=") { - return nil, status.Errorf(codes.InvalidArgument, "invalid range header format") - } - - rangeSpec := strings.TrimPrefix(rangeHeader, "bytes=") - parts := strings.Split(rangeSpec, "-") - if len(parts) != 2 { - return nil, status.Errorf(codes.InvalidArgument, "invalid range specification") - } - - fileSize := int64(len(data)) - start, end := int64(0), fileSize-1 - - // Parse start position - if parts[0] != "" { - if s, err := strconv.ParseInt(parts[0], 10, 64); err == nil { - start = s - } else { - return nil, status.Errorf(codes.InvalidArgument, "invalid range start: %s", parts[0]) - } - } - - // Parse end position - if parts[1] != "" { - if e, err := strconv.ParseInt(parts[1], 10, 64); err == nil { - end = e - } else { - return nil, status.Errorf(codes.InvalidArgument, "invalid range end: %s", parts[1]) - } - } - - // Validate range - if start < 0 || end >= fileSize || start > end { - // Set Content-Range header for 416 response - if err := setResponseHeaders(ctx, map[string]string{ - "content-range": fmt.Sprintf("bytes */%d", fileSize), - }); err != nil { - slog.Warn("failed to set content-range header", slog.Any("error", err)) - } - return nil, status.Errorf(codes.OutOfRange, "requested range not satisfiable") - } - - // Set partial content headers (HTTP 206) - if err := setResponseHeaders(ctx, map[string]string{ - "accept-ranges": "bytes", - "content-range": fmt.Sprintf("bytes %d-%d/%d", start, end, fileSize), - "content-length": fmt.Sprintf("%d", end-start+1), - "cache-control": "public, max-age=3600", - }); err != nil { - slog.Warn("failed to set partial content headers", slog.Any("error", err)) - } - - // Extract the requested range - rangeData := data[start : end+1] - - slog.Debug("serving partial content", - slog.Int64("start", start), - slog.Int64("end", end), - slog.Int64("total", fileSize), - slog.Int("chunk_size", len(rangeData))) - - return &httpbody.HttpBody{ - ContentType: contentType, - Data: rangeData, - }, nil -} - -// setResponseHeaders is a helper function to set gRPC response headers. -func setResponseHeaders(ctx context.Context, headers map[string]string) error { - pairs := make([]string, 0, len(headers)*2) - for key, value := range headers { - pairs = append(pairs, key, value) - } - return grpc.SetHeader(ctx, metadata.Pairs(pairs...)) -} - func validateFilename(filename string) bool { // Reject path traversal attempts and make sure no additional directories are created if !filepath.IsLocal(filename) || strings.ContainsAny(filename, "/\\") { diff --git a/server/router/api/v1/user_service.go b/server/router/api/v1/user_service.go index 053713307..0e71bfa29 100644 --- a/server/router/api/v1/user_service.go +++ b/server/router/api/v1/user_service.go @@ -3,7 +3,6 @@ package v1 import ( "context" "crypto/rand" - "encoding/base64" "encoding/hex" "fmt" "net/http" @@ -19,7 +18,6 @@ import ( "github.com/labstack/echo/v4" "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" - "google.golang.org/genproto/googleapis/api/httpbody" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" @@ -106,39 +104,6 @@ func (s *APIV1Service) GetUser(ctx context.Context, request *v1pb.GetUserRequest return convertUserFromStore(user), nil } -func (s *APIV1Service) GetUserAvatar(ctx context.Context, request *v1pb.GetUserAvatarRequest) (*httpbody.HttpBody, error) { - userID, err := ExtractUserIDFromName(request.Name) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err) - } - user, err := s.Store.GetUser(ctx, &store.FindUser{ - ID: &userID, - }) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to get user: %v", err) - } - if user == nil { - return nil, status.Errorf(codes.NotFound, "user not found") - } - if user.AvatarURL == "" { - return nil, status.Errorf(codes.NotFound, "avatar not found") - } - - imageType, base64Data, err := extractImageInfo(user.AvatarURL) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to extract image info: %v", err) - } - imageData, err := base64.StdEncoding.DecodeString(base64Data) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to decode string: %v", err) - } - httpBody := &httpbody.HttpBody{ - ContentType: imageType, - Data: imageData, - } - return httpBody, nil -} - func (s *APIV1Service) CreateUser(ctx context.Context, request *v1pb.CreateUserRequest) (*v1pb.User, error) { // Get current user (might be nil for unauthenticated requests) currentUser, _ := s.GetCurrentUser(ctx) @@ -1151,7 +1116,7 @@ func convertUserFromStore(user *store.User) *v1pb.User { // Check if avatar url is base64 format. _, _, err := extractImageInfo(user.AvatarURL) if err == nil { - userpb.AvatarUrl = fmt.Sprintf("/api/v1/%s/avatar", userpb.Name) + userpb.AvatarUrl = fmt.Sprintf("/file/%s/avatar", userpb.Name) } else { userpb.AvatarUrl = user.AvatarURL } @@ -1183,11 +1148,13 @@ func convertUserRoleToStore(role v1pb.User_Role) store.Role { } } +// extractImageInfo extracts image type and base64 data from a data URI. +// Data URI format: data:image/png;base64,iVBORw0KGgo... func extractImageInfo(dataURI string) (string, string, error) { dataURIRegex := regexp.MustCompile(`^data:(?P.+);base64,(?P.+)`) matches := dataURIRegex.FindStringSubmatch(dataURI) if len(matches) != 3 { - return "", "", errors.New("Invalid data URI format") + return "", "", errors.New("invalid data URI format") } imageType := matches[1] base64Data := matches[2] diff --git a/server/router/fileserver/README.md b/server/router/fileserver/README.md new file mode 100644 index 000000000..22d98104c --- /dev/null +++ b/server/router/fileserver/README.md @@ -0,0 +1,309 @@ +# Fileserver Package + +## Overview + +The `fileserver` package handles all binary file serving for Memos using native HTTP handlers. It was created to replace gRPC-based binary serving, which had limitations with HTTP range requests (required for Safari video/audio playback). + +## Responsibilities + +- Serve attachment binary files (images, videos, audio, documents) +- Serve user avatar images +- Handle HTTP range requests for video/audio streaming +- Authenticate requests using session cookies or JWT tokens +- Check permissions for private content +- Generate and serve image thumbnails +- Prevent XSS attacks on uploaded content +- Support S3 external storage + +## Architecture + +### Design Principles + +1. **Separation of Concerns**: Binary files via HTTP, metadata via gRPC +2. **DRY**: Imports auth constants from `api/v1` package (single source of truth) +3. **Security First**: Authentication, authorization, and XSS prevention +4. **Performance**: Native HTTP streaming with proper caching headers + +### Package Structure + +``` +fileserver/ +├── fileserver.go # Main service and HTTP handlers +├── README.md # This file +└── fileserver_test.go # Tests (to be added) +``` + +## API Endpoints + +### 1. Attachment Binary +``` +GET /file/attachments/:uid/:filename[?thumbnail=true] +``` + +**Parameters:** +- `uid` - Attachment unique identifier +- `filename` - Original filename +- `thumbnail` (optional) - Return thumbnail for images + +**Authentication:** Required for non-public memos + +**Response:** +- `200 OK` - File content with proper Content-Type +- `206 Partial Content` - For range requests (video/audio) +- `401 Unauthorized` - Authentication required +- `403 Forbidden` - User not authorized +- `404 Not Found` - Attachment not found + +**Headers:** +- `Content-Type` - MIME type of the file +- `Cache-Control: public, max-age=3600` +- `Accept-Ranges: bytes` - For video/audio +- `Content-Range` - For partial responses (206) + +### 2. User Avatar +``` +GET /file/users/:identifier/avatar +``` + +**Parameters:** +- `identifier` - User ID (e.g., `1`) or username (e.g., `steven`) + +**Authentication:** Not required (avatars are public) + +**Response:** +- `200 OK` - Avatar image (PNG/JPEG) +- `404 Not Found` - User not found or no avatar set + +**Headers:** +- `Content-Type` - image/png or image/jpeg +- `Cache-Control: public, max-age=3600` + +## Authentication + +### Supported Methods + +The fileserver supports two authentication methods, checked in order: + +1. **Session Cookie** (`user_session`) + - Cookie format: `{userID}-{sessionID}` + - Validates session exists and hasn't expired (14-day sliding window) + - Updates last accessed time on success + +2. **JWT Bearer Token** (`Authorization: Bearer {token}`) + - Validates JWT signature using server secret + - Checks token exists in user's access tokens (for revocation) + - Extracts user ID from token claims + +### Authentication Flow + +``` +Request → getCurrentUser() + ├─→ Try Session Cookie + │ ├─→ Parse cookie value + │ ├─→ Get user from DB + │ ├─→ Validate session + │ └─→ Return user (if valid) + │ + └─→ Try JWT Token + ├─→ Parse Authorization header + ├─→ Verify JWT signature + ├─→ Get user from DB + ├─→ Validate token in access tokens list + └─→ Return user (if valid) +``` + +### Permission Model + +**Attachments:** +- Unlinked: Public (no auth required) +- Public memo: Public (no auth required) +- Protected memo: Requires authentication +- Private memo: Creator only + +**Avatars:** +- Always public (no auth required) + +## Key Functions + +### HTTP Handlers + +#### `serveAttachmentFile(c echo.Context) error` +Main handler for attachment binary serving. + +**Flow:** +1. Extract UID from URL parameter +2. Fetch attachment from database +3. Check permissions (memo visibility) +4. Get binary blob (local file, S3, or database) +5. Handle thumbnail request (if applicable) +6. Set security headers (XSS prevention) +7. Serve with range request support (video/audio) + +#### `serveUserAvatar(c echo.Context) error` +Main handler for user avatar serving. + +**Flow:** +1. Extract identifier (ID or username) from URL +2. Lookup user in database +3. Check if avatar exists +4. Decode base64 data URI +5. Serve with proper content type and caching + +### Authentication + +#### `getCurrentUser(ctx, c) (*store.User, error)` +Authenticates request using session cookie or JWT token. + +#### `authenticateBySession(ctx, cookie) (*store.User, error)` +Validates session cookie and returns authenticated user. + +#### `authenticateByJWT(ctx, token) (*store.User, error)` +Validates JWT access token and returns authenticated user. + +### Permission Checks + +#### `checkAttachmentPermission(ctx, c, attachment) error` +Validates user has permission to access attachment based on memo visibility. + +### File Operations + +#### `getAttachmentBlob(attachment) ([]byte, error)` +Retrieves binary content from local storage, S3, or database. + +#### `getOrGenerateThumbnail(ctx, attachment) ([]byte, error)` +Returns cached thumbnail or generates new one (with semaphore limiting). + +### Utilities + +#### `getUserByIdentifier(ctx, identifier) (*store.User, error)` +Finds user by ID (int) or username (string). + +#### `extractImageInfo(dataURI) (type, base64, error)` +Parses data URI to extract MIME type and base64 data. + +## Dependencies + +### External Packages +- `github.com/labstack/echo/v4` - HTTP router and middleware +- `github.com/golang-jwt/jwt/v5` - JWT parsing and validation +- `github.com/disintegration/imaging` - Image thumbnail generation +- `golang.org/x/sync/semaphore` - Concurrency control for thumbnails + +### Internal Packages +- `server/router/api/v1` - Auth constants (SessionCookieName, ClaimsMessage, etc.) +- `store` - Database operations +- `internal/profile` - Server configuration +- `plugin/storage/s3` - S3 storage client + +## Configuration + +### Constants + +All auth-related constants are imported from `server/router/api/v1/auth.go`: +- `apiv1.SessionCookieName` - "user_session" +- `apiv1.SessionSlidingDuration` - 14 days +- `apiv1.KeyID` - "v1" (JWT key identifier) +- `apiv1.ClaimsMessage` - JWT claims struct + +Package-specific constants: +- `ThumbnailCacheFolder` - ".thumbnail_cache" +- `thumbnailMaxSize` - 600px +- `SupportedThumbnailMimeTypes` - ["image/png", "image/jpeg"] + +## Error Handling + +All handlers return Echo HTTP errors with appropriate status codes: + +```go +// Bad request +echo.NewHTTPError(http.StatusBadRequest, "message") + +// Unauthorized (no auth) +echo.NewHTTPError(http.StatusUnauthorized, "message") + +// Forbidden (auth but no permission) +echo.NewHTTPError(http.StatusForbidden, "message") + +// Not found +echo.NewHTTPError(http.StatusNotFound, "message") + +// Internal error +echo.NewHTTPError(http.StatusInternalServerError, "message").SetInternal(err) +``` + +## Security Considerations + +### 1. XSS Prevention +SVG and HTML files are served as `application/octet-stream` to prevent script execution: + +```go +if contentType == "image/svg+xml" || + contentType == "text/html" || + contentType == "application/xhtml+xml" { + contentType = "application/octet-stream" +} +``` + +### 2. Authentication +Private content requires valid session or JWT token. + +### 3. Authorization +Memo visibility rules enforced before serving attachments. + +### 4. Input Validation +- Attachment UID validated from database +- User identifier validated (ID or username) +- Range requests validated before processing + +## Performance Optimizations + +### 1. Thumbnail Caching +Thumbnails cached on disk to avoid regeneration: +- Cache location: `{data_dir}/.thumbnail_cache/` +- Filename: `{attachment_id}{extension}` +- Semaphore limits concurrent generation (max 3) + +### 2. HTTP Range Requests +Video/audio files use `http.ServeContent()` for efficient streaming: +- Automatic range parsing +- Efficient memory usage (streaming, not loading full file) +- Safari-compatible partial content responses + +### 3. Caching Headers +All responses include cache headers: +``` +Cache-Control: public, max-age=3600 +``` + +### 4. S3 External Links +S3 files served via presigned URLs (no server download). + +## Testing + +### Unit Tests (To Add) +See SAFARI_FIX.md for recommended test coverage. + +### Manual Testing +```bash +# Test attachment +curl "http://localhost:8081/file/attachments/{uid}/file.jpg" + +# Test avatar by ID +curl "http://localhost:8081/file/users/1/avatar" + +# Test avatar by username +curl "http://localhost:8081/file/users/steven/avatar" + +# Test range request +curl -H "Range: bytes=0-999" "http://localhost:8081/file/attachments/{uid}/video.mp4" +``` + +## Future Improvements + +See SAFARI_FIX.md section "Future Improvements" for planned enhancements. + +## Related Documentation + +- [SAFARI_FIX.md](../../../SAFARI_FIX.md) - Full migration guide +- [server/router/api/v1/auth.go](../api/v1/auth.go) - Auth constants source of truth +- [RFC 7233](https://tools.ietf.org/html/rfc7233) - HTTP Range Requests spec diff --git a/server/router/fileserver/fileserver.go b/server/router/fileserver/fileserver.go new file mode 100644 index 000000000..9295628d5 --- /dev/null +++ b/server/router/fileserver/fileserver.go @@ -0,0 +1,569 @@ +package fileserver + +import ( + "bytes" + "context" + "encoding/base64" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "github.com/disintegration/imaging" + "github.com/golang-jwt/jwt/v5" + "github.com/labstack/echo/v4" + "github.com/pkg/errors" + "golang.org/x/sync/semaphore" + + "github.com/usememos/memos/internal/profile" + "github.com/usememos/memos/internal/util" + "github.com/usememos/memos/plugin/storage/s3" + storepb "github.com/usememos/memos/proto/gen/store" + apiv1 "github.com/usememos/memos/server/router/api/v1" + "github.com/usememos/memos/store" +) + +const ( + // ThumbnailCacheFolder is the folder name where the thumbnail images are stored. + ThumbnailCacheFolder = ".thumbnail_cache" + // thumbnailMaxSize is the maximum size in pixels for the largest dimension of the thumbnail image. + thumbnailMaxSize = 600 +) + +var SupportedThumbnailMimeTypes = []string{ + "image/png", + "image/jpeg", +} + +// FileServerService handles HTTP file serving with proper range request support. +// This service bypasses gRPC-Gateway to use native HTTP serving via http.ServeContent(), +// which is required for Safari video/audio playback. +type FileServerService struct { + Profile *profile.Profile + Store *store.Store + Secret string + + // thumbnailSemaphore limits concurrent thumbnail generation to prevent memory exhaustion + thumbnailSemaphore *semaphore.Weighted +} + +// NewFileServerService creates a new file server service. +func NewFileServerService(profile *profile.Profile, store *store.Store, secret string) *FileServerService { + return &FileServerService{ + Profile: profile, + Store: store, + Secret: secret, + thumbnailSemaphore: semaphore.NewWeighted(3), // Limit to 3 concurrent thumbnail generations + } +} + +// RegisterRoutes registers HTTP file serving routes. +func (s *FileServerService) RegisterRoutes(echoServer *echo.Echo) { + fileGroup := echoServer.Group("/file") + + // Serve attachment binary files + fileGroup.GET("/attachments/:uid/:filename", s.serveAttachmentFile) + + // Serve user avatar images + fileGroup.GET("/users/:identifier/avatar", s.serveUserAvatar) +} + +// serveAttachmentFile serves attachment binary content using native HTTP. +// This properly handles range requests required by Safari for video/audio playback. +func (s *FileServerService) serveAttachmentFile(c echo.Context) error { + ctx := c.Request().Context() + uid := c.Param("uid") + thumbnail := c.QueryParam("thumbnail") == "true" + + // Get attachment from database + attachment, err := s.Store.GetAttachment(ctx, &store.FindAttachment{ + UID: &uid, + GetBlob: true, + }) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to get attachment").SetInternal(err) + } + if attachment == nil { + return echo.NewHTTPError(http.StatusNotFound, "attachment not found") + } + + // Check permissions - verify memo visibility if attachment belongs to a memo + if err := s.checkAttachmentPermission(ctx, c, attachment); err != nil { + return err + } + + // Get the binary content + blob, err := s.getAttachmentBlob(attachment) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to get attachment blob").SetInternal(err) + } + + // Handle thumbnail requests for images + if thumbnail && s.isImageType(attachment.Type) { + thumbnailBlob, err := s.getOrGenerateThumbnail(ctx, attachment) + if err != nil { + // Log warning but fall back to original image + c.Logger().Warnf("failed to get thumbnail: %v", err) + } else { + blob = thumbnailBlob + } + } + + // Determine content type + contentType := attachment.Type + if strings.HasPrefix(contentType, "text/") { + contentType += "; charset=utf-8" + } + // Prevent XSS attacks by serving potentially unsafe files as octet-stream + if strings.EqualFold(contentType, "image/svg+xml") || + strings.EqualFold(contentType, "text/html") || + strings.EqualFold(contentType, "application/xhtml+xml") { + contentType = "application/octet-stream" + } + + // Set common headers + c.Response().Header().Set("Content-Type", contentType) + c.Response().Header().Set("Cache-Control", "public, max-age=3600") + + // For video/audio: Use http.ServeContent for automatic range request support + // This is critical for Safari which REQUIRES range request support + if strings.HasPrefix(contentType, "video/") || strings.HasPrefix(contentType, "audio/") { + // ServeContent automatically handles: + // - Range request parsing + // - HTTP 206 Partial Content responses + // - Content-Range headers + // - Accept-Ranges: bytes header + modTime := time.Unix(attachment.UpdatedTs, 0) + http.ServeContent(c.Response(), c.Request(), attachment.Filename, modTime, bytes.NewReader(blob)) + return nil + } + + // For other files: Simple blob response + return c.Blob(http.StatusOK, contentType, blob) +} + +// serveUserAvatar serves user avatar images. +// Supports both user ID and username as identifier. +func (s *FileServerService) serveUserAvatar(c echo.Context) error { + ctx := c.Request().Context() + identifier := c.Param("identifier") + + // Try to find user by ID or username + user, err := s.getUserByIdentifier(ctx, identifier) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to get user").SetInternal(err) + } + if user == nil { + return echo.NewHTTPError(http.StatusNotFound, "user not found") + } + if user.AvatarURL == "" { + return echo.NewHTTPError(http.StatusNotFound, "avatar not found") + } + + // Extract image info from data URI + imageType, base64Data, err := s.extractImageInfo(user.AvatarURL) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to extract image info").SetInternal(err) + } + + // Decode base64 data + imageData, err := base64.StdEncoding.DecodeString(base64Data) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to decode image data").SetInternal(err) + } + + // Set cache headers for avatars + c.Response().Header().Set("Content-Type", imageType) + c.Response().Header().Set("Cache-Control", "public, max-age=3600") + + return c.Blob(http.StatusOK, imageType, imageData) +} + +// getUserByIdentifier finds a user by either ID or username. +func (s *FileServerService) getUserByIdentifier(ctx context.Context, identifier string) (*store.User, error) { + // Try to parse as ID first + if userID, err := util.ConvertStringToInt32(identifier); err == nil { + return s.Store.GetUser(ctx, &store.FindUser{ID: &userID}) + } + + // Otherwise, treat as username + return s.Store.GetUser(ctx, &store.FindUser{Username: &identifier}) +} + +// extractImageInfo extracts image type and base64 data from a data URI. +// Data URI format: data:image/png;base64,iVBORw0KGgo... +func (*FileServerService) extractImageInfo(dataURI string) (string, string, error) { + dataURIRegex := regexp.MustCompile(`^data:(?P.+);base64,(?P.+)`) + matches := dataURIRegex.FindStringSubmatch(dataURI) + if len(matches) != 3 { + return "", "", errors.New("invalid data URI format") + } + imageType := matches[1] + base64Data := matches[2] + return imageType, base64Data, nil +} + +// checkAttachmentPermission verifies the user has permission to access the attachment. +func (s *FileServerService) checkAttachmentPermission(ctx context.Context, c echo.Context, attachment *store.Attachment) error { + // If attachment is not linked to a memo, allow access + if attachment.MemoID == nil { + return nil + } + + // Check memo visibility + memo, err := s.Store.GetMemo(ctx, &store.FindMemo{ + ID: attachment.MemoID, + }) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to find memo").SetInternal(err) + } + if memo == nil { + return echo.NewHTTPError(http.StatusNotFound, "memo not found") + } + + // Public memos are accessible to everyone + if memo.Visibility == store.Public { + return nil + } + + // For non-public memos, check authentication + user, err := s.getCurrentUser(ctx, c) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to get current user").SetInternal(err) + } + if user == nil { + return echo.NewHTTPError(http.StatusUnauthorized, "unauthorized access") + } + + // Private memos can only be accessed by the creator + if memo.Visibility == store.Private && user.ID != attachment.CreatorID { + return echo.NewHTTPError(http.StatusForbidden, "forbidden access") + } + + return nil +} + +// getCurrentUser retrieves the current authenticated user from the Echo context. +// It checks both session cookies and Bearer tokens for authentication. +func (s *FileServerService) getCurrentUser(ctx context.Context, c echo.Context) (*store.User, error) { + // Try session cookie authentication first + if cookie, err := c.Cookie(apiv1.SessionCookieName); err == nil && cookie.Value != "" { + user, err := s.authenticateBySession(ctx, cookie.Value) + if err == nil && user != nil { + return user, nil + } + } + + // Try JWT Bearer token authentication + authHeader := c.Request().Header.Get("Authorization") + if authHeader != "" { + parts := strings.Fields(authHeader) + if len(parts) == 2 && strings.ToLower(parts[0]) == "bearer" { + user, err := s.authenticateByJWT(ctx, parts[1]) + if err == nil && user != nil { + return user, nil + } + } + } + + // No valid authentication found + return nil, nil +} + +// authenticateBySession authenticates a user using session ID from cookie. +func (s *FileServerService) authenticateBySession(ctx context.Context, sessionCookieValue string) (*store.User, error) { + if sessionCookieValue == "" { + return nil, errors.New("session cookie value not found") + } + + // Parse the cookie value to extract userID and sessionID + userID, sessionID, err := s.parseSessionCookieValue(sessionCookieValue) + if err != nil { + return nil, errors.Wrap(err, "invalid session cookie format") + } + + // Get the user + user, err := s.Store.GetUser(ctx, &store.FindUser{ + ID: &userID, + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get user") + } + if user == nil { + return nil, errors.New("user not found") + } + if user.RowStatus == store.Archived { + return nil, errors.New("user is archived") + } + + // Get user sessions and validate the sessionID + sessions, err := s.Store.GetUserSessions(ctx, user.ID) + if err != nil { + return nil, errors.Wrap(err, "failed to get user sessions") + } + + if !s.validateUserSession(sessionID, sessions) { + return nil, errors.New("invalid or expired session") + } + + return user, nil +} + +// authenticateByJWT authenticates a user using JWT access token from Authorization header. +func (s *FileServerService) authenticateByJWT(ctx context.Context, accessToken string) (*store.User, error) { + if accessToken == "" { + return nil, errors.New("access token not found") + } + + claims := &apiv1.ClaimsMessage{} + _, err := jwt.ParseWithClaims(accessToken, claims, func(t *jwt.Token) (any, error) { + if t.Method.Alg() != jwt.SigningMethodHS256.Name { + return nil, errors.Errorf("unexpected access token signing method=%v, expect %v", t.Header["alg"], jwt.SigningMethodHS256) + } + if kid, ok := t.Header["kid"].(string); ok { + if kid == apiv1.KeyID { + return []byte(s.Secret), nil + } + } + return nil, errors.Errorf("unexpected access token kid=%v", t.Header["kid"]) + }) + if err != nil { + return nil, errors.Wrap(err, "Invalid or expired access token") + } + + // Get user from JWT claims + userID, err := util.ConvertStringToInt32(claims.Subject) + if err != nil { + return nil, errors.Wrap(err, "malformed ID in the token") + } + user, err := s.Store.GetUser(ctx, &store.FindUser{ + ID: &userID, + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get user") + } + if user == nil { + return nil, errors.Errorf("user %q not exists", userID) + } + if user.RowStatus == store.Archived { + return nil, errors.Errorf("user %q is archived", userID) + } + + // Validate that this access token exists in the user's access tokens + accessTokens, err := s.Store.GetUserAccessTokens(ctx, user.ID) + if err != nil { + return nil, errors.Wrapf(err, "failed to get user access tokens") + } + if !s.validateAccessToken(accessToken, accessTokens) { + return nil, errors.New("invalid access token") + } + + return user, nil +} + +// parseSessionCookieValue parses the session cookie value to extract userID and sessionID. +func (*FileServerService) parseSessionCookieValue(cookieValue string) (int32, string, error) { + parts := strings.SplitN(cookieValue, "-", 2) + if len(parts) != 2 { + return 0, "", errors.New("invalid session cookie format") + } + + userID, err := util.ConvertStringToInt32(parts[0]) + if err != nil { + return 0, "", errors.Errorf("invalid user ID in session cookie: %v", err) + } + + return userID, parts[1], nil +} + +// validateUserSession checks if a session exists and is still valid using sliding expiration. +func (*FileServerService) validateUserSession(sessionID string, userSessions []*storepb.SessionsUserSetting_Session) bool { + for _, session := range userSessions { + if sessionID == session.SessionId { + // Use sliding expiration: check if last_accessed_time + 14 days > current_time + if session.LastAccessedTime != nil { + expirationTime := session.LastAccessedTime.AsTime().Add(apiv1.SessionSlidingDuration) + if expirationTime.Before(time.Now()) { + return false + } + } + return true + } + } + return false +} + +// validateAccessToken checks if the provided JWT token exists in the user's access tokens list. +func (*FileServerService) validateAccessToken(accessTokenString string, userAccessTokens []*storepb.AccessTokensUserSetting_AccessToken) bool { + for _, userAccessToken := range userAccessTokens { + if accessTokenString == userAccessToken.AccessToken { + return true + } + } + return false +} + +// isImageType checks if the mime type is an image that supports thumbnails. +func (*FileServerService) isImageType(mimeType string) bool { + return mimeType == "image/png" || mimeType == "image/jpeg" +} + +// getAttachmentBlob retrieves the binary content of an attachment from storage. +func (s *FileServerService) getAttachmentBlob(attachment *store.Attachment) ([]byte, error) { + // For local storage, read the file from the local disk. + if attachment.StorageType == storepb.AttachmentStorageType_LOCAL { + attachmentPath := filepath.FromSlash(attachment.Reference) + if !filepath.IsAbs(attachmentPath) { + attachmentPath = filepath.Join(s.Profile.Data, attachmentPath) + } + + file, err := os.Open(attachmentPath) + if err != nil { + if os.IsNotExist(err) { + return nil, errors.Wrap(err, "file not found") + } + return nil, errors.Wrap(err, "failed to open the file") + } + defer file.Close() + blob, err := io.ReadAll(file) + if err != nil { + return nil, errors.Wrap(err, "failed to read the file") + } + return blob, nil + } + // For S3 storage, download the file from S3. + if attachment.StorageType == storepb.AttachmentStorageType_S3 { + if attachment.Payload == nil { + return nil, errors.New("attachment payload is missing") + } + s3Object := attachment.Payload.GetS3Object() + if s3Object == nil { + return nil, errors.New("S3 object payload is missing") + } + if s3Object.S3Config == nil { + return nil, errors.New("S3 config is missing") + } + if s3Object.Key == "" { + return nil, errors.New("S3 object key is missing") + } + + s3Client, err := s3.NewClient(context.Background(), s3Object.S3Config) + if err != nil { + return nil, errors.Wrap(err, "failed to create S3 client") + } + + blob, err := s3Client.GetObject(context.Background(), s3Object.Key) + if err != nil { + return nil, errors.Wrap(err, "failed to get object from S3") + } + return blob, nil + } + // For database storage, return the blob from the database. + return attachment.Blob, nil +} + +// getOrGenerateThumbnail returns the thumbnail image of the attachment. +// Uses semaphore to limit concurrent thumbnail generation and prevent memory exhaustion. +func (s *FileServerService) getOrGenerateThumbnail(ctx context.Context, attachment *store.Attachment) ([]byte, error) { + thumbnailCacheFolder := filepath.Join(s.Profile.Data, ThumbnailCacheFolder) + if err := os.MkdirAll(thumbnailCacheFolder, os.ModePerm); err != nil { + return nil, errors.Wrap(err, "failed to create thumbnail cache folder") + } + filePath := filepath.Join(thumbnailCacheFolder, fmt.Sprintf("%d%s", attachment.ID, filepath.Ext(attachment.Filename))) + + // Check if thumbnail already exists + if _, err := os.Stat(filePath); err == nil { + // Thumbnail exists, read and return it + thumbnailFile, err := os.Open(filePath) + if err != nil { + return nil, errors.Wrap(err, "failed to open thumbnail file") + } + defer thumbnailFile.Close() + blob, err := io.ReadAll(thumbnailFile) + if err != nil { + return nil, errors.Wrap(err, "failed to read thumbnail file") + } + return blob, nil + } else if !os.IsNotExist(err) { + return nil, errors.Wrap(err, "failed to check thumbnail image stat") + } + + // Thumbnail doesn't exist, acquire semaphore to limit concurrent generation + if err := s.thumbnailSemaphore.Acquire(ctx, 1); err != nil { + return nil, errors.Wrap(err, "failed to acquire thumbnail generation semaphore") + } + defer s.thumbnailSemaphore.Release(1) + + // Double-check if thumbnail was created while waiting for semaphore + if _, err := os.Stat(filePath); err == nil { + thumbnailFile, err := os.Open(filePath) + if err != nil { + return nil, errors.Wrap(err, "failed to open thumbnail file") + } + defer thumbnailFile.Close() + blob, err := io.ReadAll(thumbnailFile) + if err != nil { + return nil, errors.Wrap(err, "failed to read thumbnail file") + } + return blob, nil + } + + // Generate the thumbnail + blob, err := s.getAttachmentBlob(attachment) + if err != nil { + return nil, errors.Wrap(err, "failed to get attachment blob") + } + + // Decode image - this is memory intensive + img, err := imaging.Decode(bytes.NewReader(blob), imaging.AutoOrientation(true)) + if err != nil { + return nil, errors.Wrap(err, "failed to decode thumbnail image") + } + + // The largest dimension is set to thumbnailMaxSize and the smaller dimension is scaled proportionally. + // Small images are not enlarged. + width := img.Bounds().Dx() + height := img.Bounds().Dy() + var thumbnailWidth, thumbnailHeight int + + // Only resize if the image is larger than thumbnailMaxSize + if max(width, height) > thumbnailMaxSize { + if width >= height { + // Landscape or square - constrain width, maintain aspect ratio for height + thumbnailWidth = thumbnailMaxSize + thumbnailHeight = 0 + } else { + // Portrait - constrain height, maintain aspect ratio for width + thumbnailWidth = 0 + thumbnailHeight = thumbnailMaxSize + } + } else { + // Keep original dimensions for small images + thumbnailWidth = width + thumbnailHeight = height + } + + // Resize the image to the calculated dimensions. + thumbnailImage := imaging.Resize(img, thumbnailWidth, thumbnailHeight, imaging.Lanczos) + + // Save thumbnail to disk + if err := imaging.Save(thumbnailImage, filePath); err != nil { + return nil, errors.Wrap(err, "failed to save thumbnail file") + } + + // Read the saved thumbnail and return it + thumbnailFile, err := os.Open(filePath) + if err != nil { + return nil, errors.Wrap(err, "failed to open thumbnail file") + } + defer thumbnailFile.Close() + thumbnailBlob, err := io.ReadAll(thumbnailFile) + if err != nil { + return nil, errors.Wrap(err, "failed to read thumbnail file") + } + return thumbnailBlob, nil +} diff --git a/server/server.go b/server/server.go index da142fd06..ace7415c1 100644 --- a/server/server.go +++ b/server/server.go @@ -22,6 +22,7 @@ import ( "github.com/usememos/memos/internal/profile" storepb "github.com/usememos/memos/proto/gen/store" apiv1 "github.com/usememos/memos/server/router/api/v1" + "github.com/usememos/memos/server/router/fileserver" "github.com/usememos/memos/server/router/frontend" "github.com/usememos/memos/server/router/rss" "github.com/usememos/memos/server/runner/s3presign" @@ -87,6 +88,11 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store apiV1Service := apiv1.NewAPIV1Service(s.Secret, profile, store, grpcServer) + // Register HTTP file server routes BEFORE gRPC-Gateway to ensure proper range request handling for Safari. + // This uses native HTTP serving (http.ServeContent) instead of gRPC for video/audio files. + fileServerService := fileserver.NewFileServerService(s.Profile, s.Store, s.Secret) + fileServerService.RegisterRoutes(echoServer) + // Create and register RSS routes (needs markdown service from apiV1Service). rss.NewRSSService(s.Profile, s.Store, apiV1Service.MarkdownService).RegisterRoutes(rootGroup) // Register gRPC gateway as api v1. diff --git a/web/src/types/proto/api/v1/attachment_service.ts b/web/src/types/proto/api/v1/attachment_service.ts index 4e58480f6..0e536a94b 100644 --- a/web/src/types/proto/api/v1/attachment_service.ts +++ b/web/src/types/proto/api/v1/attachment_service.ts @@ -6,7 +6,6 @@ /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HttpBody } from "../../google/api/httpbody"; import { Empty } from "../../google/protobuf/empty"; import { FieldMask } from "../../google/protobuf/field_mask"; import { Timestamp } from "../../google/protobuf/timestamp"; @@ -99,18 +98,6 @@ export interface GetAttachmentRequest { name: string; } -export interface GetAttachmentBinaryRequest { - /** - * Required. The attachment name of the attachment. - * Format: attachments/{attachment} - */ - name: string; - /** The filename of the attachment. Mainly used for downloading. */ - filename: string; - /** Optional. A flag indicating if the thumbnail version of the attachment should be returned. */ - thumbnail: boolean; -} - export interface UpdateAttachmentRequest { /** Required. The attachment which replaces the attachment on the server. */ attachment?: @@ -525,76 +512,6 @@ export const GetAttachmentRequest: MessageFns = { }, }; -function createBaseGetAttachmentBinaryRequest(): GetAttachmentBinaryRequest { - return { name: "", filename: "", thumbnail: false }; -} - -export const GetAttachmentBinaryRequest: MessageFns = { - encode(message: GetAttachmentBinaryRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.name !== "") { - writer.uint32(10).string(message.name); - } - if (message.filename !== "") { - writer.uint32(18).string(message.filename); - } - if (message.thumbnail !== false) { - writer.uint32(24).bool(message.thumbnail); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): GetAttachmentBinaryRequest { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGetAttachmentBinaryRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.name = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.filename = reader.string(); - continue; - } - case 3: { - if (tag !== 24) { - break; - } - - message.thumbnail = reader.bool(); - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - create(base?: DeepPartial): GetAttachmentBinaryRequest { - return GetAttachmentBinaryRequest.fromPartial(base ?? {}); - }, - fromPartial(object: DeepPartial): GetAttachmentBinaryRequest { - const message = createBaseGetAttachmentBinaryRequest(); - message.name = object.name ?? ""; - message.filename = object.filename ?? ""; - message.thumbnail = object.thumbnail ?? false; - return message; - }, -}; - function createBaseUpdateAttachmentRequest(): UpdateAttachmentRequest { return { attachment: undefined, updateMask: undefined }; } @@ -843,90 +760,6 @@ export const AttachmentServiceDefinition = { }, }, }, - /** GetAttachmentBinary returns a attachment binary by name. */ - getAttachmentBinary: { - name: "GetAttachmentBinary", - requestType: GetAttachmentBinaryRequest, - requestStream: false, - responseType: HttpBody, - responseStream: false, - options: { - _unknownFields: { - 8410: [ - new Uint8Array([ - 23, - 110, - 97, - 109, - 101, - 44, - 102, - 105, - 108, - 101, - 110, - 97, - 109, - 101, - 44, - 116, - 104, - 117, - 109, - 98, - 110, - 97, - 105, - 108, - ]), - ], - 578365826: [ - new Uint8Array([ - 39, - 18, - 37, - 47, - 102, - 105, - 108, - 101, - 47, - 123, - 110, - 97, - 109, - 101, - 61, - 97, - 116, - 116, - 97, - 99, - 104, - 109, - 101, - 110, - 116, - 115, - 47, - 42, - 125, - 47, - 123, - 102, - 105, - 108, - 101, - 110, - 97, - 109, - 101, - 125, - ]), - ], - }, - }, - }, /** UpdateAttachment updates a attachment. */ updateAttachment: { name: "UpdateAttachment", diff --git a/web/src/types/proto/api/v1/user_service.ts b/web/src/types/proto/api/v1/user_service.ts index 2569af3c4..abc8cb140 100644 --- a/web/src/types/proto/api/v1/user_service.ts +++ b/web/src/types/proto/api/v1/user_service.ts @@ -6,7 +6,6 @@ /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HttpBody } from "../../google/api/httpbody"; import { Empty } from "../../google/protobuf/empty"; import { FieldMask } from "../../google/protobuf/field_mask"; import { Timestamp } from "../../google/protobuf/timestamp"; @@ -189,14 +188,6 @@ export interface DeleteUserRequest { force: boolean; } -export interface GetUserAvatarRequest { - /** - * Required. The resource name of the user. - * Format: users/{user} - */ - name: string; -} - /** User statistics messages */ export interface UserStats { /** @@ -1298,52 +1289,6 @@ export const DeleteUserRequest: MessageFns = { }, }; -function createBaseGetUserAvatarRequest(): GetUserAvatarRequest { - return { name: "" }; -} - -export const GetUserAvatarRequest: MessageFns = { - encode(message: GetUserAvatarRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.name !== "") { - writer.uint32(10).string(message.name); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): GetUserAvatarRequest { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGetUserAvatarRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.name = reader.string(); - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - create(base?: DeepPartial): GetUserAvatarRequest { - return GetUserAvatarRequest.fromPartial(base ?? {}); - }, - fromPartial(object: DeepPartial): GetUserAvatarRequest { - const message = createBaseGetUserAvatarRequest(); - message.name = object.name ?? ""; - return message; - }, -}; - function createBaseUserStats(): UserStats { return { name: "", @@ -3885,55 +3830,6 @@ export const UserServiceDefinition = { }, }, }, - /** GetUserAvatar gets the avatar of a user. */ - getUserAvatar: { - name: "GetUserAvatar", - requestType: GetUserAvatarRequest, - requestStream: false, - responseType: HttpBody, - responseStream: false, - options: { - _unknownFields: { - 8410: [new Uint8Array([4, 110, 97, 109, 101])], - 578365826: [ - new Uint8Array([ - 31, - 18, - 29, - 47, - 97, - 112, - 105, - 47, - 118, - 49, - 47, - 123, - 110, - 97, - 109, - 101, - 61, - 117, - 115, - 101, - 114, - 115, - 47, - 42, - 125, - 47, - 97, - 118, - 97, - 116, - 97, - 114, - ]), - ], - }, - }, - }, /** ListAllUserStats returns statistics for all users. */ listAllUserStats: { name: "ListAllUserStats", diff --git a/web/src/types/proto/google/api/httpbody.ts b/web/src/types/proto/google/api/httpbody.ts deleted file mode 100644 index 1c4ac74b7..000000000 --- a/web/src/types/proto/google/api/httpbody.ts +++ /dev/null @@ -1,152 +0,0 @@ -// Code generated by protoc-gen-ts_proto. DO NOT EDIT. -// versions: -// protoc-gen-ts_proto v2.6.1 -// protoc unknown -// source: google/api/httpbody.proto - -/* eslint-disable */ -import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Any } from "../protobuf/any"; - -export const protobufPackage = "google.api"; - -/** - * Message that represents an arbitrary HTTP body. It should only be used for - * payload formats that can't be represented as JSON, such as raw binary or - * an HTML page. - * - * This message can be used both in streaming and non-streaming API methods in - * the request as well as the response. - * - * It can be used as a top-level request field, which is convenient if one - * wants to extract parameters from either the URL or HTTP template into the - * request fields and also want access to the raw HTTP body. - * - * Example: - * - * message GetResourceRequest { - * // A unique request id. - * string request_id = 1; - * - * // The raw HTTP body is bound to this field. - * google.api.HttpBody http_body = 2; - * - * } - * - * service ResourceService { - * rpc GetResource(GetResourceRequest) - * returns (google.api.HttpBody); - * rpc UpdateResource(google.api.HttpBody) - * returns (google.protobuf.Empty); - * - * } - * - * Example with streaming methods: - * - * service CaldavService { - * rpc GetCalendar(stream google.api.HttpBody) - * returns (stream google.api.HttpBody); - * rpc UpdateCalendar(stream google.api.HttpBody) - * returns (stream google.api.HttpBody); - * - * } - * - * Use of this type only changes how the request and response bodies are - * handled, all other features will continue to work unchanged. - */ -export interface HttpBody { - /** The HTTP Content-Type header value specifying the content type of the body. */ - contentType: string; - /** The HTTP request/response body as raw binary. */ - data: Uint8Array; - /** - * Application specific response metadata. Must be set in the first response - * for streaming APIs. - */ - extensions: Any[]; -} - -function createBaseHttpBody(): HttpBody { - return { contentType: "", data: new Uint8Array(0), extensions: [] }; -} - -export const HttpBody: MessageFns = { - encode(message: HttpBody, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.contentType !== "") { - writer.uint32(10).string(message.contentType); - } - if (message.data.length !== 0) { - writer.uint32(18).bytes(message.data); - } - for (const v of message.extensions) { - Any.encode(v!, writer.uint32(26).fork()).join(); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): HttpBody { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseHttpBody(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.contentType = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.data = reader.bytes(); - continue; - } - case 3: { - if (tag !== 26) { - break; - } - - message.extensions.push(Any.decode(reader, reader.uint32())); - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - create(base?: DeepPartial): HttpBody { - return HttpBody.fromPartial(base ?? {}); - }, - fromPartial(object: DeepPartial): HttpBody { - const message = createBaseHttpBody(); - message.contentType = object.contentType ?? ""; - message.data = object.data ?? new Uint8Array(0); - message.extensions = object.extensions?.map((e) => Any.fromPartial(e)) || []; - return message; - }, -}; - -type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; - -export type DeepPartial = T extends Builtin ? T - : T extends globalThis.Array ? globalThis.Array> - : T extends ReadonlyArray ? ReadonlyArray> - : T extends {} ? { [K in keyof T]?: DeepPartial } - : Partial; - -export interface MessageFns { - encode(message: T, writer?: BinaryWriter): BinaryWriter; - decode(input: BinaryReader | Uint8Array, length?: number): T; - create(base?: DeepPartial): T; - fromPartial(object: DeepPartial): T; -} diff --git a/web/src/types/proto/google/protobuf/any.ts b/web/src/types/proto/google/protobuf/any.ts deleted file mode 100644 index 278afc8f0..000000000 --- a/web/src/types/proto/google/protobuf/any.ts +++ /dev/null @@ -1,206 +0,0 @@ -// Code generated by protoc-gen-ts_proto. DO NOT EDIT. -// versions: -// protoc-gen-ts_proto v2.6.1 -// protoc unknown -// source: google/protobuf/any.proto - -/* eslint-disable */ -import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; - -export const protobufPackage = "google.protobuf"; - -/** - * `Any` contains an arbitrary serialized protocol buffer message along with a - * URL that describes the type of the serialized message. - * - * Protobuf library provides support to pack/unpack Any values in the form - * of utility functions or additional generated methods of the Any type. - * - * Example 1: Pack and unpack a message in C++. - * - * Foo foo = ...; - * Any any; - * any.PackFrom(foo); - * ... - * if (any.UnpackTo(&foo)) { - * ... - * } - * - * Example 2: Pack and unpack a message in Java. - * - * Foo foo = ...; - * Any any = Any.pack(foo); - * ... - * if (any.is(Foo.class)) { - * foo = any.unpack(Foo.class); - * } - * // or ... - * if (any.isSameTypeAs(Foo.getDefaultInstance())) { - * foo = any.unpack(Foo.getDefaultInstance()); - * } - * - * Example 3: Pack and unpack a message in Python. - * - * foo = Foo(...) - * any = Any() - * any.Pack(foo) - * ... - * if any.Is(Foo.DESCRIPTOR): - * any.Unpack(foo) - * ... - * - * Example 4: Pack and unpack a message in Go - * - * foo := &pb.Foo{...} - * any, err := anypb.New(foo) - * if err != nil { - * ... - * } - * ... - * foo := &pb.Foo{} - * if err := any.UnmarshalTo(foo); err != nil { - * ... - * } - * - * The pack methods provided by protobuf library will by default use - * 'type.googleapis.com/full.type.name' as the type URL and the unpack - * methods only use the fully qualified type name after the last '/' - * in the type URL, for example "foo.bar.com/x/y.z" will yield type - * name "y.z". - * - * JSON - * ==== - * The JSON representation of an `Any` value uses the regular - * representation of the deserialized, embedded message, with an - * additional field `@type` which contains the type URL. Example: - * - * package google.profile; - * message Person { - * string first_name = 1; - * string last_name = 2; - * } - * - * { - * "@type": "type.googleapis.com/google.profile.Person", - * "firstName": , - * "lastName": - * } - * - * If the embedded message type is well-known and has a custom JSON - * representation, that representation will be embedded adding a field - * `value` which holds the custom JSON in addition to the `@type` - * field. Example (for message [google.protobuf.Duration][]): - * - * { - * "@type": "type.googleapis.com/google.protobuf.Duration", - * "value": "1.212s" - * } - */ -export interface Any { - /** - * A URL/resource name that uniquely identifies the type of the serialized - * protocol buffer message. This string must contain at least - * one "/" character. The last segment of the URL's path must represent - * the fully qualified name of the type (as in - * `path/google.protobuf.Duration`). The name should be in a canonical form - * (e.g., leading "." is not accepted). - * - * In practice, teams usually precompile into the binary all types that they - * expect it to use in the context of Any. However, for URLs which use the - * scheme `http`, `https`, or no scheme, one can optionally set up a type - * server that maps type URLs to message definitions as follows: - * - * * If no scheme is provided, `https` is assumed. - * * An HTTP GET on the URL must yield a [google.protobuf.Type][] - * value in binary format, or produce an error. - * * Applications are allowed to cache lookup results based on the - * URL, or have them precompiled into a binary to avoid any - * lookup. Therefore, binary compatibility needs to be preserved - * on changes to types. (Use versioned type names to manage - * breaking changes.) - * - * Note: this functionality is not currently available in the official - * protobuf release, and it is not used for type URLs beginning with - * type.googleapis.com. As of May 2023, there are no widely used type server - * implementations and no plans to implement one. - * - * Schemes other than `http`, `https` (or the empty scheme) might be - * used with implementation specific semantics. - */ - typeUrl: string; - /** Must be a valid serialized protocol buffer of the above specified type. */ - value: Uint8Array; -} - -function createBaseAny(): Any { - return { typeUrl: "", value: new Uint8Array(0) }; -} - -export const Any: MessageFns = { - encode(message: Any, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.typeUrl !== "") { - writer.uint32(10).string(message.typeUrl); - } - if (message.value.length !== 0) { - writer.uint32(18).bytes(message.value); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): Any { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseAny(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.typeUrl = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.value = reader.bytes(); - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - create(base?: DeepPartial): Any { - return Any.fromPartial(base ?? {}); - }, - fromPartial(object: DeepPartial): Any { - const message = createBaseAny(); - message.typeUrl = object.typeUrl ?? ""; - message.value = object.value ?? new Uint8Array(0); - return message; - }, -}; - -type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; - -export type DeepPartial = T extends Builtin ? T - : T extends globalThis.Array ? globalThis.Array> - : T extends ReadonlyArray ? ReadonlyArray> - : T extends {} ? { [K in keyof T]?: DeepPartial } - : Partial; - -export interface MessageFns { - encode(message: T, writer?: BinaryWriter): BinaryWriter; - decode(input: BinaryReader | Uint8Array, length?: number): T; - create(base?: DeepPartial): T; - fromPartial(object: DeepPartial): T; -}