chore: import upstream snapshot with attribution
Backend Tests / Tests (other) (push) Failing after 1s
Backend Tests / Static Checks (push) Failing after 2s
Backend Tests / Tests (internal) (push) Failing after 2s
Backend Tests / Tests (server) (push) Failing after 1s
Backend Tests / Tests (store) (push) Failing after 1s
Build Canary Image / build-frontend (push) Failing after 1s
Frontend Tests / Lint (push) Failing after 1s
Build Canary Image / build-push (linux/amd64) (push) Has been skipped
Build Canary Image / build-push (linux/arm64) (push) Has been skipped
Build Canary Image / merge (push) Has been skipped
Frontend Tests / Build (push) Failing after 1s
Release Please / release-please (push) Failing after 0s
Proto Linter / Lint Protos (push) Failing after 2s
Backend Tests / Tests (other) (push) Failing after 1s
Backend Tests / Static Checks (push) Failing after 2s
Backend Tests / Tests (internal) (push) Failing after 2s
Backend Tests / Tests (server) (push) Failing after 1s
Backend Tests / Tests (store) (push) Failing after 1s
Build Canary Image / build-frontend (push) Failing after 1s
Frontend Tests / Lint (push) Failing after 1s
Build Canary Image / build-push (linux/amd64) (push) Has been skipped
Build Canary Image / build-push (linux/arm64) (push) Has been skipped
Build Canary Image / merge (push) Has been skipped
Frontend Tests / Build (push) Failing after 1s
Release Please / release-please (push) Failing after 0s
Proto Linter / Lint Protos (push) Failing after 2s
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Memos API Design
|
||||
|
||||
This API design should follow the guidelines and best practices outlined in the [Google API Improvement Proposals (AIPs)](https://google.aip.dev/).
|
||||
@@ -0,0 +1,46 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package memos.api.v1;
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/client.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
|
||||
option go_package = "gen/api/v1";
|
||||
|
||||
service AIService {
|
||||
// Transcribe transcribes an audio file using an instance AI provider.
|
||||
rpc Transcribe(TranscribeRequest) returns (TranscribeResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/ai:transcribe"
|
||||
body: "*"
|
||||
};
|
||||
option (google.api.method_signature) = "audio";
|
||||
}
|
||||
}
|
||||
|
||||
message TranscribeRequest {
|
||||
// Required. Audio input.
|
||||
TranscriptionAudio audio = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message TranscriptionAudio {
|
||||
oneof source {
|
||||
// Inline audio bytes.
|
||||
bytes content = 1 [(google.api.field_behavior) = INPUT_ONLY];
|
||||
|
||||
// URI for audio content. Reserved for future use.
|
||||
string uri = 2;
|
||||
}
|
||||
|
||||
// Optional. The uploaded filename.
|
||||
string filename = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The MIME type of the input audio.
|
||||
string content_type = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message TranscribeResponse {
|
||||
// The transcribed text.
|
||||
string text = 1;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
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";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "gen/api/v1";
|
||||
|
||||
service AttachmentService {
|
||||
// CreateAttachment creates a new attachment.
|
||||
rpc CreateAttachment(CreateAttachmentRequest) returns (Attachment) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/attachments"
|
||||
body: "attachment"
|
||||
};
|
||||
option (google.api.method_signature) = "attachment";
|
||||
}
|
||||
// ListAttachments lists all attachments.
|
||||
rpc ListAttachments(ListAttachmentsRequest) returns (ListAttachmentsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/attachments"};
|
||||
}
|
||||
// GetAttachment returns an attachment by name.
|
||||
rpc GetAttachment(GetAttachmentRequest) returns (Attachment) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=attachments/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// UpdateAttachment updates an attachment.
|
||||
rpc UpdateAttachment(UpdateAttachmentRequest) returns (Attachment) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{attachment.name=attachments/*}"
|
||||
body: "attachment"
|
||||
};
|
||||
option (google.api.method_signature) = "attachment,update_mask";
|
||||
}
|
||||
// DeleteAttachment deletes an attachment by name.
|
||||
rpc DeleteAttachment(DeleteAttachmentRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=attachments/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// BatchDeleteAttachments deletes multiple attachments in one request.
|
||||
rpc BatchDeleteAttachments(BatchDeleteAttachmentsRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/attachments:batchDelete"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
enum MotionMediaFamily {
|
||||
MOTION_MEDIA_FAMILY_UNSPECIFIED = 0;
|
||||
APPLE_LIVE_PHOTO = 1;
|
||||
ANDROID_MOTION_PHOTO = 2;
|
||||
}
|
||||
|
||||
enum MotionMediaRole {
|
||||
MOTION_MEDIA_ROLE_UNSPECIFIED = 0;
|
||||
STILL = 1;
|
||||
VIDEO = 2;
|
||||
CONTAINER = 3;
|
||||
}
|
||||
|
||||
message MotionMedia {
|
||||
MotionMediaFamily family = 1;
|
||||
MotionMediaRole role = 2;
|
||||
string group_id = 3;
|
||||
int64 presentation_timestamp_us = 4;
|
||||
bool has_embedded_video = 5;
|
||||
}
|
||||
|
||||
message Attachment {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/Attachment"
|
||||
pattern: "attachments/{attachment}"
|
||||
singular: "attachment"
|
||||
plural: "attachments"
|
||||
};
|
||||
|
||||
// The name of the attachment.
|
||||
// Format: attachments/{attachment}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// Output only. The creation timestamp.
|
||||
google.protobuf.Timestamp create_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// The filename of the attachment.
|
||||
string filename = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Input only. The content of the attachment.
|
||||
bytes content = 4 [(google.api.field_behavior) = INPUT_ONLY];
|
||||
|
||||
// Optional. The external link of the attachment.
|
||||
string external_link = 5 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// The MIME type of the attachment.
|
||||
string type = 6 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Output only. The size of the attachment in bytes.
|
||||
int64 size = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Optional. The related memo. Refer to `Memo.name`.
|
||||
// Format: memos/{memo}
|
||||
optional string memo = 8 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Motion media metadata.
|
||||
MotionMedia motion_media = 9 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message CreateAttachmentRequest {
|
||||
// Required. The attachment to create.
|
||||
Attachment attachment = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. The attachment ID to use for this attachment.
|
||||
// If empty, a unique ID will be generated.
|
||||
string attachment_id = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListAttachmentsRequest {
|
||||
// Optional. The maximum number of attachments to return.
|
||||
// The service may return fewer than this value.
|
||||
// If unspecified, at most 50 attachments will be returned.
|
||||
// The maximum value is 1000; values above 1000 will be coerced to 1000.
|
||||
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token, received from a previous `ListAttachments` call.
|
||||
// Provide this to retrieve the subsequent page.
|
||||
string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Filter to apply to the list results.
|
||||
// Example: "mime_type==\"image/png\"" or "filename.contains(\"test\")"
|
||||
// Supported operators: =, !=, <, <=, >, >=, : (contains), in
|
||||
// Supported fields: filename, mime_type, create_time, memo
|
||||
string filter = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The order to sort results by.
|
||||
// Example: "create_time desc" or "filename asc"
|
||||
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListAttachmentsResponse {
|
||||
// The list of attachments.
|
||||
repeated Attachment attachments = 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;
|
||||
}
|
||||
|
||||
message GetAttachmentRequest {
|
||||
// Required. The attachment name of the attachment to retrieve.
|
||||
// Format: attachments/{attachment}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Attachment"}
|
||||
];
|
||||
}
|
||||
|
||||
message UpdateAttachmentRequest {
|
||||
// Required. The attachment which replaces the attachment on the server.
|
||||
Attachment attachment = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The list of fields to update.
|
||||
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message DeleteAttachmentRequest {
|
||||
// Required. The attachment name of the attachment to delete.
|
||||
// Format: attachments/{attachment}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Attachment"}
|
||||
];
|
||||
}
|
||||
|
||||
message BatchDeleteAttachmentsRequest {
|
||||
repeated string names = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package memos.api.v1;
|
||||
|
||||
import "api/v1/user_service.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "gen/api/v1";
|
||||
|
||||
service AuthService {
|
||||
// GetCurrentUser returns the authenticated user's information.
|
||||
// Validates the access token and returns user details.
|
||||
// Similar to OIDC's /userinfo endpoint.
|
||||
rpc GetCurrentUser(GetCurrentUserRequest) returns (GetCurrentUserResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/auth/me"};
|
||||
}
|
||||
|
||||
// SignIn authenticates a user with credentials and returns tokens.
|
||||
// On success, returns an access token and sets a refresh token cookie.
|
||||
// Supports password-based and SSO authentication methods.
|
||||
rpc SignIn(SignInRequest) returns (SignInResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/auth/signin"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
// SignOut terminates the user's authentication.
|
||||
// Revokes the refresh token and clears the authentication cookie.
|
||||
rpc SignOut(SignOutRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {post: "/api/v1/auth/signout"};
|
||||
}
|
||||
|
||||
// RefreshToken exchanges a valid refresh token for a new access token.
|
||||
// The refresh token is read from the HttpOnly cookie.
|
||||
// Returns a new short-lived access token.
|
||||
rpc RefreshToken(RefreshTokenRequest) returns (RefreshTokenResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/auth/refresh"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message GetCurrentUserRequest {}
|
||||
|
||||
message GetCurrentUserResponse {
|
||||
// The authenticated user's information.
|
||||
User user = 1;
|
||||
}
|
||||
|
||||
message SignInRequest {
|
||||
// Nested message for password-based authentication credentials.
|
||||
message PasswordCredentials {
|
||||
// The username to sign in with.
|
||||
string username = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The password to sign in with.
|
||||
string password = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
// Nested message for SSO authentication credentials.
|
||||
message SSOCredentials {
|
||||
// The resource name of the SSO provider.
|
||||
// Format: identity-providers/{uid}
|
||||
string idp_name = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The authorization code from the SSO provider.
|
||||
string code = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The redirect URI used in the SSO flow.
|
||||
string redirect_uri = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The PKCE code verifier for enhanced security (RFC 7636).
|
||||
// Optional - enables PKCE flow protection against authorization code interception.
|
||||
string code_verifier = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
// Authentication credentials. Provide one method.
|
||||
oneof credentials {
|
||||
// Username and password authentication.
|
||||
PasswordCredentials password_credentials = 1;
|
||||
|
||||
// SSO provider authentication.
|
||||
SSOCredentials sso_credentials = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message SignInResponse {
|
||||
// The authenticated user's information.
|
||||
User user = 1;
|
||||
|
||||
// The short-lived access token for API requests.
|
||||
// Store in memory only, not in localStorage.
|
||||
string access_token = 2;
|
||||
|
||||
// When the access token expires.
|
||||
// Client should call RefreshToken before this time.
|
||||
google.protobuf.Timestamp access_token_expires_at = 3;
|
||||
}
|
||||
|
||||
message SignOutRequest {}
|
||||
|
||||
message RefreshTokenRequest {}
|
||||
|
||||
message RefreshTokenResponse {
|
||||
// The new short-lived access token.
|
||||
string access_token = 1;
|
||||
|
||||
// When the access token expires.
|
||||
google.protobuf.Timestamp expires_at = 2;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package memos.api.v1;
|
||||
|
||||
option go_package = "gen/api/v1";
|
||||
|
||||
enum State {
|
||||
STATE_UNSPECIFIED = 0;
|
||||
NORMAL = 1;
|
||||
ARCHIVED = 2;
|
||||
}
|
||||
|
||||
// Used internally for obfuscating the page token.
|
||||
message PageToken {
|
||||
int32 limit = 1;
|
||||
int32 offset = 2;
|
||||
}
|
||||
|
||||
enum Direction {
|
||||
DIRECTION_UNSPECIFIED = 0;
|
||||
ASC = 1;
|
||||
DESC = 2;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
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 IdentityProviderService {
|
||||
// ListIdentityProviders lists identity providers.
|
||||
rpc ListIdentityProviders(ListIdentityProvidersRequest) returns (ListIdentityProvidersResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/identity-providers"};
|
||||
}
|
||||
|
||||
// GetIdentityProvider gets an identity provider.
|
||||
rpc GetIdentityProvider(GetIdentityProviderRequest) returns (IdentityProvider) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=identity-providers/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// CreateIdentityProvider creates an identity provider.
|
||||
rpc CreateIdentityProvider(CreateIdentityProviderRequest) returns (IdentityProvider) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/identity-providers"
|
||||
body: "identity_provider"
|
||||
};
|
||||
option (google.api.method_signature) = "identity_provider";
|
||||
}
|
||||
|
||||
// UpdateIdentityProvider updates an identity provider.
|
||||
rpc UpdateIdentityProvider(UpdateIdentityProviderRequest) returns (IdentityProvider) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{identity_provider.name=identity-providers/*}"
|
||||
body: "identity_provider"
|
||||
};
|
||||
option (google.api.method_signature) = "identity_provider,update_mask";
|
||||
}
|
||||
|
||||
// DeleteIdentityProvider deletes an identity provider.
|
||||
rpc DeleteIdentityProvider(DeleteIdentityProviderRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=identity-providers/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
}
|
||||
|
||||
message IdentityProvider {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/IdentityProvider"
|
||||
pattern: "identity-providers/{idp}"
|
||||
name_field: "name"
|
||||
singular: "identityProvider"
|
||||
plural: "identityProviders"
|
||||
};
|
||||
|
||||
// The resource name of the identity provider.
|
||||
// Format: identity-providers/{idp}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// Required. The type of the identity provider.
|
||||
Type type = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The display title of the identity provider.
|
||||
string title = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. Filter applied to user identifiers.
|
||||
string identifier_filter = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Required. Configuration for the identity provider.
|
||||
IdentityProviderConfig config = 5 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
enum Type {
|
||||
TYPE_UNSPECIFIED = 0;
|
||||
// OAuth2 identity provider.
|
||||
OAUTH2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message IdentityProviderConfig {
|
||||
oneof config {
|
||||
OAuth2Config oauth2_config = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message FieldMapping {
|
||||
string identifier = 1;
|
||||
string display_name = 2;
|
||||
string email = 3;
|
||||
string avatar_url = 4;
|
||||
}
|
||||
|
||||
message OAuth2Config {
|
||||
string client_id = 1;
|
||||
string client_secret = 2;
|
||||
string auth_url = 3;
|
||||
string token_url = 4;
|
||||
string user_info_url = 5;
|
||||
repeated string scopes = 6;
|
||||
FieldMapping field_mapping = 7;
|
||||
}
|
||||
|
||||
message ListIdentityProvidersRequest {}
|
||||
|
||||
message ListIdentityProvidersResponse {
|
||||
// The list of identity providers.
|
||||
repeated IdentityProvider identity_providers = 1;
|
||||
}
|
||||
|
||||
message GetIdentityProviderRequest {
|
||||
// Required. The resource name of the identity provider to get.
|
||||
// Format: identity-providers/{idp}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
|
||||
];
|
||||
}
|
||||
|
||||
message CreateIdentityProviderRequest {
|
||||
// Required. The identity provider to create.
|
||||
IdentityProvider identity_provider = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. The ID to use for the identity provider, which will become the final component of the resource name.
|
||||
// If not provided, the system will generate one.
|
||||
string identity_provider_id = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message UpdateIdentityProviderRequest {
|
||||
// Required. The identity provider to update.
|
||||
IdentityProvider identity_provider = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The update mask applies to the resource. Only the top level fields of
|
||||
// IdentityProvider are supported.
|
||||
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message DeleteIdentityProviderRequest {
|
||||
// Required. The resource name of the identity provider to delete.
|
||||
// Format: identity-providers/{idp}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package memos.api.v1;
|
||||
|
||||
import "api/v1/user_service.proto";
|
||||
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";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/type/color.proto";
|
||||
|
||||
option go_package = "gen/api/v1";
|
||||
|
||||
service InstanceService {
|
||||
// Gets the instance profile.
|
||||
rpc GetInstanceProfile(GetInstanceProfileRequest) returns (InstanceProfile) {
|
||||
option (google.api.http) = {get: "/api/v1/instance/profile"};
|
||||
}
|
||||
|
||||
// Gets an instance setting.
|
||||
rpc GetInstanceSetting(GetInstanceSettingRequest) returns (InstanceSetting) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=instance/settings/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// Batch gets instance settings.
|
||||
rpc BatchGetInstanceSettings(BatchGetInstanceSettingsRequest) returns (BatchGetInstanceSettingsResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/instance/settings:batchGet"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
// Updates an instance setting.
|
||||
rpc UpdateInstanceSetting(UpdateInstanceSettingRequest) returns (InstanceSetting) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{setting.name=instance/settings/*}"
|
||||
body: "setting"
|
||||
};
|
||||
option (google.api.method_signature) = "setting,update_mask";
|
||||
}
|
||||
|
||||
// Tests notification email delivery with the provided or stored SMTP settings.
|
||||
rpc TestInstanceEmailSetting(TestInstanceEmailSettingRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/instance/settings/notification:testEmail"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
// GetInstanceStats returns resource usage statistics for the instance. Admin only.
|
||||
rpc GetInstanceStats(GetInstanceStatsRequest) returns (InstanceStats) {
|
||||
option (google.api.http) = {get: "/api/v1/instance/stats"};
|
||||
}
|
||||
}
|
||||
|
||||
// Instance profile message containing basic instance information.
|
||||
message InstanceProfile {
|
||||
// Version is the current version of instance.
|
||||
string version = 2;
|
||||
|
||||
// Demo indicates if the instance is in demo mode.
|
||||
bool demo = 3;
|
||||
|
||||
// Instance URL is the URL of the instance.
|
||||
string instance_url = 6;
|
||||
|
||||
// The first administrator who set up this instance, for display purposes.
|
||||
// May be null on an instance that has lost all admins; use needs_setup to
|
||||
// determine whether initial setup is actually required.
|
||||
User admin = 7;
|
||||
|
||||
// Commit is the current build commit of instance.
|
||||
string commit = 8;
|
||||
|
||||
// NeedsSetup is true when the instance has no users yet and requires initial
|
||||
// setup (creating the first admin account). Unlike a null admin, this stays
|
||||
// false once any user exists, so an instance that has lost its admins is not
|
||||
// mistaken for a fresh install.
|
||||
bool needs_setup = 9;
|
||||
}
|
||||
|
||||
// Request for instance profile.
|
||||
message GetInstanceProfileRequest {}
|
||||
|
||||
// An instance setting resource.
|
||||
message InstanceSetting {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/InstanceSetting"
|
||||
pattern: "instance/settings/{setting}"
|
||||
singular: "instanceSetting"
|
||||
plural: "instanceSettings"
|
||||
};
|
||||
|
||||
// The name of the instance setting.
|
||||
// Format: instance/settings/{setting}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
oneof value {
|
||||
GeneralSetting general_setting = 2;
|
||||
StorageSetting storage_setting = 3;
|
||||
MemoRelatedSetting memo_related_setting = 4;
|
||||
TagsSetting tags_setting = 5;
|
||||
NotificationSetting notification_setting = 6;
|
||||
AISetting ai_setting = 7;
|
||||
}
|
||||
|
||||
// Enumeration of instance setting keys.
|
||||
enum Key {
|
||||
KEY_UNSPECIFIED = 0;
|
||||
// GENERAL is the key for general settings.
|
||||
GENERAL = 1;
|
||||
// STORAGE is the key for storage settings.
|
||||
STORAGE = 2;
|
||||
// MEMO_RELATED is the key for memo related settings.
|
||||
MEMO_RELATED = 3;
|
||||
// TAGS is the key for tag metadata.
|
||||
TAGS = 4;
|
||||
// NOTIFICATION is the key for notification transport settings.
|
||||
NOTIFICATION = 5;
|
||||
// AI is the key for AI provider settings.
|
||||
AI = 6;
|
||||
}
|
||||
|
||||
// General instance settings configuration.
|
||||
message GeneralSetting {
|
||||
// disallow_user_registration disallows user registration.
|
||||
bool disallow_user_registration = 2;
|
||||
// disallow_password_auth disallows password authentication.
|
||||
bool disallow_password_auth = 3;
|
||||
// additional_script is the additional script.
|
||||
string additional_script = 4;
|
||||
// additional_style is the additional style.
|
||||
string additional_style = 5;
|
||||
// custom_profile is the custom profile.
|
||||
CustomProfile custom_profile = 6;
|
||||
// week_start_day_offset is the week start day offset from Sunday.
|
||||
// 0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday
|
||||
// Default is Sunday.
|
||||
int32 week_start_day_offset = 7;
|
||||
|
||||
// disallow_change_username disallows changing username.
|
||||
bool disallow_change_username = 8;
|
||||
// disallow_change_nickname disallows changing nickname.
|
||||
bool disallow_change_nickname = 9;
|
||||
|
||||
// Custom profile configuration for instance branding.
|
||||
message CustomProfile {
|
||||
string title = 1;
|
||||
string description = 2;
|
||||
string logo_url = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Storage configuration settings for instance attachments.
|
||||
message StorageSetting {
|
||||
// Storage type enumeration for different storage backends.
|
||||
enum StorageType {
|
||||
STORAGE_TYPE_UNSPECIFIED = 0;
|
||||
// DATABASE is the database storage type.
|
||||
DATABASE = 1;
|
||||
// LOCAL is the local storage type.
|
||||
LOCAL = 2;
|
||||
// S3 is the S3 storage type.
|
||||
S3 = 3;
|
||||
}
|
||||
// storage_type is the storage type.
|
||||
StorageType storage_type = 1;
|
||||
// The template of file path.
|
||||
// e.g. assets/{timestamp}_{filename}
|
||||
string filepath_template = 2;
|
||||
// The max upload size in megabytes.
|
||||
int64 upload_size_limit_mb = 3;
|
||||
|
||||
// S3 configuration for cloud storage backend.
|
||||
// Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/
|
||||
message S3Config {
|
||||
string access_key_id = 1;
|
||||
string access_key_secret = 2 [(google.api.field_behavior) = INPUT_ONLY];
|
||||
string endpoint = 3;
|
||||
string region = 4;
|
||||
string bucket = 5;
|
||||
bool use_path_style = 6;
|
||||
// insecure_skip_tls_verify disables TLS certificate verification when connecting
|
||||
// to the S3 endpoint. Only enable this for trusted endpoints that use a self-signed
|
||||
// certificate; it removes protection against man-in-the-middle attacks.
|
||||
bool insecure_skip_tls_verify = 7;
|
||||
}
|
||||
// The S3 config.
|
||||
S3Config s3_config = 4;
|
||||
}
|
||||
|
||||
// Memo-related instance settings and policies.
|
||||
message MemoRelatedSetting {
|
||||
reserved 2;
|
||||
reserved "display_with_update_time";
|
||||
// content_length_limit is the limit of content length. Unit is byte.
|
||||
int32 content_length_limit = 3;
|
||||
// enable_double_click_edit enables editing on double click.
|
||||
bool enable_double_click_edit = 4;
|
||||
// reactions is the list of reactions.
|
||||
repeated string reactions = 7;
|
||||
}
|
||||
|
||||
// Metadata for a tag.
|
||||
message TagMetadata {
|
||||
// Optional background color for the tag label.
|
||||
// When unset, the default tag color is used.
|
||||
google.type.Color background_color = 1;
|
||||
// Whether memos with this tag should have their content blurred.
|
||||
bool blur_content = 2;
|
||||
}
|
||||
|
||||
// Tag metadata configuration.
|
||||
// Active tag metadata is stored in per-user tag settings.
|
||||
// This message remains for backward compatibility with existing clients and migrations.
|
||||
message TagsSetting {
|
||||
// Map of tag name pattern to tag metadata.
|
||||
// Each key is treated as an anchored regular expression (^pattern$),
|
||||
// so a single entry like "project/.*" matches all tags under that prefix.
|
||||
// Exact tag names are also valid (they are trivially valid regex patterns).
|
||||
map<string, TagMetadata> tags = 1;
|
||||
}
|
||||
|
||||
// Notification transport configuration.
|
||||
message NotificationSetting {
|
||||
EmailSetting email = 1;
|
||||
|
||||
// Email delivery configuration for notifications.
|
||||
message EmailSetting {
|
||||
bool enabled = 1;
|
||||
string smtp_host = 2;
|
||||
int32 smtp_port = 3;
|
||||
string smtp_username = 4;
|
||||
string smtp_password = 5 [(google.api.field_behavior) = INPUT_ONLY];
|
||||
string from_email = 6;
|
||||
string from_name = 7;
|
||||
string reply_to = 8;
|
||||
bool use_tls = 9;
|
||||
bool use_ssl = 10;
|
||||
}
|
||||
}
|
||||
|
||||
// AI provider configuration settings.
|
||||
message AISetting {
|
||||
// providers is the list of AI provider configurations available instance-wide.
|
||||
repeated AIProviderConfig providers = 1;
|
||||
|
||||
// transcription is the speech-to-text feature configuration.
|
||||
// When unset or transcription.provider_id is empty, transcription is disabled.
|
||||
TranscriptionConfig transcription = 2;
|
||||
}
|
||||
|
||||
// AIProviderConfig represents one callable AI provider connection.
|
||||
message AIProviderConfig {
|
||||
string id = 1;
|
||||
string title = 2;
|
||||
AIProviderType type = 3;
|
||||
string endpoint = 4;
|
||||
// api_key is write-only and is never returned by GetInstanceSetting.
|
||||
string api_key = 5 [(google.api.field_behavior) = INPUT_ONLY];
|
||||
// api_key_set indicates whether an API key is stored for this provider.
|
||||
bool api_key_set = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
// api_key_hint is a masked hint for the stored API key.
|
||||
string api_key_hint = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
}
|
||||
|
||||
// AIProviderType is the provider implementation type.
|
||||
enum AIProviderType {
|
||||
AI_PROVIDER_TYPE_UNSPECIFIED = 0;
|
||||
OPENAI = 1;
|
||||
GEMINI = 2;
|
||||
}
|
||||
|
||||
// TranscriptionConfig configures the speech-to-text feature.
|
||||
message TranscriptionConfig {
|
||||
// provider_id references an entry in AISetting.providers[].id.
|
||||
// Empty string means transcription is disabled.
|
||||
string provider_id = 1;
|
||||
|
||||
// model is the provider-specific model identifier.
|
||||
// Empty string falls back to the engine default
|
||||
// (whisper-1 for OPENAI providers, gemini-2.5-flash for GEMINI providers).
|
||||
string model = 2;
|
||||
|
||||
// language is the default ISO 639-1 language hint sent to the provider.
|
||||
// Empty string lets the provider auto-detect.
|
||||
string language = 3;
|
||||
|
||||
// prompt is a default spelling/vocabulary hint passed to the provider.
|
||||
string prompt = 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Request message for GetInstanceSetting method.
|
||||
message GetInstanceSettingRequest {
|
||||
// The resource name of the instance setting.
|
||||
// Format: instance/settings/{setting}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/InstanceSetting"}
|
||||
];
|
||||
}
|
||||
|
||||
// Request message for BatchGetInstanceSettings method.
|
||||
message BatchGetInstanceSettingsRequest {
|
||||
// The resource names of the instance settings.
|
||||
// Format: instance/settings/{setting}
|
||||
repeated string names = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/InstanceSetting"}
|
||||
];
|
||||
}
|
||||
|
||||
// Response message for BatchGetInstanceSettings method.
|
||||
message BatchGetInstanceSettingsResponse {
|
||||
// The instance settings in the same order as the input names.
|
||||
repeated InstanceSetting settings = 1;
|
||||
}
|
||||
|
||||
// Request message for UpdateInstanceSetting method.
|
||||
message UpdateInstanceSettingRequest {
|
||||
// The instance setting resource which replaces the resource on the server.
|
||||
InstanceSetting setting = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The list of fields to update.
|
||||
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
// Request message for TestInstanceEmailSetting method.
|
||||
message TestInstanceEmailSettingRequest {
|
||||
// Optional. SMTP email settings to test. If omitted, the stored notification email setting is used.
|
||||
InstanceSetting.NotificationSetting.EmailSetting email = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Recipient email address. If omitted, the current user's email address is used.
|
||||
string recipient_email = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
// Request message for GetInstanceStats.
|
||||
message GetInstanceStatsRequest {}
|
||||
|
||||
// Resource usage statistics for the instance.
|
||||
message InstanceStats {
|
||||
DatabaseStats database = 1;
|
||||
// Recursive size of the data directory in bytes. -1 if unavailable.
|
||||
int64 local_storage_bytes = 2;
|
||||
// Server-side timestamp when the snapshot was generated.
|
||||
google.protobuf.Timestamp generated_time = 4;
|
||||
|
||||
// Database size statistics.
|
||||
message DatabaseStats {
|
||||
// driver is one of "sqlite", "mysql", "postgres".
|
||||
string driver = 1;
|
||||
// size_bytes is the database size in bytes; -1 if unavailable.
|
||||
int64 size_bytes = 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,656 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package memos.api.v1;
|
||||
|
||||
import "api/v1/attachment_service.proto";
|
||||
import "api/v1/common.proto";
|
||||
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";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "gen/api/v1";
|
||||
|
||||
service MemoService {
|
||||
// CreateMemo creates a memo. The request body is a Memo; set its content
|
||||
// (Markdown) and visibility (PRIVATE | PROTECTED | PUBLIC, default PRIVATE).
|
||||
// The memo is owned by the authenticated user; requires authentication.
|
||||
rpc CreateMemo(CreateMemoRequest) returns (Memo) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/memos"
|
||||
body: "memo"
|
||||
};
|
||||
option (google.api.method_signature) = "memo";
|
||||
}
|
||||
// ListMemos lists memos with pagination and filter.
|
||||
rpc ListMemos(ListMemosRequest) returns (ListMemosResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/memos"};
|
||||
option (google.api.method_signature) = "";
|
||||
}
|
||||
// GetMemo gets a memo.
|
||||
rpc GetMemo(GetMemoRequest) returns (Memo) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=memos/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// UpdateMemo updates a memo.
|
||||
rpc UpdateMemo(UpdateMemoRequest) returns (Memo) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{memo.name=memos/*}"
|
||||
body: "memo"
|
||||
};
|
||||
option (google.api.method_signature) = "memo,update_mask";
|
||||
}
|
||||
// DeleteMemo deletes a memo.
|
||||
rpc DeleteMemo(DeleteMemoRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=memos/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// SetMemoAttachments replaces the full set of attachments on a memo with the
|
||||
// provided list (not an append). Pass the complete desired set; an empty list
|
||||
// clears all attachments. Idempotent.
|
||||
rpc SetMemoAttachments(SetMemoAttachmentsRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{name=memos/*}/attachments"
|
||||
body: "*"
|
||||
};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// ListMemoAttachments lists attachments for a memo.
|
||||
rpc ListMemoAttachments(ListMemoAttachmentsRequest) returns (ListMemoAttachmentsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=memos/*}/attachments"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// SetMemoRelations replaces the full set of relations on a memo with the
|
||||
// provided list (not an append). Pass the complete desired set; an empty list
|
||||
// clears all relations. Idempotent.
|
||||
rpc SetMemoRelations(SetMemoRelationsRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{name=memos/*}/relations"
|
||||
body: "*"
|
||||
};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// ListMemoRelations lists relations for a memo.
|
||||
rpc ListMemoRelations(ListMemoRelationsRequest) returns (ListMemoRelationsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=memos/*}/relations"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// CreateMemoComment creates a comment for a memo.
|
||||
rpc CreateMemoComment(CreateMemoCommentRequest) returns (Memo) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/{name=memos/*}/comments"
|
||||
body: "comment"
|
||||
};
|
||||
option (google.api.method_signature) = "name,comment";
|
||||
}
|
||||
// ListMemoComments lists comments for a memo.
|
||||
rpc ListMemoComments(ListMemoCommentsRequest) returns (ListMemoCommentsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=memos/*}/comments"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// ListMemoReactions lists reactions for a memo.
|
||||
rpc ListMemoReactions(ListMemoReactionsRequest) returns (ListMemoReactionsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=memos/*}/reactions"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// UpsertMemoReaction adds or updates the authenticated user's reaction on a
|
||||
// memo. The reaction's content_id is the memo's resource name (memos/{memo}).
|
||||
rpc UpsertMemoReaction(UpsertMemoReactionRequest) returns (Reaction) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/{name=memos/*}/reactions"
|
||||
body: "*"
|
||||
};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// DeleteMemoReaction deletes a reaction for a memo.
|
||||
rpc DeleteMemoReaction(DeleteMemoReactionRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=memos/*/reactions/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// CreateMemoShare creates a share link for a memo. Requires authentication as the memo creator.
|
||||
rpc CreateMemoShare(CreateMemoShareRequest) returns (MemoShare) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/{parent=memos/*}/shares"
|
||||
body: "memo_share"
|
||||
};
|
||||
option (google.api.method_signature) = "parent,memo_share";
|
||||
}
|
||||
// ListMemoShares lists all share links for a memo. Requires authentication as the memo creator.
|
||||
rpc ListMemoShares(ListMemoSharesRequest) returns (ListMemoSharesResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{parent=memos/*}/shares"};
|
||||
option (google.api.method_signature) = "parent";
|
||||
}
|
||||
// DeleteMemoShare revokes a share link. Requires authentication as the memo creator.
|
||||
rpc DeleteMemoShare(DeleteMemoShareRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=memos/*/shares/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
// GetMemoByShare resolves a share token to its memo. No authentication required.
|
||||
// Returns NOT_FOUND if the token is invalid or expired.
|
||||
rpc GetMemoByShare(GetMemoByShareRequest) returns (Memo) {
|
||||
option (google.api.http) = {get: "/api/v1/shares/{share_id}"};
|
||||
}
|
||||
// GetLinkMetadata gets metadata for a link.
|
||||
rpc GetLinkMetadata(GetLinkMetadataRequest) returns (LinkMetadata) {
|
||||
option (google.api.http) = {get: "/api/v1/memos/-/linkMetadata"};
|
||||
}
|
||||
// BatchGetLinkMetadata gets metadata for links.
|
||||
rpc BatchGetLinkMetadata(BatchGetLinkMetadataRequest) returns (BatchGetLinkMetadataResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/memos/-/linkMetadata:batchGet"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Visibility controls who can read a memo.
|
||||
enum Visibility {
|
||||
VISIBILITY_UNSPECIFIED = 0;
|
||||
// PRIVATE: only the creator can read the memo.
|
||||
PRIVATE = 1;
|
||||
// PROTECTED: signed-in users of the instance can read the memo.
|
||||
PROTECTED = 2;
|
||||
// PUBLIC: anyone, including anonymous visitors, can read the memo.
|
||||
PUBLIC = 3;
|
||||
}
|
||||
|
||||
message Reaction {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/Reaction"
|
||||
pattern: "memos/{memo}/reactions/{reaction}"
|
||||
name_field: "name"
|
||||
singular: "reaction"
|
||||
plural: "reactions"
|
||||
};
|
||||
|
||||
// The resource name of the reaction.
|
||||
// Format: memos/{memo}/reactions/{reaction}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = OUTPUT_ONLY,
|
||||
(google.api.field_behavior) = IDENTIFIER
|
||||
];
|
||||
|
||||
// The resource name of the creator.
|
||||
// Format: users/{user}
|
||||
string creator = 2 [
|
||||
(google.api.field_behavior) = OUTPUT_ONLY,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
// The resource name of the content.
|
||||
// For memo reactions, this should be the memo's resource name.
|
||||
// Format: memos/{memo}
|
||||
string content_id = 3 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Required. The type of reaction (e.g., "👍", "❤️", "😄").
|
||||
string reaction_type = 4 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Output only. The creation timestamp.
|
||||
google.protobuf.Timestamp create_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
}
|
||||
|
||||
message Memo {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/Memo"
|
||||
pattern: "memos/{memo}"
|
||||
name_field: "name"
|
||||
singular: "memo"
|
||||
plural: "memos"
|
||||
};
|
||||
|
||||
// The resource name of the memo.
|
||||
// Format: memos/{memo}, memo is the user defined id or uuid.
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// The state of the memo.
|
||||
State state = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The name of the creator.
|
||||
// Format: users/{user}
|
||||
string creator = 3 [
|
||||
(google.api.field_behavior) = OUTPUT_ONLY,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
// The creation timestamp.
|
||||
// If not set on creation, the server will set it to the current time.
|
||||
google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// The last update timestamp.
|
||||
// If not set on creation, the server will set it to the current time.
|
||||
google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
reserved 6;
|
||||
reserved "display_time";
|
||||
|
||||
// Required. The content of the memo in Markdown format.
|
||||
string content = 7 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The visibility of the memo.
|
||||
// One of PRIVATE (creator only), PROTECTED (signed-in users), or
|
||||
// PUBLIC (anyone). Defaults to PRIVATE on creation when unspecified.
|
||||
Visibility visibility = 9 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Output only. The tags extracted from the content.
|
||||
repeated string tags = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Whether the memo is pinned.
|
||||
bool pinned = 11 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The attachments of the memo.
|
||||
repeated Attachment attachments = 12 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The relations of the memo.
|
||||
repeated MemoRelation relations = 13 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Output only. The reactions to the memo.
|
||||
repeated Reaction reactions = 14 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Output only. The computed properties of the memo.
|
||||
Property property = 15 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Output only. The name of the parent memo.
|
||||
// Format: memos/{memo}
|
||||
optional string parent = 16 [
|
||||
(google.api.field_behavior) = OUTPUT_ONLY,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Output only. The snippet of the memo content. Plain text only.
|
||||
string snippet = 17 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Optional. The location of the memo.
|
||||
optional Location location = 18 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Computed properties of a memo.
|
||||
message Property {
|
||||
bool has_link = 1;
|
||||
bool has_task_list = 2;
|
||||
bool has_code = 3;
|
||||
bool has_incomplete_tasks = 4;
|
||||
// The title extracted from the first H1 heading, if present.
|
||||
string title = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message Location {
|
||||
// A placeholder text for the location.
|
||||
string placeholder = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// The latitude of the location.
|
||||
double latitude = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// The longitude of the location.
|
||||
double longitude = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message CreateMemoRequest {
|
||||
// Required. The memo to create.
|
||||
Memo memo = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. The memo ID to use for this memo.
|
||||
// If empty, a unique ID will be generated.
|
||||
string memo_id = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListMemosRequest {
|
||||
// Optional. The maximum number of memos to return.
|
||||
// The service may return fewer than this value.
|
||||
// If unspecified, at most 50 memos will be returned.
|
||||
// The maximum value is 1000; values above 1000 will be coerced to 1000.
|
||||
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token, received from a previous `ListMemos` call.
|
||||
// Provide this to retrieve the subsequent page.
|
||||
string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The state of the memos to list.
|
||||
// Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
|
||||
State state = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The order to sort results by.
|
||||
// Default to "create_time desc".
|
||||
// Supports comma-separated list of fields following AIP-132.
|
||||
// Example: "pinned desc, create_time desc" or "update_time asc"
|
||||
// Supported fields: pinned, create_time, update_time, name.
|
||||
// Note: order_by uses create_time / update_time, while the filter
|
||||
// expression uses created_ts / updated_ts for the same timestamps.
|
||||
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A CEL expression to filter memos. Combine terms with && and ||.
|
||||
// Available fields:
|
||||
// content (string), creator (string, e.g. "users/1"),
|
||||
// created_ts / updated_ts (timestamp), pinned (bool),
|
||||
// visibility (string: PRIVATE | PROTECTED | PUBLIC),
|
||||
// tags (list<string>; match with `"work" in tags`, not `tag == "work"`),
|
||||
// has_task_list / has_link / has_code / has_incomplete_tasks (bool).
|
||||
// Note: the time fields here are created_ts / updated_ts, which differ from
|
||||
// the create_time / update_time names used by order_by.
|
||||
// Examples:
|
||||
// pinned == true && visibility == "PUBLIC"
|
||||
// tags.exists(t, t == "urgent")
|
||||
// content.contains("roadmap") && created_ts > now - duration("168h")
|
||||
string filter = 5 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. If true, show deleted memos in the response.
|
||||
bool show_deleted = 6 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListMemosResponse {
|
||||
// The list of memos.
|
||||
repeated Memo memos = 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;
|
||||
}
|
||||
|
||||
message GetMemoRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
}
|
||||
|
||||
message UpdateMemoRequest {
|
||||
// Required. The memo to update.
|
||||
// The `name` field is required.
|
||||
Memo memo = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The list of fields to update.
|
||||
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message DeleteMemoRequest {
|
||||
// Required. The resource name of the memo to delete.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Optional. If set to true, the memo will be deleted even if it has associated data.
|
||||
bool force = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message SetMemoAttachmentsRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Required. The attachments to set for the memo.
|
||||
repeated Attachment attachments = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message ListMemoAttachmentsRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Optional. The maximum number of attachments to return.
|
||||
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token for pagination.
|
||||
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListMemoAttachmentsResponse {
|
||||
// The list of attachments.
|
||||
repeated Attachment attachments = 1;
|
||||
|
||||
// A token for the next page of results.
|
||||
string next_page_token = 2;
|
||||
}
|
||||
|
||||
message MemoRelation {
|
||||
// The memo in the relation.
|
||||
Memo memo = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The related memo.
|
||||
Memo related_memo = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The type of the relation.
|
||||
enum Type {
|
||||
TYPE_UNSPECIFIED = 0;
|
||||
REFERENCE = 1;
|
||||
COMMENT = 2;
|
||||
}
|
||||
Type type = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Memo reference in relations.
|
||||
message Memo {
|
||||
// The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Output only. The snippet of the memo content. Plain text only.
|
||||
string snippet = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
}
|
||||
}
|
||||
|
||||
message SetMemoRelationsRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Required. The relations to set for the memo.
|
||||
repeated MemoRelation relations = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message ListMemoRelationsRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Optional. The maximum number of relations to return.
|
||||
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token for pagination.
|
||||
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListMemoRelationsResponse {
|
||||
// The list of relations.
|
||||
repeated MemoRelation relations = 1;
|
||||
|
||||
// A token for the next page of results.
|
||||
string next_page_token = 2;
|
||||
}
|
||||
|
||||
message CreateMemoCommentRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Required. The comment to create.
|
||||
Memo comment = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. The comment ID to use.
|
||||
string comment_id = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListMemoCommentsRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Optional. The maximum number of comments to return.
|
||||
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token for pagination.
|
||||
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The order to sort results by.
|
||||
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListMemoCommentsResponse {
|
||||
// The list of comment memos.
|
||||
repeated Memo memos = 1;
|
||||
|
||||
// A token for the next page of results.
|
||||
string next_page_token = 2;
|
||||
}
|
||||
|
||||
message ListMemoReactionsRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Optional. The maximum number of reactions to return.
|
||||
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token for pagination.
|
||||
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListMemoReactionsResponse {
|
||||
// The list of reactions.
|
||||
repeated Reaction reactions = 1;
|
||||
|
||||
// A token for the next page of results.
|
||||
string next_page_token = 2;
|
||||
}
|
||||
|
||||
message UpsertMemoReactionRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Required. The reaction to upsert.
|
||||
Reaction reaction = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message DeleteMemoReactionRequest {
|
||||
// Required. The resource name of the reaction to delete.
|
||||
// Format: memos/{memo}/reactions/{reaction}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Reaction"}
|
||||
];
|
||||
}
|
||||
|
||||
// MemoShare is an access grant that permits read-only access to a memo via an opaque bearer token.
|
||||
message MemoShare {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/MemoShare"
|
||||
pattern: "memos/{memo}/shares/{share}"
|
||||
singular: "share"
|
||||
plural: "shares"
|
||||
};
|
||||
|
||||
// The resource name of the share. Format: memos/{memo}/shares/{share}
|
||||
// The {share} segment is the opaque token used in the share URL.
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// Output only. When this share link was created.
|
||||
google.protobuf.Timestamp create_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Optional. When set, the share link stops working after this time.
|
||||
// If unset, the link never expires.
|
||||
optional google.protobuf.Timestamp expire_time = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message CreateMemoShareRequest {
|
||||
// Required. The resource name of the memo to share.
|
||||
// Format: memos/{memo}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
|
||||
// Required. The share to create.
|
||||
MemoShare memo_share = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message ListMemoSharesRequest {
|
||||
// Required. The resource name of the memo.
|
||||
// Format: memos/{memo}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
|
||||
];
|
||||
}
|
||||
|
||||
message ListMemoSharesResponse {
|
||||
// The list of share links.
|
||||
repeated MemoShare memo_shares = 1;
|
||||
}
|
||||
|
||||
message DeleteMemoShareRequest {
|
||||
// Required. The resource name of the share to delete.
|
||||
// Format: memos/{memo}/shares/{share}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/MemoShare"}
|
||||
];
|
||||
}
|
||||
|
||||
message GetMemoByShareRequest {
|
||||
// Required. The share token extracted from the share URL (/s/{share_id}).
|
||||
string share_id = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message GetLinkMetadataRequest {
|
||||
// Required. The link URL.
|
||||
string url = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message BatchGetLinkMetadataRequest {
|
||||
// Required. The link URLs.
|
||||
repeated string urls = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message BatchGetLinkMetadataResponse {
|
||||
// The link metadata list, in the same order as the input URLs.
|
||||
repeated LinkMetadata link_metadata = 1;
|
||||
}
|
||||
|
||||
message LinkMetadata {
|
||||
// The original link URL.
|
||||
string url = 1;
|
||||
|
||||
// The link title.
|
||||
string title = 2;
|
||||
|
||||
// The link description.
|
||||
string description = 3;
|
||||
|
||||
// The link image URL.
|
||||
string image = 4;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
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 ShortcutService {
|
||||
// ListShortcuts returns a user's saved shortcuts. Each shortcut is a named,
|
||||
// reusable CEL filter (see Shortcut.filter); pass its filter string directly
|
||||
// to the ListMemos `filter` argument to reuse a saved view.
|
||||
rpc ListShortcuts(ListShortcutsRequest) returns (ListShortcutsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{parent=users/*}/shortcuts"};
|
||||
option (google.api.method_signature) = "parent";
|
||||
}
|
||||
|
||||
// GetShortcut gets a shortcut by name.
|
||||
rpc GetShortcut(GetShortcutRequest) returns (Shortcut) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=users/*/shortcuts/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// CreateShortcut creates a new shortcut for a user.
|
||||
rpc CreateShortcut(CreateShortcutRequest) returns (Shortcut) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/{parent=users/*}/shortcuts"
|
||||
body: "shortcut"
|
||||
};
|
||||
option (google.api.method_signature) = "parent,shortcut";
|
||||
}
|
||||
|
||||
// UpdateShortcut updates a shortcut for a user.
|
||||
rpc UpdateShortcut(UpdateShortcutRequest) returns (Shortcut) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{shortcut.name=users/*/shortcuts/*}"
|
||||
body: "shortcut"
|
||||
};
|
||||
option (google.api.method_signature) = "shortcut,update_mask";
|
||||
}
|
||||
|
||||
// DeleteShortcut deletes a shortcut for a user.
|
||||
rpc DeleteShortcut(DeleteShortcutRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=users/*/shortcuts/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
}
|
||||
|
||||
message Shortcut {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/Shortcut"
|
||||
pattern: "users/{username}/shortcuts/{shortcut}"
|
||||
singular: "shortcut"
|
||||
plural: "shortcuts"
|
||||
};
|
||||
|
||||
// The resource name of the shortcut.
|
||||
// Format: users/{username}/shortcuts/{shortcut}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// The title of the shortcut.
|
||||
string title = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The CEL filter expression for the shortcut, using the same grammar as the
|
||||
// ListMemos `filter` argument. Reuse it by passing this value to ListMemos.
|
||||
string filter = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListShortcutsRequest {
|
||||
// Required. The parent resource where shortcuts are listed.
|
||||
// Format: users/{username}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {child_type: "memos.api.v1/Shortcut"}
|
||||
];
|
||||
}
|
||||
|
||||
message ListShortcutsResponse {
|
||||
// The list of shortcuts.
|
||||
repeated Shortcut shortcuts = 1;
|
||||
}
|
||||
|
||||
message GetShortcutRequest {
|
||||
// Required. The resource name of the shortcut to retrieve.
|
||||
// Format: users/{username}/shortcuts/{shortcut}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Shortcut"}
|
||||
];
|
||||
}
|
||||
|
||||
message CreateShortcutRequest {
|
||||
// Required. The parent resource where this shortcut will be created.
|
||||
// Format: users/{username}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {child_type: "memos.api.v1/Shortcut"}
|
||||
];
|
||||
|
||||
// Required. The shortcut to create.
|
||||
Shortcut shortcut = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. If set, validate the request, but do not actually create the shortcut.
|
||||
bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message UpdateShortcutRequest {
|
||||
// Required. The shortcut resource which replaces the resource on the server.
|
||||
Shortcut shortcut = 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 DeleteShortcutRequest {
|
||||
// Required. The resource name of the shortcut to delete.
|
||||
// Format: users/{username}/shortcuts/{shortcut}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/Shortcut"}
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,880 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package memos.api.v1;
|
||||
|
||||
import "api/v1/common.proto";
|
||||
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";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/type/color.proto";
|
||||
|
||||
option go_package = "gen/api/v1";
|
||||
|
||||
service UserService {
|
||||
// ListUsers returns a list of users.
|
||||
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/users"};
|
||||
}
|
||||
|
||||
// BatchGetUsers returns active users by usernames.
|
||||
rpc BatchGetUsers(BatchGetUsersRequest) returns (BatchGetUsersResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/users:batchGet"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
// GetUser gets a user by username.
|
||||
// Format: users/{username} (e.g., users/steven)
|
||||
rpc GetUser(GetUserRequest) returns (User) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=users/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// CreateUser creates a new user.
|
||||
rpc CreateUser(CreateUserRequest) returns (User) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/users"
|
||||
body: "user"
|
||||
};
|
||||
option (google.api.method_signature) = "user";
|
||||
}
|
||||
|
||||
// UpdateUser updates a user.
|
||||
rpc UpdateUser(UpdateUserRequest) returns (User) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{user.name=users/*}"
|
||||
body: "user"
|
||||
};
|
||||
option (google.api.method_signature) = "user,update_mask";
|
||||
}
|
||||
|
||||
// DeleteUser deletes a user.
|
||||
rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=users/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// ListAllUserStats returns statistics for all users.
|
||||
rpc ListAllUserStats(ListAllUserStatsRequest) returns (ListAllUserStatsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/users:stats"};
|
||||
}
|
||||
|
||||
// GetUserStats returns statistics for a specific user.
|
||||
rpc GetUserStats(GetUserStatsRequest) returns (UserStats) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=users/*}:getStats"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// GetUserSetting returns the user setting.
|
||||
rpc GetUserSetting(GetUserSettingRequest) returns (UserSetting) {
|
||||
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/*/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";
|
||||
}
|
||||
|
||||
// ListLinkedIdentities returns a list of linked SSO identities for a user.
|
||||
rpc ListLinkedIdentities(ListLinkedIdentitiesRequest) returns (ListLinkedIdentitiesResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{parent=users/*}/linkedIdentities"};
|
||||
option (google.api.method_signature) = "parent";
|
||||
}
|
||||
|
||||
// CreateLinkedIdentity links an SSO identity to the authenticated user.
|
||||
rpc CreateLinkedIdentity(CreateLinkedIdentityRequest) returns (LinkedIdentity) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/{parent=users/*}/linkedIdentities"
|
||||
body: "*"
|
||||
};
|
||||
option (google.api.method_signature) = "parent,idp_name";
|
||||
}
|
||||
|
||||
// GetLinkedIdentity gets a linked SSO identity for a user.
|
||||
rpc GetLinkedIdentity(GetLinkedIdentityRequest) returns (LinkedIdentity) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=users/*/linkedIdentities/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// DeleteLinkedIdentity unlinks an SSO identity from a user.
|
||||
rpc DeleteLinkedIdentity(DeleteLinkedIdentityRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=users/*/linkedIdentities/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// ListPersonalAccessTokens returns a list of Personal Access Tokens (PATs) for a user.
|
||||
// PATs are long-lived tokens for API/script access, distinct from short-lived JWT access tokens.
|
||||
rpc ListPersonalAccessTokens(ListPersonalAccessTokensRequest) returns (ListPersonalAccessTokensResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{parent=users/*}/personalAccessTokens"};
|
||||
option (google.api.method_signature) = "parent";
|
||||
}
|
||||
|
||||
// CreatePersonalAccessToken creates a new Personal Access Token for a user.
|
||||
// The token value is only returned once upon creation.
|
||||
rpc CreatePersonalAccessToken(CreatePersonalAccessTokenRequest) returns (CreatePersonalAccessTokenResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/{parent=users/*}/personalAccessTokens"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
// DeletePersonalAccessToken deletes a Personal Access Token.
|
||||
rpc DeletePersonalAccessToken(DeletePersonalAccessTokenRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=users/*/personalAccessTokens/*}"};
|
||||
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";
|
||||
}
|
||||
|
||||
// GetUserWebhookSigningSecret returns the signing secret for a webhook.
|
||||
// The secret is returned only through this explicit, owner-gated call; it is
|
||||
// never included in List/Create/Update responses.
|
||||
rpc GetUserWebhookSigningSecret(GetUserWebhookSigningSecretRequest) returns (GetUserWebhookSigningSecretResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{name=users/*/webhooks/*}:getSigningSecret"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// ListUserNotifications lists notifications for a user.
|
||||
rpc ListUserNotifications(ListUserNotificationsRequest) returns (ListUserNotificationsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{parent=users/*}/notifications"};
|
||||
option (google.api.method_signature) = "parent";
|
||||
}
|
||||
|
||||
// UpdateUserNotification updates a notification.
|
||||
rpc UpdateUserNotification(UpdateUserNotificationRequest) returns (UserNotification) {
|
||||
option (google.api.http) = {
|
||||
patch: "/api/v1/{notification.name=users/*/notifications/*}"
|
||||
body: "notification"
|
||||
};
|
||||
option (google.api.method_signature) = "notification,update_mask";
|
||||
}
|
||||
|
||||
// DeleteUserNotification deletes a notification.
|
||||
rpc DeleteUserNotification(DeleteUserNotificationRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=users/*/notifications/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
}
|
||||
|
||||
message User {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/User"
|
||||
pattern: "users/{user}"
|
||||
name_field: "name"
|
||||
singular: "user"
|
||||
plural: "users"
|
||||
};
|
||||
|
||||
// The resource name of the user.
|
||||
// Format: users/{user}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// The role of the user.
|
||||
Role role = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The unique username for login.
|
||||
string username = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. The email address of the user.
|
||||
string email = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The display name of the user.
|
||||
string display_name = 5 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The avatar URL of the user.
|
||||
string avatar_url = 6 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. The description of the user.
|
||||
string description = 7 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Input only. The password for the user.
|
||||
string password = 8 [(google.api.field_behavior) = INPUT_ONLY];
|
||||
|
||||
// The state of the user.
|
||||
State state = 9 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Output only. The creation timestamp.
|
||||
google.protobuf.Timestamp create_time = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Output only. The last update timestamp.
|
||||
google.protobuf.Timestamp update_time = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// User role enumeration.
|
||||
enum Role {
|
||||
ROLE_UNSPECIFIED = 0;
|
||||
// Admin role with system access.
|
||||
ADMIN = 2;
|
||||
// User role with limited access.
|
||||
USER = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ListUsersRequest {
|
||||
// Optional. The maximum number of users to return.
|
||||
// The service may return fewer than this value.
|
||||
// If unspecified, at most 50 users will be returned.
|
||||
// The maximum value is 1000; values above 1000 will be coerced to 1000.
|
||||
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token, received from a previous `ListUsers` call.
|
||||
// Provide this to retrieve the subsequent page.
|
||||
string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Filter to apply to the list results.
|
||||
// Example: "username == 'steven'"
|
||||
// Supported operators: ==
|
||||
// Supported fields: username
|
||||
string filter = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. If true, show deleted users in the response.
|
||||
bool show_deleted = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListUsersResponse {
|
||||
// The list of users.
|
||||
repeated User users = 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;
|
||||
}
|
||||
|
||||
message BatchGetUsersRequest {
|
||||
repeated string usernames = 1;
|
||||
}
|
||||
|
||||
message BatchGetUsersResponse {
|
||||
repeated User users = 1;
|
||||
}
|
||||
|
||||
message GetUserRequest {
|
||||
// Required. The resource name of the user.
|
||||
// Format: users/{username}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
// Optional. The fields to return in the response.
|
||||
// If not specified, all fields are returned.
|
||||
google.protobuf.FieldMask read_mask = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message CreateUserRequest {
|
||||
// Required. The user to create.
|
||||
User user = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.field_behavior) = INPUT_ONLY
|
||||
];
|
||||
|
||||
// Optional. The user ID to use for this user.
|
||||
// If empty, a unique ID will be generated.
|
||||
// Must match the pattern [a-z0-9-]+
|
||||
string user_id = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. If set, validate the request but don't actually create the user.
|
||||
bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. An idempotency token that can be used to ensure that multiple
|
||||
// requests to create a user have the same result.
|
||||
string request_id = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message UpdateUserRequest {
|
||||
// Required. The user to update.
|
||||
User user = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The list of fields to update.
|
||||
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. If set to true, allows updating sensitive fields.
|
||||
bool allow_missing = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message DeleteUserRequest {
|
||||
// Required. The resource name of the user to delete.
|
||||
// Format: users/{user}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
// Optional. If set to true, the user will be deleted even if they have associated data.
|
||||
bool force = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
// User statistics messages
|
||||
message UserStats {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/UserStats"
|
||||
pattern: "users/{user}"
|
||||
singular: "userStats"
|
||||
plural: "userStats"
|
||||
};
|
||||
|
||||
// The resource name of the user whose stats these are.
|
||||
// Format: users/{user}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
reserved 2;
|
||||
reserved "memo_display_timestamps";
|
||||
|
||||
// The stats of memo types.
|
||||
MemoTypeStats memo_type_stats = 3;
|
||||
|
||||
// The count of tags.
|
||||
map<string, int32> tag_count = 4;
|
||||
|
||||
// The creation timestamps of the user's memos.
|
||||
repeated google.protobuf.Timestamp memo_created_timestamps = 7;
|
||||
|
||||
// The latest update timestamps of the user's memos (one per memo,
|
||||
// mirrors memo_created_timestamps). Used by the activity heatmap when
|
||||
// the client's view is set to update_time basis.
|
||||
repeated google.protobuf.Timestamp memo_updated_timestamps = 8;
|
||||
|
||||
// The pinned memos of the user.
|
||||
repeated string pinned_memos = 5;
|
||||
|
||||
// Total memo count.
|
||||
int32 total_memo_count = 6;
|
||||
|
||||
// Memo type statistics.
|
||||
message MemoTypeStats {
|
||||
int32 link_count = 1;
|
||||
int32 code_count = 2;
|
||||
int32 todo_count = 3;
|
||||
int32 undo_count = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message GetUserStatsRequest {
|
||||
// Required. The resource name of the user.
|
||||
// Format: users/{user}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
}
|
||||
|
||||
message ListAllUserStatsRequest {
|
||||
// Optional. The state of memos to include. Defaults to NORMAL.
|
||||
State state = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Filter to apply to memo stats.
|
||||
// Uses the same filter syntax as ListMemos.
|
||||
string filter = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
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/{username}/settings/{setting}"
|
||||
singular: "userSetting"
|
||||
plural: "userSettings"
|
||||
};
|
||||
|
||||
// The name of the user setting.
|
||||
// Format: users/{username}/settings/{setting}, {setting} is the key for the setting.
|
||||
// For example, "users/steven/settings/GENERAL" for general settings.
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
oneof value {
|
||||
GeneralSetting general_setting = 2;
|
||||
WebhooksSetting webhooks_setting = 5;
|
||||
TagsSetting tags_setting = 6;
|
||||
}
|
||||
|
||||
// Enumeration of user setting keys.
|
||||
enum Key {
|
||||
KEY_UNSPECIFIED = 0;
|
||||
// GENERAL is the key for general user settings.
|
||||
GENERAL = 1;
|
||||
// WEBHOOKS is the key for user webhooks.
|
||||
WEBHOOKS = 4;
|
||||
// TAGS is the key for per-user tag metadata.
|
||||
TAGS = 5;
|
||||
}
|
||||
|
||||
// General user settings configuration.
|
||||
message GeneralSetting {
|
||||
// The preferred locale of the user.
|
||||
string locale = 1 [(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];
|
||||
}
|
||||
|
||||
// Tag metadata for user-specific display rules.
|
||||
message TagMetadata {
|
||||
// Optional background color for the tag label.
|
||||
// When unset, the default tag color is used.
|
||||
google.type.Color background_color = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
// Whether memos with this tag should have their content blurred.
|
||||
bool blur_content = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
// User-specific tag metadata.
|
||||
message TagsSetting {
|
||||
// Map of tag name pattern to tag metadata.
|
||||
// Each key is treated as an anchored regular expression (^pattern$).
|
||||
map<string, TagMetadata> tags = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
// User webhooks configuration.
|
||||
message WebhooksSetting {
|
||||
// List of user webhooks.
|
||||
repeated UserWebhook webhooks = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message GetUserSettingRequest {
|
||||
// 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/UserSetting"}
|
||||
];
|
||||
}
|
||||
|
||||
message UpdateUserSettingRequest {
|
||||
// Required. The user setting to update.
|
||||
UserSetting setting = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The list of fields to update.
|
||||
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;
|
||||
}
|
||||
|
||||
// LinkedIdentity represents an SSO identity linked to a user account.
|
||||
message LinkedIdentity {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/LinkedIdentity"
|
||||
pattern: "users/{user}/linkedIdentities/{linked_identity}"
|
||||
singular: "linkedIdentity"
|
||||
plural: "linkedIdentities"
|
||||
};
|
||||
|
||||
// The resource name of the linked identity.
|
||||
// Format: users/{user}/linkedIdentities/{linked_identity}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// The resource name of the identity provider.
|
||||
// Format: identity-providers/{uid}
|
||||
string idp_name = 2 [
|
||||
(google.api.field_behavior) = OUTPUT_ONLY,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
|
||||
];
|
||||
|
||||
// The external user identifier from the identity provider.
|
||||
string extern_uid = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
}
|
||||
|
||||
message ListLinkedIdentitiesRequest {
|
||||
// Required. The parent resource whose linked identities will be listed.
|
||||
// Format: users/{user}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
}
|
||||
|
||||
message ListLinkedIdentitiesResponse {
|
||||
// The list of linked identities.
|
||||
repeated LinkedIdentity linked_identities = 1;
|
||||
}
|
||||
|
||||
message CreateLinkedIdentityRequest {
|
||||
// Required. The parent user who owns the linked identity.
|
||||
// Format: users/{user}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
// Required. The identity provider to link.
|
||||
// Format: identity-providers/{uid}
|
||||
string idp_name = 2 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
|
||||
];
|
||||
|
||||
// Required. The authorization code from the identity provider.
|
||||
string code = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Required. The redirect URI used in the OAuth flow.
|
||||
string redirect_uri = 4 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Optional. The PKCE code verifier used in the OAuth flow.
|
||||
string code_verifier = 5 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message GetLinkedIdentityRequest {
|
||||
// Required. The resource name of the linked identity to get.
|
||||
// Format: users/{user}/linkedIdentities/{linked_identity}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/LinkedIdentity"}
|
||||
];
|
||||
}
|
||||
|
||||
message DeleteLinkedIdentityRequest {
|
||||
// Required. The resource name of the linked identity to delete.
|
||||
// Format: users/{user}/linkedIdentities/{linked_identity}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/LinkedIdentity"}
|
||||
];
|
||||
}
|
||||
|
||||
// PersonalAccessToken represents a long-lived token for API/script access.
|
||||
// PATs are distinct from short-lived JWT access tokens used for session authentication.
|
||||
message PersonalAccessToken {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/PersonalAccessToken"
|
||||
pattern: "users/{user}/personalAccessTokens/{personal_access_token}"
|
||||
singular: "personalAccessToken"
|
||||
plural: "personalAccessTokens"
|
||||
};
|
||||
|
||||
// The resource name of the personal access token.
|
||||
// Format: users/{user}/personalAccessTokens/{personal_access_token}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// The description of the token.
|
||||
string description = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Output only. The creation timestamp.
|
||||
google.protobuf.Timestamp created_at = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Optional. The expiration timestamp.
|
||||
google.protobuf.Timestamp expires_at = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Output only. The last used timestamp.
|
||||
google.protobuf.Timestamp last_used_at = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
}
|
||||
|
||||
message ListPersonalAccessTokensRequest {
|
||||
// Required. The parent resource whose personal access tokens 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 tokens to return.
|
||||
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. A page token for pagination.
|
||||
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListPersonalAccessTokensResponse {
|
||||
// The list of personal access tokens.
|
||||
repeated PersonalAccessToken personal_access_tokens = 1;
|
||||
|
||||
// A token for the next page of results.
|
||||
string next_page_token = 2;
|
||||
}
|
||||
|
||||
message CreatePersonalAccessTokenRequest {
|
||||
// Required. The parent resource where this token will be created.
|
||||
// Format: users/{user}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
// Optional. Description of the personal access token.
|
||||
string description = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Expiration duration in days (0 = never expires).
|
||||
int32 expires_in_days = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message CreatePersonalAccessTokenResponse {
|
||||
// The personal access token metadata.
|
||||
PersonalAccessToken personal_access_token = 1;
|
||||
|
||||
// The actual token value - only returned on creation.
|
||||
// This is the only time the token value will be visible.
|
||||
string token = 2;
|
||||
}
|
||||
|
||||
message DeletePersonalAccessTokenRequest {
|
||||
// Required. The resource name of the personal access token to delete.
|
||||
// Format: users/{user}/personalAccessTokens/{personal_access_token}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/PersonalAccessToken"}
|
||||
];
|
||||
}
|
||||
|
||||
// UserWebhook represents a webhook owned by a user.
|
||||
message UserWebhook {
|
||||
// The name of the webhook.
|
||||
// Format: users/{user}/webhooks/{webhook}
|
||||
string name = 1;
|
||||
|
||||
// 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];
|
||||
|
||||
// Optional. Signing secret used to HMAC-SHA256 sign the webhook request body.
|
||||
// This field is input-only; it is never returned in responses.
|
||||
string signing_secret = 6 [(google.api.field_behavior) = INPUT_ONLY];
|
||||
|
||||
// Whether a signing secret is configured for this webhook.
|
||||
bool signing_secret_set = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
message GetUserWebhookSigningSecretRequest {
|
||||
// The name of the webhook whose signing secret to reveal.
|
||||
// Format: users/{user}/webhooks/{webhook}
|
||||
string name = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message GetUserWebhookSigningSecretResponse {
|
||||
// The signing secret, in the Standard Webhooks "whsec_<base64>" form.
|
||||
string signing_secret = 1;
|
||||
}
|
||||
|
||||
message UserNotification {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/UserNotification"
|
||||
pattern: "users/{user}/notifications/{notification}"
|
||||
name_field: "name"
|
||||
singular: "notification"
|
||||
plural: "notifications"
|
||||
};
|
||||
|
||||
// The resource name of the notification.
|
||||
// Format: users/{user}/notifications/{notification}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = OUTPUT_ONLY,
|
||||
(google.api.field_behavior) = IDENTIFIER
|
||||
];
|
||||
|
||||
// The sender of the notification.
|
||||
// Format: users/{user}
|
||||
string sender = 2 [
|
||||
(google.api.field_behavior) = OUTPUT_ONLY,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
// The sender user details.
|
||||
User sender_user = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// The status of the notification.
|
||||
Status status = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// The creation timestamp.
|
||||
google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// The type of the notification.
|
||||
Type type = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
oneof payload {
|
||||
MemoCommentPayload memo_comment = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
MemoMentionPayload memo_mention = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
}
|
||||
|
||||
message MemoCommentPayload {
|
||||
// The memo name of comment.
|
||||
// Format: memos/{memo}
|
||||
string memo = 1;
|
||||
|
||||
// The name of related memo.
|
||||
// Format: memos/{memo}
|
||||
string related_memo = 2;
|
||||
|
||||
// Preview text of the comment memo.
|
||||
string memo_snippet = 3;
|
||||
|
||||
// Preview text of the related memo.
|
||||
string related_memo_snippet = 4;
|
||||
}
|
||||
|
||||
message MemoMentionPayload {
|
||||
// The memo that contains the mention.
|
||||
// Format: memos/{memo}
|
||||
string memo = 1;
|
||||
|
||||
// The related parent memo when the mention was created in a comment.
|
||||
// Format: memos/{memo}
|
||||
string related_memo = 2;
|
||||
|
||||
// Preview text of the memo that contains the mention.
|
||||
string memo_snippet = 3;
|
||||
|
||||
// Preview text of the related parent memo.
|
||||
string related_memo_snippet = 4;
|
||||
}
|
||||
|
||||
enum Status {
|
||||
STATUS_UNSPECIFIED = 0;
|
||||
UNREAD = 1;
|
||||
ARCHIVED = 2;
|
||||
}
|
||||
|
||||
enum Type {
|
||||
TYPE_UNSPECIFIED = 0;
|
||||
MEMO_COMMENT = 1;
|
||||
MEMO_MENTION = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ListUserNotificationsRequest {
|
||||
// The parent user resource.
|
||||
// Format: users/{user}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
|
||||
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
|
||||
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
string filter = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message ListUserNotificationsResponse {
|
||||
repeated UserNotification notifications = 1;
|
||||
string next_page_token = 2;
|
||||
}
|
||||
|
||||
message UpdateUserNotificationRequest {
|
||||
UserNotification notification = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
message DeleteUserNotificationRequest {
|
||||
// Format: users/{user}/notifications/{notification}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/UserNotification"}
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user