fix: get user by username

pull/4966/head
johnnyjoy 3 months ago
parent fa2fa8a5d7
commit 506b477d50

@ -36,6 +36,11 @@ var MemoFilterCELAttributes = []cel.EnvOption{
), ),
} }
// UserFilterCELAttributes are the CEL attributes for user.
var UserFilterCELAttributes = []cel.EnvOption{
cel.Variable("username", cel.StringType),
}
// Parse parses the filter string and returns the parsed expression. // Parse parses the filter string and returns the parsed expression.
// The filter string should be a CEL expression. // The filter string should be a CEL expression.
func Parse(filter string, opts ...cel.EnvOption) (expr *exprv1.ParsedExpr, err error) { func Parse(filter string, opts ...cel.EnvOption) (expr *exprv1.ParsedExpr, err error) {

@ -50,12 +50,6 @@ service UserService {
option (google.api.method_signature) = "name"; option (google.api.method_signature) = "name";
} }
// SearchUsers searches for users based on query.
rpc SearchUsers(SearchUsersRequest) returns (SearchUsersResponse) {
option (google.api.http) = {get: "/api/v1/users:search"};
option (google.api.method_signature) = "query";
}
// GetUserAvatar gets the avatar of a user. // GetUserAvatar gets the avatar of a user.
rpc GetUserAvatar(GetUserAvatarRequest) returns (google.api.HttpBody) { rpc GetUserAvatar(GetUserAvatarRequest) returns (google.api.HttpBody) {
option (google.api.http) = {get: "/api/v1/{name=users/*}/avatar"}; option (google.api.http) = {get: "/api/v1/{name=users/*}/avatar"};
@ -231,12 +225,8 @@ message ListUsersRequest {
// Supported fields: username, email, role, state, create_time, update_time // Supported fields: username, email, role, state, create_time, update_time
string filter = 3 [(google.api.field_behavior) = OPTIONAL]; string filter = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. The order to sort results by.
// Example: "create_time desc" or "username asc"
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
// Optional. If true, show deleted users in the response. // Optional. If true, show deleted users in the response.
bool show_deleted = 5 [(google.api.field_behavior) = OPTIONAL]; bool show_deleted = 4 [(google.api.field_behavior) = OPTIONAL];
} }
message ListUsersResponse { message ListUsersResponse {
@ -307,28 +297,6 @@ message DeleteUserRequest {
bool force = 2 [(google.api.field_behavior) = OPTIONAL]; bool force = 2 [(google.api.field_behavior) = OPTIONAL];
} }
message SearchUsersRequest {
// Required. The search query.
string query = 1 [(google.api.field_behavior) = REQUIRED];
// Optional. The maximum number of users to return.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token for pagination.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
message SearchUsersResponse {
// The list of users matching the search query.
repeated User users = 1;
// A token for the next page of results.
string next_page_token = 2;
// The total count of matching users.
int32 total_size = 3;
}
message GetUserAvatarRequest { message GetUserAvatarRequest {
// Required. The resource name of the user. // Required. The resource name of the user.
// Format: users/{user} // Format: users/{user}

File diff suppressed because it is too large Load Diff

@ -298,41 +298,6 @@ func local_request_UserService_DeleteUser_0(ctx context.Context, marshaler runti
return msg, metadata, err return msg, metadata, err
} }
var filter_UserService_SearchUsers_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
func request_UserService_SearchUsers_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq SearchUsersRequest
metadata runtime.ServerMetadata
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_SearchUsers_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.SearchUsers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_UserService_SearchUsers_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq SearchUsersRequest
metadata runtime.ServerMetadata
)
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_SearchUsers_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.SearchUsers(ctx, &protoReq)
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) { 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 ( var (
protoReq GetUserAvatarRequest protoReq GetUserAvatarRequest
@ -1144,26 +1109,6 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
} }
forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodGet, pattern_UserService_SearchUsers_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/SearchUsers", runtime.WithHTTPPathPattern("/api/v1/users:search"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_UserService_SearchUsers_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_SearchUsers_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) { 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()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
@ -1589,23 +1534,6 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
} }
forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_UserService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodGet, pattern_UserService_SearchUsers_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/SearchUsers", runtime.WithHTTPPathPattern("/api/v1/users:search"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_UserService_SearchUsers_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_SearchUsers_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) { 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()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
@ -1870,7 +1798,6 @@ var (
pattern_UserService_CreateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, "")) 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_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_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_SearchUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, "search"))
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_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_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_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"))
@ -1894,7 +1821,6 @@ var (
forward_UserService_CreateUser_0 = runtime.ForwardResponseMessage forward_UserService_CreateUser_0 = runtime.ForwardResponseMessage
forward_UserService_UpdateUser_0 = runtime.ForwardResponseMessage forward_UserService_UpdateUser_0 = runtime.ForwardResponseMessage
forward_UserService_DeleteUser_0 = runtime.ForwardResponseMessage forward_UserService_DeleteUser_0 = runtime.ForwardResponseMessage
forward_UserService_SearchUsers_0 = runtime.ForwardResponseMessage
forward_UserService_GetUserAvatar_0 = runtime.ForwardResponseMessage forward_UserService_GetUserAvatar_0 = runtime.ForwardResponseMessage
forward_UserService_ListAllUserStats_0 = runtime.ForwardResponseMessage forward_UserService_ListAllUserStats_0 = runtime.ForwardResponseMessage
forward_UserService_GetUserStats_0 = runtime.ForwardResponseMessage forward_UserService_GetUserStats_0 = runtime.ForwardResponseMessage

@ -26,7 +26,6 @@ const (
UserService_CreateUser_FullMethodName = "/memos.api.v1.UserService/CreateUser" UserService_CreateUser_FullMethodName = "/memos.api.v1.UserService/CreateUser"
UserService_UpdateUser_FullMethodName = "/memos.api.v1.UserService/UpdateUser" UserService_UpdateUser_FullMethodName = "/memos.api.v1.UserService/UpdateUser"
UserService_DeleteUser_FullMethodName = "/memos.api.v1.UserService/DeleteUser" UserService_DeleteUser_FullMethodName = "/memos.api.v1.UserService/DeleteUser"
UserService_SearchUsers_FullMethodName = "/memos.api.v1.UserService/SearchUsers"
UserService_GetUserAvatar_FullMethodName = "/memos.api.v1.UserService/GetUserAvatar" UserService_GetUserAvatar_FullMethodName = "/memos.api.v1.UserService/GetUserAvatar"
UserService_ListAllUserStats_FullMethodName = "/memos.api.v1.UserService/ListAllUserStats" UserService_ListAllUserStats_FullMethodName = "/memos.api.v1.UserService/ListAllUserStats"
UserService_GetUserStats_FullMethodName = "/memos.api.v1.UserService/GetUserStats" UserService_GetUserStats_FullMethodName = "/memos.api.v1.UserService/GetUserStats"
@ -58,8 +57,6 @@ type UserServiceClient interface {
UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error) UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error)
// DeleteUser deletes a user. // DeleteUser deletes a user.
DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// SearchUsers searches for users based on query.
SearchUsers(ctx context.Context, in *SearchUsersRequest, opts ...grpc.CallOption) (*SearchUsersResponse, error)
// GetUserAvatar gets the avatar of a user. // GetUserAvatar gets the avatar of a user.
GetUserAvatar(ctx context.Context, in *GetUserAvatarRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) GetUserAvatar(ctx context.Context, in *GetUserAvatarRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error)
// ListAllUserStats returns statistics for all users. // ListAllUserStats returns statistics for all users.
@ -150,16 +147,6 @@ func (c *userServiceClient) DeleteUser(ctx context.Context, in *DeleteUserReques
return out, nil return out, nil
} }
func (c *userServiceClient) SearchUsers(ctx context.Context, in *SearchUsersRequest, opts ...grpc.CallOption) (*SearchUsersResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SearchUsersResponse)
err := c.cc.Invoke(ctx, UserService_SearchUsers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) GetUserAvatar(ctx context.Context, in *GetUserAvatarRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) { func (c *userServiceClient) GetUserAvatar(ctx context.Context, in *GetUserAvatarRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(httpbody.HttpBody) out := new(httpbody.HttpBody)
@ -324,8 +311,6 @@ type UserServiceServer interface {
UpdateUser(context.Context, *UpdateUserRequest) (*User, error) UpdateUser(context.Context, *UpdateUserRequest) (*User, error)
// DeleteUser deletes a user. // DeleteUser deletes a user.
DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error)
// SearchUsers searches for users based on query.
SearchUsers(context.Context, *SearchUsersRequest) (*SearchUsersResponse, error)
// GetUserAvatar gets the avatar of a user. // GetUserAvatar gets the avatar of a user.
GetUserAvatar(context.Context, *GetUserAvatarRequest) (*httpbody.HttpBody, error) GetUserAvatar(context.Context, *GetUserAvatarRequest) (*httpbody.HttpBody, error)
// ListAllUserStats returns statistics for all users. // ListAllUserStats returns statistics for all users.
@ -381,9 +366,6 @@ func (UnimplementedUserServiceServer) UpdateUser(context.Context, *UpdateUserReq
func (UnimplementedUserServiceServer) DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) { func (UnimplementedUserServiceServer) DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented") return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented")
} }
func (UnimplementedUserServiceServer) SearchUsers(context.Context, *SearchUsersRequest) (*SearchUsersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SearchUsers not implemented")
}
func (UnimplementedUserServiceServer) GetUserAvatar(context.Context, *GetUserAvatarRequest) (*httpbody.HttpBody, error) { func (UnimplementedUserServiceServer) GetUserAvatar(context.Context, *GetUserAvatarRequest) (*httpbody.HttpBody, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUserAvatar not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetUserAvatar not implemented")
} }
@ -540,24 +522,6 @@ func _UserService_DeleteUser_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _UserService_SearchUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SearchUsersRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).SearchUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_SearchUsers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).SearchUsers(ctx, req.(*SearchUsersRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_GetUserAvatar_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _UserService_GetUserAvatar_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUserAvatarRequest) in := new(GetUserAvatarRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@ -855,10 +819,6 @@ var UserService_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteUser", MethodName: "DeleteUser",
Handler: _UserService_DeleteUser_Handler, Handler: _UserService_DeleteUser_Handler,
}, },
{
MethodName: "SearchUsers",
Handler: _UserService_SearchUsers_Handler,
},
{ {
MethodName: "GetUserAvatar", MethodName: "GetUserAvatar",
Handler: _UserService_GetUserAvatar_Handler, Handler: _UserService_GetUserAvatar_Handler,

@ -15,19 +15,13 @@ paths:
parameters: parameters:
- name: pageSize - name: pageSize
in: query in: query
description: |- description: "The maximum number of activities to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 100 activities will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
The maximum number of activities to return.
The service may return fewer than this value.
If unspecified, at most 100 activities will be returned.
The maximum value is 1000; values above 1000 will be coerced to 1000.
schema: schema:
type: integer type: integer
format: int32 format: int32
- name: pageToken - name: pageToken
in: query in: query
description: |- description: "A page token, received from a previous `ListActivities` call.\r\n Provide this to retrieve the subsequent page."
A page token, received from a previous `ListActivities` call.
Provide this to retrieve the subsequent page.
schema: schema:
type: string type: string
responses: responses:
@ -78,35 +72,23 @@ paths:
parameters: parameters:
- name: pageSize - name: pageSize
in: query in: query
description: |- description: "Optional. The maximum number of attachments to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 50 attachments will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
Optional. The maximum number of attachments to return.
The service may return fewer than this value.
If unspecified, at most 50 attachments will be returned.
The maximum value is 1000; values above 1000 will be coerced to 1000.
schema: schema:
type: integer type: integer
format: int32 format: int32
- name: pageToken - name: pageToken
in: query in: query
description: |- description: "Optional. A page token, received from a previous `ListAttachments` call.\r\n Provide this to retrieve the subsequent page."
Optional. A page token, received from a previous `ListAttachments` call.
Provide this to retrieve the subsequent page.
schema: schema:
type: string type: string
- name: filter - name: filter
in: query in: query
description: |- description: "Optional. Filter to apply to the list results.\r\n Example: \"type=image/png\" or \"filename:*.jpg\"\r\n Supported operators: =, !=, <, <=, >, >=, :\r\n Supported fields: filename, type, size, create_time, memo"
Optional. Filter to apply to the list results.
Example: "type=image/png" or "filename:*.jpg"
Supported operators: =, !=, <, <=, >, >=, :
Supported fields: filename, type, size, create_time, memo
schema: schema:
type: string type: string
- name: orderBy - name: orderBy
in: query in: query
description: |- description: "Optional. The order to sort results by.\r\n Example: \"create_time desc\" or \"filename asc\""
Optional. The order to sort results by.
Example: "create_time desc" or "filename asc"
schema: schema:
type: string type: string
responses: responses:
@ -130,9 +112,7 @@ paths:
parameters: parameters:
- name: attachmentId - name: attachmentId
in: query in: query
description: |- description: "Optional. The attachment ID to use for this attachment.\r\n If empty, a unique ID will be generated."
Optional. The attachment ID to use for this attachment.
If empty, a unique ID will be generated.
schema: schema:
type: string type: string
requestBody: requestBody:
@ -243,9 +223,7 @@ paths:
post: post:
tags: tags:
- AuthService - AuthService
description: |- description: "CreateSession authenticates a user and creates a new session.\r\n Returns the authenticated user information upon successful authentication."
CreateSession authenticates a user and creates a new session.
Returns the authenticated user information upon successful authentication.
operationId: AuthService_CreateSession operationId: AuthService_CreateSession
requestBody: requestBody:
content: content:
@ -270,9 +248,7 @@ paths:
get: get:
tags: tags:
- AuthService - AuthService
description: |- description: "GetCurrentSession returns the current active session information.\r\n This method is idempotent and safe, suitable for checking current session state."
GetCurrentSession returns the current active session information.
This method is idempotent and safe, suitable for checking current session state.
operationId: AuthService_GetCurrentSession operationId: AuthService_GetCurrentSession
responses: responses:
"200": "200":
@ -290,9 +266,7 @@ paths:
delete: delete:
tags: tags:
- AuthService - AuthService
description: |- description: "DeleteSession terminates the current user session.\r\n This is an idempotent operation that invalidates the user's authentication."
DeleteSession terminates the current user session.
This is an idempotent operation that invalidates the user's authentication.
operationId: AuthService_DeleteSession operationId: AuthService_DeleteSession
responses: responses:
"200": "200":
@ -331,9 +305,7 @@ paths:
parameters: parameters:
- name: identityProviderId - name: identityProviderId
in: query in: query
description: |- description: "Optional. The ID to use for the identity provider, which will become the final component of the resource name.\r\n If not provided, the system will generate one."
Optional. The ID to use for the identity provider, which will become the final component of the resource name.
If not provided, the system will generate one.
schema: schema:
type: string type: string
requestBody: requestBody:
@ -417,9 +389,7 @@ paths:
type: string type: string
- name: updateMask - name: updateMask
in: query in: query
description: |- description: "Required. The update mask applies to the resource. Only the top level fields of\r\n IdentityProvider are supported."
Required. The update mask applies to the resource. Only the top level fields of
IdentityProvider are supported.
schema: schema:
type: string type: string
format: field-mask format: field-mask
@ -511,9 +481,7 @@ paths:
get: get:
tags: tags:
- MarkdownService - MarkdownService
description: |- description: "GetLinkMetadata returns metadata for a given link.\r\n This is useful for generating link previews."
GetLinkMetadata returns metadata for a given link.
This is useful for generating link previews.
operationId: MarkdownService_GetLinkMetadata operationId: MarkdownService_GetLinkMetadata
parameters: parameters:
- name: link - name: link
@ -538,9 +506,7 @@ paths:
post: post:
tags: tags:
- MarkdownService - MarkdownService
description: |- description: "ParseMarkdown parses the given markdown content and returns a list of nodes.\r\n This is a utility method that transforms markdown text into structured nodes."
ParseMarkdown parses the given markdown content and returns a list of nodes.
This is a utility method that transforms markdown text into structured nodes.
operationId: MarkdownService_ParseMarkdown operationId: MarkdownService_ParseMarkdown
requestBody: requestBody:
content: content:
@ -565,9 +531,7 @@ paths:
post: post:
tags: tags:
- MarkdownService - MarkdownService
description: |- description: "RestoreMarkdownNodes restores the given nodes to markdown content.\r\n This is the inverse operation of ParseMarkdown."
RestoreMarkdownNodes restores the given nodes to markdown content.
This is the inverse operation of ParseMarkdown.
operationId: MarkdownService_RestoreMarkdownNodes operationId: MarkdownService_RestoreMarkdownNodes
requestBody: requestBody:
content: content:
@ -592,9 +556,7 @@ paths:
post: post:
tags: tags:
- MarkdownService - MarkdownService
description: |- description: "StringifyMarkdownNodes stringify the given nodes to plain text content.\r\n This removes all markdown formatting and returns plain text."
StringifyMarkdownNodes stringify the given nodes to plain text content.
This removes all markdown formatting and returns plain text.
operationId: MarkdownService_StringifyMarkdownNodes operationId: MarkdownService_StringifyMarkdownNodes
requestBody: requestBody:
content: content:
@ -624,26 +586,18 @@ paths:
parameters: parameters:
- name: pageSize - name: pageSize
in: query in: query
description: |- description: "Optional. The maximum number of memos to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 50 memos will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
Optional. The maximum number of memos to return.
The service may return fewer than this value.
If unspecified, at most 50 memos will be returned.
The maximum value is 1000; values above 1000 will be coerced to 1000.
schema: schema:
type: integer type: integer
format: int32 format: int32
- name: pageToken - name: pageToken
in: query in: query
description: |- description: "Optional. A page token, received from a previous `ListMemos` call.\r\n Provide this to retrieve the subsequent page."
Optional. A page token, received from a previous `ListMemos` call.
Provide this to retrieve the subsequent page.
schema: schema:
type: string type: string
- name: state - name: state
in: query in: query
description: |- description: "Optional. The state of the memos to list.\r\n Default to `NORMAL`. Set to `ARCHIVED` to list archived memos."
Optional. The state of the memos to list.
Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
schema: schema:
enum: enum:
- STATE_UNSPECIFIED - STATE_UNSPECIFIED
@ -653,18 +607,12 @@ paths:
format: enum format: enum
- name: orderBy - name: orderBy
in: query in: query
description: |- description: "Optional. The order to sort results by.\r\n Default to \"display_time desc\".\r\n Example: \"display_time desc\" or \"create_time asc\""
Optional. The order to sort results by.
Default to "display_time desc".
Example: "display_time desc" or "create_time asc"
schema: schema:
type: string type: string
- name: filter - name: filter
in: query in: query
description: |- description: "Optional. Filter to apply to the list results.\r\n Filter is a CEL expression to filter memos.\r\n Refer to `Shortcut.filter`."
Optional. Filter to apply to the list results.
Filter is a CEL expression to filter memos.
Refer to `Shortcut.filter`.
schema: schema:
type: string type: string
- name: showDeleted - name: showDeleted
@ -693,9 +641,7 @@ paths:
parameters: parameters:
- name: memoId - name: memoId
in: query in: query
description: |- description: "Optional. The memo ID to use for this memo.\r\n If empty, a unique ID will be generated."
Optional. The memo ID to use for this memo.
If empty, a unique ID will be generated.
schema: schema:
type: string type: string
- name: validateOnly - name: validateOnly
@ -742,9 +688,7 @@ paths:
type: string type: string
- name: readMask - name: readMask
in: query in: query
description: |- description: "Optional. The fields to return in the response.\r\n If not specified, all fields are returned."
Optional. The fields to return in the response.
If not specified, all fields are returned.
schema: schema:
type: string type: string
format: field-mask format: field-mask
@ -1207,35 +1151,18 @@ paths:
parameters: parameters:
- name: pageSize - name: pageSize
in: query in: query
description: |- description: "Optional. The maximum number of users to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 50 users will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
Optional. The maximum number of users to return.
The service may return fewer than this value.
If unspecified, at most 50 users will be returned.
The maximum value is 1000; values above 1000 will be coerced to 1000.
schema: schema:
type: integer type: integer
format: int32 format: int32
- name: pageToken - name: pageToken
in: query in: query
description: |- description: "Optional. A page token, received from a previous `ListUsers` call.\r\n Provide this to retrieve the subsequent page."
Optional. A page token, received from a previous `ListUsers` call.
Provide this to retrieve the subsequent page.
schema: schema:
type: string type: string
- name: filter - name: filter
in: query in: query
description: |- description: "Optional. Filter to apply to the list results.\r\n Example: \"state=ACTIVE\" or \"role=USER\" or \"email:@example.com\"\r\n Supported operators: =, !=, <, <=, >, >=, :\r\n Supported fields: username, email, role, state, create_time, update_time"
Optional. Filter to apply to the list results.
Example: "state=ACTIVE" or "role=USER" or "email:@example.com"
Supported operators: =, !=, <, <=, >, >=, :
Supported fields: username, email, role, state, create_time, update_time
schema:
type: string
- name: orderBy
in: query
description: |-
Optional. The order to sort results by.
Example: "create_time desc" or "username asc"
schema: schema:
type: string type: string
- name: showDeleted - name: showDeleted
@ -1264,10 +1191,7 @@ paths:
parameters: parameters:
- name: userId - name: userId
in: query in: query
description: |- description: "Optional. The user ID to use for this user.\r\n If empty, a unique ID will be generated.\r\n Must match the pattern [a-z0-9-]+"
Optional. The user ID to use for this user.
If empty, a unique ID will be generated.
Must match the pattern [a-z0-9-]+
schema: schema:
type: string type: string
- name: validateOnly - name: validateOnly
@ -1277,9 +1201,7 @@ paths:
type: boolean type: boolean
- name: requestId - name: requestId
in: query in: query
description: |- description: "Optional. An idempotency token that can be used to ensure that multiple\r\n requests to create a user have the same result."
Optional. An idempotency token that can be used to ensure that multiple
requests to create a user have the same result.
schema: schema:
type: string type: string
requestBody: requestBody:
@ -1316,9 +1238,7 @@ paths:
type: string type: string
- name: readMask - name: readMask
in: query in: query
description: |- description: "Optional. The fields to return in the response.\r\n If not specified, all fields are returned."
Optional. The fields to return in the response.
If not specified, all fields are returned.
schema: schema:
type: string type: string
format: field-mask format: field-mask
@ -1545,35 +1465,23 @@ paths:
type: string type: string
- name: pageSize - name: pageSize
in: query in: query
description: |- description: "Optional. The maximum number of inboxes to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 50 inboxes will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
Optional. The maximum number of inboxes to return.
The service may return fewer than this value.
If unspecified, at most 50 inboxes will be returned.
The maximum value is 1000; values above 1000 will be coerced to 1000.
schema: schema:
type: integer type: integer
format: int32 format: int32
- name: pageToken - name: pageToken
in: query in: query
description: |- description: "Optional. A page token, received from a previous `ListInboxes` call.\r\n Provide this to retrieve the subsequent page."
Optional. A page token, received from a previous `ListInboxes` call.
Provide this to retrieve the subsequent page.
schema: schema:
type: string type: string
- name: filter - name: filter
in: query in: query
description: |- description: "Optional. Filter to apply to the list results.\r\n Example: \"status=UNREAD\" or \"type=MEMO_COMMENT\"\r\n Supported operators: =, !=\r\n Supported fields: status, type, sender, create_time"
Optional. Filter to apply to the list results.
Example: "status=UNREAD" or "type=MEMO_COMMENT"
Supported operators: =, !=
Supported fields: status, type, sender, create_time
schema: schema:
type: string type: string
- name: orderBy - name: orderBy
in: query in: query
description: |- description: "Optional. The order to sort results by.\r\n Example: \"create_time desc\" or \"status asc\""
Optional. The order to sort results by.
Example: "create_time desc" or "status asc"
schema: schema:
type: string type: string
responses: responses:
@ -1659,19 +1567,13 @@ paths:
type: string type: string
- name: pageSize - name: pageSize
in: query in: query
description: |- description: "Optional. The maximum number of settings to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 50 settings will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
Optional. The maximum number of settings to return.
The service may return fewer than this value.
If unspecified, at most 50 settings will be returned.
The maximum value is 1000; values above 1000 will be coerced to 1000.
schema: schema:
type: integer type: integer
format: int32 format: int32
- name: pageToken - name: pageToken
in: query in: query
description: |- description: "Optional. A page token, received from a previous `ListUserSettings` call.\r\n Provide this to retrieve the subsequent page."
Optional. A page token, received from a previous `ListUserSettings` call.
Provide this to retrieve the subsequent page.
schema: schema:
type: string type: string
responses: responses:
@ -2082,42 +1984,6 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/Status' $ref: '#/components/schemas/Status'
/api/v1/users:search:
get:
tags:
- UserService
description: SearchUsers searches for users based on query.
operationId: UserService_SearchUsers
parameters:
- name: query
in: query
description: Required. The search query.
schema:
type: string
- name: pageSize
in: query
description: Optional. The maximum number of users to return.
schema:
type: integer
format: int32
- name: pageToken
in: query
description: Optional. A page token for pagination.
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/SearchUsersResponse'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users:stats: /api/v1/users:stats:
get: get:
tags: tags:
@ -2262,15 +2128,11 @@ components:
name: name:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The name of the activity.\r\n Format: activities/{id}"
The name of the activity.
Format: activities/{id}
creator: creator:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The name of the creator.\r\n Format: users/{user}"
The name of the creator.
Format: users/{user}
type: type:
readOnly: true readOnly: true
enum: enum:
@ -2305,14 +2167,10 @@ components:
properties: properties:
memo: memo:
type: string type: string
description: |- description: "The memo name of comment.\r\n Format: memos/{memo}"
The memo name of comment.
Format: memos/{memo}
relatedMemo: relatedMemo:
type: string type: string
description: |- description: "The name of related memo.\r\n Format: memos/{memo}"
The name of related memo.
Format: memos/{memo}
description: ActivityMemoCommentPayload represents the payload of a memo comment activity. description: ActivityMemoCommentPayload represents the payload of a memo comment activity.
ActivityPayload: ActivityPayload:
type: object type: object
@ -2329,9 +2187,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The name of the attachment.\r\n Format: attachments/{attachment}"
The name of the attachment.
Format: attachments/{attachment}
createTime: createTime:
readOnly: true readOnly: true
type: string type: string
@ -2357,9 +2213,7 @@ components:
description: Output only. The size of the attachment in bytes. description: Output only. The size of the attachment in bytes.
memo: memo:
type: string type: string
description: |- description: "Optional. The related memo. Refer to `Memo.name`.\r\n Format: memos/{memo}"
Optional. The related memo. Refer to `Memo.name`.
Format: memos/{memo}
AutoLinkNode: AutoLinkNode:
type: object type: object
properties: properties:
@ -2421,14 +2275,10 @@ components:
properties: properties:
username: username:
type: string type: string
description: |- description: "The username to sign in with.\r\n Required field for password-based authentication."
The username to sign in with.
Required field for password-based authentication.
password: password:
type: string type: string
description: |- description: "The password to sign in with.\r\n Required field for password-based authentication."
The password to sign in with.
Required field for password-based authentication.
description: Nested message for password-based authentication credentials. description: Nested message for password-based authentication credentials.
CreateSessionRequest_SSOCredentials: CreateSessionRequest_SSOCredentials:
required: required:
@ -2439,20 +2289,14 @@ components:
properties: properties:
idpId: idpId:
type: integer type: integer
description: |- description: "The ID of the SSO provider.\r\n Required field to identify the SSO provider."
The ID of the SSO provider.
Required field to identify the SSO provider.
format: int32 format: int32
code: code:
type: string type: string
description: |- description: "The authorization code from the SSO provider.\r\n Required field for completing the SSO flow."
The authorization code from the SSO provider.
Required field for completing the SSO flow.
redirectUri: redirectUri:
type: string type: string
description: |- description: "The redirect URI used in the SSO flow.\r\n Required field for security validation."
The redirect URI used in the SSO flow.
Required field for security validation.
description: Nested message for SSO authentication credentials. description: Nested message for SSO authentication credentials.
CreateSessionResponse: CreateSessionResponse:
type: object type: object
@ -2463,9 +2307,7 @@ components:
description: The authenticated user information. description: The authenticated user information.
lastAccessedAt: lastAccessedAt:
type: string type: string
description: |- description: "Last time the session was accessed.\r\n Used for sliding expiration calculation (last_accessed_time + 2 weeks)."
Last time the session was accessed.
Used for sliding expiration calculation (last_accessed_time + 2 weeks).
format: date-time format: date-time
EmbeddedContentNode: EmbeddedContentNode:
type: object type: object
@ -2513,9 +2355,7 @@ components:
$ref: '#/components/schemas/User' $ref: '#/components/schemas/User'
lastAccessedAt: lastAccessedAt:
type: string type: string
description: |- description: "Last time the session was accessed.\r\n Used for sliding expiration calculation (last_accessed_time + 2 weeks)."
Last time the session was accessed.
Used for sliding expiration calculation (last_accessed_time + 2 weeks).
format: date-time format: date-time
GoogleProtobufAny: GoogleProtobufAny:
type: object type: object
@ -2563,9 +2403,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the identity provider.\r\n Format: identityProviders/{idp}"
The resource name of the identity provider.
Format: identityProviders/{idp}
type: type:
enum: enum:
- TYPE_UNSPECIFIED - TYPE_UNSPECIFIED
@ -2600,21 +2438,15 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the inbox.\r\n Format: inboxes/{inbox}"
The resource name of the inbox.
Format: inboxes/{inbox}
sender: sender:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The sender of the inbox notification.\r\n Format: users/{user}"
The sender of the inbox notification.
Format: users/{user}
receiver: receiver:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The receiver of the inbox notification.\r\n Format: users/{user}"
The receiver of the inbox notification.
Format: users/{user}
status: status:
enum: enum:
- STATUS_UNSPECIFIED - STATUS_UNSPECIFIED
@ -2684,10 +2516,7 @@ components:
description: The activities. description: The activities.
nextPageToken: nextPageToken:
type: string type: string
description: |- description: "A token to retrieve the next page of results.\r\n Pass this value in the page_token field in the subsequent call to `ListActivities`\r\n method to retrieve the next page of results."
A token to retrieve the next page of results.
Pass this value in the page_token field in the subsequent call to `ListActivities`
method to retrieve the next page of results.
ListAllUserStatsResponse: ListAllUserStatsResponse:
type: object type: object
properties: properties:
@ -2706,9 +2535,7 @@ components:
description: The list of attachments. description: The list of attachments.
nextPageToken: nextPageToken:
type: string type: string
description: |- description: "A token that can be sent as `page_token` to retrieve the next page.\r\n If this field is omitted, there are no subsequent pages."
A token that can be sent as `page_token` to retrieve the next page.
If this field is omitted, there are no subsequent pages.
totalSize: totalSize:
type: integer type: integer
description: The total count of attachments (may be approximate). description: The total count of attachments (may be approximate).
@ -2731,9 +2558,7 @@ components:
description: The list of inboxes. description: The list of inboxes.
nextPageToken: nextPageToken:
type: string type: string
description: |- description: "A token that can be sent as `page_token` to retrieve the next page.\r\n If this field is omitted, there are no subsequent pages."
A token that can be sent as `page_token` to retrieve the next page.
If this field is omitted, there are no subsequent pages.
totalSize: totalSize:
type: integer type: integer
description: The total count of inboxes (may be approximate). description: The total count of inboxes (may be approximate).
@ -2808,9 +2633,7 @@ components:
description: The list of memos. description: The list of memos.
nextPageToken: nextPageToken:
type: string type: string
description: |- description: "A token that can be sent as `page_token` to retrieve the next page.\r\n If this field is omitted, there are no subsequent pages."
A token that can be sent as `page_token` to retrieve the next page.
If this field is omitted, there are no subsequent pages.
totalSize: totalSize:
type: integer type: integer
description: The total count of memos (may be approximate). description: The total count of memos (may be approximate).
@ -2874,9 +2697,7 @@ components:
description: The list of user settings. description: The list of user settings.
nextPageToken: nextPageToken:
type: string type: string
description: |- description: "A token that can be sent as `page_token` to retrieve the next page.\r\n If this field is omitted, there are no subsequent pages."
A token that can be sent as `page_token` to retrieve the next page.
If this field is omitted, there are no subsequent pages.
totalSize: totalSize:
type: integer type: integer
description: The total count of settings (may be approximate). description: The total count of settings (may be approximate).
@ -2900,9 +2721,7 @@ components:
description: The list of users. description: The list of users.
nextPageToken: nextPageToken:
type: string type: string
description: |- description: "A token that can be sent as `page_token` to retrieve the next page.\r\n If this field is omitted, there are no subsequent pages."
A token that can be sent as `page_token` to retrieve the next page.
If this field is omitted, there are no subsequent pages.
totalSize: totalSize:
type: integer type: integer
description: The total count of users (may be approximate). description: The total count of users (may be approximate).
@ -2940,9 +2759,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the memo.\r\n Format: memos/{memo}, memo is the user defined id or uuid."
The resource name of the memo.
Format: memos/{memo}, memo is the user defined id or uuid.
state: state:
enum: enum:
- STATE_UNSPECIFIED - STATE_UNSPECIFIED
@ -2954,9 +2771,7 @@ components:
creator: creator:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The name of the creator.\r\n Format: users/{user}"
The name of the creator.
Format: users/{user}
createTime: createTime:
readOnly: true readOnly: true
type: string type: string
@ -3022,9 +2837,7 @@ components:
parent: parent:
readOnly: true readOnly: true
type: string type: string
description: |- description: "Output only. The name of the parent memo.\r\n Format: memos/{memo}"
Output only. The name of the parent memo.
Format: memos/{memo}
snippet: snippet:
readOnly: true readOnly: true
type: string type: string
@ -3062,9 +2875,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the memo.\r\n Format: memos/{memo}"
The resource name of the memo.
Format: memos/{memo}
snippet: snippet:
readOnly: true readOnly: true
type: string type: string
@ -3250,21 +3061,14 @@ components:
name: name:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The resource name of the reaction.\r\n Format: reactions/{reaction}"
The resource name of the reaction.
Format: reactions/{reaction}
creator: creator:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The resource name of the creator.\r\n Format: users/{user}"
The resource name of the creator.
Format: users/{user}
contentId: contentId:
type: string type: string
description: |- description: "The resource name of the content.\r\n For memo reactions, this should be the memo's resource name.\r\n Format: memos/{memo}"
The resource name of the content.
For memo reactions, this should be the memo's resource name.
Format: memos/{memo}
reactionType: reactionType:
type: string type: string
description: "Required. The type of reaction (e.g., \"\U0001F44D\", \"❤️\", \"\U0001F604\")." description: "Required. The type of reaction (e.g., \"\U0001F44D\", \"❤️\", \"\U0001F604\")."
@ -3291,9 +3095,7 @@ components:
properties: properties:
parent: parent:
type: string type: string
description: |- description: "Required. The parent, who owns the tags.\r\n Format: memos/{memo}. Use \"memos/-\" to rename all tags."
Required. The parent, who owns the tags.
Format: memos/{memo}. Use "memos/-" to rename all tags.
oldTag: oldTag:
type: string type: string
description: Required. The old tag name to rename. description: Required. The old tag name to rename.
@ -3316,21 +3118,6 @@ components:
markdown: markdown:
type: string type: string
description: The restored markdown content. description: The restored markdown content.
SearchUsersResponse:
type: object
properties:
users:
type: array
items:
$ref: '#/components/schemas/User'
description: The list of users matching the search query.
nextPageToken:
type: string
description: A token for the next page of results.
totalSize:
type: integer
description: The total count of matching users.
format: int32
SetMemoAttachmentsRequest: SetMemoAttachmentsRequest:
required: required:
- name - name
@ -3339,9 +3126,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "Required. The resource name of the memo.\r\n Format: memos/{memo}"
Required. The resource name of the memo.
Format: memos/{memo}
attachments: attachments:
type: array type: array
items: items:
@ -3355,9 +3140,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "Required. The resource name of the memo.\r\n Format: memos/{memo}"
Required. The resource name of the memo.
Format: memos/{memo}
relations: relations:
type: array type: array
items: items:
@ -3370,9 +3153,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the shortcut.\r\n Format: users/{user}/shortcuts/{shortcut}"
The resource name of the shortcut.
Format: users/{user}/shortcuts/{shortcut}
title: title:
type: string type: string
description: The title of the shortcut. description: The title of the shortcut.
@ -3415,9 +3196,7 @@ components:
type: string type: string
usePathStyle: usePathStyle:
type: boolean type: boolean
description: |- description: "S3 configuration for cloud storage backend.\r\n Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/"
S3 configuration for cloud storage backend.
Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/
StrikethroughNode: StrikethroughNode:
type: object type: object
properties: properties:
@ -3515,9 +3294,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "Required. The resource name of the memo.\r\n Format: memos/{memo}"
Required. The resource name of the memo.
Format: memos/{memo}
reaction: reaction:
allOf: allOf:
- $ref: '#/components/schemas/Reaction' - $ref: '#/components/schemas/Reaction'
@ -3531,9 +3308,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the user.\r\n Format: users/{user}"
The resource name of the user.
Format: users/{user}
role: role:
enum: enum:
- ROLE_UNSPECIFIED - ROLE_UNSPECIFIED
@ -3585,9 +3360,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the access token.\r\n Format: users/{user}/accessTokens/{access_token}"
The resource name of the access token.
Format: users/{user}/accessTokens/{access_token}
accessToken: accessToken:
readOnly: true readOnly: true
type: string type: string
@ -3610,9 +3383,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the session.\r\n Format: users/{user}/sessions/{session}"
The resource name of the session.
Format: users/{user}/sessions/{session}
sessionId: sessionId:
readOnly: true readOnly: true
type: string type: string
@ -3625,9 +3396,7 @@ components:
lastAccessedTime: lastAccessedTime:
readOnly: true readOnly: true
type: string type: string
description: |- description: "The timestamp when the session was last accessed.\r\n Used for sliding expiration calculation (last_accessed_time + 2 weeks)."
The timestamp when the session was last accessed.
Used for sliding expiration calculation (last_accessed_time + 2 weeks).
format: date-time format: date-time
clientInfo: clientInfo:
readOnly: true readOnly: true
@ -3657,10 +3426,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The name of the user setting.\r\n Format: users/{user}/settings/{setting}, {setting} is the key for the setting.\r\n For example, \"users/123/settings/GENERAL\" for general settings."
The name of the user setting.
Format: users/{user}/settings/{setting}, {setting} is the key for the setting.
For example, "users/123/settings/GENERAL" for general settings.
generalSetting: generalSetting:
$ref: '#/components/schemas/UserSetting_GeneralSetting' $ref: '#/components/schemas/UserSetting_GeneralSetting'
sessionsSetting: sessionsSetting:
@ -3693,10 +3459,7 @@ components:
description: The default visibility of the memo. description: The default visibility of the memo.
theme: theme:
type: string type: string
description: |- description: "The preferred theme of the user.\r\n This references a CSS file in the web/public/themes/ directory.\r\n If not set, the default theme will be used."
The preferred theme of the user.
This references a CSS file in the web/public/themes/ directory.
If not set, the default theme will be used.
description: General user settings configuration. description: General user settings configuration.
UserSetting_SessionsSetting: UserSetting_SessionsSetting:
type: object type: object
@ -3721,9 +3484,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The resource name of the user whose stats these are.\r\n Format: users/{user}"
The resource name of the user whose stats these are.
Format: users/{user}
memoDisplayTimestamps: memoDisplayTimestamps:
type: array type: array
items: items:
@ -3771,9 +3532,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The name of the webhook.\r\n Format: users/{user}/webhooks/{webhook}"
The name of the webhook.
Format: users/{user}/webhooks/{webhook}
url: url:
type: string type: string
description: The URL to send the webhook to. description: The URL to send the webhook to.
@ -3796,9 +3555,7 @@ components:
properties: properties:
owner: owner:
type: string type: string
description: |- description: "The name of instance owner.\r\n Format: users/{user}"
The name of instance owner.
Format: users/{user}
version: version:
type: string type: string
description: Version is the current version of instance. description: Version is the current version of instance.
@ -3814,9 +3571,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: |- description: "The name of the workspace setting.\r\n Format: workspace/settings/{setting}"
The name of the workspace setting.
Format: workspace/settings/{setting}
generalSetting: generalSetting:
$ref: '#/components/schemas/WorkspaceSetting_GeneralSetting' $ref: '#/components/schemas/WorkspaceSetting_GeneralSetting'
storageSetting: storageSetting:
@ -3829,9 +3584,7 @@ components:
properties: properties:
theme: theme:
type: string type: string
description: |- description: "theme is the name of the selected theme.\r\n This references a CSS file in the web/public/themes/ directory."
theme is the name of the selected theme.
This references a CSS file in the web/public/themes/ directory.
disallowUserRegistration: disallowUserRegistration:
type: boolean type: boolean
description: disallow_user_registration disallows user registration. description: disallow_user_registration disallows user registration.
@ -3850,10 +3603,7 @@ components:
description: custom_profile is the custom profile. description: custom_profile is the custom profile.
weekStartDayOffset: weekStartDayOffset:
type: integer type: integer
description: |- description: "week_start_day_offset is the week start day offset from Sunday.\r\n 0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday\r\n Default is Sunday."
week_start_day_offset is the week start day offset from Sunday.
0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday
Default is Sunday.
format: int32 format: int32
disallowChangeUsername: disallowChangeUsername:
type: boolean type: boolean
@ -3912,9 +3662,7 @@ components:
format: enum format: enum
filepathTemplate: filepathTemplate:
type: string type: string
description: |- description: "The template of file path.\r\n e.g. assets/{timestamp}_{filename}"
The template of file path.
e.g. assets/{timestamp}_{filename}
uploadSizeLimitMb: uploadSizeLimitMb:
type: string type: string
description: The max upload size in megabytes. description: The max upload size in megabytes.

@ -0,0 +1,68 @@
package v1
import (
"testing"
"github.com/usememos/memos/plugin/filter"
)
func TestUserFilterValidation(t *testing.T) {
testCases := []struct {
name string
filter string
expectErr bool
}{
{
name: "valid username filter with equals",
filter: `username == "testuser"`,
expectErr: false,
},
{
name: "valid username filter with contains",
filter: `username.contains("admin")`,
expectErr: false,
},
{
name: "invalid filter - unknown field",
filter: `invalid_field == "test"`,
expectErr: true,
},
{
name: "empty filter",
filter: "",
expectErr: true,
},
{
name: "invalid syntax",
filter: `username ==`,
expectErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Test the filter parsing directly
_, err := filter.Parse(tc.filter, filter.UserFilterCELAttributes...)
if tc.expectErr && err == nil {
t.Errorf("Expected error for filter %q, but got none", tc.filter)
}
if !tc.expectErr && err != nil {
t.Errorf("Expected no error for filter %q, but got: %v", tc.filter, err)
}
})
}
}
func TestUserFilterCELAttributes(t *testing.T) {
// Test that our UserFilterCELAttributes contains the username variable
expectedAttributes := map[string]bool{
"username": true,
}
// This is a basic test to ensure the attributes are defined
// In a real test, you would create a CEL environment and verify the attributes
for attrName := range expectedAttributes {
t.Logf("Expected attribute %s should be available in UserFilterCELAttributes", attrName)
}
}

@ -25,12 +25,13 @@ import (
"github.com/usememos/memos/internal/base" "github.com/usememos/memos/internal/base"
"github.com/usememos/memos/internal/util" "github.com/usememos/memos/internal/util"
"github.com/usememos/memos/plugin/filter"
v1pb "github.com/usememos/memos/proto/gen/api/v1" v1pb "github.com/usememos/memos/proto/gen/api/v1"
storepb "github.com/usememos/memos/proto/gen/store" storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
) )
func (s *APIV1Service) ListUsers(ctx context.Context, _ *v1pb.ListUsersRequest) (*v1pb.ListUsersResponse, error) { func (s *APIV1Service) ListUsers(ctx context.Context, request *v1pb.ListUsersRequest) (*v1pb.ListUsersResponse, error) {
currentUser, err := s.GetCurrentUser(ctx) currentUser, err := s.GetCurrentUser(ctx)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err) return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
@ -39,12 +40,21 @@ func (s *APIV1Service) ListUsers(ctx context.Context, _ *v1pb.ListUsersRequest)
return nil, status.Errorf(codes.PermissionDenied, "permission denied") return nil, status.Errorf(codes.PermissionDenied, "permission denied")
} }
users, err := s.Store.ListUsers(ctx, &store.FindUser{}) userFind := &store.FindUser{}
if request.Filter != "" {
if err := s.validateUserFilter(ctx, request.Filter); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid filter: %v", err)
}
userFind.Filters = append(userFind.Filters, request.Filter)
}
users, err := s.Store.ListUsers(ctx, userFind)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list users: %v", err) return nil, status.Errorf(codes.Internal, "failed to list users: %v", err)
} }
// TODO: Implement proper filtering, ordering, and pagination // TODO: Implement proper ordering, and pagination
// For now, return all users with basic structure // For now, return all users with basic structure
response := &v1pb.ListUsersResponse{ response := &v1pb.ListUsersResponse{
Users: []*v1pb.User{}, Users: []*v1pb.User{},
@ -70,47 +80,7 @@ func (s *APIV1Service) GetUser(ctx context.Context, request *v1pb.GetUserRequest
if user == nil { if user == nil {
return nil, status.Errorf(codes.NotFound, "user not found") return nil, status.Errorf(codes.NotFound, "user not found")
} }
userPb := convertUserFromStore(user) return convertUserFromStore(user), nil
// TODO: Implement read_mask field filtering
// For now, return all fields
return userPb, nil
}
func (s *APIV1Service) SearchUsers(ctx context.Context, request *v1pb.SearchUsersRequest) (*v1pb.SearchUsersResponse, error) {
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
}
if currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Search users by username, email, or display name
users, err := s.Store.ListUsers(ctx, &store.FindUser{})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list users: %v", err)
}
var filteredUsers []*store.User
query := strings.ToLower(request.Query)
for _, user := range users {
if strings.Contains(strings.ToLower(user.Username), query) ||
strings.Contains(strings.ToLower(user.Email), query) ||
strings.Contains(strings.ToLower(user.Nickname), query) {
filteredUsers = append(filteredUsers, user)
}
}
response := &v1pb.SearchUsersResponse{
Users: []*v1pb.User{},
TotalSize: int32(len(filteredUsers)),
}
for _, user := range filteredUsers {
response.Users = append(response.Users, convertUserFromStore(user))
}
return response, nil
} }
func (s *APIV1Service) GetUserAvatar(ctx context.Context, request *v1pb.GetUserAvatarRequest) (*httpbody.HttpBody, error) { func (s *APIV1Service) GetUserAvatar(ctx context.Context, request *v1pb.GetUserAvatarRequest) (*httpbody.HttpBody, error) {
@ -1316,3 +1286,37 @@ func extractWebhookIDFromName(name string) string {
} }
return "" return ""
} }
// validateUserFilter validates the user filter string.
func (s *APIV1Service) validateUserFilter(_ context.Context, filterStr string) error {
if filterStr == "" {
return errors.New("filter cannot be empty")
}
// Validate the filter.
parsedExpr, err := filter.Parse(filterStr, filter.UserFilterCELAttributes...)
if err != nil {
return errors.Wrap(err, "failed to parse filter")
}
convertCtx := filter.NewConvertContext()
// Determine the dialect based on the actual database driver
var dialect filter.SQLDialect
switch s.Profile.Driver {
case "sqlite":
dialect = &filter.SQLiteDialect{}
case "mysql":
dialect = &filter.MySQLDialect{}
case "postgres":
dialect = &filter.PostgreSQLDialect{}
default:
// Default to SQLite for unknown drivers
dialect = &filter.SQLiteDialect{}
}
converter := filter.NewCommonSQLConverter(dialect)
err = converter.ConvertExprToSQL(convertCtx, parsedExpr.GetExpr())
if err != nil {
return errors.Wrap(err, "failed to convert filter to SQL")
}
return nil
}

@ -7,6 +7,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/usememos/memos/plugin/filter"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
) )
@ -84,6 +85,26 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U
func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) { func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) {
where, args := []string{"1 = 1"}, []any{} where, args := []string{"1 = 1"}, []any{}
for _, filterStr := range find.Filters {
// Parse filter string and return the parsed expression.
// The filter string should be a CEL expression.
parsedExpr, err := filter.Parse(filterStr, filter.UserFilterCELAttributes...)
if err != nil {
return nil, err
}
convertCtx := filter.NewConvertContext()
// ConvertExprToSQL converts the parsed expression to a SQL condition string.
converter := filter.NewCommonSQLConverter(&filter.MySQLDialect{})
if err := converter.ConvertExprToSQL(convertCtx, parsedExpr.GetExpr()); err != nil {
return nil, err
}
condition := convertCtx.Buffer.String()
if condition != "" {
where = append(where, fmt.Sprintf("(%s)", condition))
args = append(args, convertCtx.Args...)
}
}
if v := find.ID; v != nil { if v := find.ID; v != nil {
where, args = append(where, "`id` = ?"), append(args, *v) where, args = append(where, "`id` = ?"), append(args, *v)
} }

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/usememos/memos/plugin/filter"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
) )
@ -85,6 +86,26 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U
func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) { func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) {
where, args := []string{"1 = 1"}, []any{} where, args := []string{"1 = 1"}, []any{}
for _, filterStr := range find.Filters {
// Parse filter string and return the parsed expression.
// The filter string should be a CEL expression.
parsedExpr, err := filter.Parse(filterStr, filter.UserFilterCELAttributes...)
if err != nil {
return nil, err
}
convertCtx := filter.NewConvertContext()
// ConvertExprToSQL converts the parsed expression to a SQL condition string.
converter := filter.NewCommonSQLConverter(&filter.PostgreSQLDialect{})
if err := converter.ConvertExprToSQL(convertCtx, parsedExpr.GetExpr()); err != nil {
return nil, err
}
condition := convertCtx.Buffer.String()
if condition != "" {
where = append(where, fmt.Sprintf("(%s)", condition))
args = append(args, convertCtx.Args...)
}
}
if v := find.ID; v != nil { if v := find.ID; v != nil {
where, args = append(where, "id = "+placeholder(len(args)+1)), append(args, *v) where, args = append(where, "id = "+placeholder(len(args)+1)), append(args, *v)
} }

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/usememos/memos/plugin/filter"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
) )
@ -86,6 +87,26 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U
func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) { func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) {
where, args := []string{"1 = 1"}, []any{} where, args := []string{"1 = 1"}, []any{}
for _, filterStr := range find.Filters {
// Parse filter string and return the parsed expression.
// The filter string should be a CEL expression.
parsedExpr, err := filter.Parse(filterStr, filter.UserFilterCELAttributes...)
if err != nil {
return nil, err
}
convertCtx := filter.NewConvertContext()
// ConvertExprToSQL converts the parsed expression to a SQL condition string.
converter := filter.NewCommonSQLConverter(&filter.SQLiteDialect{})
if err := converter.ConvertExprToSQL(convertCtx, parsedExpr.GetExpr()); err != nil {
return nil, err
}
condition := convertCtx.Buffer.String()
if condition != "" {
where = append(where, fmt.Sprintf("(%s)", condition))
args = append(args, convertCtx.Args...)
}
}
if v := find.ID; v != nil { if v := find.ID; v != nil {
where, args = append(where, "id = ?"), append(args, *v) where, args = append(where, "id = ?"), append(args, *v)
} }

@ -83,6 +83,9 @@ type FindUser struct {
Email *string Email *string
Nickname *string Nickname *string
// Domain specific fields
Filters []string
// The maximum number of users to return. // The maximum number of users to return.
Limit *int Limit *int
} }

@ -84,8 +84,8 @@ const userStore = (() => {
} }
} }
// Use search instead of the deprecated getUserByUsername // Use search instead of the deprecated getUserByUsername
const { users } = await userServiceClient.searchUsers({ const { users } = await userServiceClient.listUsers({
query: username, filter: `username == "${username}"`,
pageSize: 10, pageSize: 10,
}); });
const user = users.find((u) => u.username === username); const user = users.find((u) => u.username === username);

@ -114,11 +114,6 @@ export interface ListUsersRequest {
* Supported fields: username, email, role, state, create_time, update_time * Supported fields: username, email, role, state, create_time, update_time
*/ */
filter: string; filter: string;
/**
* Optional. The order to sort results by.
* Example: "create_time desc" or "username asc"
*/
orderBy: string;
/** Optional. If true, show deleted users in the response. */ /** Optional. If true, show deleted users in the response. */
showDeleted: boolean; showDeleted: boolean;
} }
@ -191,24 +186,6 @@ export interface DeleteUserRequest {
force: boolean; force: boolean;
} }
export interface SearchUsersRequest {
/** Required. The search query. */
query: string;
/** Optional. The maximum number of users to return. */
pageSize: number;
/** Optional. A page token for pagination. */
pageToken: string;
}
export interface SearchUsersResponse {
/** The list of users matching the search query. */
users: User[];
/** A token for the next page of results. */
nextPageToken: string;
/** The total count of matching users. */
totalSize: number;
}
export interface GetUserAvatarRequest { export interface GetUserAvatarRequest {
/** /**
* Required. The resource name of the user. * Required. The resource name of the user.
@ -780,7 +757,7 @@ export const User: MessageFns<User> = {
}; };
function createBaseListUsersRequest(): ListUsersRequest { function createBaseListUsersRequest(): ListUsersRequest {
return { pageSize: 0, pageToken: "", filter: "", orderBy: "", showDeleted: false }; return { pageSize: 0, pageToken: "", filter: "", showDeleted: false };
} }
export const ListUsersRequest: MessageFns<ListUsersRequest> = { export const ListUsersRequest: MessageFns<ListUsersRequest> = {
@ -794,11 +771,8 @@ export const ListUsersRequest: MessageFns<ListUsersRequest> = {
if (message.filter !== "") { if (message.filter !== "") {
writer.uint32(26).string(message.filter); writer.uint32(26).string(message.filter);
} }
if (message.orderBy !== "") {
writer.uint32(34).string(message.orderBy);
}
if (message.showDeleted !== false) { if (message.showDeleted !== false) {
writer.uint32(40).bool(message.showDeleted); writer.uint32(32).bool(message.showDeleted);
} }
return writer; return writer;
}, },
@ -835,15 +809,7 @@ export const ListUsersRequest: MessageFns<ListUsersRequest> = {
continue; continue;
} }
case 4: { case 4: {
if (tag !== 34) { if (tag !== 32) {
break;
}
message.orderBy = reader.string();
continue;
}
case 5: {
if (tag !== 40) {
break; break;
} }
@ -867,7 +833,6 @@ export const ListUsersRequest: MessageFns<ListUsersRequest> = {
message.pageSize = object.pageSize ?? 0; message.pageSize = object.pageSize ?? 0;
message.pageToken = object.pageToken ?? ""; message.pageToken = object.pageToken ?? "";
message.filter = object.filter ?? ""; message.filter = object.filter ?? "";
message.orderBy = object.orderBy ?? "";
message.showDeleted = object.showDeleted ?? false; message.showDeleted = object.showDeleted ?? false;
return message; return message;
}, },
@ -1211,146 +1176,6 @@ export const DeleteUserRequest: MessageFns<DeleteUserRequest> = {
}, },
}; };
function createBaseSearchUsersRequest(): SearchUsersRequest {
return { query: "", pageSize: 0, pageToken: "" };
}
export const SearchUsersRequest: MessageFns<SearchUsersRequest> = {
encode(message: SearchUsersRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.query !== "") {
writer.uint32(10).string(message.query);
}
if (message.pageSize !== 0) {
writer.uint32(16).int32(message.pageSize);
}
if (message.pageToken !== "") {
writer.uint32(26).string(message.pageToken);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): SearchUsersRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseSearchUsersRequest();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.query = reader.string();
continue;
}
case 2: {
if (tag !== 16) {
break;
}
message.pageSize = reader.int32();
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.pageToken = reader.string();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<SearchUsersRequest>): SearchUsersRequest {
return SearchUsersRequest.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<SearchUsersRequest>): SearchUsersRequest {
const message = createBaseSearchUsersRequest();
message.query = object.query ?? "";
message.pageSize = object.pageSize ?? 0;
message.pageToken = object.pageToken ?? "";
return message;
},
};
function createBaseSearchUsersResponse(): SearchUsersResponse {
return { users: [], nextPageToken: "", totalSize: 0 };
}
export const SearchUsersResponse: MessageFns<SearchUsersResponse> = {
encode(message: SearchUsersResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.users) {
User.encode(v!, writer.uint32(10).fork()).join();
}
if (message.nextPageToken !== "") {
writer.uint32(18).string(message.nextPageToken);
}
if (message.totalSize !== 0) {
writer.uint32(24).int32(message.totalSize);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): SearchUsersResponse {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseSearchUsersResponse();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.users.push(User.decode(reader, reader.uint32()));
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.nextPageToken = reader.string();
continue;
}
case 3: {
if (tag !== 24) {
break;
}
message.totalSize = reader.int32();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<SearchUsersResponse>): SearchUsersResponse {
return SearchUsersResponse.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<SearchUsersResponse>): SearchUsersResponse {
const message = createBaseSearchUsersResponse();
message.users = object.users?.map((e) => User.fromPartial(e)) || [];
message.nextPageToken = object.nextPageToken ?? "";
message.totalSize = object.totalSize ?? 0;
return message;
},
};
function createBaseGetUserAvatarRequest(): GetUserAvatarRequest { function createBaseGetUserAvatarRequest(): GetUserAvatarRequest {
return { name: "" }; return { name: "" };
} }
@ -3586,46 +3411,6 @@ export const UserServiceDefinition = {
}, },
}, },
}, },
/** SearchUsers searches for users based on query. */
searchUsers: {
name: "SearchUsers",
requestType: SearchUsersRequest,
requestStream: false,
responseType: SearchUsersResponse,
responseStream: false,
options: {
_unknownFields: {
8410: [new Uint8Array([5, 113, 117, 101, 114, 121])],
578365826: [
new Uint8Array([
22,
18,
20,
47,
97,
112,
105,
47,
118,
49,
47,
117,
115,
101,
114,
115,
58,
115,
101,
97,
114,
99,
104,
]),
],
},
},
},
/** GetUserAvatar gets the avatar of a user. */ /** GetUserAvatar gets the avatar of a user. */
getUserAvatar: { getUserAvatar: {
name: "GetUserAvatar", name: "GetUserAvatar",

@ -35,7 +35,7 @@ export enum Edition {
EDITION_2024 = "EDITION_2024", EDITION_2024 = "EDITION_2024",
/** /**
* EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be * EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be
* used or relied on outside of tests. * used or relyed on outside of tests.
*/ */
EDITION_1_TEST_ONLY = "EDITION_1_TEST_ONLY", EDITION_1_TEST_ONLY = "EDITION_1_TEST_ONLY",
EDITION_2_TEST_ONLY = "EDITION_2_TEST_ONLY", EDITION_2_TEST_ONLY = "EDITION_2_TEST_ONLY",
@ -177,19 +177,11 @@ export interface FileDescriptorProto {
* The supported values are "proto2", "proto3", and "editions". * The supported values are "proto2", "proto3", and "editions".
* *
* If `edition` is present, this value must be "editions". * If `edition` is present, this value must be "editions".
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/ */
syntax?: syntax?:
| string | string
| undefined; | undefined;
/** /** The edition of the proto file. */
* The edition of the proto file.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
edition?: Edition | undefined; edition?: Edition | undefined;
} }
@ -836,12 +828,7 @@ export interface FileOptions {
rubyPackage?: rubyPackage?:
| string | string
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
@ -979,12 +966,7 @@ export interface MessageOptions {
deprecatedLegacyJsonFieldConflicts?: deprecatedLegacyJsonFieldConflicts?:
| boolean | boolean
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
@ -994,13 +976,12 @@ export interface MessageOptions {
export interface FieldOptions { export interface FieldOptions {
/** /**
* NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead.
* The ctype option instructs the C++ code generator to use a different * The ctype option instructs the C++ code generator to use a different
* representation of the field than it normally would. See the specific * representation of the field than it normally would. See the specific
* options below. This option is only implemented to support use of * options below. This option is only implemented to support use of
* [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of
* type "bytes" in the open source release. * type "bytes" in the open source release -- sorry, we'll try to include
* TODO: make ctype actually deprecated. * other types in a future version!
*/ */
ctype?: ctype?:
| FieldOptions_CType | FieldOptions_CType
@ -1089,12 +1070,7 @@ export interface FieldOptions {
retention?: FieldOptions_OptionRetention | undefined; retention?: FieldOptions_OptionRetention | undefined;
targets: FieldOptions_OptionTargetType[]; targets: FieldOptions_OptionTargetType[];
editionDefaults: FieldOptions_EditionDefault[]; editionDefaults: FieldOptions_EditionDefault[];
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: FeatureSet | undefined; features?: FeatureSet | undefined;
featureSupport?: featureSupport?:
| FieldOptions_FeatureSupport | FieldOptions_FeatureSupport
@ -1193,7 +1169,11 @@ export function fieldOptions_JSTypeToNumber(object: FieldOptions_JSType): number
} }
} }
/** If set to RETENTION_SOURCE, the option will be omitted from the binary. */ /**
* If set to RETENTION_SOURCE, the option will be omitted from the binary.
* Note: as of January 2023, support for this is in progress and does not yet
* have an effect (b/264593489).
*/
export enum FieldOptions_OptionRetention { export enum FieldOptions_OptionRetention {
RETENTION_UNKNOWN = "RETENTION_UNKNOWN", RETENTION_UNKNOWN = "RETENTION_UNKNOWN",
RETENTION_RUNTIME = "RETENTION_RUNTIME", RETENTION_RUNTIME = "RETENTION_RUNTIME",
@ -1236,7 +1216,8 @@ export function fieldOptions_OptionRetentionToNumber(object: FieldOptions_Option
/** /**
* This indicates the types of entities that the field may apply to when used * This indicates the types of entities that the field may apply to when used
* as an option. If it is unset, then the field may be freely used as an * as an option. If it is unset, then the field may be freely used as an
* option on any kind of entity. * option on any kind of entity. Note: as of January 2023, support for this is
* in progress and does not yet have an effect (b/264593489).
*/ */
export enum FieldOptions_OptionTargetType { export enum FieldOptions_OptionTargetType {
TARGET_TYPE_UNKNOWN = "TARGET_TYPE_UNKNOWN", TARGET_TYPE_UNKNOWN = "TARGET_TYPE_UNKNOWN",
@ -1360,12 +1341,7 @@ export interface FieldOptions_FeatureSupport {
} }
export interface OneofOptions { export interface OneofOptions {
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
@ -1403,12 +1379,7 @@ export interface EnumOptions {
deprecatedLegacyJsonFieldConflicts?: deprecatedLegacyJsonFieldConflicts?:
| boolean | boolean
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
@ -1426,12 +1397,7 @@ export interface EnumValueOptions {
deprecated?: deprecated?:
| boolean | boolean
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
@ -1452,12 +1418,7 @@ export interface EnumValueOptions {
} }
export interface ServiceOptions { export interface ServiceOptions {
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
@ -1485,12 +1446,7 @@ export interface MethodOptions {
idempotencyLevel?: idempotencyLevel?:
| MethodOptions_IdempotencyLevel | MethodOptions_IdempotencyLevel
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
@ -1593,7 +1549,6 @@ export interface FeatureSet {
utf8Validation?: FeatureSet_Utf8Validation | undefined; utf8Validation?: FeatureSet_Utf8Validation | undefined;
messageEncoding?: FeatureSet_MessageEncoding | undefined; messageEncoding?: FeatureSet_MessageEncoding | undefined;
jsonFormat?: FeatureSet_JsonFormat | undefined; jsonFormat?: FeatureSet_JsonFormat | undefined;
enforceNamingStyle?: FeatureSet_EnforceNamingStyle | undefined;
} }
export enum FeatureSet_FieldPresence { export enum FeatureSet_FieldPresence {
@ -1836,45 +1791,6 @@ export function featureSet_JsonFormatToNumber(object: FeatureSet_JsonFormat): nu
} }
} }
export enum FeatureSet_EnforceNamingStyle {
ENFORCE_NAMING_STYLE_UNKNOWN = "ENFORCE_NAMING_STYLE_UNKNOWN",
STYLE2024 = "STYLE2024",
STYLE_LEGACY = "STYLE_LEGACY",
UNRECOGNIZED = "UNRECOGNIZED",
}
export function featureSet_EnforceNamingStyleFromJSON(object: any): FeatureSet_EnforceNamingStyle {
switch (object) {
case 0:
case "ENFORCE_NAMING_STYLE_UNKNOWN":
return FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN;
case 1:
case "STYLE2024":
return FeatureSet_EnforceNamingStyle.STYLE2024;
case 2:
case "STYLE_LEGACY":
return FeatureSet_EnforceNamingStyle.STYLE_LEGACY;
case -1:
case "UNRECOGNIZED":
default:
return FeatureSet_EnforceNamingStyle.UNRECOGNIZED;
}
}
export function featureSet_EnforceNamingStyleToNumber(object: FeatureSet_EnforceNamingStyle): number {
switch (object) {
case FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN:
return 0;
case FeatureSet_EnforceNamingStyle.STYLE2024:
return 1;
case FeatureSet_EnforceNamingStyle.STYLE_LEGACY:
return 2;
case FeatureSet_EnforceNamingStyle.UNRECOGNIZED:
default:
return -1;
}
}
/** /**
* A compiled specification for the defaults of a set of features. These * A compiled specification for the defaults of a set of features. These
* messages are generated from FeatureSet extensions and can be used to seed * messages are generated from FeatureSet extensions and can be used to seed
@ -4998,7 +4914,6 @@ function createBaseFeatureSet(): FeatureSet {
utf8Validation: FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN, utf8Validation: FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN,
messageEncoding: FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN, messageEncoding: FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN,
jsonFormat: FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN, jsonFormat: FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN,
enforceNamingStyle: FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN,
}; };
} }
@ -5033,12 +4948,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
if (message.jsonFormat !== undefined && message.jsonFormat !== FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN) { if (message.jsonFormat !== undefined && message.jsonFormat !== FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN) {
writer.uint32(48).int32(featureSet_JsonFormatToNumber(message.jsonFormat)); writer.uint32(48).int32(featureSet_JsonFormatToNumber(message.jsonFormat));
} }
if (
message.enforceNamingStyle !== undefined &&
message.enforceNamingStyle !== FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN
) {
writer.uint32(56).int32(featureSet_EnforceNamingStyleToNumber(message.enforceNamingStyle));
}
return writer; return writer;
}, },
@ -5097,14 +5006,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
message.jsonFormat = featureSet_JsonFormatFromJSON(reader.int32()); message.jsonFormat = featureSet_JsonFormatFromJSON(reader.int32());
continue; continue;
} }
case 7: {
if (tag !== 56) {
break;
}
message.enforceNamingStyle = featureSet_EnforceNamingStyleFromJSON(reader.int32());
continue;
}
} }
if ((tag & 7) === 4 || tag === 0) { if ((tag & 7) === 4 || tag === 0) {
break; break;
@ -5126,8 +5027,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
message.utf8Validation = object.utf8Validation ?? FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN; message.utf8Validation = object.utf8Validation ?? FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN;
message.messageEncoding = object.messageEncoding ?? FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN; message.messageEncoding = object.messageEncoding ?? FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN;
message.jsonFormat = object.jsonFormat ?? FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN; message.jsonFormat = object.jsonFormat ?? FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN;
message.enforceNamingStyle = object.enforceNamingStyle ??
FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN;
return message; return message;
}, },
}; };

Loading…
Cancel
Save