chore: update user settings

This commit is contained in:
johnnyjoy 2025-07-27 23:12:42 +08:00
parent 3f56ce47d2
commit c5d497a1f0
25 changed files with 5330 additions and 3741 deletions

View File

@ -75,19 +75,25 @@ service UserService {
// GetUserSetting returns the user setting.
rpc GetUserSetting(GetUserSettingRequest) returns (UserSetting) {
option (google.api.http) = {get: "/api/v1/{name=users/*}:getSetting"};
option (google.api.http) = {get: "/api/v1/{name=users/*/settings/*}"};
option (google.api.method_signature) = "name";
}
// UpdateUserSetting updates the user setting.
rpc UpdateUserSetting(UpdateUserSettingRequest) returns (UserSetting) {
option (google.api.http) = {
patch: "/api/v1/{setting.name=users/*}:updateSetting"
patch: "/api/v1/{setting.name=users/*/settings/*}"
body: "setting"
};
option (google.api.method_signature) = "setting,update_mask";
}
// ListUserSettings returns a list of user settings.
rpc ListUserSettings(ListUserSettingsRequest) returns (ListUserSettingsResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/settings"};
option (google.api.method_signature) = "parent";
}
// ListUserAccessTokens returns a list of access tokens for a user.
rpc ListUserAccessTokens(ListUserAccessTokensRequest) returns (ListUserAccessTokensResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/accessTokens"};
@ -120,6 +126,36 @@ service UserService {
option (google.api.http) = {delete: "/api/v1/{name=users/*/sessions/*}"};
option (google.api.method_signature) = "name";
}
// ListUserWebhooks returns a list of webhooks for a user.
rpc ListUserWebhooks(ListUserWebhooksRequest) returns (ListUserWebhooksResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/webhooks"};
option (google.api.method_signature) = "parent";
}
// CreateUserWebhook creates a new webhook for a user.
rpc CreateUserWebhook(CreateUserWebhookRequest) returns (UserWebhook) {
option (google.api.http) = {
post: "/api/v1/{parent=users/*}/webhooks"
body: "webhook"
};
option (google.api.method_signature) = "parent,webhook";
}
// UpdateUserWebhook updates an existing webhook for a user.
rpc UpdateUserWebhook(UpdateUserWebhookRequest) returns (UserWebhook) {
option (google.api.http) = {
patch: "/api/v1/{webhook.name=users/*/webhooks/*}"
body: "webhook"
};
option (google.api.method_signature) = "webhook,update_mask";
}
// DeleteUserWebhook deletes a webhook for a user.
rpc DeleteUserWebhook(DeleteUserWebhookRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*/webhooks/*}"};
option (google.api.method_signature) = "name";
}
}
message User {
@ -348,40 +384,152 @@ message GetUserStatsRequest {
];
}
message ListAllUserStatsRequest {
// This endpoint doesn't take any parameters.
}
message ListAllUserStatsResponse {
// The list of user statistics.
repeated UserStats stats = 1;
}
// User settings message
message UserSetting {
option (google.api.resource) = {
type: "memos.api.v1/UserSetting"
pattern: "users/{user}"
pattern: "users/{user}/settings/{setting}"
singular: "userSetting"
plural: "userSettings"
};
// The resource name of the user whose setting this is.
// Format: users/{user}
// The name of the user setting.
// Format: users/{user}/settings/{setting}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The preferred locale of the user.
string locale = 2 [(google.api.field_behavior) = OPTIONAL];
oneof value {
GeneralSetting general_setting = 2;
SessionsSetting sessions_setting = 3;
AccessTokensSetting access_tokens_setting = 4;
ShortcutsSetting shortcuts_setting = 5;
WebhooksSetting webhooks_setting = 6;
}
// The preferred appearance of the user.
string appearance = 3 [(google.api.field_behavior) = OPTIONAL];
// Enumeration of user setting keys.
enum Key {
KEY_UNSPECIFIED = 0;
// GENERAL is the key for general user settings.
GENERAL = 1;
// SESSIONS is the key for user authentication sessions.
SESSIONS = 2;
// ACCESS_TOKENS is the key for access tokens.
ACCESS_TOKENS = 3;
// SHORTCUTS is the key for user shortcuts.
SHORTCUTS = 4;
// WEBHOOKS is the key for user webhooks.
WEBHOOKS = 5;
}
// The default visibility of the memo.
string memo_visibility = 4 [(google.api.field_behavior) = OPTIONAL];
// General user settings configuration.
message GeneralSetting {
// The preferred locale of the user.
string locale = 1 [(google.api.field_behavior) = OPTIONAL];
// The preferred appearance of the user.
string appearance = 2 [(google.api.field_behavior) = OPTIONAL];
// The default visibility of the memo.
string memo_visibility = 3 [(google.api.field_behavior) = OPTIONAL];
// 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.
string theme = 4 [(google.api.field_behavior) = OPTIONAL];
}
// 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.
string theme = 5 [(google.api.field_behavior) = OPTIONAL];
// User authentication sessions configuration.
message SessionsSetting {
// List of active user sessions.
repeated Session sessions = 1;
// User session information.
message Session {
// Unique session identifier.
string session_id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
// Timestamp when the session was created.
google.protobuf.Timestamp create_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
// Timestamp when the session was last accessed.
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
google.protobuf.Timestamp last_accessed_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
// Client information associated with this session.
ClientInfo client_info = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
}
// Client information for a session.
message ClientInfo {
// User agent string of the client.
string user_agent = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
// IP address of the client.
string ip_address = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. Device type (e.g., "mobile", "desktop", "tablet").
string device_type = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. Operating system (e.g., "iOS 17.0", "Windows 11").
string os = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. Browser name and version (e.g., "Chrome 119.0").
string browser = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
}
}
// User access tokens configuration.
message AccessTokensSetting {
// List of user access tokens.
repeated AccessToken access_tokens = 1;
// User access token information.
message AccessToken {
// The access token is a JWT token.
// Including expiration time, issuer, etc.
string access_token = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
// A description for the access token.
string description = 2 [(google.api.field_behavior) = OPTIONAL];
}
}
// User shortcuts configuration.
message ShortcutsSetting {
// List of user shortcuts.
repeated Shortcut shortcuts = 1;
// User shortcut definition.
message Shortcut {
// Unique identifier for the shortcut.
string id = 1 [(google.api.field_behavior) = REQUIRED];
// Display title for the shortcut.
string title = 2 [(google.api.field_behavior) = REQUIRED];
// Filter expression for the shortcut.
string filter = 3 [(google.api.field_behavior) = REQUIRED];
}
}
// User webhooks configuration.
message WebhooksSetting {
// List of user webhooks.
repeated Webhook webhooks = 1;
// User webhook definition.
message Webhook {
// Unique identifier for the webhook.
string id = 1 [(google.api.field_behavior) = REQUIRED];
// Descriptive title for the webhook.
string title = 2 [(google.api.field_behavior) = REQUIRED];
// The webhook URL endpoint.
string url = 3 [(google.api.field_behavior) = REQUIRED];
}
}
}
message GetUserSettingRequest {
// Required. The resource name of the user.
// Format: users/{user}
// Required. The resource name of the user setting.
// Format: users/{user}/settings/{setting}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
(google.api.resource_reference) = {type: "memos.api.v1/UserSetting"}
];
}
@ -393,6 +541,39 @@ message UpdateUserSettingRequest {
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
}
// Request message for ListUserSettings method.
message ListUserSettingsRequest {
// Required. The parent resource whose settings will be listed.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// 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.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token, received from a previous `ListUserSettings` call.
// Provide this to retrieve the subsequent page.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
// Response message for ListUserSettings method.
message ListUserSettingsResponse {
// The list of user settings.
repeated UserSetting settings = 1;
// A token that can be sent as `page_token` to retrieve the next page.
// If this field is omitted, there are no subsequent pages.
string next_page_token = 2;
// The total count of settings (may be approximate).
int32 total_size = 3;
}
// User access token message
message UserAccessToken {
option (google.api.resource) = {
@ -526,29 +707,60 @@ message ListUserSessionsResponse {
}
message RevokeUserSessionRequest {
// Required. The resource name of the session to revoke.
// The name of the session to revoke.
// Format: users/{user}/sessions/{session}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/UserSession"}
];
string name = 1 [(google.api.field_behavior) = REQUIRED];
}
message ListAllUserStatsRequest {
// Optional. The maximum number of user stats to return.
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
// UserWebhook represents a webhook owned by a user.
message UserWebhook {
// The name of the webhook.
// Format: users/{user}/webhooks/{webhook}
string name = 1;
// Optional. A page token for pagination.
string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
// The URL to send the webhook to.
string url = 2;
// Optional. Human-readable name for the webhook.
string display_name = 3;
// The creation time of the webhook.
google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
// The last update time of the webhook.
google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
}
message ListAllUserStatsResponse {
// The list of user statistics.
repeated UserStats user_stats = 1;
// A token for the next page of results.
string next_page_token = 2;
// The total count of user statistics.
int32 total_size = 3;
message ListUserWebhooksRequest {
// The parent user resource.
// Format: users/{user}
string parent = 1 [(google.api.field_behavior) = REQUIRED];
}
message ListUserWebhooksResponse {
// The list of webhooks.
repeated UserWebhook webhooks = 1;
}
message CreateUserWebhookRequest {
// The parent user resource.
// Format: users/{user}
string parent = 1 [(google.api.field_behavior) = REQUIRED];
// The webhook to create.
UserWebhook webhook = 2 [(google.api.field_behavior) = REQUIRED];
}
message UpdateUserWebhookRequest {
// The webhook to update.
UserWebhook webhook = 1 [(google.api.field_behavior) = REQUIRED];
// The list of fields to update.
google.protobuf.FieldMask update_mask = 2;
}
message DeleteUserWebhookRequest {
// The name of the webhook to delete.
// Format: users/{user}/webhooks/{webhook}
string name = 1 [(google.api.field_behavior) = REQUIRED];
}

View File

@ -1,124 +0,0 @@
syntax = "proto3";
package memos.api.v1;
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
option go_package = "gen/api/v1";
service WebhookService {
// ListWebhooks returns a list of webhooks for a user.
rpc ListWebhooks(ListWebhooksRequest) returns (ListWebhooksResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/webhooks"};
option (google.api.method_signature) = "parent";
}
// GetWebhook gets a webhook by name.
rpc GetWebhook(GetWebhookRequest) returns (Webhook) {
option (google.api.http) = {get: "/api/v1/{name=users/*/webhooks/*}"};
option (google.api.method_signature) = "name";
}
// CreateWebhook creates a new webhook for a user.
rpc CreateWebhook(CreateWebhookRequest) returns (Webhook) {
option (google.api.http) = {
post: "/api/v1/{parent=users/*}/webhooks"
body: "webhook"
};
option (google.api.method_signature) = "parent,webhook";
}
// UpdateWebhook updates a webhook for a user.
rpc UpdateWebhook(UpdateWebhookRequest) returns (Webhook) {
option (google.api.http) = {
patch: "/api/v1/{webhook.name=users/*/webhooks/*}"
body: "webhook"
};
option (google.api.method_signature) = "webhook,update_mask";
}
// DeleteWebhook deletes a webhook for a user.
rpc DeleteWebhook(DeleteWebhookRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*/webhooks/*}"};
option (google.api.method_signature) = "name";
}
}
message Webhook {
option (google.api.resource) = {
type: "memos.api.v1/Webhook"
pattern: "users/{user}/webhooks/{webhook}"
singular: "webhook"
plural: "webhooks"
};
// The resource name of the webhook.
// Format: users/{user}/webhooks/{webhook}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The display name of the webhook.
string display_name = 2 [(google.api.field_behavior) = REQUIRED];
// The target URL for the webhook.
string url = 3 [(google.api.field_behavior) = REQUIRED];
}
message ListWebhooksRequest {
// Required. The parent resource where webhooks are listed.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {child_type: "memos.api.v1/Webhook"}
];
}
message ListWebhooksResponse {
// The list of webhooks.
repeated Webhook webhooks = 1;
}
message GetWebhookRequest {
// Required. The resource name of the webhook to retrieve.
// Format: users/{user}/webhooks/{webhook}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Webhook"}
];
}
message CreateWebhookRequest {
// Required. The parent resource where this webhook will be created.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {child_type: "memos.api.v1/Webhook"}
];
// Required. The webhook to create.
Webhook webhook = 2 [(google.api.field_behavior) = REQUIRED];
// Optional. If set, validate the request, but do not actually create the webhook.
bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateWebhookRequest {
// Required. The webhook resource which replaces the resource on the server.
Webhook webhook = 1 [(google.api.field_behavior) = REQUIRED];
// Optional. The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = OPTIONAL];
}
message DeleteWebhookRequest {
// Required. The resource name of the webhook to delete.
// Format: users/{user}/webhooks/{webhook}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Webhook"}
];
}

File diff suppressed because it is too large Load Diff

View File

@ -372,8 +372,6 @@ func local_request_UserService_GetUserAvatar_0(ctx context.Context, marshaler ru
return msg, metadata, err
}
var filter_UserService_ListAllUserStats_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
func request_UserService_ListAllUserStats_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListAllUserStatsRequest
@ -382,12 +380,6 @@ func request_UserService_ListAllUserStats_0(ctx context.Context, marshaler runti
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_ListAllUserStats_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.ListAllUserStats(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
@ -397,12 +389,6 @@ func local_request_UserService_ListAllUserStats_0(ctx context.Context, marshaler
protoReq ListAllUserStatsRequest
metadata runtime.ServerMetadata
)
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_ListAllUserStats_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.ListAllUserStats(ctx, &protoReq)
return msg, metadata, err
}
@ -566,6 +552,59 @@ func local_request_UserService_UpdateUserSetting_0(ctx context.Context, marshale
return msg, metadata, err
}
var filter_UserService_ListUserSettings_0 = &utilities.DoubleArray{Encoding: map[string]int{"parent": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
func request_UserService_ListUserSettings_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListUserSettingsRequest
metadata runtime.ServerMetadata
err error
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_ListUserSettings_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.ListUserSettings(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_UserService_ListUserSettings_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListUserSettingsRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_ListUserSettings_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.ListUserSettings(ctx, &protoReq)
return msg, metadata, err
}
var filter_UserService_ListUserAccessTokens_0 = &utilities.DoubleArray{Encoding: map[string]int{"parent": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
func request_UserService_ListUserAccessTokens_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@ -795,6 +834,210 @@ func local_request_UserService_RevokeUserSession_0(ctx context.Context, marshale
return msg, metadata, err
}
func request_UserService_ListUserWebhooks_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListUserWebhooksRequest
metadata runtime.ServerMetadata
err error
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := client.ListUserWebhooks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_UserService_ListUserWebhooks_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListUserWebhooksRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := server.ListUserWebhooks(ctx, &protoReq)
return msg, metadata, err
}
func request_UserService_CreateUserWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CreateUserWebhookRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := client.CreateUserWebhook(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_UserService_CreateUserWebhook_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CreateUserWebhookRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := server.CreateUserWebhook(ctx, &protoReq)
return msg, metadata, err
}
var filter_UserService_UpdateUserWebhook_0 = &utilities.DoubleArray{Encoding: map[string]int{"webhook": 0, "name": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}}
func request_UserService_UpdateUserWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateUserWebhookRequest
metadata runtime.ServerMetadata
err error
)
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Webhook); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} else {
protoReq.UpdateMask = fieldMask
}
}
val, ok := pathParams["webhook.name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "webhook.name")
}
err = runtime.PopulateFieldFromPath(&protoReq, "webhook.name", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "webhook.name", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_UpdateUserWebhook_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.UpdateUserWebhook(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_UserService_UpdateUserWebhook_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateUserWebhookRequest
metadata runtime.ServerMetadata
err error
)
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Webhook); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} else {
protoReq.UpdateMask = fieldMask
}
}
val, ok := pathParams["webhook.name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "webhook.name")
}
err = runtime.PopulateFieldFromPath(&protoReq, "webhook.name", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "webhook.name", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_UpdateUserWebhook_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.UpdateUserWebhook(ctx, &protoReq)
return msg, metadata, err
}
func request_UserService_DeleteUserWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq DeleteUserWebhookRequest
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.DeleteUserWebhook(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_UserService_DeleteUserWebhook_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq DeleteUserWebhookRequest
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.DeleteUserWebhook(ctx, &protoReq)
return msg, metadata, err
}
// RegisterUserServiceHandlerServer registers the http handlers for service UserService to "mux".
// UnaryRPC :call UserServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@ -987,7 +1230,7 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
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/GetUserSetting", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}:getSetting"))
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/GetUserSetting", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/settings/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@ -1007,7 +1250,7 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
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/UpdateUserSetting", runtime.WithHTTPPathPattern("/api/v1/{setting.name=users/*}:updateSetting"))
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/UpdateUserSetting", runtime.WithHTTPPathPattern("/api/v1/{setting.name=users/*/settings/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@ -1021,6 +1264,26 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
}
forward_UserService_UpdateUserSetting_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_UserService_ListUserSettings_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/ListUserSettings", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/settings"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_UserService_ListUserSettings_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_ListUserSettings_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_UserService_ListUserAccessTokens_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -1121,6 +1384,86 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
}
forward_UserService_RevokeUserSession_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_UserService_ListUserWebhooks_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/ListUserWebhooks", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_UserService_ListUserWebhooks_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_ListUserWebhooks_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_UserService_CreateUserWebhook_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/CreateUserWebhook", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_UserService_CreateUserWebhook_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_CreateUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPatch, pattern_UserService_UpdateUserWebhook_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/UpdateUserWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_UserService_UpdateUserWebhook_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_UpdateUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodDelete, pattern_UserService_DeleteUserWebhook_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/DeleteUserWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_UserService_DeleteUserWebhook_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_DeleteUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -1318,7 +1661,7 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
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/GetUserSetting", runtime.WithHTTPPathPattern("/api/v1/{name=users/*}:getSetting"))
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/GetUserSetting", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/settings/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@ -1335,7 +1678,7 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
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/UpdateUserSetting", runtime.WithHTTPPathPattern("/api/v1/{setting.name=users/*}:updateSetting"))
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/UpdateUserSetting", runtime.WithHTTPPathPattern("/api/v1/{setting.name=users/*/settings/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@ -1348,6 +1691,23 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
}
forward_UserService_UpdateUserSetting_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_UserService_ListUserSettings_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/ListUserSettings", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/settings"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_UserService_ListUserSettings_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_ListUserSettings_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_UserService_ListUserAccessTokens_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -1433,6 +1793,74 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
}
forward_UserService_RevokeUserSession_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_UserService_ListUserWebhooks_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/ListUserWebhooks", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_UserService_ListUserWebhooks_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_ListUserWebhooks_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_UserService_CreateUserWebhook_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/CreateUserWebhook", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_UserService_CreateUserWebhook_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_CreateUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPatch, pattern_UserService_UpdateUserWebhook_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/UpdateUserWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_UserService_UpdateUserWebhook_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_UpdateUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodDelete, pattern_UserService_DeleteUserWebhook_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/DeleteUserWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_UserService_DeleteUserWebhook_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_DeleteUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -1446,13 +1874,18 @@ var (
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, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, "getSetting"))
pattern_UserService_UpdateUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "setting.name"}, "updateSetting"))
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"}, ""))
pattern_UserService_UpdateUserSetting_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", "setting.name"}, ""))
pattern_UserService_ListUserSettings_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", "parent", "settings"}, ""))
pattern_UserService_ListUserAccessTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "accessTokens"}, ""))
pattern_UserService_CreateUserAccessToken_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", "parent", "accessTokens"}, ""))
pattern_UserService_DeleteUserAccessToken_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", "accessTokens", "name"}, ""))
pattern_UserService_ListUserSessions_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", "parent", "sessions"}, ""))
pattern_UserService_RevokeUserSession_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", "sessions", "name"}, ""))
pattern_UserService_ListUserWebhooks_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", "parent", "webhooks"}, ""))
pattern_UserService_CreateUserWebhook_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", "parent", "webhooks"}, ""))
pattern_UserService_UpdateUserWebhook_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", "webhooks", "webhook.name"}, ""))
pattern_UserService_DeleteUserWebhook_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", "webhooks", "name"}, ""))
)
var (
@ -1467,9 +1900,14 @@ var (
forward_UserService_GetUserStats_0 = runtime.ForwardResponseMessage
forward_UserService_GetUserSetting_0 = runtime.ForwardResponseMessage
forward_UserService_UpdateUserSetting_0 = runtime.ForwardResponseMessage
forward_UserService_ListUserSettings_0 = runtime.ForwardResponseMessage
forward_UserService_ListUserAccessTokens_0 = runtime.ForwardResponseMessage
forward_UserService_CreateUserAccessToken_0 = runtime.ForwardResponseMessage
forward_UserService_DeleteUserAccessToken_0 = runtime.ForwardResponseMessage
forward_UserService_ListUserSessions_0 = runtime.ForwardResponseMessage
forward_UserService_RevokeUserSession_0 = runtime.ForwardResponseMessage
forward_UserService_ListUserWebhooks_0 = runtime.ForwardResponseMessage
forward_UserService_CreateUserWebhook_0 = runtime.ForwardResponseMessage
forward_UserService_UpdateUserWebhook_0 = runtime.ForwardResponseMessage
forward_UserService_DeleteUserWebhook_0 = runtime.ForwardResponseMessage
)

View File

@ -32,11 +32,16 @@ const (
UserService_GetUserStats_FullMethodName = "/memos.api.v1.UserService/GetUserStats"
UserService_GetUserSetting_FullMethodName = "/memos.api.v1.UserService/GetUserSetting"
UserService_UpdateUserSetting_FullMethodName = "/memos.api.v1.UserService/UpdateUserSetting"
UserService_ListUserSettings_FullMethodName = "/memos.api.v1.UserService/ListUserSettings"
UserService_ListUserAccessTokens_FullMethodName = "/memos.api.v1.UserService/ListUserAccessTokens"
UserService_CreateUserAccessToken_FullMethodName = "/memos.api.v1.UserService/CreateUserAccessToken"
UserService_DeleteUserAccessToken_FullMethodName = "/memos.api.v1.UserService/DeleteUserAccessToken"
UserService_ListUserSessions_FullMethodName = "/memos.api.v1.UserService/ListUserSessions"
UserService_RevokeUserSession_FullMethodName = "/memos.api.v1.UserService/RevokeUserSession"
UserService_ListUserWebhooks_FullMethodName = "/memos.api.v1.UserService/ListUserWebhooks"
UserService_CreateUserWebhook_FullMethodName = "/memos.api.v1.UserService/CreateUserWebhook"
UserService_UpdateUserWebhook_FullMethodName = "/memos.api.v1.UserService/UpdateUserWebhook"
UserService_DeleteUserWebhook_FullMethodName = "/memos.api.v1.UserService/DeleteUserWebhook"
)
// UserServiceClient is the client API for UserService service.
@ -65,6 +70,8 @@ type UserServiceClient interface {
GetUserSetting(ctx context.Context, in *GetUserSettingRequest, opts ...grpc.CallOption) (*UserSetting, error)
// UpdateUserSetting updates the user setting.
UpdateUserSetting(ctx context.Context, in *UpdateUserSettingRequest, opts ...grpc.CallOption) (*UserSetting, error)
// ListUserSettings returns a list of user settings.
ListUserSettings(ctx context.Context, in *ListUserSettingsRequest, opts ...grpc.CallOption) (*ListUserSettingsResponse, error)
// ListUserAccessTokens returns a list of access tokens for a user.
ListUserAccessTokens(ctx context.Context, in *ListUserAccessTokensRequest, opts ...grpc.CallOption) (*ListUserAccessTokensResponse, error)
// CreateUserAccessToken creates a new access token for a user.
@ -75,6 +82,14 @@ type UserServiceClient interface {
ListUserSessions(ctx context.Context, in *ListUserSessionsRequest, opts ...grpc.CallOption) (*ListUserSessionsResponse, error)
// RevokeUserSession revokes a specific session for a user.
RevokeUserSession(ctx context.Context, in *RevokeUserSessionRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// ListUserWebhooks returns a list of webhooks for a user.
ListUserWebhooks(ctx context.Context, in *ListUserWebhooksRequest, opts ...grpc.CallOption) (*ListUserWebhooksResponse, error)
// CreateUserWebhook creates a new webhook for a user.
CreateUserWebhook(ctx context.Context, in *CreateUserWebhookRequest, opts ...grpc.CallOption) (*UserWebhook, error)
// UpdateUserWebhook updates an existing webhook for a user.
UpdateUserWebhook(ctx context.Context, in *UpdateUserWebhookRequest, opts ...grpc.CallOption) (*UserWebhook, error)
// DeleteUserWebhook deletes a webhook for a user.
DeleteUserWebhook(ctx context.Context, in *DeleteUserWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
type userServiceClient struct {
@ -195,6 +210,16 @@ func (c *userServiceClient) UpdateUserSetting(ctx context.Context, in *UpdateUse
return out, nil
}
func (c *userServiceClient) ListUserSettings(ctx context.Context, in *ListUserSettingsRequest, opts ...grpc.CallOption) (*ListUserSettingsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListUserSettingsResponse)
err := c.cc.Invoke(ctx, UserService_ListUserSettings_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) ListUserAccessTokens(ctx context.Context, in *ListUserAccessTokensRequest, opts ...grpc.CallOption) (*ListUserAccessTokensResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListUserAccessTokensResponse)
@ -245,6 +270,46 @@ func (c *userServiceClient) RevokeUserSession(ctx context.Context, in *RevokeUse
return out, nil
}
func (c *userServiceClient) ListUserWebhooks(ctx context.Context, in *ListUserWebhooksRequest, opts ...grpc.CallOption) (*ListUserWebhooksResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListUserWebhooksResponse)
err := c.cc.Invoke(ctx, UserService_ListUserWebhooks_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) CreateUserWebhook(ctx context.Context, in *CreateUserWebhookRequest, opts ...grpc.CallOption) (*UserWebhook, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UserWebhook)
err := c.cc.Invoke(ctx, UserService_CreateUserWebhook_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) UpdateUserWebhook(ctx context.Context, in *UpdateUserWebhookRequest, opts ...grpc.CallOption) (*UserWebhook, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UserWebhook)
err := c.cc.Invoke(ctx, UserService_UpdateUserWebhook_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) DeleteUserWebhook(ctx context.Context, in *DeleteUserWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, UserService_DeleteUserWebhook_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// UserServiceServer is the server API for UserService service.
// All implementations must embed UnimplementedUserServiceServer
// for forward compatibility.
@ -271,6 +336,8 @@ type UserServiceServer interface {
GetUserSetting(context.Context, *GetUserSettingRequest) (*UserSetting, error)
// UpdateUserSetting updates the user setting.
UpdateUserSetting(context.Context, *UpdateUserSettingRequest) (*UserSetting, error)
// ListUserSettings returns a list of user settings.
ListUserSettings(context.Context, *ListUserSettingsRequest) (*ListUserSettingsResponse, error)
// ListUserAccessTokens returns a list of access tokens for a user.
ListUserAccessTokens(context.Context, *ListUserAccessTokensRequest) (*ListUserAccessTokensResponse, error)
// CreateUserAccessToken creates a new access token for a user.
@ -281,6 +348,14 @@ type UserServiceServer interface {
ListUserSessions(context.Context, *ListUserSessionsRequest) (*ListUserSessionsResponse, error)
// RevokeUserSession revokes a specific session for a user.
RevokeUserSession(context.Context, *RevokeUserSessionRequest) (*emptypb.Empty, error)
// ListUserWebhooks returns a list of webhooks for a user.
ListUserWebhooks(context.Context, *ListUserWebhooksRequest) (*ListUserWebhooksResponse, error)
// CreateUserWebhook creates a new webhook for a user.
CreateUserWebhook(context.Context, *CreateUserWebhookRequest) (*UserWebhook, error)
// UpdateUserWebhook updates an existing webhook for a user.
UpdateUserWebhook(context.Context, *UpdateUserWebhookRequest) (*UserWebhook, error)
// DeleteUserWebhook deletes a webhook for a user.
DeleteUserWebhook(context.Context, *DeleteUserWebhookRequest) (*emptypb.Empty, error)
mustEmbedUnimplementedUserServiceServer()
}
@ -324,6 +399,9 @@ func (UnimplementedUserServiceServer) GetUserSetting(context.Context, *GetUserSe
func (UnimplementedUserServiceServer) UpdateUserSetting(context.Context, *UpdateUserSettingRequest) (*UserSetting, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateUserSetting not implemented")
}
func (UnimplementedUserServiceServer) ListUserSettings(context.Context, *ListUserSettingsRequest) (*ListUserSettingsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListUserSettings not implemented")
}
func (UnimplementedUserServiceServer) ListUserAccessTokens(context.Context, *ListUserAccessTokensRequest) (*ListUserAccessTokensResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListUserAccessTokens not implemented")
}
@ -339,6 +417,18 @@ func (UnimplementedUserServiceServer) ListUserSessions(context.Context, *ListUse
func (UnimplementedUserServiceServer) RevokeUserSession(context.Context, *RevokeUserSessionRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method RevokeUserSession not implemented")
}
func (UnimplementedUserServiceServer) ListUserWebhooks(context.Context, *ListUserWebhooksRequest) (*ListUserWebhooksResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListUserWebhooks not implemented")
}
func (UnimplementedUserServiceServer) CreateUserWebhook(context.Context, *CreateUserWebhookRequest) (*UserWebhook, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateUserWebhook not implemented")
}
func (UnimplementedUserServiceServer) UpdateUserWebhook(context.Context, *UpdateUserWebhookRequest) (*UserWebhook, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateUserWebhook not implemented")
}
func (UnimplementedUserServiceServer) DeleteUserWebhook(context.Context, *DeleteUserWebhookRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteUserWebhook not implemented")
}
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
@ -558,6 +648,24 @@ func _UserService_UpdateUserSetting_Handler(srv interface{}, ctx context.Context
return interceptor(ctx, in, info, handler)
}
func _UserService_ListUserSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUserSettingsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).ListUserSettings(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_ListUserSettings_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).ListUserSettings(ctx, req.(*ListUserSettingsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_ListUserAccessTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUserAccessTokensRequest)
if err := dec(in); err != nil {
@ -648,6 +756,78 @@ func _UserService_RevokeUserSession_Handler(srv interface{}, ctx context.Context
return interceptor(ctx, in, info, handler)
}
func _UserService_ListUserWebhooks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUserWebhooksRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).ListUserWebhooks(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_ListUserWebhooks_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).ListUserWebhooks(ctx, req.(*ListUserWebhooksRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_CreateUserWebhook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateUserWebhookRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).CreateUserWebhook(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_CreateUserWebhook_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).CreateUserWebhook(ctx, req.(*CreateUserWebhookRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_UpdateUserWebhook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateUserWebhookRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).UpdateUserWebhook(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_UpdateUserWebhook_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).UpdateUserWebhook(ctx, req.(*UpdateUserWebhookRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_DeleteUserWebhook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteUserWebhookRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).DeleteUserWebhook(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_DeleteUserWebhook_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).DeleteUserWebhook(ctx, req.(*DeleteUserWebhookRequest))
}
return interceptor(ctx, in, info, handler)
}
// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -699,6 +879,10 @@ var UserService_ServiceDesc = grpc.ServiceDesc{
MethodName: "UpdateUserSetting",
Handler: _UserService_UpdateUserSetting_Handler,
},
{
MethodName: "ListUserSettings",
Handler: _UserService_ListUserSettings_Handler,
},
{
MethodName: "ListUserAccessTokens",
Handler: _UserService_ListUserAccessTokens_Handler,
@ -719,6 +903,22 @@ var UserService_ServiceDesc = grpc.ServiceDesc{
MethodName: "RevokeUserSession",
Handler: _UserService_RevokeUserSession_Handler,
},
{
MethodName: "ListUserWebhooks",
Handler: _UserService_ListUserWebhooks_Handler,
},
{
MethodName: "CreateUserWebhook",
Handler: _UserService_CreateUserWebhook_Handler,
},
{
MethodName: "UpdateUserWebhook",
Handler: _UserService_UpdateUserWebhook_Handler,
},
{
MethodName: "DeleteUserWebhook",
Handler: _UserService_DeleteUserWebhook_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/v1/user_service.proto",

View File

@ -1,497 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc (unknown)
// source: api/v1/webhook_service.proto
package apiv1
import (
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Webhook struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The resource name of the webhook.
// Format: users/{user}/webhooks/{webhook}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// The display name of the webhook.
DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"`
// The target URL for the webhook.
Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Webhook) Reset() {
*x = Webhook{}
mi := &file_api_v1_webhook_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Webhook) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Webhook) ProtoMessage() {}
func (x *Webhook) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_service_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Webhook.ProtoReflect.Descriptor instead.
func (*Webhook) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{0}
}
func (x *Webhook) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Webhook) GetDisplayName() string {
if x != nil {
return x.DisplayName
}
return ""
}
func (x *Webhook) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
type ListWebhooksRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Required. The parent resource where webhooks are listed.
// Format: users/{user}
Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListWebhooksRequest) Reset() {
*x = ListWebhooksRequest{}
mi := &file_api_v1_webhook_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListWebhooksRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListWebhooksRequest) ProtoMessage() {}
func (x *ListWebhooksRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_service_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListWebhooksRequest.ProtoReflect.Descriptor instead.
func (*ListWebhooksRequest) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{1}
}
func (x *ListWebhooksRequest) GetParent() string {
if x != nil {
return x.Parent
}
return ""
}
type ListWebhooksResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The list of webhooks.
Webhooks []*Webhook `protobuf:"bytes,1,rep,name=webhooks,proto3" json:"webhooks,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListWebhooksResponse) Reset() {
*x = ListWebhooksResponse{}
mi := &file_api_v1_webhook_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListWebhooksResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListWebhooksResponse) ProtoMessage() {}
func (x *ListWebhooksResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_service_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListWebhooksResponse.ProtoReflect.Descriptor instead.
func (*ListWebhooksResponse) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{2}
}
func (x *ListWebhooksResponse) GetWebhooks() []*Webhook {
if x != nil {
return x.Webhooks
}
return nil
}
type GetWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Required. The resource name of the webhook to retrieve.
// Format: users/{user}/webhooks/{webhook}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetWebhookRequest) Reset() {
*x = GetWebhookRequest{}
mi := &file_api_v1_webhook_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetWebhookRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetWebhookRequest) ProtoMessage() {}
func (x *GetWebhookRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_service_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetWebhookRequest.ProtoReflect.Descriptor instead.
func (*GetWebhookRequest) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{3}
}
func (x *GetWebhookRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type CreateWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Required. The parent resource where this webhook will be created.
// Format: users/{user}
Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"`
// Required. The webhook to create.
Webhook *Webhook `protobuf:"bytes,2,opt,name=webhook,proto3" json:"webhook,omitempty"`
// Optional. If set, validate the request, but do not actually create the webhook.
ValidateOnly bool `protobuf:"varint,3,opt,name=validate_only,json=validateOnly,proto3" json:"validate_only,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateWebhookRequest) Reset() {
*x = CreateWebhookRequest{}
mi := &file_api_v1_webhook_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateWebhookRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateWebhookRequest) ProtoMessage() {}
func (x *CreateWebhookRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_service_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateWebhookRequest.ProtoReflect.Descriptor instead.
func (*CreateWebhookRequest) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{4}
}
func (x *CreateWebhookRequest) GetParent() string {
if x != nil {
return x.Parent
}
return ""
}
func (x *CreateWebhookRequest) GetWebhook() *Webhook {
if x != nil {
return x.Webhook
}
return nil
}
func (x *CreateWebhookRequest) GetValidateOnly() bool {
if x != nil {
return x.ValidateOnly
}
return false
}
type UpdateWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Required. The webhook resource which replaces the resource on the server.
Webhook *Webhook `protobuf:"bytes,1,opt,name=webhook,proto3" json:"webhook,omitempty"`
// Optional. The list of fields to update.
UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UpdateWebhookRequest) Reset() {
*x = UpdateWebhookRequest{}
mi := &file_api_v1_webhook_service_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateWebhookRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdateWebhookRequest) ProtoMessage() {}
func (x *UpdateWebhookRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_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 UpdateWebhookRequest.ProtoReflect.Descriptor instead.
func (*UpdateWebhookRequest) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{5}
}
func (x *UpdateWebhookRequest) GetWebhook() *Webhook {
if x != nil {
return x.Webhook
}
return nil
}
func (x *UpdateWebhookRequest) GetUpdateMask() *fieldmaskpb.FieldMask {
if x != nil {
return x.UpdateMask
}
return nil
}
type DeleteWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Required. The resource name of the webhook to delete.
// Format: users/{user}/webhooks/{webhook}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteWebhookRequest) Reset() {
*x = DeleteWebhookRequest{}
mi := &file_api_v1_webhook_service_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteWebhookRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteWebhookRequest) ProtoMessage() {}
func (x *DeleteWebhookRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_service_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteWebhookRequest.ProtoReflect.Descriptor instead.
func (*DeleteWebhookRequest) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{6}
}
func (x *DeleteWebhookRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
var File_api_v1_webhook_service_proto protoreflect.FileDescriptor
const file_api_v1_webhook_service_proto_rawDesc = "" +
"\n" +
"\x1capi/v1/webhook_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\"\xb0\x01\n" +
"\aWebhook\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12&\n" +
"\fdisplay_name\x18\x02 \x01(\tB\x03\xe0A\x02R\vdisplayName\x12\x15\n" +
"\x03url\x18\x03 \x01(\tB\x03\xe0A\x02R\x03url:M\xeaAJ\n" +
"\x14memos.api.v1/Webhook\x12\x1fusers/{user}/webhooks/{webhook}*\bwebhooks2\awebhook\"K\n" +
"\x13ListWebhooksRequest\x124\n" +
"\x06parent\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\x12\x14memos.api.v1/WebhookR\x06parent\"I\n" +
"\x14ListWebhooksResponse\x121\n" +
"\bwebhooks\x18\x01 \x03(\v2\x15.memos.api.v1.WebhookR\bwebhooks\"E\n" +
"\x11GetWebhookRequest\x120\n" +
"\x04name\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\n" +
"\x14memos.api.v1/WebhookR\x04name\"\xac\x01\n" +
"\x14CreateWebhookRequest\x124\n" +
"\x06parent\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\x12\x14memos.api.v1/WebhookR\x06parent\x124\n" +
"\awebhook\x18\x02 \x01(\v2\x15.memos.api.v1.WebhookB\x03\xe0A\x02R\awebhook\x12(\n" +
"\rvalidate_only\x18\x03 \x01(\bB\x03\xe0A\x01R\fvalidateOnly\"\x8e\x01\n" +
"\x14UpdateWebhookRequest\x124\n" +
"\awebhook\x18\x01 \x01(\v2\x15.memos.api.v1.WebhookB\x03\xe0A\x02R\awebhook\x12@\n" +
"\vupdate_mask\x18\x02 \x01(\v2\x1a.google.protobuf.FieldMaskB\x03\xe0A\x01R\n" +
"updateMask\"H\n" +
"\x14DeleteWebhookRequest\x120\n" +
"\x04name\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\n" +
"\x14memos.api.v1/WebhookR\x04name2\xc4\x05\n" +
"\x0eWebhookService\x12\x89\x01\n" +
"\fListWebhooks\x12!.memos.api.v1.ListWebhooksRequest\x1a\".memos.api.v1.ListWebhooksResponse\"2\xdaA\x06parent\x82\xd3\xe4\x93\x02#\x12!/api/v1/{parent=users/*}/webhooks\x12v\n" +
"\n" +
"GetWebhook\x12\x1f.memos.api.v1.GetWebhookRequest\x1a\x15.memos.api.v1.Webhook\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#\x12!/api/v1/{name=users/*/webhooks/*}\x12\x8f\x01\n" +
"\rCreateWebhook\x12\".memos.api.v1.CreateWebhookRequest\x1a\x15.memos.api.v1.Webhook\"C\xdaA\x0eparent,webhook\x82\xd3\xe4\x93\x02,:\awebhook\"!/api/v1/{parent=users/*}/webhooks\x12\x9c\x01\n" +
"\rUpdateWebhook\x12\".memos.api.v1.UpdateWebhookRequest\x1a\x15.memos.api.v1.Webhook\"P\xdaA\x13webhook,update_mask\x82\xd3\xe4\x93\x024:\awebhook2)/api/v1/{webhook.name=users/*/webhooks/*}\x12}\n" +
"\rDeleteWebhook\x12\".memos.api.v1.DeleteWebhookRequest\x1a\x16.google.protobuf.Empty\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#*!/api/v1/{name=users/*/webhooks/*}B\xab\x01\n" +
"\x10com.memos.api.v1B\x13WebhookServiceProtoP\x01Z0github.com/usememos/memos/proto/gen/api/v1;apiv1\xa2\x02\x03MAX\xaa\x02\fMemos.Api.V1\xca\x02\fMemos\\Api\\V1\xe2\x02\x18Memos\\Api\\V1\\GPBMetadata\xea\x02\x0eMemos::Api::V1b\x06proto3"
var (
file_api_v1_webhook_service_proto_rawDescOnce sync.Once
file_api_v1_webhook_service_proto_rawDescData []byte
)
func file_api_v1_webhook_service_proto_rawDescGZIP() []byte {
file_api_v1_webhook_service_proto_rawDescOnce.Do(func() {
file_api_v1_webhook_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_v1_webhook_service_proto_rawDesc), len(file_api_v1_webhook_service_proto_rawDesc)))
})
return file_api_v1_webhook_service_proto_rawDescData
}
var file_api_v1_webhook_service_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_api_v1_webhook_service_proto_goTypes = []any{
(*Webhook)(nil), // 0: memos.api.v1.Webhook
(*ListWebhooksRequest)(nil), // 1: memos.api.v1.ListWebhooksRequest
(*ListWebhooksResponse)(nil), // 2: memos.api.v1.ListWebhooksResponse
(*GetWebhookRequest)(nil), // 3: memos.api.v1.GetWebhookRequest
(*CreateWebhookRequest)(nil), // 4: memos.api.v1.CreateWebhookRequest
(*UpdateWebhookRequest)(nil), // 5: memos.api.v1.UpdateWebhookRequest
(*DeleteWebhookRequest)(nil), // 6: memos.api.v1.DeleteWebhookRequest
(*fieldmaskpb.FieldMask)(nil), // 7: google.protobuf.FieldMask
(*emptypb.Empty)(nil), // 8: google.protobuf.Empty
}
var file_api_v1_webhook_service_proto_depIdxs = []int32{
0, // 0: memos.api.v1.ListWebhooksResponse.webhooks:type_name -> memos.api.v1.Webhook
0, // 1: memos.api.v1.CreateWebhookRequest.webhook:type_name -> memos.api.v1.Webhook
0, // 2: memos.api.v1.UpdateWebhookRequest.webhook:type_name -> memos.api.v1.Webhook
7, // 3: memos.api.v1.UpdateWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask
1, // 4: memos.api.v1.WebhookService.ListWebhooks:input_type -> memos.api.v1.ListWebhooksRequest
3, // 5: memos.api.v1.WebhookService.GetWebhook:input_type -> memos.api.v1.GetWebhookRequest
4, // 6: memos.api.v1.WebhookService.CreateWebhook:input_type -> memos.api.v1.CreateWebhookRequest
5, // 7: memos.api.v1.WebhookService.UpdateWebhook:input_type -> memos.api.v1.UpdateWebhookRequest
6, // 8: memos.api.v1.WebhookService.DeleteWebhook:input_type -> memos.api.v1.DeleteWebhookRequest
2, // 9: memos.api.v1.WebhookService.ListWebhooks:output_type -> memos.api.v1.ListWebhooksResponse
0, // 10: memos.api.v1.WebhookService.GetWebhook:output_type -> memos.api.v1.Webhook
0, // 11: memos.api.v1.WebhookService.CreateWebhook:output_type -> memos.api.v1.Webhook
0, // 12: memos.api.v1.WebhookService.UpdateWebhook:output_type -> memos.api.v1.Webhook
8, // 13: memos.api.v1.WebhookService.DeleteWebhook:output_type -> google.protobuf.Empty
9, // [9:14] is the sub-list for method output_type
4, // [4:9] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_api_v1_webhook_service_proto_init() }
func file_api_v1_webhook_service_proto_init() {
if File_api_v1_webhook_service_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_webhook_service_proto_rawDesc), len(file_api_v1_webhook_service_proto_rawDesc)),
NumEnums: 0,
NumMessages: 7,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_api_v1_webhook_service_proto_goTypes,
DependencyIndexes: file_api_v1_webhook_service_proto_depIdxs,
MessageInfos: file_api_v1_webhook_service_proto_msgTypes,
}.Build()
File_api_v1_webhook_service_proto = out.File
file_api_v1_webhook_service_proto_goTypes = nil
file_api_v1_webhook_service_proto_depIdxs = nil
}

View File

@ -1,543 +0,0 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: api/v1/webhook_service.proto
/*
Package apiv1 is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package apiv1
import (
"context"
"errors"
"io"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// Suppress "imported and not used" errors
var (
_ codes.Code
_ io.Reader
_ status.Status
_ = errors.New
_ = runtime.String
_ = utilities.NewDoubleArray
_ = metadata.Join
)
func request_WebhookService_ListWebhooks_0(ctx context.Context, marshaler runtime.Marshaler, client WebhookServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListWebhooksRequest
metadata runtime.ServerMetadata
err error
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := client.ListWebhooks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_WebhookService_ListWebhooks_0(ctx context.Context, marshaler runtime.Marshaler, server WebhookServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListWebhooksRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := server.ListWebhooks(ctx, &protoReq)
return msg, metadata, err
}
func request_WebhookService_GetWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client WebhookServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetWebhookRequest
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.GetWebhook(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_WebhookService_GetWebhook_0(ctx context.Context, marshaler runtime.Marshaler, server WebhookServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetWebhookRequest
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.GetWebhook(ctx, &protoReq)
return msg, metadata, err
}
var filter_WebhookService_CreateWebhook_0 = &utilities.DoubleArray{Encoding: map[string]int{"webhook": 0, "parent": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
func request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client WebhookServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CreateWebhookRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WebhookService_CreateWebhook_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.CreateWebhook(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler runtime.Marshaler, server WebhookServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CreateWebhookRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WebhookService_CreateWebhook_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.CreateWebhook(ctx, &protoReq)
return msg, metadata, err
}
var filter_WebhookService_UpdateWebhook_0 = &utilities.DoubleArray{Encoding: map[string]int{"webhook": 0, "name": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}}
func request_WebhookService_UpdateWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client WebhookServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateWebhookRequest
metadata runtime.ServerMetadata
err error
)
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Webhook); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} else {
protoReq.UpdateMask = fieldMask
}
}
val, ok := pathParams["webhook.name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "webhook.name")
}
err = runtime.PopulateFieldFromPath(&protoReq, "webhook.name", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "webhook.name", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WebhookService_UpdateWebhook_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.UpdateWebhook(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_WebhookService_UpdateWebhook_0(ctx context.Context, marshaler runtime.Marshaler, server WebhookServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateWebhookRequest
metadata runtime.ServerMetadata
err error
)
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Webhook); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} else {
protoReq.UpdateMask = fieldMask
}
}
val, ok := pathParams["webhook.name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "webhook.name")
}
err = runtime.PopulateFieldFromPath(&protoReq, "webhook.name", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "webhook.name", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WebhookService_UpdateWebhook_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.UpdateWebhook(ctx, &protoReq)
return msg, metadata, err
}
func request_WebhookService_DeleteWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client WebhookServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq DeleteWebhookRequest
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.DeleteWebhook(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_WebhookService_DeleteWebhook_0(ctx context.Context, marshaler runtime.Marshaler, server WebhookServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq DeleteWebhookRequest
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.DeleteWebhook(ctx, &protoReq)
return msg, metadata, err
}
// RegisterWebhookServiceHandlerServer registers the http handlers for service WebhookService to "mux".
// UnaryRPC :call WebhookServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterWebhookServiceHandlerFromEndpoint instead.
// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server WebhookServiceServer) error {
mux.Handle(http.MethodGet, pattern_WebhookService_ListWebhooks_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.WebhookService/ListWebhooks", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_WebhookService_ListWebhooks_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_WebhookService_ListWebhooks_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_WebhookService_GetWebhook_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.WebhookService/GetWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_WebhookService_GetWebhook_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_WebhookService_GetWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_WebhookService_CreateWebhook_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.WebhookService/CreateWebhook", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_WebhookService_CreateWebhook_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_WebhookService_CreateWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPatch, pattern_WebhookService_UpdateWebhook_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.WebhookService/UpdateWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_WebhookService_UpdateWebhook_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_WebhookService_UpdateWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodDelete, pattern_WebhookService_DeleteWebhook_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.WebhookService/DeleteWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_WebhookService_DeleteWebhook_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_WebhookService_DeleteWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterWebhookServiceHandlerFromEndpoint is same as RegisterWebhookServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterWebhookServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.NewClient(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterWebhookServiceHandler(ctx, mux, conn)
}
// RegisterWebhookServiceHandler registers the http handlers for service WebhookService to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterWebhookServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterWebhookServiceHandlerClient(ctx, mux, NewWebhookServiceClient(conn))
}
// RegisterWebhookServiceHandlerClient registers the http handlers for service WebhookService
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "WebhookServiceClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "WebhookServiceClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "WebhookServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client WebhookServiceClient) error {
mux.Handle(http.MethodGet, pattern_WebhookService_ListWebhooks_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.WebhookService/ListWebhooks", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_WebhookService_ListWebhooks_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_WebhookService_ListWebhooks_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_WebhookService_GetWebhook_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.WebhookService/GetWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_WebhookService_GetWebhook_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_WebhookService_GetWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_WebhookService_CreateWebhook_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.WebhookService/CreateWebhook", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_WebhookService_CreateWebhook_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_WebhookService_CreateWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPatch, pattern_WebhookService_UpdateWebhook_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.WebhookService/UpdateWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_WebhookService_UpdateWebhook_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_WebhookService_UpdateWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodDelete, pattern_WebhookService_DeleteWebhook_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.WebhookService/DeleteWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_WebhookService_DeleteWebhook_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_WebhookService_DeleteWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_WebhookService_ListWebhooks_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", "parent", "webhooks"}, ""))
pattern_WebhookService_GetWebhook_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", "webhooks", "name"}, ""))
pattern_WebhookService_CreateWebhook_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", "parent", "webhooks"}, ""))
pattern_WebhookService_UpdateWebhook_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", "webhooks", "webhook.name"}, ""))
pattern_WebhookService_DeleteWebhook_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", "webhooks", "name"}, ""))
)
var (
forward_WebhookService_ListWebhooks_0 = runtime.ForwardResponseMessage
forward_WebhookService_GetWebhook_0 = runtime.ForwardResponseMessage
forward_WebhookService_CreateWebhook_0 = runtime.ForwardResponseMessage
forward_WebhookService_UpdateWebhook_0 = runtime.ForwardResponseMessage
forward_WebhookService_DeleteWebhook_0 = runtime.ForwardResponseMessage
)

View File

@ -1,284 +0,0 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc (unknown)
// source: api/v1/webhook_service.proto
package apiv1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
WebhookService_ListWebhooks_FullMethodName = "/memos.api.v1.WebhookService/ListWebhooks"
WebhookService_GetWebhook_FullMethodName = "/memos.api.v1.WebhookService/GetWebhook"
WebhookService_CreateWebhook_FullMethodName = "/memos.api.v1.WebhookService/CreateWebhook"
WebhookService_UpdateWebhook_FullMethodName = "/memos.api.v1.WebhookService/UpdateWebhook"
WebhookService_DeleteWebhook_FullMethodName = "/memos.api.v1.WebhookService/DeleteWebhook"
)
// WebhookServiceClient is the client API for WebhookService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type WebhookServiceClient interface {
// ListWebhooks returns a list of webhooks for a user.
ListWebhooks(ctx context.Context, in *ListWebhooksRequest, opts ...grpc.CallOption) (*ListWebhooksResponse, error)
// GetWebhook gets a webhook by name.
GetWebhook(ctx context.Context, in *GetWebhookRequest, opts ...grpc.CallOption) (*Webhook, error)
// CreateWebhook creates a new webhook for a user.
CreateWebhook(ctx context.Context, in *CreateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error)
// UpdateWebhook updates a webhook for a user.
UpdateWebhook(ctx context.Context, in *UpdateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error)
// DeleteWebhook deletes a webhook for a user.
DeleteWebhook(ctx context.Context, in *DeleteWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
type webhookServiceClient struct {
cc grpc.ClientConnInterface
}
func NewWebhookServiceClient(cc grpc.ClientConnInterface) WebhookServiceClient {
return &webhookServiceClient{cc}
}
func (c *webhookServiceClient) ListWebhooks(ctx context.Context, in *ListWebhooksRequest, opts ...grpc.CallOption) (*ListWebhooksResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListWebhooksResponse)
err := c.cc.Invoke(ctx, WebhookService_ListWebhooks_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *webhookServiceClient) GetWebhook(ctx context.Context, in *GetWebhookRequest, opts ...grpc.CallOption) (*Webhook, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Webhook)
err := c.cc.Invoke(ctx, WebhookService_GetWebhook_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *webhookServiceClient) CreateWebhook(ctx context.Context, in *CreateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Webhook)
err := c.cc.Invoke(ctx, WebhookService_CreateWebhook_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *webhookServiceClient) UpdateWebhook(ctx context.Context, in *UpdateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Webhook)
err := c.cc.Invoke(ctx, WebhookService_UpdateWebhook_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *webhookServiceClient) DeleteWebhook(ctx context.Context, in *DeleteWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, WebhookService_DeleteWebhook_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// WebhookServiceServer is the server API for WebhookService service.
// All implementations must embed UnimplementedWebhookServiceServer
// for forward compatibility.
type WebhookServiceServer interface {
// ListWebhooks returns a list of webhooks for a user.
ListWebhooks(context.Context, *ListWebhooksRequest) (*ListWebhooksResponse, error)
// GetWebhook gets a webhook by name.
GetWebhook(context.Context, *GetWebhookRequest) (*Webhook, error)
// CreateWebhook creates a new webhook for a user.
CreateWebhook(context.Context, *CreateWebhookRequest) (*Webhook, error)
// UpdateWebhook updates a webhook for a user.
UpdateWebhook(context.Context, *UpdateWebhookRequest) (*Webhook, error)
// DeleteWebhook deletes a webhook for a user.
DeleteWebhook(context.Context, *DeleteWebhookRequest) (*emptypb.Empty, error)
mustEmbedUnimplementedWebhookServiceServer()
}
// UnimplementedWebhookServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedWebhookServiceServer struct{}
func (UnimplementedWebhookServiceServer) ListWebhooks(context.Context, *ListWebhooksRequest) (*ListWebhooksResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListWebhooks not implemented")
}
func (UnimplementedWebhookServiceServer) GetWebhook(context.Context, *GetWebhookRequest) (*Webhook, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetWebhook not implemented")
}
func (UnimplementedWebhookServiceServer) CreateWebhook(context.Context, *CreateWebhookRequest) (*Webhook, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateWebhook not implemented")
}
func (UnimplementedWebhookServiceServer) UpdateWebhook(context.Context, *UpdateWebhookRequest) (*Webhook, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateWebhook not implemented")
}
func (UnimplementedWebhookServiceServer) DeleteWebhook(context.Context, *DeleteWebhookRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteWebhook not implemented")
}
func (UnimplementedWebhookServiceServer) mustEmbedUnimplementedWebhookServiceServer() {}
func (UnimplementedWebhookServiceServer) testEmbeddedByValue() {}
// UnsafeWebhookServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to WebhookServiceServer will
// result in compilation errors.
type UnsafeWebhookServiceServer interface {
mustEmbedUnimplementedWebhookServiceServer()
}
func RegisterWebhookServiceServer(s grpc.ServiceRegistrar, srv WebhookServiceServer) {
// If the following call pancis, it indicates UnimplementedWebhookServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&WebhookService_ServiceDesc, srv)
}
func _WebhookService_ListWebhooks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListWebhooksRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WebhookServiceServer).ListWebhooks(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WebhookService_ListWebhooks_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WebhookServiceServer).ListWebhooks(ctx, req.(*ListWebhooksRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WebhookService_GetWebhook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetWebhookRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WebhookServiceServer).GetWebhook(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WebhookService_GetWebhook_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WebhookServiceServer).GetWebhook(ctx, req.(*GetWebhookRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WebhookService_CreateWebhook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateWebhookRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WebhookServiceServer).CreateWebhook(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WebhookService_CreateWebhook_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WebhookServiceServer).CreateWebhook(ctx, req.(*CreateWebhookRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WebhookService_UpdateWebhook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateWebhookRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WebhookServiceServer).UpdateWebhook(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WebhookService_UpdateWebhook_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WebhookServiceServer).UpdateWebhook(ctx, req.(*UpdateWebhookRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WebhookService_DeleteWebhook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteWebhookRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WebhookServiceServer).DeleteWebhook(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WebhookService_DeleteWebhook_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WebhookServiceServer).DeleteWebhook(ctx, req.(*DeleteWebhookRequest))
}
return interceptor(ctx, in, info, handler)
}
// WebhookService_ServiceDesc is the grpc.ServiceDesc for WebhookService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var WebhookService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "memos.api.v1.WebhookService",
HandlerType: (*WebhookServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListWebhooks",
Handler: _WebhookService_ListWebhooks_Handler,
},
{
MethodName: "GetWebhook",
Handler: _WebhookService_GetWebhook_Handler,
},
{
MethodName: "CreateWebhook",
Handler: _WebhookService_CreateWebhook_Handler,
},
{
MethodName: "UpdateWebhook",
Handler: _WebhookService_UpdateWebhook_Handler,
},
{
MethodName: "DeleteWebhook",
Handler: _WebhookService_DeleteWebhook_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/v1/webhook_service.proto",
}

View File

@ -1644,6 +1644,124 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users/{user}/settings:
get:
tags:
- UserService
description: ListUserSettings returns a list of user settings.
operationId: UserService_ListUserSettings
parameters:
- name: user
in: path
description: The user id.
required: true
schema:
type: string
- name: pageSize
in: query
description: |-
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:
type: integer
format: int32
- name: pageToken
in: query
description: |-
Optional. A page token, received from a previous `ListUserSettings` call.
Provide this to retrieve the subsequent page.
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ListUserSettingsResponse'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users/{user}/settings/{setting}:
get:
tags:
- UserService
description: GetUserSetting returns the user setting.
operationId: UserService_GetUserSetting
parameters:
- name: user
in: path
description: The user id.
required: true
schema:
type: string
- name: setting
in: path
description: The setting id.
required: true
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserSetting'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
patch:
tags:
- UserService
description: UpdateUserSetting updates the user setting.
operationId: UserService_UpdateUserSetting
parameters:
- name: user
in: path
description: The user id.
required: true
schema:
type: string
- name: setting
in: path
description: The setting id.
required: true
schema:
type: string
- name: updateMask
in: query
description: Required. The list of fields to update.
schema:
type: string
format: field-mask
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UserSetting'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserSetting'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users/{user}/shortcuts:
get:
tags:
@ -1812,9 +1930,9 @@ paths:
/api/v1/users/{user}/webhooks:
get:
tags:
- WebhookService
description: ListWebhooks returns a list of webhooks for a user.
operationId: WebhookService_ListWebhooks
- UserService
description: ListUserWebhooks returns a list of webhooks for a user.
operationId: UserService_ListUserWebhooks
parameters:
- name: user
in: path
@ -1828,7 +1946,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/ListWebhooksResponse'
$ref: '#/components/schemas/ListUserWebhooksResponse'
default:
description: Default error response
content:
@ -1837,9 +1955,9 @@ paths:
$ref: '#/components/schemas/Status'
post:
tags:
- WebhookService
description: CreateWebhook creates a new webhook for a user.
operationId: WebhookService_CreateWebhook
- UserService
description: CreateUserWebhook creates a new webhook for a user.
operationId: UserService_CreateUserWebhook
parameters:
- name: user
in: path
@ -1847,16 +1965,11 @@ paths:
required: true
schema:
type: string
- name: validateOnly
in: query
description: Optional. If set, validate the request, but do not actually create the webhook.
schema:
type: boolean
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Webhook'
$ref: '#/components/schemas/UserWebhook'
required: true
responses:
"200":
@ -1864,7 +1977,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Webhook'
$ref: '#/components/schemas/UserWebhook'
default:
description: Default error response
content:
@ -1872,42 +1985,11 @@ paths:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users/{user}/webhooks/{webhook}:
get:
tags:
- WebhookService
description: GetWebhook gets a webhook by name.
operationId: WebhookService_GetWebhook
parameters:
- name: user
in: path
description: The user id.
required: true
schema:
type: string
- name: webhook
in: path
description: The webhook id.
required: true
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Webhook'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
delete:
tags:
- WebhookService
description: DeleteWebhook deletes a webhook for a user.
operationId: WebhookService_DeleteWebhook
- UserService
description: DeleteUserWebhook deletes a webhook for a user.
operationId: UserService_DeleteUserWebhook
parameters:
- name: user
in: path
@ -1933,9 +2015,9 @@ paths:
$ref: '#/components/schemas/Status'
patch:
tags:
- WebhookService
description: UpdateWebhook updates a webhook for a user.
operationId: WebhookService_UpdateWebhook
- UserService
description: UpdateUserWebhook updates an existing webhook for a user.
operationId: UserService_UpdateUserWebhook
parameters:
- name: user
in: path
@ -1951,7 +2033,7 @@ paths:
type: string
- name: updateMask
in: query
description: Optional. The list of fields to update.
description: The list of fields to update.
schema:
type: string
format: field-mask
@ -1959,7 +2041,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Webhook'
$ref: '#/components/schemas/UserWebhook'
required: true
responses:
"200":
@ -1967,33 +2049,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Webhook'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users/{user}:getSetting:
get:
tags:
- UserService
description: GetUserSetting returns the user setting.
operationId: UserService_GetUserSetting
parameters:
- name: user
in: path
description: The user id.
required: true
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserSetting'
$ref: '#/components/schemas/UserWebhook'
default:
description: Default error response
content:
@ -2026,44 +2082,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users/{user}:updateSetting:
patch:
tags:
- UserService
description: UpdateUserSetting updates the user setting.
operationId: UserService_UpdateUserSetting
parameters:
- name: user
in: path
description: The user id.
required: true
schema:
type: string
- name: updateMask
in: query
description: Required. The list of fields to update.
schema:
type: string
format: field-mask
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UserSetting'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserSetting'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/users:search:
get:
tags:
@ -2106,18 +2124,6 @@ paths:
- UserService
description: ListAllUserStats returns statistics for all users.
operationId: UserService_ListAllUserStats
parameters:
- name: pageSize
in: query
description: Optional. The maximum number of user stats 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
@ -2250,6 +2256,19 @@ paths:
$ref: '#/components/schemas/Status'
components:
schemas:
AccessTokensSetting_AccessToken:
type: object
properties:
accessToken:
readOnly: true
type: string
description: |-
The access token is a JWT token.
Including expiration time, issuer, etc.
description:
type: string
description: A description for the access token.
description: User access token information.
Activity:
type: object
properties:
@ -2685,18 +2704,11 @@ components:
ListAllUserStatsResponse:
type: object
properties:
userStats:
stats:
type: array
items:
$ref: '#/components/schemas/UserStats'
description: The list of user statistics.
nextPageToken:
type: string
description: A token for the next page of results.
totalSize:
type: integer
description: The total count of user statistics.
format: int32
ListAttachmentsResponse:
type: object
properties:
@ -2865,6 +2877,32 @@ components:
items:
$ref: '#/components/schemas/UserSession'
description: The list of user sessions.
ListUserSettingsResponse:
type: object
properties:
settings:
type: array
items:
$ref: '#/components/schemas/UserSetting'
description: The list of user settings.
nextPageToken:
type: string
description: |-
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:
type: integer
description: The total count of settings (may be approximate).
format: int32
description: Response message for ListUserSettings method.
ListUserWebhooksResponse:
type: object
properties:
webhooks:
type: array
items:
$ref: '#/components/schemas/UserWebhook'
description: The list of webhooks.
ListUsersResponse:
type: object
properties:
@ -2882,14 +2920,6 @@ components:
type: integer
description: The total count of users (may be approximate).
format: int32
ListWebhooksResponse:
type: object
properties:
webhooks:
type: array
items:
$ref: '#/components/schemas/Webhook'
description: The list of webhooks.
Location:
type: object
properties:
@ -3314,6 +3344,55 @@ components:
type: integer
description: The total count of matching users.
format: int32
SessionsSetting_ClientInfo:
type: object
properties:
userAgent:
readOnly: true
type: string
description: User agent string of the client.
ipAddress:
readOnly: true
type: string
description: IP address of the client.
deviceType:
readOnly: true
type: string
description: Optional. Device type (e.g., "mobile", "desktop", "tablet").
os:
readOnly: true
type: string
description: Optional. Operating system (e.g., "iOS 17.0", "Windows 11").
browser:
readOnly: true
type: string
description: Optional. Browser name and version (e.g., "Chrome 119.0").
description: Client information for a session.
SessionsSetting_Session:
type: object
properties:
sessionId:
readOnly: true
type: string
description: Unique session identifier.
createTime:
readOnly: true
type: string
description: Timestamp when the session was created.
format: date-time
lastAccessedTime:
readOnly: true
type: string
description: |-
Timestamp when the session was last accessed.
Used for sliding expiration calculation (last_accessed_time + 2 weeks).
format: date-time
clientInfo:
readOnly: true
allOf:
- $ref: '#/components/schemas/SessionsSetting_ClientInfo'
description: Client information associated with this session.
description: User session information.
SetMemoAttachmentsRequest:
required:
- name
@ -3362,6 +3441,23 @@ components:
filter:
type: string
description: The filter expression for the shortcut.
ShortcutsSetting_Shortcut:
required:
- id
- title
- filter
type: object
properties:
id:
type: string
description: Unique identifier for the shortcut.
title:
type: string
description: Display title for the shortcut.
filter:
type: string
description: Filter expression for the shortcut.
description: User shortcut definition.
SpoilerNode:
type: object
properties:
@ -3641,8 +3737,31 @@ components:
name:
type: string
description: |-
The resource name of the user whose setting this is.
Format: users/{user}
The name of the user setting.
Format: users/{user}/settings/{setting}
generalSetting:
$ref: '#/components/schemas/UserSetting_GeneralSetting'
sessionsSetting:
$ref: '#/components/schemas/UserSetting_SessionsSetting'
accessTokensSetting:
$ref: '#/components/schemas/UserSetting_AccessTokensSetting'
shortcutsSetting:
$ref: '#/components/schemas/UserSetting_ShortcutsSetting'
webhooksSetting:
$ref: '#/components/schemas/UserSetting_WebhooksSetting'
description: User settings message
UserSetting_AccessTokensSetting:
type: object
properties:
accessTokens:
type: array
items:
$ref: '#/components/schemas/AccessTokensSetting_AccessToken'
description: List of user access tokens.
description: User access tokens configuration.
UserSetting_GeneralSetting:
type: object
properties:
locale:
type: string
description: The preferred locale of the user.
@ -3658,7 +3777,34 @@ components:
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: User settings message
description: General user settings configuration.
UserSetting_SessionsSetting:
type: object
properties:
sessions:
type: array
items:
$ref: '#/components/schemas/SessionsSetting_Session'
description: List of active user sessions.
description: User authentication sessions configuration.
UserSetting_ShortcutsSetting:
type: object
properties:
shortcuts:
type: array
items:
$ref: '#/components/schemas/ShortcutsSetting_Shortcut'
description: List of user shortcuts.
description: User shortcuts configuration.
UserSetting_WebhooksSetting:
type: object
properties:
webhooks:
type: array
items:
$ref: '#/components/schemas/WebhooksSetting_Webhook'
description: List of user webhooks.
description: User webhooks configuration.
UserStats:
type: object
properties:
@ -3709,23 +3855,48 @@ components:
type: integer
format: int32
description: Memo type statistics.
Webhook:
required:
- displayName
- url
UserWebhook:
type: object
properties:
name:
type: string
description: |-
The resource name of the webhook.
The name of the webhook.
Format: users/{user}/webhooks/{webhook}
displayName:
type: string
description: The display name of the webhook.
url:
type: string
description: The target URL for the webhook.
description: The URL to send the webhook to.
displayName:
type: string
description: Optional. Human-readable name for the webhook.
createTime:
readOnly: true
type: string
description: The creation time of the webhook.
format: date-time
updateTime:
readOnly: true
type: string
description: The last update time of the webhook.
format: date-time
description: UserWebhook represents a webhook owned by a user.
WebhooksSetting_Webhook:
required:
- id
- title
- url
type: object
properties:
id:
type: string
description: Unique identifier for the webhook.
title:
type: string
description: Descriptive title for the webhook.
url:
type: string
description: The webhook URL endpoint.
description: User webhook definition.
WorkspaceProfile:
type: object
properties:
@ -3871,5 +4042,4 @@ tags:
- name: MemoService
- name: ShortcutService
- name: UserService
- name: WebhookService
- name: WorkspaceService

View File

@ -1,406 +0,0 @@
package v1
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/fieldmaskpb"
v1pb "github.com/usememos/memos/proto/gen/api/v1"
)
func TestCreateWebhook(t *testing.T) {
ctx := context.Background()
t.Run("CreateWebhook with host user", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create and authenticate as host user
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook
req := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook",
Url: "https://example.com/webhook",
},
}
resp, err := ts.Service.CreateWebhook(userCtx, req)
// Verify response
require.NoError(t, err)
require.NotNil(t, resp)
require.Equal(t, "Test Webhook", resp.DisplayName)
require.Equal(t, "https://example.com/webhook", resp.Url)
require.Contains(t, resp.Name, "webhooks/")
require.Contains(t, resp.Name, fmt.Sprintf("users/%d", hostUser.ID))
})
t.Run("CreateWebhook fails without authentication", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Try to create webhook without authentication
req := &v1pb.CreateWebhookRequest{
Parent: "users/1", // Dummy parent since we don't have a real user
Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook",
Url: "https://example.com/webhook",
},
}
_, err := ts.Service.CreateWebhook(ctx, req)
// Should fail with permission denied or unauthenticated
require.Error(t, err)
})
t.Run("CreateWebhook fails with regular user", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create and authenticate as regular user
regularUser, err := ts.CreateRegularUser(ctx, "user1")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, regularUser.ID)
// Try to create webhook as regular user
req := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", regularUser.ID),
Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook",
Url: "https://example.com/webhook",
},
}
_, err = ts.Service.CreateWebhook(userCtx, req)
// Should fail with permission denied
require.Error(t, err)
require.Contains(t, err.Error(), "permission denied")
})
t.Run("CreateWebhook validates required fields", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create and authenticate as host user
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Try to create webhook with missing URL
req := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook",
// URL missing
},
}
_, err = ts.Service.CreateWebhook(userCtx, req)
// Should fail with validation error
require.Error(t, err)
})
}
func TestListWebhooks(t *testing.T) {
ctx := context.Background()
t.Run("ListWebhooks returns empty list initially", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user for authentication
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// List webhooks
req := &v1pb.ListWebhooksRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
}
resp, err := ts.Service.ListWebhooks(userCtx, req)
// Verify response
require.NoError(t, err)
require.NotNil(t, resp)
require.Empty(t, resp.Webhooks)
})
t.Run("ListWebhooks returns created webhooks", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user and authenticate
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook
createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook",
Url: "https://example.com/webhook",
},
}
createdWebhook, err := ts.Service.CreateWebhook(userCtx, createReq)
require.NoError(t, err)
// List webhooks
listReq := &v1pb.ListWebhooksRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
}
resp, err := ts.Service.ListWebhooks(userCtx, listReq)
// Verify response
require.NoError(t, err)
require.NotNil(t, resp)
require.Len(t, resp.Webhooks, 1)
require.Equal(t, createdWebhook.Name, resp.Webhooks[0].Name)
require.Equal(t, createdWebhook.Url, resp.Webhooks[0].Url)
})
t.Run("ListWebhooks fails without authentication", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Try to list webhooks without authentication
req := &v1pb.ListWebhooksRequest{
Parent: "users/1", // Dummy parent since we don't have a real user
}
_, err := ts.Service.ListWebhooks(ctx, req)
// Should fail with permission denied or unauthenticated
require.Error(t, err)
})
}
func TestGetWebhook(t *testing.T) {
ctx := context.Background()
t.Run("GetWebhook returns webhook by name", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user and authenticate
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook
createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook",
Url: "https://example.com/webhook",
},
}
createdWebhook, err := ts.Service.CreateWebhook(userCtx, createReq)
require.NoError(t, err)
// Get the webhook
getReq := &v1pb.GetWebhookRequest{
Name: createdWebhook.Name,
}
resp, err := ts.Service.GetWebhook(userCtx, getReq)
// Verify response
require.NoError(t, err)
require.NotNil(t, resp)
require.Equal(t, createdWebhook.Name, resp.Name)
require.Equal(t, createdWebhook.Url, resp.Url)
})
t.Run("GetWebhook fails with invalid name", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user and authenticate
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Try to get webhook with invalid name
req := &v1pb.GetWebhookRequest{
Name: "invalid/webhook/name",
}
_, err = ts.Service.GetWebhook(userCtx, req)
// Should return an error
require.Error(t, err)
})
t.Run("GetWebhook fails with non-existent webhook", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user and authenticate
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Try to get non-existent webhook
req := &v1pb.GetWebhookRequest{
Name: fmt.Sprintf("users/%d/webhooks/999", hostUser.ID),
}
_, err = ts.Service.GetWebhook(userCtx, req)
// Should return not found error
require.Error(t, err)
require.Contains(t, err.Error(), "not found")
})
}
func TestUpdateWebhook(t *testing.T) {
ctx := context.Background()
t.Run("UpdateWebhook updates webhook properties", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user and authenticate
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook
createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{
DisplayName: "Original Webhook",
Url: "https://example.com/webhook",
},
}
createdWebhook, err := ts.Service.CreateWebhook(userCtx, createReq)
require.NoError(t, err)
// Update the webhook
updateReq := &v1pb.UpdateWebhookRequest{
Webhook: &v1pb.Webhook{
Name: createdWebhook.Name,
Url: "https://updated.example.com/webhook",
},
UpdateMask: &fieldmaskpb.FieldMask{
Paths: []string{"url"},
},
}
resp, err := ts.Service.UpdateWebhook(userCtx, updateReq)
// Verify response
require.NoError(t, err)
require.NotNil(t, resp)
require.Equal(t, createdWebhook.Name, resp.Name)
require.Equal(t, "https://updated.example.com/webhook", resp.Url)
})
t.Run("UpdateWebhook fails without authentication", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Try to update webhook without authentication
req := &v1pb.UpdateWebhookRequest{
Webhook: &v1pb.Webhook{
Name: "users/1/webhooks/1",
Url: "https://updated.example.com/webhook",
},
}
_, err := ts.Service.UpdateWebhook(ctx, req)
// Should fail with permission denied or unauthenticated
require.Error(t, err)
})
}
func TestDeleteWebhook(t *testing.T) {
ctx := context.Background()
t.Run("DeleteWebhook removes webhook", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user and authenticate
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook
createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook",
Url: "https://example.com/webhook",
},
}
createdWebhook, err := ts.Service.CreateWebhook(userCtx, createReq)
require.NoError(t, err)
// Delete the webhook
deleteReq := &v1pb.DeleteWebhookRequest{
Name: createdWebhook.Name,
}
_, err = ts.Service.DeleteWebhook(userCtx, deleteReq)
// Verify deletion
require.NoError(t, err)
// Try to get the deleted webhook
getReq := &v1pb.GetWebhookRequest{
Name: createdWebhook.Name,
}
_, err = ts.Service.GetWebhook(userCtx, getReq)
// Should return not found error
require.Error(t, err)
require.Contains(t, err.Error(), "not found")
})
t.Run("DeleteWebhook fails without authentication", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Try to delete webhook without authentication
req := &v1pb.DeleteWebhookRequest{
Name: "users/1/webhooks/1",
}
_, err := ts.Service.DeleteWebhook(ctx, req)
// Should fail with permission denied or unauthenticated
require.Error(t, err)
})
t.Run("DeleteWebhook fails with non-existent webhook", func(t *testing.T) {
// Create test service for this specific test
ts := NewTestService(t)
defer ts.Cleanup()
// Create host user and authenticate
hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Try to delete non-existent webhook
req := &v1pb.DeleteWebhookRequest{
Name: fmt.Sprintf("users/%d/webhooks/999", hostUser.ID),
}
_, err = ts.Service.DeleteWebhook(userCtx, req)
// Should return not found error
require.Error(t, err)
require.Contains(t, err.Error(), "not found")
})
}

View File

@ -2,11 +2,14 @@ package v1
import (
"context"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"fmt"
"net/http"
"regexp"
"slices"
"strconv"
"strings"
"time"
@ -21,6 +24,7 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/usememos/memos/internal/base"
"github.com/usememos/memos/internal/util"
v1pb "github.com/usememos/memos/proto/gen/api/v1"
storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/store"
@ -329,9 +333,8 @@ func (s *APIV1Service) DeleteUser(ctx context.Context, request *v1pb.DeleteUserR
return &emptypb.Empty{}, nil
}
func getDefaultUserSetting() *v1pb.UserSetting {
return &v1pb.UserSetting{
Name: "", // Will be set by caller
func getDefaultUserGeneralSetting() *v1pb.UserSetting_GeneralSetting {
return &v1pb.UserSetting_GeneralSetting{
Locale: "en",
Appearance: "system",
MemoVisibility: "PRIVATE",
@ -340,9 +343,10 @@ func getDefaultUserSetting() *v1pb.UserSetting {
}
func (s *APIV1Service) GetUserSetting(ctx context.Context, request *v1pb.GetUserSettingRequest) (*v1pb.UserSetting, error) {
userID, err := ExtractUserIDFromName(request.Name)
// Parse resource name: users/{user}/settings/{setting}
userID, settingKey, err := ExtractUserIDAndSettingKeyFromName(request.Name)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err)
return nil, status.Errorf(codes.InvalidArgument, "invalid resource name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
@ -355,49 +359,28 @@ func (s *APIV1Service) GetUserSetting(ctx context.Context, request *v1pb.GetUser
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
userSettings, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{
// Convert setting key string to store enum
storeKey, err := convertSettingKeyToStore(settingKey)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid setting key: %v", err)
}
userSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storeKey,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list user settings: %v", err)
return nil, status.Errorf(codes.Internal, "failed to get user setting: %v", err)
}
userSettingMessage := getDefaultUserSetting()
userSettingMessage.Name = fmt.Sprintf("users/%d", userID)
for _, setting := range userSettings {
if setting.Key == storepb.UserSetting_GENERAL {
general := setting.GetGeneral()
if general != nil {
userSettingMessage.Locale = general.Locale
userSettingMessage.Appearance = general.Appearance
userSettingMessage.MemoVisibility = general.MemoVisibility
userSettingMessage.Theme = general.Theme
}
}
}
// Backfill theme if empty: use workspace theme or default to "default"
if userSettingMessage.Theme == "" {
workspaceGeneralSetting, err := s.Store.GetWorkspaceGeneralSetting(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get workspace general setting: %v", err)
}
workspaceTheme := workspaceGeneralSetting.Theme
if workspaceTheme == "" {
workspaceTheme = "default"
}
userSettingMessage.Theme = workspaceTheme
}
return userSettingMessage, nil
return convertUserSettingFromStore(userSetting, userID, storeKey), nil
}
func (s *APIV1Service) UpdateUserSetting(ctx context.Context, request *v1pb.UpdateUserSettingRequest) (*v1pb.UserSetting, error) {
// Extract user ID from the setting resource name
userID, err := ExtractUserIDFromName(request.Setting.Name)
// Parse resource name: users/{user}/settings/{setting}
userID, settingKey, err := ExtractUserIDAndSettingKeyFromName(request.Setting.Name)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err)
return nil, status.Errorf(codes.InvalidArgument, "invalid resource name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
@ -414,62 +397,83 @@ func (s *APIV1Service) UpdateUserSetting(ctx context.Context, request *v1pb.Upda
return nil, status.Errorf(codes.InvalidArgument, "update mask is empty")
}
// Get the current general setting
existingGeneralSetting, err := s.Store.GetUserSetting(ctx, &store.FindUserSetting{
UserID: &userID,
Key: storepb.UserSetting_GENERAL,
})
// Convert setting key string to store enum
storeKey, err := convertSettingKeyToStore(settingKey)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get existing general setting: %v", err)
return nil, status.Errorf(codes.InvalidArgument, "invalid setting key: %v", err)
}
// Create or update the general setting
generalSetting := &storepb.GeneralUserSetting{
Locale: "en",
Appearance: "system",
MemoVisibility: "PRIVATE",
Theme: "",
// Convert API setting to store setting
storeSetting, err := convertUserSettingToStore(request.Setting, userID, storeKey)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to convert setting: %v", err)
}
// If there's an existing setting, use its values as defaults
if existingGeneralSetting != nil && existingGeneralSetting.GetGeneral() != nil {
existing := existingGeneralSetting.GetGeneral()
generalSetting.Locale = existing.Locale
generalSetting.Appearance = existing.Appearance
generalSetting.MemoVisibility = existing.MemoVisibility
generalSetting.Theme = existing.Theme
}
// Apply updates based on the update mask
for _, field := range request.UpdateMask.Paths {
switch field {
case "locale":
generalSetting.Locale = request.Setting.Locale
case "appearance":
generalSetting.Appearance = request.Setting.Appearance
case "memo_visibility":
generalSetting.MemoVisibility = request.Setting.MemoVisibility
case "theme":
generalSetting.Theme = request.Setting.Theme
default:
return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field)
}
}
// Upsert the general setting
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSetting_GENERAL,
Value: &storepb.UserSetting_General{
General: generalSetting,
},
}); err != nil {
// Upsert the setting
if _, err := s.Store.UpsertUserSetting(ctx, storeSetting); err != nil {
return nil, status.Errorf(codes.Internal, "failed to upsert user setting: %v", err)
}
return s.GetUserSetting(ctx, &v1pb.GetUserSettingRequest{Name: request.Setting.Name})
}
func (s *APIV1Service) ListUserSettings(ctx context.Context, request *v1pb.ListUserSettingsRequest) (*v1pb.ListUserSettingsResponse, error) {
userID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid parent name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
}
// Only allow user to list their own settings
if currentUser.ID != userID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
userSettings, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{
UserID: &userID,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list user settings: %v", err)
}
settings := make([]*v1pb.UserSetting, 0, len(userSettings))
for _, storeSetting := range userSettings {
apiSetting := convertUserSettingFromStore(storeSetting, userID, storeSetting.Key)
if apiSetting != nil {
settings = append(settings, apiSetting)
}
}
// If no general setting exists, add a default one
hasGeneral := false
for _, setting := range settings {
if setting.GetGeneralSetting() != nil {
hasGeneral = true
break
}
}
if !hasGeneral {
defaultGeneral := &v1pb.UserSetting{
Name: fmt.Sprintf("users/%d/settings/general", userID),
Value: &v1pb.UserSetting_GeneralSetting_{
GeneralSetting: getDefaultUserGeneralSetting(),
},
}
settings = append([]*v1pb.UserSetting{defaultGeneral}, settings...)
}
response := &v1pb.ListUserSettingsResponse{
Settings: settings,
TotalSize: int32(len(settings)),
}
return response, nil
}
func (s *APIV1Service) ListUserAccessTokens(ctx context.Context, request *v1pb.ListUserAccessTokensRequest) (*v1pb.ListUserAccessTokensResponse, error) {
userID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
@ -767,6 +771,216 @@ func (s *APIV1Service) UpsertAccessTokenToStore(ctx context.Context, user *store
return nil
}
func (s *APIV1Service) ListUserWebhooks(ctx context.Context, request *v1pb.ListUserWebhooksRequest) (*v1pb.ListUserWebhooksResponse, error) {
userID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
webhooks, err := s.Store.GetUserWebhooks(ctx, userID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user webhooks: %v", err)
}
userWebhooks := make([]*v1pb.UserWebhook, 0, len(webhooks))
for _, webhook := range webhooks {
userWebhooks = append(userWebhooks, convertUserWebhookFromUserSetting(webhook, userID))
}
return &v1pb.ListUserWebhooksResponse{
Webhooks: userWebhooks,
}, nil
}
func (s *APIV1Service) CreateUserWebhook(ctx context.Context, request *v1pb.CreateUserWebhookRequest) (*v1pb.UserWebhook, error) {
userID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
if request.Webhook.Url == "" {
return nil, status.Errorf(codes.InvalidArgument, "webhook URL is required")
}
webhookID := generateUserWebhookID()
webhook := &storepb.WebhooksUserSetting_Webhook{
Id: webhookID,
Title: request.Webhook.DisplayName,
Url: strings.TrimSpace(request.Webhook.Url),
}
err = s.Store.AddUserWebhook(ctx, userID, webhook)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create webhook: %v", err)
}
return convertUserWebhookFromUserSetting(webhook, userID), nil
}
func (s *APIV1Service) UpdateUserWebhook(ctx context.Context, request *v1pb.UpdateUserWebhookRequest) (*v1pb.UserWebhook, error) {
if request.Webhook == nil {
return nil, status.Errorf(codes.InvalidArgument, "webhook is required")
}
webhookID, userID, err := parseUserWebhookName(request.Webhook.Name)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Get existing webhooks
webhooks, err := s.Store.GetUserWebhooks(ctx, userID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user webhooks: %v", err)
}
// Find the webhook to update
var targetWebhook *storepb.WebhooksUserSetting_Webhook
for _, webhook := range webhooks {
if webhook.Id == webhookID {
targetWebhook = webhook
break
}
}
if targetWebhook == nil {
return nil, status.Errorf(codes.NotFound, "webhook not found")
}
// Update the webhook
updatedWebhook := &storepb.WebhooksUserSetting_Webhook{
Id: webhookID,
Title: targetWebhook.Title,
Url: targetWebhook.Url,
}
if request.UpdateMask != nil {
for _, path := range request.UpdateMask.Paths {
switch path {
case "url":
if request.Webhook.Url != "" {
updatedWebhook.Url = strings.TrimSpace(request.Webhook.Url)
}
case "display_name":
updatedWebhook.Title = request.Webhook.DisplayName
}
}
} else {
// If no update mask is provided, update all fields
if request.Webhook.Url != "" {
updatedWebhook.Url = strings.TrimSpace(request.Webhook.Url)
}
updatedWebhook.Title = request.Webhook.DisplayName
}
err = s.Store.UpdateUserWebhook(ctx, userID, updatedWebhook)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to update webhook: %v", err)
}
return convertUserWebhookFromUserSetting(updatedWebhook, userID), nil
}
func (s *APIV1Service) DeleteUserWebhook(ctx context.Context, request *v1pb.DeleteUserWebhookRequest) (*emptypb.Empty, error) {
webhookID, userID, err := parseUserWebhookName(request.Name)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Get existing webhooks to verify the webhook exists
webhooks, err := s.Store.GetUserWebhooks(ctx, userID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user webhooks: %v", err)
}
// Check if webhook exists
found := false
for _, webhook := range webhooks {
if webhook.Id == webhookID {
found = true
break
}
}
if !found {
return nil, status.Errorf(codes.NotFound, "webhook not found")
}
err = s.Store.RemoveUserWebhook(ctx, userID, webhookID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to delete webhook: %v", err)
}
return &emptypb.Empty{}, nil
}
// Helper functions for webhook operations
// generateUserWebhookID generates a unique ID for user webhooks
func generateUserWebhookID() string {
b := make([]byte, 8)
rand.Read(b)
return hex.EncodeToString(b)
}
// parseUserWebhookName parses a webhook name and returns the webhook ID and user ID
// Format: users/{user}/webhooks/{webhook}
func parseUserWebhookName(name string) (string, int32, error) {
parts := strings.Split(name, "/")
if len(parts) != 4 || parts[0] != "users" || parts[2] != "webhooks" {
return "", 0, errors.New("invalid webhook name format")
}
userID, err := strconv.ParseInt(parts[1], 10, 32)
if err != nil {
return "", 0, errors.New("invalid user ID in webhook name")
}
return parts[3], int32(userID), nil
}
// convertUserWebhookFromUserSetting converts a storepb webhook to a v1pb UserWebhook
func convertUserWebhookFromUserSetting(webhook *storepb.WebhooksUserSetting_Webhook, userID int32) *v1pb.UserWebhook {
return &v1pb.UserWebhook{
Name: fmt.Sprintf("users/%d/webhooks/%s", userID, webhook.Id),
Url: webhook.Url,
DisplayName: webhook.Title,
// Note: create_time and update_time are not available in the user setting webhook structure
// This is a limitation of storing webhooks in user settings vs the dedicated webhook table
}
}
func convertUserFromStore(user *store.User) *v1pb.User {
userpb := &v1pb.User{
Name: fmt.Sprintf("%s%d", UserNamePrefix, user.ID),
@ -829,3 +1043,307 @@ func extractImageInfo(dataURI string) (string, string, error) {
base64Data := matches[2]
return imageType, base64Data, nil
}
// Helper functions for user settings
// ExtractUserIDAndSettingKeyFromName extracts user ID and setting key from resource name
// e.g., "users/123/settings/general" -> 123, "general"
func ExtractUserIDAndSettingKeyFromName(name string) (int32, string, error) {
// Expected format: users/{user}/settings/{setting}
parts := strings.Split(name, "/")
if len(parts) != 4 || parts[0] != "users" || parts[2] != "settings" {
return 0, "", errors.Errorf("invalid resource name format: %s", name)
}
userID, err := util.ConvertStringToInt32(parts[1])
if err != nil {
return 0, "", errors.Errorf("invalid user ID: %s", parts[1])
}
settingKey := parts[3]
return userID, settingKey, nil
}
// convertSettingKeyToStore converts API setting key to store enum
func convertSettingKeyToStore(key string) (storepb.UserSetting_Key, error) {
switch key {
case "general":
return storepb.UserSetting_GENERAL, nil
case "sessions":
return storepb.UserSetting_SESSIONS, nil
case "access-tokens":
return storepb.UserSetting_ACCESS_TOKENS, nil
case "shortcuts":
return storepb.UserSetting_SHORTCUTS, nil
case "webhooks":
return storepb.UserSetting_WEBHOOKS, nil
default:
return storepb.UserSetting_KEY_UNSPECIFIED, errors.Errorf("unknown setting key: %s", key)
}
}
// convertSettingKeyFromStore converts store enum to API setting key
func convertSettingKeyFromStore(key storepb.UserSetting_Key) string {
switch key {
case storepb.UserSetting_GENERAL:
return "general"
case storepb.UserSetting_SESSIONS:
return "sessions"
case storepb.UserSetting_ACCESS_TOKENS:
return "access-tokens"
case storepb.UserSetting_SHORTCUTS:
return "shortcuts"
case storepb.UserSetting_WEBHOOKS:
return "webhooks"
default:
return "unknown"
}
}
// convertUserSettingFromStore converts store UserSetting to API UserSetting
func convertUserSettingFromStore(storeSetting *storepb.UserSetting, userID int32, key storepb.UserSetting_Key) *v1pb.UserSetting {
if storeSetting == nil {
// Return default setting if none exists
settingKey := convertSettingKeyFromStore(key)
setting := &v1pb.UserSetting{
Name: fmt.Sprintf("users/%d/settings/%s", userID, settingKey),
}
switch key {
case storepb.UserSetting_GENERAL:
setting.Value = &v1pb.UserSetting_GeneralSetting_{
GeneralSetting: getDefaultUserGeneralSetting(),
}
case storepb.UserSetting_SESSIONS:
setting.Value = &v1pb.UserSetting_SessionsSetting_{
SessionsSetting: &v1pb.UserSetting_SessionsSetting{
Sessions: []*v1pb.UserSetting_SessionsSetting_Session{},
},
}
case storepb.UserSetting_ACCESS_TOKENS:
setting.Value = &v1pb.UserSetting_AccessTokensSetting_{
AccessTokensSetting: &v1pb.UserSetting_AccessTokensSetting{
AccessTokens: []*v1pb.UserSetting_AccessTokensSetting_AccessToken{},
},
}
case storepb.UserSetting_SHORTCUTS:
setting.Value = &v1pb.UserSetting_ShortcutsSetting_{
ShortcutsSetting: &v1pb.UserSetting_ShortcutsSetting{
Shortcuts: []*v1pb.UserSetting_ShortcutsSetting_Shortcut{},
},
}
case storepb.UserSetting_WEBHOOKS:
setting.Value = &v1pb.UserSetting_WebhooksSetting_{
WebhooksSetting: &v1pb.UserSetting_WebhooksSetting{
Webhooks: []*v1pb.UserSetting_WebhooksSetting_Webhook{},
},
}
}
return setting
}
settingKey := convertSettingKeyFromStore(storeSetting.Key)
setting := &v1pb.UserSetting{
Name: fmt.Sprintf("users/%d/settings/%s", userID, settingKey),
}
switch storeSetting.Key {
case storepb.UserSetting_GENERAL:
if general := storeSetting.GetGeneral(); general != nil {
setting.Value = &v1pb.UserSetting_GeneralSetting_{
GeneralSetting: &v1pb.UserSetting_GeneralSetting{
Locale: general.Locale,
Appearance: general.Appearance,
MemoVisibility: general.MemoVisibility,
Theme: general.Theme,
},
}
} else {
setting.Value = &v1pb.UserSetting_GeneralSetting_{
GeneralSetting: getDefaultUserGeneralSetting(),
}
}
case storepb.UserSetting_SESSIONS:
sessions := storeSetting.GetSessions()
apiSessions := make([]*v1pb.UserSetting_SessionsSetting_Session, 0, len(sessions.Sessions))
for _, session := range sessions.Sessions {
apiSession := &v1pb.UserSetting_SessionsSetting_Session{
SessionId: session.SessionId,
CreateTime: session.CreateTime,
LastAccessedTime: session.LastAccessedTime,
ClientInfo: &v1pb.UserSetting_SessionsSetting_ClientInfo{
UserAgent: session.ClientInfo.UserAgent,
IpAddress: session.ClientInfo.IpAddress,
DeviceType: session.ClientInfo.DeviceType,
Os: session.ClientInfo.Os,
Browser: session.ClientInfo.Browser,
},
}
apiSessions = append(apiSessions, apiSession)
}
setting.Value = &v1pb.UserSetting_SessionsSetting_{
SessionsSetting: &v1pb.UserSetting_SessionsSetting{
Sessions: apiSessions,
},
}
case storepb.UserSetting_ACCESS_TOKENS:
accessTokens := storeSetting.GetAccessTokens()
apiTokens := make([]*v1pb.UserSetting_AccessTokensSetting_AccessToken, 0, len(accessTokens.AccessTokens))
for _, token := range accessTokens.AccessTokens {
apiToken := &v1pb.UserSetting_AccessTokensSetting_AccessToken{
AccessToken: token.AccessToken,
Description: token.Description,
}
apiTokens = append(apiTokens, apiToken)
}
setting.Value = &v1pb.UserSetting_AccessTokensSetting_{
AccessTokensSetting: &v1pb.UserSetting_AccessTokensSetting{
AccessTokens: apiTokens,
},
}
case storepb.UserSetting_SHORTCUTS:
shortcuts := storeSetting.GetShortcuts()
apiShortcuts := make([]*v1pb.UserSetting_ShortcutsSetting_Shortcut, 0, len(shortcuts.Shortcuts))
for _, shortcut := range shortcuts.Shortcuts {
apiShortcut := &v1pb.UserSetting_ShortcutsSetting_Shortcut{
Id: shortcut.Id,
Title: shortcut.Title,
Filter: shortcut.Filter,
}
apiShortcuts = append(apiShortcuts, apiShortcut)
}
setting.Value = &v1pb.UserSetting_ShortcutsSetting_{
ShortcutsSetting: &v1pb.UserSetting_ShortcutsSetting{
Shortcuts: apiShortcuts,
},
}
case storepb.UserSetting_WEBHOOKS:
webhooks := storeSetting.GetWebhooks()
apiWebhooks := make([]*v1pb.UserSetting_WebhooksSetting_Webhook, 0, len(webhooks.Webhooks))
for _, webhook := range webhooks.Webhooks {
apiWebhook := &v1pb.UserSetting_WebhooksSetting_Webhook{
Id: webhook.Id,
Title: webhook.Title,
Url: webhook.Url,
}
apiWebhooks = append(apiWebhooks, apiWebhook)
}
setting.Value = &v1pb.UserSetting_WebhooksSetting_{
WebhooksSetting: &v1pb.UserSetting_WebhooksSetting{
Webhooks: apiWebhooks,
},
}
}
return setting
}
// convertUserSettingToStore converts API UserSetting to store UserSetting
func convertUserSettingToStore(apiSetting *v1pb.UserSetting, userID int32, key storepb.UserSetting_Key) (*storepb.UserSetting, error) {
storeSetting := &storepb.UserSetting{
UserId: userID,
Key: key,
}
switch key {
case storepb.UserSetting_GENERAL:
if general := apiSetting.GetGeneralSetting(); general != nil {
storeSetting.Value = &storepb.UserSetting_General{
General: &storepb.GeneralUserSetting{
Locale: general.Locale,
Appearance: general.Appearance,
MemoVisibility: general.MemoVisibility,
Theme: general.Theme,
},
}
} else {
return nil, errors.Errorf("general setting is required")
}
case storepb.UserSetting_SESSIONS:
if sessions := apiSetting.GetSessionsSetting(); sessions != nil {
storeSessions := make([]*storepb.SessionsUserSetting_Session, 0, len(sessions.Sessions))
for _, session := range sessions.Sessions {
storeSession := &storepb.SessionsUserSetting_Session{
SessionId: session.SessionId,
CreateTime: session.CreateTime,
LastAccessedTime: session.LastAccessedTime,
ClientInfo: &storepb.SessionsUserSetting_ClientInfo{
UserAgent: session.ClientInfo.UserAgent,
IpAddress: session.ClientInfo.IpAddress,
DeviceType: session.ClientInfo.DeviceType,
Os: session.ClientInfo.Os,
Browser: session.ClientInfo.Browser,
},
}
storeSessions = append(storeSessions, storeSession)
}
storeSetting.Value = &storepb.UserSetting_Sessions{
Sessions: &storepb.SessionsUserSetting{
Sessions: storeSessions,
},
}
} else {
return nil, errors.Errorf("sessions setting is required")
}
case storepb.UserSetting_ACCESS_TOKENS:
if accessTokens := apiSetting.GetAccessTokensSetting(); accessTokens != nil {
storeTokens := make([]*storepb.AccessTokensUserSetting_AccessToken, 0, len(accessTokens.AccessTokens))
for _, token := range accessTokens.AccessTokens {
storeToken := &storepb.AccessTokensUserSetting_AccessToken{
AccessToken: token.AccessToken,
Description: token.Description,
}
storeTokens = append(storeTokens, storeToken)
}
storeSetting.Value = &storepb.UserSetting_AccessTokens{
AccessTokens: &storepb.AccessTokensUserSetting{
AccessTokens: storeTokens,
},
}
} else {
return nil, errors.Errorf("access tokens setting is required")
}
case storepb.UserSetting_SHORTCUTS:
if shortcuts := apiSetting.GetShortcutsSetting(); shortcuts != nil {
storeShortcuts := make([]*storepb.ShortcutsUserSetting_Shortcut, 0, len(shortcuts.Shortcuts))
for _, shortcut := range shortcuts.Shortcuts {
storeShortcut := &storepb.ShortcutsUserSetting_Shortcut{
Id: shortcut.Id,
Title: shortcut.Title,
Filter: shortcut.Filter,
}
storeShortcuts = append(storeShortcuts, storeShortcut)
}
storeSetting.Value = &storepb.UserSetting_Shortcuts{
Shortcuts: &storepb.ShortcutsUserSetting{
Shortcuts: storeShortcuts,
},
}
} else {
return nil, errors.Errorf("shortcuts setting is required")
}
case storepb.UserSetting_WEBHOOKS:
if webhooks := apiSetting.GetWebhooksSetting(); webhooks != nil {
storeWebhooks := make([]*storepb.WebhooksUserSetting_Webhook, 0, len(webhooks.Webhooks))
for _, webhook := range webhooks.Webhooks {
storeWebhook := &storepb.WebhooksUserSetting_Webhook{
Id: webhook.Id,
Title: webhook.Title,
Url: webhook.Url,
}
storeWebhooks = append(storeWebhooks, storeWebhook)
}
storeSetting.Value = &storepb.UserSetting_Webhooks{
Webhooks: &storepb.WebhooksUserSetting{
Webhooks: storeWebhooks,
},
}
} else {
return nil, errors.Errorf("webhooks setting is required")
}
default:
return nil, errors.Errorf("unsupported setting key: %v", key)
}
return storeSetting, nil
}

View File

@ -65,7 +65,7 @@ func (s *APIV1Service) ListAllUserStats(ctx context.Context, _ *v1pb.ListAllUser
}
response := &v1pb.ListAllUserStatsResponse{
UserStats: userMemoStats,
Stats: userMemoStats,
}
return response, nil
}

View File

@ -30,7 +30,6 @@ type APIV1Service struct {
v1pb.UnimplementedShortcutServiceServer
v1pb.UnimplementedInboxServiceServer
v1pb.UnimplementedActivityServiceServer
v1pb.UnimplementedWebhookServiceServer
v1pb.UnimplementedMarkdownServiceServer
v1pb.UnimplementedIdentityProviderServiceServer
@ -58,7 +57,6 @@ func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store
v1pb.RegisterShortcutServiceServer(grpcServer, apiv1Service)
v1pb.RegisterInboxServiceServer(grpcServer, apiv1Service)
v1pb.RegisterActivityServiceServer(grpcServer, apiv1Service)
v1pb.RegisterWebhookServiceServer(grpcServer, apiv1Service)
v1pb.RegisterMarkdownServiceServer(grpcServer, apiv1Service)
v1pb.RegisterIdentityProviderServiceServer(grpcServer, apiv1Service)
reflection.Register(grpcServer)
@ -107,9 +105,6 @@ func (s *APIV1Service) RegisterGateway(ctx context.Context, echoServer *echo.Ech
if err := v1pb.RegisterActivityServiceHandler(ctx, gwMux, conn); err != nil {
return err
}
if err := v1pb.RegisterWebhookServiceHandler(ctx, gwMux, conn); err != nil {
return err
}
if err := v1pb.RegisterMarkdownServiceHandler(ctx, gwMux, conn); err != nil {
return err
}

View File

@ -1,317 +0,0 @@
package v1
import (
"context"
"crypto/rand"
"encoding/hex"
"fmt"
"strings"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"github.com/usememos/memos/internal/util"
v1pb "github.com/usememos/memos/proto/gen/api/v1"
storepb "github.com/usememos/memos/proto/gen/store"
)
func (s *APIV1Service) CreateWebhook(ctx context.Context, request *v1pb.CreateWebhookRequest) (*v1pb.Webhook, error) {
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
}
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
// Extract user ID from parent (format: users/{user})
parentUserID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}
// Users can only create webhooks for themselves
if parentUserID != currentUser.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Only host users can create webhooks
if !isSuperUser(currentUser) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Validate required fields
if request.Webhook == nil {
return nil, status.Errorf(codes.InvalidArgument, "webhook is required")
}
if strings.TrimSpace(request.Webhook.Url) == "" {
return nil, status.Errorf(codes.InvalidArgument, "webhook URL is required")
}
// Handle validate_only field
if request.ValidateOnly {
// Perform validation checks without actually creating the webhook
return &v1pb.Webhook{
Name: fmt.Sprintf("users/%d/webhooks/validate", currentUser.ID),
DisplayName: request.Webhook.DisplayName,
Url: request.Webhook.Url,
}, nil
}
err = s.Store.AddUserWebhook(ctx, currentUser.ID, &storepb.WebhooksUserSetting_Webhook{
Id: generateWebhookID(),
Title: request.Webhook.DisplayName,
Url: strings.TrimSpace(request.Webhook.Url),
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create webhook, error: %+v", err)
}
// Return the newly created webhook
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user webhooks, error: %+v", err)
}
// Find the webhook we just created
for _, webhook := range webhooks {
if webhook.Title == request.Webhook.DisplayName && webhook.Url == strings.TrimSpace(request.Webhook.Url) {
return convertWebhookFromUserSetting(webhook, currentUser.ID), nil
}
}
return nil, status.Errorf(codes.Internal, "failed to find created webhook")
}
func (s *APIV1Service) ListWebhooks(ctx context.Context, request *v1pb.ListWebhooksRequest) (*v1pb.ListWebhooksResponse, error) {
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
}
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
// Extract user ID from parent (format: users/{user})
parentUserID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}
// Users can only list their own webhooks
if parentUserID != currentUser.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list webhooks, error: %+v", err)
}
response := &v1pb.ListWebhooksResponse{
Webhooks: []*v1pb.Webhook{},
}
for _, webhook := range webhooks {
response.Webhooks = append(response.Webhooks, convertWebhookFromUserSetting(webhook, currentUser.ID))
}
return response, nil
}
func (s *APIV1Service) GetWebhook(ctx context.Context, request *v1pb.GetWebhookRequest) (*v1pb.Webhook, error) {
// Extract user ID and webhook ID from name (format: users/{user}/webhooks/{webhook})
tokens, err := GetNameParentTokens(request.Name, UserNamePrefix, WebhookNamePrefix)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
}
if len(tokens) != 2 {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name format")
}
userIDStr := tokens[0]
webhookID := tokens[1]
requestedUserID, err := util.ConvertStringToInt32(userIDStr)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user ID in webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
}
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
// Users can only access their own webhooks
if requestedUserID != currentUser.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get webhooks, error: %+v", err)
}
// Find webhook by ID
for _, webhook := range webhooks {
if webhook.Id == webhookID {
return convertWebhookFromUserSetting(webhook, currentUser.ID), nil
}
}
return nil, status.Errorf(codes.NotFound, "webhook not found")
}
func (s *APIV1Service) UpdateWebhook(ctx context.Context, request *v1pb.UpdateWebhookRequest) (*v1pb.Webhook, error) {
if request.UpdateMask == nil || len(request.UpdateMask.Paths) == 0 {
return nil, status.Errorf(codes.InvalidArgument, "update_mask is required")
}
// Extract user ID and webhook ID from name (format: users/{user}/webhooks/{webhook})
tokens, err := GetNameParentTokens(request.Webhook.Name, UserNamePrefix, WebhookNamePrefix)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
}
if len(tokens) != 2 {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name format")
}
userIDStr := tokens[0]
webhookID := tokens[1]
requestedUserID, err := util.ConvertStringToInt32(userIDStr)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user ID in webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
}
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
// Users can only update their own webhooks
if requestedUserID != currentUser.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Get existing webhooks from user settings
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get webhooks: %v", err)
}
// Find the webhook to update
var existingWebhook *storepb.WebhooksUserSetting_Webhook
for _, webhook := range webhooks {
if webhook.Id == webhookID {
existingWebhook = webhook
break
}
}
if existingWebhook == nil {
return nil, status.Errorf(codes.NotFound, "webhook not found")
}
// Create updated webhook
updatedWebhook := &storepb.WebhooksUserSetting_Webhook{
Id: existingWebhook.Id,
Title: existingWebhook.Title,
Url: existingWebhook.Url,
}
// Apply updates based on update mask
for _, field := range request.UpdateMask.Paths {
switch field {
case "display_name":
updatedWebhook.Title = request.Webhook.DisplayName
case "url":
updatedWebhook.Url = request.Webhook.Url
default:
return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field)
}
}
// Update the webhook in user settings
err = s.Store.UpdateUserWebhook(ctx, currentUser.ID, updatedWebhook)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to update webhook: %v", err)
}
return convertWebhookFromUserSetting(updatedWebhook, currentUser.ID), nil
}
func (s *APIV1Service) DeleteWebhook(ctx context.Context, request *v1pb.DeleteWebhookRequest) (*emptypb.Empty, error) {
// Extract user ID and webhook ID from name (format: users/{user}/webhooks/{webhook})
tokens, err := GetNameParentTokens(request.Name, UserNamePrefix, WebhookNamePrefix)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
}
if len(tokens) != 2 {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name format")
}
userIDStr := tokens[0]
webhookID := tokens[1]
requestedUserID, err := util.ConvertStringToInt32(userIDStr)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user ID in webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
}
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
// Users can only delete their own webhooks
if requestedUserID != currentUser.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Get existing webhooks from user settings to verify it exists
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get webhooks: %v", err)
}
// Check if webhook exists
webhookExists := false
for _, webhook := range webhooks {
if webhook.Id == webhookID {
webhookExists = true
break
}
}
if !webhookExists {
return nil, status.Errorf(codes.NotFound, "webhook not found")
}
err = s.Store.RemoveUserWebhook(ctx, currentUser.ID, webhookID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to delete webhook: %v", err)
}
return &emptypb.Empty{}, nil
}
func convertWebhookFromUserSetting(webhook *storepb.WebhooksUserSetting_Webhook, userID int32) *v1pb.Webhook {
return &v1pb.Webhook{
Name: fmt.Sprintf("users/%d/webhooks/%s", userID, webhook.Id),
DisplayName: webhook.Title,
Url: webhook.Url,
}
}
func generateWebhookID() string {
b := make([]byte, 8)
rand.Read(b)
return hex.EncodeToString(b)
}

View File

@ -12,7 +12,7 @@ const App = observer(() => {
const navigateTo = useNavigateTo();
const [mode, setMode] = useState<"light" | "dark">("light");
const workspaceProfile = workspaceStore.state.profile;
const userSetting = userStore.state.userSetting;
const userGeneralSetting = userStore.state.userGeneralSetting;
const workspaceGeneralSetting = workspaceStore.state.generalSetting;
// Redirect to sign up page if no instance owner.
@ -94,22 +94,22 @@ const App = observer(() => {
}, [mode]);
useEffect(() => {
if (!userSetting) {
if (!userGeneralSetting) {
return;
}
workspaceStore.state.setPartial({
locale: userSetting.locale || workspaceStore.state.locale,
appearance: userSetting.appearance || workspaceStore.state.appearance,
locale: userGeneralSetting.locale || workspaceStore.state.locale,
appearance: userGeneralSetting.appearance || workspaceStore.state.appearance,
});
}, [userSetting?.locale, userSetting?.appearance]);
}, [userGeneralSetting?.locale, userGeneralSetting?.appearance]);
// Load theme when user setting changes (user theme is already backfilled with workspace theme)
useEffect(() => {
if (userSetting?.theme) {
loadTheme(userSetting.theme);
if (userGeneralSetting?.theme) {
loadTheme(userGeneralSetting.theme);
}
}, [userSetting?.theme]);
}, [userGeneralSetting?.theme]);
return <Outlet />;
});

View File

@ -79,7 +79,7 @@ function CreateShortcutDialog({ open, onOpenChange, shortcut: initialShortcut, o
toast.success("Update shortcut successfully");
}
// Refresh shortcuts.
await userStore.fetchShortcuts();
await userStore.fetchUserSettings();
requestState.setFinish();
onSuccess?.();
onOpenChange(false);

View File

@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { webhookServiceClient } from "@/grpcweb";
import { userServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
import useLoading from "@/hooks/useLoading";
import { useTranslate } from "@/utils/i18n";
@ -32,19 +32,24 @@ function CreateWebhookDialog({ open, onOpenChange, webhookName, onSuccess }: Pro
const isCreating = webhookName === undefined;
useEffect(() => {
if (webhookName) {
webhookServiceClient
.getWebhook({
name: webhookName,
if (webhookName && currentUser) {
// For editing, we need to get the webhook data
// Since we're using user webhooks now, we need to list all webhooks and find the one we want
userServiceClient
.listUserWebhooks({
parent: currentUser.name,
})
.then((webhook) => {
setState({
displayName: webhook.displayName,
url: webhook.url,
});
.then((response) => {
const webhook = response.webhooks.find((w) => w.name === webhookName);
if (webhook) {
setState({
displayName: webhook.displayName,
url: webhook.url,
});
}
});
}
}, [webhookName]);
}, [webhookName, currentUser]);
const setPartialState = (partialState: Partial<State>) => {
setState({
@ -79,7 +84,7 @@ function CreateWebhookDialog({ open, onOpenChange, webhookName, onSuccess }: Pro
try {
requestState.setLoading();
if (isCreating) {
await webhookServiceClient.createWebhook({
await userServiceClient.createUserWebhook({
parent: currentUser.name,
webhook: {
displayName: state.displayName,
@ -87,7 +92,7 @@ function CreateWebhookDialog({ open, onOpenChange, webhookName, onSuccess }: Pro
},
});
} else {
await webhookServiceClient.updateWebhook({
await userServiceClient.updateUserWebhook({
webhook: {
name: webhookName,
displayName: state.displayName,

View File

@ -28,14 +28,14 @@ const ShortcutsSection = observer(() => {
const [editingShortcut, setEditingShortcut] = useState<Shortcut | undefined>();
useAsyncEffect(async () => {
await userStore.fetchShortcuts();
await userStore.fetchUserSettings();
}, []);
const handleDeleteShortcut = async (shortcut: Shortcut) => {
const confirmed = window.confirm("Are you sure you want to delete this shortcut?");
if (confirmed) {
await shortcutServiceClient.deleteShortcut({ name: shortcut.name });
await userStore.fetchShortcuts();
await userStore.fetchUserSettings();
}
};

View File

@ -17,7 +17,6 @@ import { memoStore, attachmentStore, userStore, workspaceStore } from "@/store";
import { extractMemoIdFromName } from "@/store/common";
import { Attachment } from "@/types/proto/api/v1/attachment_service";
import { Location, Memo, MemoRelation, MemoRelation_Type, Visibility } from "@/types/proto/api/v1/memo_service";
import { UserSetting } from "@/types/proto/api/v1/user_service";
import { useTranslate } from "@/utils/i18n";
import { convertVisibilityFromString } from "@/utils/memo";
import DateTimeInput from "../DateTimeInput";
@ -77,7 +76,7 @@ const MemoEditor = observer((props: Props) => {
const [hasContent, setHasContent] = useState<boolean>(false);
const [isVisibilitySelectorOpen, setIsVisibilitySelectorOpen] = useState(false);
const editorRef = useRef<EditorRefActions>(null);
const userSetting = userStore.state.userSetting as UserSetting;
const userGeneralSetting = userStore.state.userGeneralSetting;
const contentCacheKey = `${currentUser.name}-${cacheKey || ""}`;
const [contentCache, setContentCache] = useLocalStorage<string>(contentCacheKey, "");
const referenceRelations = memoName
@ -99,7 +98,7 @@ const MemoEditor = observer((props: Props) => {
}, [autoFocus]);
useAsyncEffect(async () => {
let visibility = convertVisibilityFromString(userSetting.memoVisibility);
let visibility = convertVisibilityFromString(userGeneralSetting?.memoVisibility || "PRIVATE");
if (workspaceMemoRelatedSetting.disallowPublicVisibility && visibility === Visibility.PUBLIC) {
visibility = Visibility.PROTECTED;
}
@ -111,7 +110,7 @@ const MemoEditor = observer((props: Props) => {
...prevState,
memoVisibility: convertVisibilityFromString(visibility),
}));
}, [parentMemoName, userSetting.memoVisibility, workspaceMemoRelatedSetting.disallowPublicVisibility]);
}, [parentMemoName, userGeneralSetting?.memoVisibility, workspaceMemoRelatedSetting.disallowPublicVisibility]);
useAsyncEffect(async () => {
if (!memoName) {

View File

@ -3,7 +3,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
import { Separator } from "@/components/ui/separator";
import { userStore } from "@/store";
import { Visibility } from "@/types/proto/api/v1/memo_service";
import { UserSetting } from "@/types/proto/api/v1/user_service";
import { UserSetting_GeneralSetting } from "@/types/proto/api/v1/user_service";
import { useTranslate } from "@/utils/i18n";
import { convertVisibilityFromString, convertVisibilityToString } from "@/utils/memo";
import AppearanceSelect from "../AppearanceSelect";
@ -14,22 +14,30 @@ import WebhookSection from "./WebhookSection";
const PreferencesSection = observer(() => {
const t = useTranslate();
const setting = userStore.state.userSetting as UserSetting;
const generalSetting = userStore.state.userGeneralSetting;
const handleLocaleSelectChange = async (locale: Locale) => {
await userStore.updateUserSetting({ locale }, ["locale"]);
await userStore.updateUserGeneralSetting({ locale }, ["locale"]);
};
const handleAppearanceSelectChange = async (appearance: Appearance) => {
await userStore.updateUserSetting({ appearance }, ["appearance"]);
await userStore.updateUserGeneralSetting({ appearance }, ["appearance"]);
};
const handleDefaultMemoVisibilityChanged = async (value: string) => {
await userStore.updateUserSetting({ memoVisibility: value }, ["memo_visibility"]);
await userStore.updateUserGeneralSetting({ memoVisibility: value }, ["memoVisibility"]);
};
const handleThemeChange = async (theme: string) => {
await userStore.updateUserSetting({ theme }, ["theme"]);
await userStore.updateUserGeneralSetting({ theme }, ["theme"]);
};
// Provide default values if setting is not loaded yet
const setting: UserSetting_GeneralSetting = generalSetting || {
locale: "en",
appearance: "system",
memoVisibility: "PRIVATE",
theme: "",
};
return (

View File

@ -2,21 +2,21 @@ import { ExternalLinkIcon, TrashIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { webhookServiceClient } from "@/grpcweb";
import { userServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
import { Webhook } from "@/types/proto/api/v1/webhook_service";
import { UserWebhook } from "@/types/proto/api/v1/user_service";
import { useTranslate } from "@/utils/i18n";
import CreateWebhookDialog from "../CreateWebhookDialog";
const WebhookSection = () => {
const t = useTranslate();
const currentUser = useCurrentUser();
const [webhooks, setWebhooks] = useState<Webhook[]>([]);
const [webhooks, setWebhooks] = useState<UserWebhook[]>([]);
const [isCreateWebhookDialogOpen, setIsCreateWebhookDialogOpen] = useState(false);
const listWebhooks = async () => {
if (!currentUser) return [];
const { webhooks } = await webhookServiceClient.listWebhooks({
const { webhooks } = await userServiceClient.listUserWebhooks({
parent: currentUser.name,
});
return webhooks;
@ -34,10 +34,10 @@ const WebhookSection = () => {
setIsCreateWebhookDialogOpen(false);
};
const handleDeleteWebhook = async (webhook: Webhook) => {
const handleDeleteWebhook = async (webhook: UserWebhook) => {
const confirmed = window.confirm(`Are you sure to delete webhook \`${webhook.displayName}\`? You cannot undo this action.`);
if (confirmed) {
await webhookServiceClient.deleteWebhook({ name: webhook.name });
await userServiceClient.deleteUserWebhook({ name: webhook.name });
setWebhooks(webhooks.filter((item) => item.name !== webhook.name));
}
};

View File

@ -8,7 +8,6 @@ import { MarkdownServiceDefinition } from "./types/proto/api/v1/markdown_service
import { MemoServiceDefinition } from "./types/proto/api/v1/memo_service";
import { ShortcutServiceDefinition } from "./types/proto/api/v1/shortcut_service";
import { UserServiceDefinition } from "./types/proto/api/v1/user_service";
import { WebhookServiceDefinition } from "./types/proto/api/v1/webhook_service";
import { WorkspaceServiceDefinition } from "./types/proto/api/v1/workspace_service";
const channel = createChannel(
@ -36,8 +35,6 @@ export const inboxServiceClient = clientFactory.create(InboxServiceDefinition, c
export const activityServiceClient = clientFactory.create(ActivityServiceDefinition, channel);
export const webhookServiceClient = clientFactory.create(WebhookServiceDefinition, channel);
export const markdownServiceClient = clientFactory.create(MarkdownServiceDefinition, channel);
export const identityProviderServiceClient = clientFactory.create(IdentityProviderServiceDefinition, channel);

View File

@ -1,15 +1,28 @@
import { uniqueId } from "lodash-es";
import { makeAutoObservable } from "mobx";
import { authServiceClient, inboxServiceClient, shortcutServiceClient, userServiceClient } from "@/grpcweb";
import { authServiceClient, inboxServiceClient, userServiceClient } from "@/grpcweb";
import { Inbox } from "@/types/proto/api/v1/inbox_service";
import { Shortcut } from "@/types/proto/api/v1/shortcut_service";
import { User, UserSetting, UserStats } from "@/types/proto/api/v1/user_service";
import {
User,
UserSetting,
UserSetting_GeneralSetting,
UserSetting_SessionsSetting,
UserSetting_AccessTokensSetting,
UserSetting_ShortcutsSetting,
UserSetting_WebhooksSetting,
UserStats,
} from "@/types/proto/api/v1/user_service";
import { findNearestMatchedLanguage } from "@/utils/i18n";
import workspaceStore from "./workspace";
class LocalState {
currentUser?: string;
userSetting?: UserSetting;
userGeneralSetting?: UserSetting_GeneralSetting;
userSessionsSetting?: UserSetting_SessionsSetting;
userAccessTokensSetting?: UserSetting_AccessTokensSetting;
userShortcutsSetting?: UserSetting_ShortcutsSetting;
userWebhooksSetting?: UserSetting_WebhooksSetting;
shortcuts: Shortcut[] = [];
inboxes: Inbox[] = [];
userMapByName: Record<string, User> = {};
@ -127,38 +140,77 @@ const userStore = (() => {
});
};
const updateUserSetting = async (userSetting: Partial<UserSetting>, updateMask: string[]) => {
const updateUserGeneralSetting = async (generalSetting: Partial<UserSetting_GeneralSetting>, updateMask: string[]) => {
if (!state.currentUser) {
throw new Error("No current user");
}
// Ensure the setting has the proper resource name
const settingWithName = {
...userSetting,
name: state.currentUser,
const settingName = `${state.currentUser}/settings/general`;
const userSetting: UserSetting = {
name: settingName,
generalSetting: generalSetting as UserSetting_GeneralSetting,
};
const updatedUserSetting = await userServiceClient.updateUserSetting({
setting: settingWithName,
setting: userSetting,
updateMask: updateMask,
});
state.setPartial({
userSetting: UserSetting.fromPartial({
...state.userSetting,
...updatedUserSetting,
}),
userGeneralSetting: updatedUserSetting.generalSetting,
});
};
const fetchShortcuts = async () => {
const getUserGeneralSetting = async () => {
if (!state.currentUser) {
throw new Error("No current user");
}
const settingName = `${state.currentUser}/settings/general`;
const userSetting = await userServiceClient.getUserSetting({ name: settingName });
state.setPartial({
userGeneralSetting: userSetting.generalSetting,
});
return userSetting.generalSetting;
};
const fetchUserSettings = async () => {
if (!state.currentUser) {
return;
}
const { shortcuts } = await shortcutServiceClient.listShortcuts({ parent: state.currentUser });
const { settings } = await userServiceClient.listUserSettings({ parent: state.currentUser });
// Extract and store each setting type
const generalSetting = settings.find((s) => s.generalSetting)?.generalSetting;
const sessionsSetting = settings.find((s) => s.sessionsSetting)?.sessionsSetting;
const accessTokensSetting = settings.find((s) => s.accessTokensSetting)?.accessTokensSetting;
const shortcutsSetting = settings.find((s) => s.shortcutsSetting)?.shortcutsSetting;
const webhooksSetting = settings.find((s) => s.webhooksSetting)?.webhooksSetting;
// Convert user setting shortcuts to proper Shortcut format
const shortcuts: Shortcut[] =
shortcutsSetting?.shortcuts.map((shortcut) => ({
name: `${state.currentUser}/shortcuts/${shortcut.id}`,
title: shortcut.title,
filter: shortcut.filter,
})) || [];
state.setPartial({
userGeneralSetting: generalSetting,
userSessionsSetting: sessionsSetting,
userAccessTokensSetting: accessTokensSetting,
userShortcutsSetting: shortcutsSetting,
userWebhooksSetting: webhooksSetting,
shortcuts,
});
};
// Note: fetchShortcuts is now handled by fetchUserSettings
// The shortcuts are extracted from the user shortcuts setting
const fetchInboxes = async () => {
if (!state.currentUser) {
throw new Error("No current user available");
@ -199,9 +251,9 @@ const userStore = (() => {
const fetchUserStats = async (user?: string) => {
const userStatsByName: Record<string, UserStats> = {};
if (!user) {
const { userStats } = await userServiceClient.listAllUserStats({});
for (const stats of userStats) {
userStatsByName[stats.name] = stats;
const { stats } = await userServiceClient.listAllUserStats({});
for (const userStats of stats) {
userStatsByName[userStats.name] = userStats;
}
} else {
const userStats = await userServiceClient.getUserStats({ name: user });
@ -227,8 +279,9 @@ const userStore = (() => {
fetchUsers,
updateUser,
deleteUser,
updateUserSetting,
fetchShortcuts,
updateUserGeneralSetting,
getUserGeneralSetting,
fetchUserSettings,
fetchInboxes,
updateInbox,
deleteInbox,
@ -244,25 +297,30 @@ export const initialUserStore = async () => {
// If no user is authenticated, we can skip the rest of the initialization.
userStore.state.setPartial({
currentUser: undefined,
userSetting: undefined,
userGeneralSetting: undefined,
userMapByName: {},
});
return;
}
const userSetting = await userServiceClient.getUserSetting({ name: currentUser.name });
// Fetch all user settings
await userStore.fetchUserSettings();
userStore.state.setPartial({
currentUser: currentUser.name,
userSetting: UserSetting.fromPartial({
...userSetting,
}),
userMapByName: {
[currentUser.name]: currentUser,
},
});
workspaceStore.state.setPartial({
locale: userSetting.locale,
appearance: userSetting.appearance,
});
// Apply general settings to workspace if available
const generalSetting = userStore.state.userGeneralSetting;
if (generalSetting) {
workspaceStore.state.setPartial({
locale: generalSetting.locale,
appearance: generalSetting.appearance,
});
}
} catch {
// find the nearest matched lang based on the `navigator.language` if the user is unauthenticated or settings retrieval fails.
const locale = findNearestMatchedLanguage(navigator.language);

File diff suppressed because it is too large Load Diff

View File

@ -1,799 +0,0 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.6.1
// protoc unknown
// source: api/v1/webhook_service.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import { Empty } from "../../google/protobuf/empty";
import { FieldMask } from "../../google/protobuf/field_mask";
export const protobufPackage = "memos.api.v1";
export interface Webhook {
/**
* The resource name of the webhook.
* Format: users/{user}/webhooks/{webhook}
*/
name: string;
/** The display name of the webhook. */
displayName: string;
/** The target URL for the webhook. */
url: string;
}
export interface ListWebhooksRequest {
/**
* Required. The parent resource where webhooks are listed.
* Format: users/{user}
*/
parent: string;
}
export interface ListWebhooksResponse {
/** The list of webhooks. */
webhooks: Webhook[];
}
export interface GetWebhookRequest {
/**
* Required. The resource name of the webhook to retrieve.
* Format: users/{user}/webhooks/{webhook}
*/
name: string;
}
export interface CreateWebhookRequest {
/**
* Required. The parent resource where this webhook will be created.
* Format: users/{user}
*/
parent: string;
/** Required. The webhook to create. */
webhook?:
| Webhook
| undefined;
/** Optional. If set, validate the request, but do not actually create the webhook. */
validateOnly: boolean;
}
export interface UpdateWebhookRequest {
/** Required. The webhook resource which replaces the resource on the server. */
webhook?:
| Webhook
| undefined;
/** Optional. The list of fields to update. */
updateMask?: string[] | undefined;
}
export interface DeleteWebhookRequest {
/**
* Required. The resource name of the webhook to delete.
* Format: users/{user}/webhooks/{webhook}
*/
name: string;
}
function createBaseWebhook(): Webhook {
return { name: "", displayName: "", url: "" };
}
export const Webhook: MessageFns<Webhook> = {
encode(message: Webhook, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.name !== "") {
writer.uint32(10).string(message.name);
}
if (message.displayName !== "") {
writer.uint32(18).string(message.displayName);
}
if (message.url !== "") {
writer.uint32(26).string(message.url);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): Webhook {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseWebhook();
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.displayName = reader.string();
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.url = reader.string();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<Webhook>): Webhook {
return Webhook.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<Webhook>): Webhook {
const message = createBaseWebhook();
message.name = object.name ?? "";
message.displayName = object.displayName ?? "";
message.url = object.url ?? "";
return message;
},
};
function createBaseListWebhooksRequest(): ListWebhooksRequest {
return { parent: "" };
}
export const ListWebhooksRequest: MessageFns<ListWebhooksRequest> = {
encode(message: ListWebhooksRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.parent !== "") {
writer.uint32(10).string(message.parent);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ListWebhooksRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseListWebhooksRequest();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.parent = reader.string();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<ListWebhooksRequest>): ListWebhooksRequest {
return ListWebhooksRequest.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<ListWebhooksRequest>): ListWebhooksRequest {
const message = createBaseListWebhooksRequest();
message.parent = object.parent ?? "";
return message;
},
};
function createBaseListWebhooksResponse(): ListWebhooksResponse {
return { webhooks: [] };
}
export const ListWebhooksResponse: MessageFns<ListWebhooksResponse> = {
encode(message: ListWebhooksResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.webhooks) {
Webhook.encode(v!, writer.uint32(10).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ListWebhooksResponse {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseListWebhooksResponse();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.webhooks.push(Webhook.decode(reader, reader.uint32()));
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<ListWebhooksResponse>): ListWebhooksResponse {
return ListWebhooksResponse.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<ListWebhooksResponse>): ListWebhooksResponse {
const message = createBaseListWebhooksResponse();
message.webhooks = object.webhooks?.map((e) => Webhook.fromPartial(e)) || [];
return message;
},
};
function createBaseGetWebhookRequest(): GetWebhookRequest {
return { name: "" };
}
export const GetWebhookRequest: MessageFns<GetWebhookRequest> = {
encode(message: GetWebhookRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.name !== "") {
writer.uint32(10).string(message.name);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): GetWebhookRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGetWebhookRequest();
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<GetWebhookRequest>): GetWebhookRequest {
return GetWebhookRequest.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<GetWebhookRequest>): GetWebhookRequest {
const message = createBaseGetWebhookRequest();
message.name = object.name ?? "";
return message;
},
};
function createBaseCreateWebhookRequest(): CreateWebhookRequest {
return { parent: "", webhook: undefined, validateOnly: false };
}
export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = {
encode(message: CreateWebhookRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.parent !== "") {
writer.uint32(10).string(message.parent);
}
if (message.webhook !== undefined) {
Webhook.encode(message.webhook, writer.uint32(18).fork()).join();
}
if (message.validateOnly !== false) {
writer.uint32(24).bool(message.validateOnly);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): CreateWebhookRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseCreateWebhookRequest();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.parent = reader.string();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.webhook = Webhook.decode(reader, reader.uint32());
continue;
}
case 3: {
if (tag !== 24) {
break;
}
message.validateOnly = reader.bool();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<CreateWebhookRequest>): CreateWebhookRequest {
return CreateWebhookRequest.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<CreateWebhookRequest>): CreateWebhookRequest {
const message = createBaseCreateWebhookRequest();
message.parent = object.parent ?? "";
message.webhook = (object.webhook !== undefined && object.webhook !== null)
? Webhook.fromPartial(object.webhook)
: undefined;
message.validateOnly = object.validateOnly ?? false;
return message;
},
};
function createBaseUpdateWebhookRequest(): UpdateWebhookRequest {
return { webhook: undefined, updateMask: undefined };
}
export const UpdateWebhookRequest: MessageFns<UpdateWebhookRequest> = {
encode(message: UpdateWebhookRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.webhook !== undefined) {
Webhook.encode(message.webhook, writer.uint32(10).fork()).join();
}
if (message.updateMask !== undefined) {
FieldMask.encode(FieldMask.wrap(message.updateMask), writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): UpdateWebhookRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseUpdateWebhookRequest();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.webhook = Webhook.decode(reader, reader.uint32());
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.updateMask = FieldMask.unwrap(FieldMask.decode(reader, reader.uint32()));
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<UpdateWebhookRequest>): UpdateWebhookRequest {
return UpdateWebhookRequest.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<UpdateWebhookRequest>): UpdateWebhookRequest {
const message = createBaseUpdateWebhookRequest();
message.webhook = (object.webhook !== undefined && object.webhook !== null)
? Webhook.fromPartial(object.webhook)
: undefined;
message.updateMask = object.updateMask ?? undefined;
return message;
},
};
function createBaseDeleteWebhookRequest(): DeleteWebhookRequest {
return { name: "" };
}
export const DeleteWebhookRequest: MessageFns<DeleteWebhookRequest> = {
encode(message: DeleteWebhookRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.name !== "") {
writer.uint32(10).string(message.name);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): DeleteWebhookRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseDeleteWebhookRequest();
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<DeleteWebhookRequest>): DeleteWebhookRequest {
return DeleteWebhookRequest.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<DeleteWebhookRequest>): DeleteWebhookRequest {
const message = createBaseDeleteWebhookRequest();
message.name = object.name ?? "";
return message;
},
};
export type WebhookServiceDefinition = typeof WebhookServiceDefinition;
export const WebhookServiceDefinition = {
name: "WebhookService",
fullName: "memos.api.v1.WebhookService",
methods: {
/** ListWebhooks returns a list of webhooks for a user. */
listWebhooks: {
name: "ListWebhooks",
requestType: ListWebhooksRequest,
requestStream: false,
responseType: ListWebhooksResponse,
responseStream: false,
options: {
_unknownFields: {
8410: [new Uint8Array([6, 112, 97, 114, 101, 110, 116])],
578365826: [
new Uint8Array([
35,
18,
33,
47,
97,
112,
105,
47,
118,
49,
47,
123,
112,
97,
114,
101,
110,
116,
61,
117,
115,
101,
114,
115,
47,
42,
125,
47,
119,
101,
98,
104,
111,
111,
107,
115,
]),
],
},
},
},
/** GetWebhook gets a webhook by name. */
getWebhook: {
name: "GetWebhook",
requestType: GetWebhookRequest,
requestStream: false,
responseType: Webhook,
responseStream: false,
options: {
_unknownFields: {
8410: [new Uint8Array([4, 110, 97, 109, 101])],
578365826: [
new Uint8Array([
35,
18,
33,
47,
97,
112,
105,
47,
118,
49,
47,
123,
110,
97,
109,
101,
61,
117,
115,
101,
114,
115,
47,
42,
47,
119,
101,
98,
104,
111,
111,
107,
115,
47,
42,
125,
]),
],
},
},
},
/** CreateWebhook creates a new webhook for a user. */
createWebhook: {
name: "CreateWebhook",
requestType: CreateWebhookRequest,
requestStream: false,
responseType: Webhook,
responseStream: false,
options: {
_unknownFields: {
8410: [new Uint8Array([14, 112, 97, 114, 101, 110, 116, 44, 119, 101, 98, 104, 111, 111, 107])],
578365826: [
new Uint8Array([
44,
58,
7,
119,
101,
98,
104,
111,
111,
107,
34,
33,
47,
97,
112,
105,
47,
118,
49,
47,
123,
112,
97,
114,
101,
110,
116,
61,
117,
115,
101,
114,
115,
47,
42,
125,
47,
119,
101,
98,
104,
111,
111,
107,
115,
]),
],
},
},
},
/** UpdateWebhook updates a webhook for a user. */
updateWebhook: {
name: "UpdateWebhook",
requestType: UpdateWebhookRequest,
requestStream: false,
responseType: Webhook,
responseStream: false,
options: {
_unknownFields: {
8410: [
new Uint8Array([
19,
119,
101,
98,
104,
111,
111,
107,
44,
117,
112,
100,
97,
116,
101,
95,
109,
97,
115,
107,
]),
],
578365826: [
new Uint8Array([
52,
58,
7,
119,
101,
98,
104,
111,
111,
107,
50,
41,
47,
97,
112,
105,
47,
118,
49,
47,
123,
119,
101,
98,
104,
111,
111,
107,
46,
110,
97,
109,
101,
61,
117,
115,
101,
114,
115,
47,
42,
47,
119,
101,
98,
104,
111,
111,
107,
115,
47,
42,
125,
]),
],
},
},
},
/** DeleteWebhook deletes a webhook for a user. */
deleteWebhook: {
name: "DeleteWebhook",
requestType: DeleteWebhookRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {
_unknownFields: {
8410: [new Uint8Array([4, 110, 97, 109, 101])],
578365826: [
new Uint8Array([
35,
42,
33,
47,
97,
112,
105,
47,
118,
49,
47,
123,
110,
97,
109,
101,
61,
117,
115,
101,
114,
115,
47,
42,
47,
119,
101,
98,
104,
111,
111,
107,
115,
47,
42,
125,
]),
],
},
},
},
},
} as const;
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
create(base?: DeepPartial<T>): T;
fromPartial(object: DeepPartial<T>): T;
}