mirror of https://github.com/usememos/memos.git
refactor(api): migrate inbox functionality to user notifications
- Remove standalone InboxService and move functionality to UserService - Rename inbox to user notifications for better API consistency - Add ListUserNotifications, UpdateUserNotification, DeleteUserNotification methods - Update frontend components to use new notification endpoints - Update store layer to support new notification model 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e915e3a46b
commit
bc1550e926
|
|
@ -61,8 +61,6 @@ message Activity {
|
||||||
TYPE_UNSPECIFIED = 0;
|
TYPE_UNSPECIFIED = 0;
|
||||||
// Memo comment activity.
|
// Memo comment activity.
|
||||||
MEMO_COMMENT = 1;
|
MEMO_COMMENT = 1;
|
||||||
// Version update activity.
|
|
||||||
VERSION_UPDATE = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activity levels.
|
// Activity levels.
|
||||||
|
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package memos.api.v1;
|
|
||||||
|
|
||||||
import "google/api/annotations.proto";
|
|
||||||
import "google/api/client.proto";
|
|
||||||
import "google/api/field_behavior.proto";
|
|
||||||
import "google/api/resource.proto";
|
|
||||||
import "google/protobuf/empty.proto";
|
|
||||||
import "google/protobuf/field_mask.proto";
|
|
||||||
import "google/protobuf/timestamp.proto";
|
|
||||||
|
|
||||||
option go_package = "gen/api/v1";
|
|
||||||
|
|
||||||
service InboxService {
|
|
||||||
// ListInboxes lists inboxes for a user.
|
|
||||||
rpc ListInboxes(ListInboxesRequest) returns (ListInboxesResponse) {
|
|
||||||
option (google.api.http) = {get: "/api/v1/{parent=users/*}/inboxes"};
|
|
||||||
option (google.api.method_signature) = "parent";
|
|
||||||
}
|
|
||||||
// UpdateInbox updates an inbox.
|
|
||||||
rpc UpdateInbox(UpdateInboxRequest) returns (Inbox) {
|
|
||||||
option (google.api.http) = {
|
|
||||||
patch: "/api/v1/{inbox.name=inboxes/*}"
|
|
||||||
body: "inbox"
|
|
||||||
};
|
|
||||||
option (google.api.method_signature) = "inbox,update_mask";
|
|
||||||
}
|
|
||||||
// DeleteInbox deletes an inbox.
|
|
||||||
rpc DeleteInbox(DeleteInboxRequest) returns (google.protobuf.Empty) {
|
|
||||||
option (google.api.http) = {delete: "/api/v1/{name=inboxes/*}"};
|
|
||||||
option (google.api.method_signature) = "name";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message Inbox {
|
|
||||||
option (google.api.resource) = {
|
|
||||||
type: "memos.api.v1/Inbox"
|
|
||||||
pattern: "inboxes/{inbox}"
|
|
||||||
name_field: "name"
|
|
||||||
singular: "inbox"
|
|
||||||
plural: "inboxes"
|
|
||||||
};
|
|
||||||
|
|
||||||
// The resource name of the inbox.
|
|
||||||
// Format: inboxes/{inbox}
|
|
||||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
|
||||||
|
|
||||||
// The sender of the inbox notification.
|
|
||||||
// Format: users/{user}
|
|
||||||
string sender = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
|
|
||||||
|
|
||||||
// The receiver of the inbox notification.
|
|
||||||
// Format: users/{user}
|
|
||||||
string receiver = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
|
|
||||||
|
|
||||||
// The status of the inbox notification.
|
|
||||||
Status status = 4 [(google.api.field_behavior) = OPTIONAL];
|
|
||||||
|
|
||||||
// Output only. The creation timestamp.
|
|
||||||
google.protobuf.Timestamp create_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
|
|
||||||
|
|
||||||
// The type of the inbox notification.
|
|
||||||
Type type = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
|
|
||||||
|
|
||||||
// Optional. The activity ID associated with this inbox notification.
|
|
||||||
optional int32 activity_id = 7 [(google.api.field_behavior) = OPTIONAL];
|
|
||||||
|
|
||||||
// Status enumeration for inbox notifications.
|
|
||||||
enum Status {
|
|
||||||
// Unspecified status.
|
|
||||||
STATUS_UNSPECIFIED = 0;
|
|
||||||
// The notification is unread.
|
|
||||||
UNREAD = 1;
|
|
||||||
// The notification is archived.
|
|
||||||
ARCHIVED = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type enumeration for inbox notifications.
|
|
||||||
enum Type {
|
|
||||||
// Unspecified type.
|
|
||||||
TYPE_UNSPECIFIED = 0;
|
|
||||||
// Memo comment notification.
|
|
||||||
MEMO_COMMENT = 1;
|
|
||||||
// Version update notification.
|
|
||||||
VERSION_UPDATE = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message ListInboxesRequest {
|
|
||||||
// Required. The parent resource whose inboxes 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 inboxes to return.
|
|
||||||
// The service may return fewer than this value.
|
|
||||||
// If unspecified, at most 50 inboxes will be returned.
|
|
||||||
// The maximum value is 1000; values above 1000 will be coerced to 1000.
|
|
||||||
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
|
|
||||||
|
|
||||||
// Optional. A page token, received from a previous `ListInboxes` call.
|
|
||||||
// Provide this to retrieve the subsequent page.
|
|
||||||
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
|
|
||||||
|
|
||||||
// Optional. Filter to apply to the list results.
|
|
||||||
// Example: "status=UNREAD" or "type=MEMO_COMMENT"
|
|
||||||
// Supported operators: =, !=
|
|
||||||
// Supported fields: status, type, sender, create_time
|
|
||||||
string filter = 4 [(google.api.field_behavior) = OPTIONAL];
|
|
||||||
|
|
||||||
// Optional. The order to sort results by.
|
|
||||||
// Example: "create_time desc" or "status asc"
|
|
||||||
string order_by = 5 [(google.api.field_behavior) = OPTIONAL];
|
|
||||||
}
|
|
||||||
|
|
||||||
message ListInboxesResponse {
|
|
||||||
// The list of inboxes.
|
|
||||||
repeated Inbox inboxes = 1;
|
|
||||||
|
|
||||||
// A token that can be sent as `page_token` to retrieve the next page.
|
|
||||||
// If this field is omitted, there are no subsequent pages.
|
|
||||||
string next_page_token = 2;
|
|
||||||
|
|
||||||
// The total count of inboxes (may be approximate).
|
|
||||||
int32 total_size = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message UpdateInboxRequest {
|
|
||||||
// Required. The inbox to update.
|
|
||||||
Inbox inbox = 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 missing fields.
|
|
||||||
bool allow_missing = 3 [(google.api.field_behavior) = OPTIONAL];
|
|
||||||
}
|
|
||||||
|
|
||||||
message DeleteInboxRequest {
|
|
||||||
// Required. The resource name of the inbox to delete.
|
|
||||||
// Format: inboxes/{inbox}
|
|
||||||
string name = 1 [
|
|
||||||
(google.api.field_behavior) = REQUIRED,
|
|
||||||
(google.api.resource_reference) = {type: "memos.api.v1/Inbox"}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -153,6 +153,27 @@ service UserService {
|
||||||
option (google.api.http) = {delete: "/api/v1/{name=users/*/webhooks/*}"};
|
option (google.api.http) = {delete: "/api/v1/{name=users/*/webhooks/*}"};
|
||||||
option (google.api.method_signature) = "name";
|
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 {
|
message User {
|
||||||
|
|
@ -672,3 +693,81 @@ message DeleteUserWebhookRequest {
|
||||||
// Format: users/{user}/webhooks/{webhook}
|
// Format: users/{user}/webhooks/{webhook}
|
||||||
string name = 1 [(google.api.field_behavior) = REQUIRED];
|
string name = 1 [(google.api.field_behavior) = REQUIRED];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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];
|
||||||
|
|
||||||
|
// The activity ID associated with this notification.
|
||||||
|
optional int32 activity_id = 6 [(google.api.field_behavior) = OPTIONAL];
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
STATUS_UNSPECIFIED = 0;
|
||||||
|
UNREAD = 1;
|
||||||
|
ARCHIVED = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
TYPE_UNSPECIFIED = 0;
|
||||||
|
MEMO_COMMENT = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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"}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@ const (
|
||||||
Activity_TYPE_UNSPECIFIED Activity_Type = 0
|
Activity_TYPE_UNSPECIFIED Activity_Type = 0
|
||||||
// Memo comment activity.
|
// Memo comment activity.
|
||||||
Activity_MEMO_COMMENT Activity_Type = 1
|
Activity_MEMO_COMMENT Activity_Type = 1
|
||||||
// Version update activity.
|
|
||||||
Activity_VERSION_UPDATE Activity_Type = 2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for Activity_Type.
|
// Enum value maps for Activity_Type.
|
||||||
|
|
@ -40,12 +38,10 @@ var (
|
||||||
Activity_Type_name = map[int32]string{
|
Activity_Type_name = map[int32]string{
|
||||||
0: "TYPE_UNSPECIFIED",
|
0: "TYPE_UNSPECIFIED",
|
||||||
1: "MEMO_COMMENT",
|
1: "MEMO_COMMENT",
|
||||||
2: "VERSION_UPDATE",
|
|
||||||
}
|
}
|
||||||
Activity_Type_value = map[string]int32{
|
Activity_Type_value = map[string]int32{
|
||||||
"TYPE_UNSPECIFIED": 0,
|
"TYPE_UNSPECIFIED": 0,
|
||||||
"MEMO_COMMENT": 1,
|
"MEMO_COMMENT": 1,
|
||||||
"VERSION_UPDATE": 2,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -513,7 +509,7 @@ var File_api_v1_activity_service_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_api_v1_activity_service_proto_rawDesc = "" +
|
const file_api_v1_activity_service_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x1dapi/v1/activity_service.proto\x12\fmemos.api.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x86\x04\n" +
|
"\x1dapi/v1/activity_service.proto\x12\fmemos.api.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xf2\x03\n" +
|
||||||
"\bActivity\x12\x1a\n" +
|
"\bActivity\x12\x1a\n" +
|
||||||
"\x04name\x18\x01 \x01(\tB\x06\xe0A\x03\xe0A\bR\x04name\x12\x1d\n" +
|
"\x04name\x18\x01 \x01(\tB\x06\xe0A\x03\xe0A\bR\x04name\x12\x1d\n" +
|
||||||
"\acreator\x18\x02 \x01(\tB\x03\xe0A\x03R\acreator\x124\n" +
|
"\acreator\x18\x02 \x01(\tB\x03\xe0A\x03R\acreator\x124\n" +
|
||||||
|
|
@ -521,11 +517,10 @@ const file_api_v1_activity_service_proto_rawDesc = "" +
|
||||||
"\x05level\x18\x04 \x01(\x0e2\x1c.memos.api.v1.Activity.LevelB\x03\xe0A\x03R\x05level\x12@\n" +
|
"\x05level\x18\x04 \x01(\x0e2\x1c.memos.api.v1.Activity.LevelB\x03\xe0A\x03R\x05level\x12@\n" +
|
||||||
"\vcreate_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
|
"\vcreate_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
|
||||||
"createTime\x12<\n" +
|
"createTime\x12<\n" +
|
||||||
"\apayload\x18\x06 \x01(\v2\x1d.memos.api.v1.ActivityPayloadB\x03\xe0A\x03R\apayload\"B\n" +
|
"\apayload\x18\x06 \x01(\v2\x1d.memos.api.v1.ActivityPayloadB\x03\xe0A\x03R\apayload\".\n" +
|
||||||
"\x04Type\x12\x14\n" +
|
"\x04Type\x12\x14\n" +
|
||||||
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
|
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
|
||||||
"\fMEMO_COMMENT\x10\x01\x12\x12\n" +
|
"\fMEMO_COMMENT\x10\x01\"=\n" +
|
||||||
"\x0eVERSION_UPDATE\x10\x02\"=\n" +
|
|
||||||
"\x05Level\x12\x15\n" +
|
"\x05Level\x12\x15\n" +
|
||||||
"\x11LEVEL_UNSPECIFIED\x10\x00\x12\b\n" +
|
"\x11LEVEL_UNSPECIFIED\x10\x00\x12\b\n" +
|
||||||
"\x04INFO\x10\x01\x12\b\n" +
|
"\x04INFO\x10\x01\x12\b\n" +
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,6 @@ const (
|
||||||
Inbox_TYPE_UNSPECIFIED Inbox_Type = 0
|
Inbox_TYPE_UNSPECIFIED Inbox_Type = 0
|
||||||
// Memo comment notification.
|
// Memo comment notification.
|
||||||
Inbox_MEMO_COMMENT Inbox_Type = 1
|
Inbox_MEMO_COMMENT Inbox_Type = 1
|
||||||
// Version update notification.
|
|
||||||
Inbox_VERSION_UPDATE Inbox_Type = 2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for Inbox_Type.
|
// Enum value maps for Inbox_Type.
|
||||||
|
|
@ -95,12 +93,10 @@ var (
|
||||||
Inbox_Type_name = map[int32]string{
|
Inbox_Type_name = map[int32]string{
|
||||||
0: "TYPE_UNSPECIFIED",
|
0: "TYPE_UNSPECIFIED",
|
||||||
1: "MEMO_COMMENT",
|
1: "MEMO_COMMENT",
|
||||||
2: "VERSION_UPDATE",
|
|
||||||
}
|
}
|
||||||
Inbox_Type_value = map[string]int32{
|
Inbox_Type_value = map[string]int32{
|
||||||
"TYPE_UNSPECIFIED": 0,
|
"TYPE_UNSPECIFIED": 0,
|
||||||
"MEMO_COMMENT": 1,
|
"MEMO_COMMENT": 1,
|
||||||
"VERSION_UPDATE": 2,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -500,7 +496,7 @@ var File_api_v1_inbox_service_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_api_v1_inbox_service_proto_rawDesc = "" +
|
const file_api_v1_inbox_service_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x1aapi/v1/inbox_service.proto\x12\fmemos.api.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x87\x04\n" +
|
"\x1aapi/v1/inbox_service.proto\x12\fmemos.api.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xf3\x03\n" +
|
||||||
"\x05Inbox\x12\x17\n" +
|
"\x05Inbox\x12\x17\n" +
|
||||||
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12\x1b\n" +
|
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12\x1b\n" +
|
||||||
"\x06sender\x18\x02 \x01(\tB\x03\xe0A\x03R\x06sender\x12\x1f\n" +
|
"\x06sender\x18\x02 \x01(\tB\x03\xe0A\x03R\x06sender\x12\x1f\n" +
|
||||||
|
|
@ -515,11 +511,10 @@ const file_api_v1_inbox_service_proto_rawDesc = "" +
|
||||||
"\x12STATUS_UNSPECIFIED\x10\x00\x12\n" +
|
"\x12STATUS_UNSPECIFIED\x10\x00\x12\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x06UNREAD\x10\x01\x12\f\n" +
|
"\x06UNREAD\x10\x01\x12\f\n" +
|
||||||
"\bARCHIVED\x10\x02\"B\n" +
|
"\bARCHIVED\x10\x02\".\n" +
|
||||||
"\x04Type\x12\x14\n" +
|
"\x04Type\x12\x14\n" +
|
||||||
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
|
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
|
||||||
"\fMEMO_COMMENT\x10\x01\x12\x12\n" +
|
"\fMEMO_COMMENT\x10\x01:>\xeaA;\n" +
|
||||||
"\x0eVERSION_UPDATE\x10\x02:>\xeaA;\n" +
|
|
||||||
"\x12memos.api.v1/Inbox\x12\x0finboxes/{inbox}\x1a\x04name*\ainboxes2\x05inboxB\x0e\n" +
|
"\x12memos.api.v1/Inbox\x12\x0finboxes/{inbox}\x1a\x04name*\ainboxes2\x05inboxB\x0e\n" +
|
||||||
"\f_activity_id\"\xca\x01\n" +
|
"\f_activity_id\"\xca\x01\n" +
|
||||||
"\x12ListInboxesRequest\x121\n" +
|
"\x12ListInboxesRequest\x121\n" +
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,101 @@ func (UserSetting_Key) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{12, 0}
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{12, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserNotification_Status int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserNotification_STATUS_UNSPECIFIED UserNotification_Status = 0
|
||||||
|
UserNotification_UNREAD UserNotification_Status = 1
|
||||||
|
UserNotification_ARCHIVED UserNotification_Status = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for UserNotification_Status.
|
||||||
|
var (
|
||||||
|
UserNotification_Status_name = map[int32]string{
|
||||||
|
0: "STATUS_UNSPECIFIED",
|
||||||
|
1: "UNREAD",
|
||||||
|
2: "ARCHIVED",
|
||||||
|
}
|
||||||
|
UserNotification_Status_value = map[string]int32{
|
||||||
|
"STATUS_UNSPECIFIED": 0,
|
||||||
|
"UNREAD": 1,
|
||||||
|
"ARCHIVED": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x UserNotification_Status) Enum() *UserNotification_Status {
|
||||||
|
p := new(UserNotification_Status)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x UserNotification_Status) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UserNotification_Status) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_api_v1_user_service_proto_enumTypes[2].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UserNotification_Status) Type() protoreflect.EnumType {
|
||||||
|
return &file_api_v1_user_service_proto_enumTypes[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x UserNotification_Status) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UserNotification_Status.Descriptor instead.
|
||||||
|
func (UserNotification_Status) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{32, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserNotification_Type int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserNotification_TYPE_UNSPECIFIED UserNotification_Type = 0
|
||||||
|
UserNotification_MEMO_COMMENT UserNotification_Type = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for UserNotification_Type.
|
||||||
|
var (
|
||||||
|
UserNotification_Type_name = map[int32]string{
|
||||||
|
0: "TYPE_UNSPECIFIED",
|
||||||
|
1: "MEMO_COMMENT",
|
||||||
|
}
|
||||||
|
UserNotification_Type_value = map[string]int32{
|
||||||
|
"TYPE_UNSPECIFIED": 0,
|
||||||
|
"MEMO_COMMENT": 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x UserNotification_Type) Enum() *UserNotification_Type {
|
||||||
|
p := new(UserNotification_Type)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x UserNotification_Type) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UserNotification_Type) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_api_v1_user_service_proto_enumTypes[3].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UserNotification_Type) Type() protoreflect.EnumType {
|
||||||
|
return &file_api_v1_user_service_proto_enumTypes[3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x UserNotification_Type) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UserNotification_Type.Descriptor instead.
|
||||||
|
func (UserNotification_Type) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{32, 1}
|
||||||
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
// The resource name of the user.
|
// The resource name of the user.
|
||||||
|
|
@ -2169,6 +2264,317 @@ func (x *DeleteUserWebhookRequest) GetName() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserNotification struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// The resource name of the notification.
|
||||||
|
// Format: users/{user}/notifications/{notification}
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
// The sender of the notification.
|
||||||
|
// Format: users/{user}
|
||||||
|
Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"`
|
||||||
|
// The status of the notification.
|
||||||
|
Status UserNotification_Status `protobuf:"varint,3,opt,name=status,proto3,enum=memos.api.v1.UserNotification_Status" json:"status,omitempty"`
|
||||||
|
// The creation timestamp.
|
||||||
|
CreateTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
|
||||||
|
// The type of the notification.
|
||||||
|
Type UserNotification_Type `protobuf:"varint,5,opt,name=type,proto3,enum=memos.api.v1.UserNotification_Type" json:"type,omitempty"`
|
||||||
|
// The activity ID associated with this notification.
|
||||||
|
ActivityId *int32 `protobuf:"varint,6,opt,name=activity_id,json=activityId,proto3,oneof" json:"activity_id,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) Reset() {
|
||||||
|
*x = UserNotification{}
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[32]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UserNotification) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UserNotification) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[32]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UserNotification.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UserNotification) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{32}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) GetName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) GetSender() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Sender
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) GetStatus() UserNotification_Status {
|
||||||
|
if x != nil {
|
||||||
|
return x.Status
|
||||||
|
}
|
||||||
|
return UserNotification_STATUS_UNSPECIFIED
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) GetCreateTime() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.CreateTime
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) GetType() UserNotification_Type {
|
||||||
|
if x != nil {
|
||||||
|
return x.Type
|
||||||
|
}
|
||||||
|
return UserNotification_TYPE_UNSPECIFIED
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserNotification) GetActivityId() int32 {
|
||||||
|
if x != nil && x.ActivityId != nil {
|
||||||
|
return *x.ActivityId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListUserNotificationsRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// The parent user resource.
|
||||||
|
// Format: users/{user}
|
||||||
|
Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"`
|
||||||
|
PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
|
||||||
|
PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"`
|
||||||
|
Filter string `protobuf:"bytes,4,opt,name=filter,proto3" json:"filter,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsRequest) Reset() {
|
||||||
|
*x = ListUserNotificationsRequest{}
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[33]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListUserNotificationsRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[33]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListUserNotificationsRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListUserNotificationsRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{33}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsRequest) GetParent() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Parent
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsRequest) GetPageSize() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.PageSize
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsRequest) GetPageToken() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PageToken
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsRequest) GetFilter() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Filter
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListUserNotificationsResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Notifications []*UserNotification `protobuf:"bytes,1,rep,name=notifications,proto3" json:"notifications,omitempty"`
|
||||||
|
NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsResponse) Reset() {
|
||||||
|
*x = ListUserNotificationsResponse{}
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[34]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListUserNotificationsResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[34]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListUserNotificationsResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListUserNotificationsResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{34}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsResponse) GetNotifications() []*UserNotification {
|
||||||
|
if x != nil {
|
||||||
|
return x.Notifications
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListUserNotificationsResponse) GetNextPageToken() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.NextPageToken
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateUserNotificationRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Notification *UserNotification `protobuf:"bytes,1,opt,name=notification,proto3" json:"notification,omitempty"`
|
||||||
|
UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpdateUserNotificationRequest) Reset() {
|
||||||
|
*x = UpdateUserNotificationRequest{}
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[35]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpdateUserNotificationRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UpdateUserNotificationRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UpdateUserNotificationRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[35]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UpdateUserNotificationRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UpdateUserNotificationRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{35}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpdateUserNotificationRequest) GetNotification() *UserNotification {
|
||||||
|
if x != nil {
|
||||||
|
return x.Notification
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpdateUserNotificationRequest) GetUpdateMask() *fieldmaskpb.FieldMask {
|
||||||
|
if x != nil {
|
||||||
|
return x.UpdateMask
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteUserNotificationRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// Format: users/{user}/notifications/{notification}
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeleteUserNotificationRequest) Reset() {
|
||||||
|
*x = DeleteUserNotificationRequest{}
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[36]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeleteUserNotificationRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DeleteUserNotificationRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *DeleteUserNotificationRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_v1_user_service_proto_msgTypes[36]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use DeleteUserNotificationRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*DeleteUserNotificationRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_v1_user_service_proto_rawDescGZIP(), []int{36}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeleteUserNotificationRequest) GetName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Memo type statistics.
|
// Memo type statistics.
|
||||||
type UserStats_MemoTypeStats struct {
|
type UserStats_MemoTypeStats struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
|
@ -2182,7 +2588,7 @@ type UserStats_MemoTypeStats struct {
|
||||||
|
|
||||||
func (x *UserStats_MemoTypeStats) Reset() {
|
func (x *UserStats_MemoTypeStats) Reset() {
|
||||||
*x = UserStats_MemoTypeStats{}
|
*x = UserStats_MemoTypeStats{}
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[33]
|
mi := &file_api_v1_user_service_proto_msgTypes[38]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2194,7 +2600,7 @@ func (x *UserStats_MemoTypeStats) String() string {
|
||||||
func (*UserStats_MemoTypeStats) ProtoMessage() {}
|
func (*UserStats_MemoTypeStats) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UserStats_MemoTypeStats) ProtoReflect() protoreflect.Message {
|
func (x *UserStats_MemoTypeStats) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[33]
|
mi := &file_api_v1_user_service_proto_msgTypes[38]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2255,7 +2661,7 @@ type UserSetting_GeneralSetting struct {
|
||||||
|
|
||||||
func (x *UserSetting_GeneralSetting) Reset() {
|
func (x *UserSetting_GeneralSetting) Reset() {
|
||||||
*x = UserSetting_GeneralSetting{}
|
*x = UserSetting_GeneralSetting{}
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[34]
|
mi := &file_api_v1_user_service_proto_msgTypes[39]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2267,7 +2673,7 @@ func (x *UserSetting_GeneralSetting) String() string {
|
||||||
func (*UserSetting_GeneralSetting) ProtoMessage() {}
|
func (*UserSetting_GeneralSetting) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UserSetting_GeneralSetting) ProtoReflect() protoreflect.Message {
|
func (x *UserSetting_GeneralSetting) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[34]
|
mi := &file_api_v1_user_service_proto_msgTypes[39]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2315,7 +2721,7 @@ type UserSetting_SessionsSetting struct {
|
||||||
|
|
||||||
func (x *UserSetting_SessionsSetting) Reset() {
|
func (x *UserSetting_SessionsSetting) Reset() {
|
||||||
*x = UserSetting_SessionsSetting{}
|
*x = UserSetting_SessionsSetting{}
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[35]
|
mi := &file_api_v1_user_service_proto_msgTypes[40]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2327,7 +2733,7 @@ func (x *UserSetting_SessionsSetting) String() string {
|
||||||
func (*UserSetting_SessionsSetting) ProtoMessage() {}
|
func (*UserSetting_SessionsSetting) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UserSetting_SessionsSetting) ProtoReflect() protoreflect.Message {
|
func (x *UserSetting_SessionsSetting) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[35]
|
mi := &file_api_v1_user_service_proto_msgTypes[40]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2361,7 +2767,7 @@ type UserSetting_AccessTokensSetting struct {
|
||||||
|
|
||||||
func (x *UserSetting_AccessTokensSetting) Reset() {
|
func (x *UserSetting_AccessTokensSetting) Reset() {
|
||||||
*x = UserSetting_AccessTokensSetting{}
|
*x = UserSetting_AccessTokensSetting{}
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[36]
|
mi := &file_api_v1_user_service_proto_msgTypes[41]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2373,7 +2779,7 @@ func (x *UserSetting_AccessTokensSetting) String() string {
|
||||||
func (*UserSetting_AccessTokensSetting) ProtoMessage() {}
|
func (*UserSetting_AccessTokensSetting) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UserSetting_AccessTokensSetting) ProtoReflect() protoreflect.Message {
|
func (x *UserSetting_AccessTokensSetting) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[36]
|
mi := &file_api_v1_user_service_proto_msgTypes[41]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2407,7 +2813,7 @@ type UserSetting_WebhooksSetting struct {
|
||||||
|
|
||||||
func (x *UserSetting_WebhooksSetting) Reset() {
|
func (x *UserSetting_WebhooksSetting) Reset() {
|
||||||
*x = UserSetting_WebhooksSetting{}
|
*x = UserSetting_WebhooksSetting{}
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[37]
|
mi := &file_api_v1_user_service_proto_msgTypes[42]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2419,7 +2825,7 @@ func (x *UserSetting_WebhooksSetting) String() string {
|
||||||
func (*UserSetting_WebhooksSetting) ProtoMessage() {}
|
func (*UserSetting_WebhooksSetting) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UserSetting_WebhooksSetting) ProtoReflect() protoreflect.Message {
|
func (x *UserSetting_WebhooksSetting) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[37]
|
mi := &file_api_v1_user_service_proto_msgTypes[42]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2460,7 +2866,7 @@ type UserSession_ClientInfo struct {
|
||||||
|
|
||||||
func (x *UserSession_ClientInfo) Reset() {
|
func (x *UserSession_ClientInfo) Reset() {
|
||||||
*x = UserSession_ClientInfo{}
|
*x = UserSession_ClientInfo{}
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[38]
|
mi := &file_api_v1_user_service_proto_msgTypes[43]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2472,7 +2878,7 @@ func (x *UserSession_ClientInfo) String() string {
|
||||||
func (*UserSession_ClientInfo) ProtoMessage() {}
|
func (*UserSession_ClientInfo) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UserSession_ClientInfo) ProtoReflect() protoreflect.Message {
|
func (x *UserSession_ClientInfo) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_api_v1_user_service_proto_msgTypes[38]
|
mi := &file_api_v1_user_service_proto_msgTypes[43]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2725,7 +3131,44 @@ const file_api_v1_user_service_proto_rawDesc = "" +
|
||||||
"\vupdate_mask\x18\x02 \x01(\v2\x1a.google.protobuf.FieldMaskR\n" +
|
"\vupdate_mask\x18\x02 \x01(\v2\x1a.google.protobuf.FieldMaskR\n" +
|
||||||
"updateMask\"3\n" +
|
"updateMask\"3\n" +
|
||||||
"\x18DeleteUserWebhookRequest\x12\x17\n" +
|
"\x18DeleteUserWebhookRequest\x12\x17\n" +
|
||||||
"\x04name\x18\x01 \x01(\tB\x03\xe0A\x02R\x04name2\xe6\x15\n" +
|
"\x04name\x18\x01 \x01(\tB\x03\xe0A\x02R\x04name\"\xbe\x04\n" +
|
||||||
|
"\x10UserNotification\x12\x1a\n" +
|
||||||
|
"\x04name\x18\x01 \x01(\tB\x06\xe0A\x03\xe0A\bR\x04name\x121\n" +
|
||||||
|
"\x06sender\x18\x02 \x01(\tB\x19\xe0A\x03\xfaA\x13\n" +
|
||||||
|
"\x11memos.api.v1/UserR\x06sender\x12B\n" +
|
||||||
|
"\x06status\x18\x03 \x01(\x0e2%.memos.api.v1.UserNotification.StatusB\x03\xe0A\x01R\x06status\x12@\n" +
|
||||||
|
"\vcreate_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
|
||||||
|
"createTime\x12<\n" +
|
||||||
|
"\x04type\x18\x05 \x01(\x0e2#.memos.api.v1.UserNotification.TypeB\x03\xe0A\x03R\x04type\x12)\n" +
|
||||||
|
"\vactivity_id\x18\x06 \x01(\x05B\x03\xe0A\x01H\x00R\n" +
|
||||||
|
"activityId\x88\x01\x01\":\n" +
|
||||||
|
"\x06Status\x12\x16\n" +
|
||||||
|
"\x12STATUS_UNSPECIFIED\x10\x00\x12\n" +
|
||||||
|
"\n" +
|
||||||
|
"\x06UNREAD\x10\x01\x12\f\n" +
|
||||||
|
"\bARCHIVED\x10\x02\".\n" +
|
||||||
|
"\x04Type\x12\x14\n" +
|
||||||
|
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
|
||||||
|
"\fMEMO_COMMENT\x10\x01:p\xeaAm\n" +
|
||||||
|
"\x1dmemos.api.v1/UserNotification\x12)users/{user}/notifications/{notification}\x1a\x04name*\rnotifications2\fnotificationB\x0e\n" +
|
||||||
|
"\f_activity_id\"\xb4\x01\n" +
|
||||||
|
"\x1cListUserNotificationsRequest\x121\n" +
|
||||||
|
"\x06parent\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" +
|
||||||
|
"\x11memos.api.v1/UserR\x06parent\x12 \n" +
|
||||||
|
"\tpage_size\x18\x02 \x01(\x05B\x03\xe0A\x01R\bpageSize\x12\"\n" +
|
||||||
|
"\n" +
|
||||||
|
"page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\x12\x1b\n" +
|
||||||
|
"\x06filter\x18\x04 \x01(\tB\x03\xe0A\x01R\x06filter\"\x8d\x01\n" +
|
||||||
|
"\x1dListUserNotificationsResponse\x12D\n" +
|
||||||
|
"\rnotifications\x18\x01 \x03(\v2\x1e.memos.api.v1.UserNotificationR\rnotifications\x12&\n" +
|
||||||
|
"\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\xaa\x01\n" +
|
||||||
|
"\x1dUpdateUserNotificationRequest\x12G\n" +
|
||||||
|
"\fnotification\x18\x01 \x01(\v2\x1e.memos.api.v1.UserNotificationB\x03\xe0A\x02R\fnotification\x12@\n" +
|
||||||
|
"\vupdate_mask\x18\x02 \x01(\v2\x1a.google.protobuf.FieldMaskB\x03\xe0A\x02R\n" +
|
||||||
|
"updateMask\"Z\n" +
|
||||||
|
"\x1dDeleteUserNotificationRequest\x129\n" +
|
||||||
|
"\x04name\x18\x01 \x01(\tB%\xe0A\x02\xfaA\x1f\n" +
|
||||||
|
"\x1dmemos.api.v1/UserNotificationR\x04name2\xf7\x19\n" +
|
||||||
"\vUserService\x12c\n" +
|
"\vUserService\x12c\n" +
|
||||||
"\tListUsers\x12\x1e.memos.api.v1.ListUsersRequest\x1a\x1f.memos.api.v1.ListUsersResponse\"\x15\x82\xd3\xe4\x93\x02\x0f\x12\r/api/v1/users\x12b\n" +
|
"\tListUsers\x12\x1e.memos.api.v1.ListUsersRequest\x1a\x1f.memos.api.v1.ListUsersResponse\"\x15\x82\xd3\xe4\x93\x02\x0f\x12\r/api/v1/users\x12b\n" +
|
||||||
"\aGetUser\x12\x1c.memos.api.v1.GetUserRequest\x1a\x12.memos.api.v1.User\"%\xdaA\x04name\x82\xd3\xe4\x93\x02\x18\x12\x16/api/v1/{name=users/*}\x12e\n" +
|
"\aGetUser\x12\x1c.memos.api.v1.GetUserRequest\x1a\x12.memos.api.v1.User\"%\xdaA\x04name\x82\xd3\xe4\x93\x02\x18\x12\x16/api/v1/{name=users/*}\x12e\n" +
|
||||||
|
|
@ -2749,7 +3192,10 @@ const file_api_v1_user_service_proto_rawDesc = "" +
|
||||||
"\x10ListUserWebhooks\x12%.memos.api.v1.ListUserWebhooksRequest\x1a&.memos.api.v1.ListUserWebhooksResponse\"2\xdaA\x06parent\x82\xd3\xe4\x93\x02#\x12!/api/v1/{parent=users/*}/webhooks\x12\x9b\x01\n" +
|
"\x10ListUserWebhooks\x12%.memos.api.v1.ListUserWebhooksRequest\x1a&.memos.api.v1.ListUserWebhooksResponse\"2\xdaA\x06parent\x82\xd3\xe4\x93\x02#\x12!/api/v1/{parent=users/*}/webhooks\x12\x9b\x01\n" +
|
||||||
"\x11CreateUserWebhook\x12&.memos.api.v1.CreateUserWebhookRequest\x1a\x19.memos.api.v1.UserWebhook\"C\xdaA\x0eparent,webhook\x82\xd3\xe4\x93\x02,:\awebhook\"!/api/v1/{parent=users/*}/webhooks\x12\xa8\x01\n" +
|
"\x11CreateUserWebhook\x12&.memos.api.v1.CreateUserWebhookRequest\x1a\x19.memos.api.v1.UserWebhook\"C\xdaA\x0eparent,webhook\x82\xd3\xe4\x93\x02,:\awebhook\"!/api/v1/{parent=users/*}/webhooks\x12\xa8\x01\n" +
|
||||||
"\x11UpdateUserWebhook\x12&.memos.api.v1.UpdateUserWebhookRequest\x1a\x19.memos.api.v1.UserWebhook\"P\xdaA\x13webhook,update_mask\x82\xd3\xe4\x93\x024:\awebhook2)/api/v1/{webhook.name=users/*/webhooks/*}\x12\x85\x01\n" +
|
"\x11UpdateUserWebhook\x12&.memos.api.v1.UpdateUserWebhookRequest\x1a\x19.memos.api.v1.UserWebhook\"P\xdaA\x13webhook,update_mask\x82\xd3\xe4\x93\x024:\awebhook2)/api/v1/{webhook.name=users/*/webhooks/*}\x12\x85\x01\n" +
|
||||||
"\x11DeleteUserWebhook\x12&.memos.api.v1.DeleteUserWebhookRequest\x1a\x16.google.protobuf.Empty\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#*!/api/v1/{name=users/*/webhooks/*}B\xa8\x01\n" +
|
"\x11DeleteUserWebhook\x12&.memos.api.v1.DeleteUserWebhookRequest\x1a\x16.google.protobuf.Empty\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#*!/api/v1/{name=users/*/webhooks/*}\x12\xa9\x01\n" +
|
||||||
|
"\x15ListUserNotifications\x12*.memos.api.v1.ListUserNotificationsRequest\x1a+.memos.api.v1.ListUserNotificationsResponse\"7\xdaA\x06parent\x82\xd3\xe4\x93\x02(\x12&/api/v1/{parent=users/*}/notifications\x12\xcb\x01\n" +
|
||||||
|
"\x16UpdateUserNotification\x12+.memos.api.v1.UpdateUserNotificationRequest\x1a\x1e.memos.api.v1.UserNotification\"d\xdaA\x18notification,update_mask\x82\xd3\xe4\x93\x02C:\fnotification23/api/v1/{notification.name=users/*/notifications/*}\x12\x94\x01\n" +
|
||||||
|
"\x16DeleteUserNotification\x12+.memos.api.v1.DeleteUserNotificationRequest\x1a\x16.google.protobuf.Empty\"5\xdaA\x04name\x82\xd3\xe4\x93\x02(*&/api/v1/{name=users/*/notifications/*}B\xa8\x01\n" +
|
||||||
"\x10com.memos.api.v1B\x10UserServiceProtoP\x01Z0github.com/usememos/memos/proto/gen/api/v1;apiv1\xa2\x02\x03MAX\xaa\x02\fMemos.Api.V1\xca\x02\fMemos\\Api\\V1\xe2\x02\x18Memos\\Api\\V1\\GPBMetadata\xea\x02\x0eMemos::Api::V1b\x06proto3"
|
"\x10com.memos.api.v1B\x10UserServiceProtoP\x01Z0github.com/usememos/memos/proto/gen/api/v1;apiv1\xa2\x02\x03MAX\xaa\x02\fMemos.Api.V1\xca\x02\fMemos\\Api\\V1\xe2\x02\x18Memos\\Api\\V1\\GPBMetadata\xea\x02\x0eMemos::Api::V1b\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -2764,139 +3210,158 @@ func file_api_v1_user_service_proto_rawDescGZIP() []byte {
|
||||||
return file_api_v1_user_service_proto_rawDescData
|
return file_api_v1_user_service_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_api_v1_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_api_v1_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
|
||||||
var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 39)
|
var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 44)
|
||||||
var file_api_v1_user_service_proto_goTypes = []any{
|
var file_api_v1_user_service_proto_goTypes = []any{
|
||||||
(User_Role)(0), // 0: memos.api.v1.User.Role
|
(User_Role)(0), // 0: memos.api.v1.User.Role
|
||||||
(UserSetting_Key)(0), // 1: memos.api.v1.UserSetting.Key
|
(UserSetting_Key)(0), // 1: memos.api.v1.UserSetting.Key
|
||||||
(*User)(nil), // 2: memos.api.v1.User
|
(UserNotification_Status)(0), // 2: memos.api.v1.UserNotification.Status
|
||||||
(*ListUsersRequest)(nil), // 3: memos.api.v1.ListUsersRequest
|
(UserNotification_Type)(0), // 3: memos.api.v1.UserNotification.Type
|
||||||
(*ListUsersResponse)(nil), // 4: memos.api.v1.ListUsersResponse
|
(*User)(nil), // 4: memos.api.v1.User
|
||||||
(*GetUserRequest)(nil), // 5: memos.api.v1.GetUserRequest
|
(*ListUsersRequest)(nil), // 5: memos.api.v1.ListUsersRequest
|
||||||
(*CreateUserRequest)(nil), // 6: memos.api.v1.CreateUserRequest
|
(*ListUsersResponse)(nil), // 6: memos.api.v1.ListUsersResponse
|
||||||
(*UpdateUserRequest)(nil), // 7: memos.api.v1.UpdateUserRequest
|
(*GetUserRequest)(nil), // 7: memos.api.v1.GetUserRequest
|
||||||
(*DeleteUserRequest)(nil), // 8: memos.api.v1.DeleteUserRequest
|
(*CreateUserRequest)(nil), // 8: memos.api.v1.CreateUserRequest
|
||||||
(*GetUserAvatarRequest)(nil), // 9: memos.api.v1.GetUserAvatarRequest
|
(*UpdateUserRequest)(nil), // 9: memos.api.v1.UpdateUserRequest
|
||||||
(*UserStats)(nil), // 10: memos.api.v1.UserStats
|
(*DeleteUserRequest)(nil), // 10: memos.api.v1.DeleteUserRequest
|
||||||
(*GetUserStatsRequest)(nil), // 11: memos.api.v1.GetUserStatsRequest
|
(*GetUserAvatarRequest)(nil), // 11: memos.api.v1.GetUserAvatarRequest
|
||||||
(*ListAllUserStatsRequest)(nil), // 12: memos.api.v1.ListAllUserStatsRequest
|
(*UserStats)(nil), // 12: memos.api.v1.UserStats
|
||||||
(*ListAllUserStatsResponse)(nil), // 13: memos.api.v1.ListAllUserStatsResponse
|
(*GetUserStatsRequest)(nil), // 13: memos.api.v1.GetUserStatsRequest
|
||||||
(*UserSetting)(nil), // 14: memos.api.v1.UserSetting
|
(*ListAllUserStatsRequest)(nil), // 14: memos.api.v1.ListAllUserStatsRequest
|
||||||
(*GetUserSettingRequest)(nil), // 15: memos.api.v1.GetUserSettingRequest
|
(*ListAllUserStatsResponse)(nil), // 15: memos.api.v1.ListAllUserStatsResponse
|
||||||
(*UpdateUserSettingRequest)(nil), // 16: memos.api.v1.UpdateUserSettingRequest
|
(*UserSetting)(nil), // 16: memos.api.v1.UserSetting
|
||||||
(*ListUserSettingsRequest)(nil), // 17: memos.api.v1.ListUserSettingsRequest
|
(*GetUserSettingRequest)(nil), // 17: memos.api.v1.GetUserSettingRequest
|
||||||
(*ListUserSettingsResponse)(nil), // 18: memos.api.v1.ListUserSettingsResponse
|
(*UpdateUserSettingRequest)(nil), // 18: memos.api.v1.UpdateUserSettingRequest
|
||||||
(*UserAccessToken)(nil), // 19: memos.api.v1.UserAccessToken
|
(*ListUserSettingsRequest)(nil), // 19: memos.api.v1.ListUserSettingsRequest
|
||||||
(*ListUserAccessTokensRequest)(nil), // 20: memos.api.v1.ListUserAccessTokensRequest
|
(*ListUserSettingsResponse)(nil), // 20: memos.api.v1.ListUserSettingsResponse
|
||||||
(*ListUserAccessTokensResponse)(nil), // 21: memos.api.v1.ListUserAccessTokensResponse
|
(*UserAccessToken)(nil), // 21: memos.api.v1.UserAccessToken
|
||||||
(*CreateUserAccessTokenRequest)(nil), // 22: memos.api.v1.CreateUserAccessTokenRequest
|
(*ListUserAccessTokensRequest)(nil), // 22: memos.api.v1.ListUserAccessTokensRequest
|
||||||
(*DeleteUserAccessTokenRequest)(nil), // 23: memos.api.v1.DeleteUserAccessTokenRequest
|
(*ListUserAccessTokensResponse)(nil), // 23: memos.api.v1.ListUserAccessTokensResponse
|
||||||
(*UserSession)(nil), // 24: memos.api.v1.UserSession
|
(*CreateUserAccessTokenRequest)(nil), // 24: memos.api.v1.CreateUserAccessTokenRequest
|
||||||
(*ListUserSessionsRequest)(nil), // 25: memos.api.v1.ListUserSessionsRequest
|
(*DeleteUserAccessTokenRequest)(nil), // 25: memos.api.v1.DeleteUserAccessTokenRequest
|
||||||
(*ListUserSessionsResponse)(nil), // 26: memos.api.v1.ListUserSessionsResponse
|
(*UserSession)(nil), // 26: memos.api.v1.UserSession
|
||||||
(*RevokeUserSessionRequest)(nil), // 27: memos.api.v1.RevokeUserSessionRequest
|
(*ListUserSessionsRequest)(nil), // 27: memos.api.v1.ListUserSessionsRequest
|
||||||
(*UserWebhook)(nil), // 28: memos.api.v1.UserWebhook
|
(*ListUserSessionsResponse)(nil), // 28: memos.api.v1.ListUserSessionsResponse
|
||||||
(*ListUserWebhooksRequest)(nil), // 29: memos.api.v1.ListUserWebhooksRequest
|
(*RevokeUserSessionRequest)(nil), // 29: memos.api.v1.RevokeUserSessionRequest
|
||||||
(*ListUserWebhooksResponse)(nil), // 30: memos.api.v1.ListUserWebhooksResponse
|
(*UserWebhook)(nil), // 30: memos.api.v1.UserWebhook
|
||||||
(*CreateUserWebhookRequest)(nil), // 31: memos.api.v1.CreateUserWebhookRequest
|
(*ListUserWebhooksRequest)(nil), // 31: memos.api.v1.ListUserWebhooksRequest
|
||||||
(*UpdateUserWebhookRequest)(nil), // 32: memos.api.v1.UpdateUserWebhookRequest
|
(*ListUserWebhooksResponse)(nil), // 32: memos.api.v1.ListUserWebhooksResponse
|
||||||
(*DeleteUserWebhookRequest)(nil), // 33: memos.api.v1.DeleteUserWebhookRequest
|
(*CreateUserWebhookRequest)(nil), // 33: memos.api.v1.CreateUserWebhookRequest
|
||||||
nil, // 34: memos.api.v1.UserStats.TagCountEntry
|
(*UpdateUserWebhookRequest)(nil), // 34: memos.api.v1.UpdateUserWebhookRequest
|
||||||
(*UserStats_MemoTypeStats)(nil), // 35: memos.api.v1.UserStats.MemoTypeStats
|
(*DeleteUserWebhookRequest)(nil), // 35: memos.api.v1.DeleteUserWebhookRequest
|
||||||
(*UserSetting_GeneralSetting)(nil), // 36: memos.api.v1.UserSetting.GeneralSetting
|
(*UserNotification)(nil), // 36: memos.api.v1.UserNotification
|
||||||
(*UserSetting_SessionsSetting)(nil), // 37: memos.api.v1.UserSetting.SessionsSetting
|
(*ListUserNotificationsRequest)(nil), // 37: memos.api.v1.ListUserNotificationsRequest
|
||||||
(*UserSetting_AccessTokensSetting)(nil), // 38: memos.api.v1.UserSetting.AccessTokensSetting
|
(*ListUserNotificationsResponse)(nil), // 38: memos.api.v1.ListUserNotificationsResponse
|
||||||
(*UserSetting_WebhooksSetting)(nil), // 39: memos.api.v1.UserSetting.WebhooksSetting
|
(*UpdateUserNotificationRequest)(nil), // 39: memos.api.v1.UpdateUserNotificationRequest
|
||||||
(*UserSession_ClientInfo)(nil), // 40: memos.api.v1.UserSession.ClientInfo
|
(*DeleteUserNotificationRequest)(nil), // 40: memos.api.v1.DeleteUserNotificationRequest
|
||||||
(State)(0), // 41: memos.api.v1.State
|
nil, // 41: memos.api.v1.UserStats.TagCountEntry
|
||||||
(*timestamppb.Timestamp)(nil), // 42: google.protobuf.Timestamp
|
(*UserStats_MemoTypeStats)(nil), // 42: memos.api.v1.UserStats.MemoTypeStats
|
||||||
(*fieldmaskpb.FieldMask)(nil), // 43: google.protobuf.FieldMask
|
(*UserSetting_GeneralSetting)(nil), // 43: memos.api.v1.UserSetting.GeneralSetting
|
||||||
(*emptypb.Empty)(nil), // 44: google.protobuf.Empty
|
(*UserSetting_SessionsSetting)(nil), // 44: memos.api.v1.UserSetting.SessionsSetting
|
||||||
(*httpbody.HttpBody)(nil), // 45: google.api.HttpBody
|
(*UserSetting_AccessTokensSetting)(nil), // 45: memos.api.v1.UserSetting.AccessTokensSetting
|
||||||
|
(*UserSetting_WebhooksSetting)(nil), // 46: memos.api.v1.UserSetting.WebhooksSetting
|
||||||
|
(*UserSession_ClientInfo)(nil), // 47: memos.api.v1.UserSession.ClientInfo
|
||||||
|
(State)(0), // 48: memos.api.v1.State
|
||||||
|
(*timestamppb.Timestamp)(nil), // 49: google.protobuf.Timestamp
|
||||||
|
(*fieldmaskpb.FieldMask)(nil), // 50: google.protobuf.FieldMask
|
||||||
|
(*emptypb.Empty)(nil), // 51: google.protobuf.Empty
|
||||||
|
(*httpbody.HttpBody)(nil), // 52: google.api.HttpBody
|
||||||
}
|
}
|
||||||
var file_api_v1_user_service_proto_depIdxs = []int32{
|
var file_api_v1_user_service_proto_depIdxs = []int32{
|
||||||
0, // 0: memos.api.v1.User.role:type_name -> memos.api.v1.User.Role
|
0, // 0: memos.api.v1.User.role:type_name -> memos.api.v1.User.Role
|
||||||
41, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State
|
48, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State
|
||||||
42, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp
|
49, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp
|
||||||
42, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp
|
49, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp
|
||||||
2, // 4: memos.api.v1.ListUsersResponse.users:type_name -> memos.api.v1.User
|
4, // 4: memos.api.v1.ListUsersResponse.users:type_name -> memos.api.v1.User
|
||||||
43, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask
|
50, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask
|
||||||
2, // 6: memos.api.v1.CreateUserRequest.user:type_name -> memos.api.v1.User
|
4, // 6: memos.api.v1.CreateUserRequest.user:type_name -> memos.api.v1.User
|
||||||
2, // 7: memos.api.v1.UpdateUserRequest.user:type_name -> memos.api.v1.User
|
4, // 7: memos.api.v1.UpdateUserRequest.user:type_name -> memos.api.v1.User
|
||||||
43, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask
|
50, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||||
42, // 9: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp
|
49, // 9: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp
|
||||||
35, // 10: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats
|
42, // 10: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats
|
||||||
34, // 11: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry
|
41, // 11: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry
|
||||||
10, // 12: memos.api.v1.ListAllUserStatsResponse.stats:type_name -> memos.api.v1.UserStats
|
12, // 12: memos.api.v1.ListAllUserStatsResponse.stats:type_name -> memos.api.v1.UserStats
|
||||||
36, // 13: memos.api.v1.UserSetting.general_setting:type_name -> memos.api.v1.UserSetting.GeneralSetting
|
43, // 13: memos.api.v1.UserSetting.general_setting:type_name -> memos.api.v1.UserSetting.GeneralSetting
|
||||||
37, // 14: memos.api.v1.UserSetting.sessions_setting:type_name -> memos.api.v1.UserSetting.SessionsSetting
|
44, // 14: memos.api.v1.UserSetting.sessions_setting:type_name -> memos.api.v1.UserSetting.SessionsSetting
|
||||||
38, // 15: memos.api.v1.UserSetting.access_tokens_setting:type_name -> memos.api.v1.UserSetting.AccessTokensSetting
|
45, // 15: memos.api.v1.UserSetting.access_tokens_setting:type_name -> memos.api.v1.UserSetting.AccessTokensSetting
|
||||||
39, // 16: memos.api.v1.UserSetting.webhooks_setting:type_name -> memos.api.v1.UserSetting.WebhooksSetting
|
46, // 16: memos.api.v1.UserSetting.webhooks_setting:type_name -> memos.api.v1.UserSetting.WebhooksSetting
|
||||||
14, // 17: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting
|
16, // 17: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting
|
||||||
43, // 18: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask
|
50, // 18: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||||
14, // 19: memos.api.v1.ListUserSettingsResponse.settings:type_name -> memos.api.v1.UserSetting
|
16, // 19: memos.api.v1.ListUserSettingsResponse.settings:type_name -> memos.api.v1.UserSetting
|
||||||
42, // 20: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp
|
49, // 20: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp
|
||||||
42, // 21: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp
|
49, // 21: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp
|
||||||
19, // 22: memos.api.v1.ListUserAccessTokensResponse.access_tokens:type_name -> memos.api.v1.UserAccessToken
|
21, // 22: memos.api.v1.ListUserAccessTokensResponse.access_tokens:type_name -> memos.api.v1.UserAccessToken
|
||||||
19, // 23: memos.api.v1.CreateUserAccessTokenRequest.access_token:type_name -> memos.api.v1.UserAccessToken
|
21, // 23: memos.api.v1.CreateUserAccessTokenRequest.access_token:type_name -> memos.api.v1.UserAccessToken
|
||||||
42, // 24: memos.api.v1.UserSession.create_time:type_name -> google.protobuf.Timestamp
|
49, // 24: memos.api.v1.UserSession.create_time:type_name -> google.protobuf.Timestamp
|
||||||
42, // 25: memos.api.v1.UserSession.last_accessed_time:type_name -> google.protobuf.Timestamp
|
49, // 25: memos.api.v1.UserSession.last_accessed_time:type_name -> google.protobuf.Timestamp
|
||||||
40, // 26: memos.api.v1.UserSession.client_info:type_name -> memos.api.v1.UserSession.ClientInfo
|
47, // 26: memos.api.v1.UserSession.client_info:type_name -> memos.api.v1.UserSession.ClientInfo
|
||||||
24, // 27: memos.api.v1.ListUserSessionsResponse.sessions:type_name -> memos.api.v1.UserSession
|
26, // 27: memos.api.v1.ListUserSessionsResponse.sessions:type_name -> memos.api.v1.UserSession
|
||||||
42, // 28: memos.api.v1.UserWebhook.create_time:type_name -> google.protobuf.Timestamp
|
49, // 28: memos.api.v1.UserWebhook.create_time:type_name -> google.protobuf.Timestamp
|
||||||
42, // 29: memos.api.v1.UserWebhook.update_time:type_name -> google.protobuf.Timestamp
|
49, // 29: memos.api.v1.UserWebhook.update_time:type_name -> google.protobuf.Timestamp
|
||||||
28, // 30: memos.api.v1.ListUserWebhooksResponse.webhooks:type_name -> memos.api.v1.UserWebhook
|
30, // 30: memos.api.v1.ListUserWebhooksResponse.webhooks:type_name -> memos.api.v1.UserWebhook
|
||||||
28, // 31: memos.api.v1.CreateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook
|
30, // 31: memos.api.v1.CreateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook
|
||||||
28, // 32: memos.api.v1.UpdateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook
|
30, // 32: memos.api.v1.UpdateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook
|
||||||
43, // 33: memos.api.v1.UpdateUserWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask
|
50, // 33: memos.api.v1.UpdateUserWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||||
24, // 34: memos.api.v1.UserSetting.SessionsSetting.sessions:type_name -> memos.api.v1.UserSession
|
2, // 34: memos.api.v1.UserNotification.status:type_name -> memos.api.v1.UserNotification.Status
|
||||||
19, // 35: memos.api.v1.UserSetting.AccessTokensSetting.access_tokens:type_name -> memos.api.v1.UserAccessToken
|
49, // 35: memos.api.v1.UserNotification.create_time:type_name -> google.protobuf.Timestamp
|
||||||
28, // 36: memos.api.v1.UserSetting.WebhooksSetting.webhooks:type_name -> memos.api.v1.UserWebhook
|
3, // 36: memos.api.v1.UserNotification.type:type_name -> memos.api.v1.UserNotification.Type
|
||||||
3, // 37: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest
|
36, // 37: memos.api.v1.ListUserNotificationsResponse.notifications:type_name -> memos.api.v1.UserNotification
|
||||||
5, // 38: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest
|
36, // 38: memos.api.v1.UpdateUserNotificationRequest.notification:type_name -> memos.api.v1.UserNotification
|
||||||
6, // 39: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest
|
50, // 39: memos.api.v1.UpdateUserNotificationRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||||
7, // 40: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest
|
26, // 40: memos.api.v1.UserSetting.SessionsSetting.sessions:type_name -> memos.api.v1.UserSession
|
||||||
8, // 41: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest
|
21, // 41: memos.api.v1.UserSetting.AccessTokensSetting.access_tokens:type_name -> memos.api.v1.UserAccessToken
|
||||||
9, // 42: memos.api.v1.UserService.GetUserAvatar:input_type -> memos.api.v1.GetUserAvatarRequest
|
30, // 42: memos.api.v1.UserSetting.WebhooksSetting.webhooks:type_name -> memos.api.v1.UserWebhook
|
||||||
12, // 43: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest
|
5, // 43: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest
|
||||||
11, // 44: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest
|
7, // 44: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest
|
||||||
15, // 45: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest
|
8, // 45: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest
|
||||||
16, // 46: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest
|
9, // 46: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest
|
||||||
17, // 47: memos.api.v1.UserService.ListUserSettings:input_type -> memos.api.v1.ListUserSettingsRequest
|
10, // 47: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest
|
||||||
20, // 48: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest
|
11, // 48: memos.api.v1.UserService.GetUserAvatar:input_type -> memos.api.v1.GetUserAvatarRequest
|
||||||
22, // 49: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest
|
14, // 49: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest
|
||||||
23, // 50: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest
|
13, // 50: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest
|
||||||
25, // 51: memos.api.v1.UserService.ListUserSessions:input_type -> memos.api.v1.ListUserSessionsRequest
|
17, // 51: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest
|
||||||
27, // 52: memos.api.v1.UserService.RevokeUserSession:input_type -> memos.api.v1.RevokeUserSessionRequest
|
18, // 52: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest
|
||||||
29, // 53: memos.api.v1.UserService.ListUserWebhooks:input_type -> memos.api.v1.ListUserWebhooksRequest
|
19, // 53: memos.api.v1.UserService.ListUserSettings:input_type -> memos.api.v1.ListUserSettingsRequest
|
||||||
31, // 54: memos.api.v1.UserService.CreateUserWebhook:input_type -> memos.api.v1.CreateUserWebhookRequest
|
22, // 54: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest
|
||||||
32, // 55: memos.api.v1.UserService.UpdateUserWebhook:input_type -> memos.api.v1.UpdateUserWebhookRequest
|
24, // 55: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest
|
||||||
33, // 56: memos.api.v1.UserService.DeleteUserWebhook:input_type -> memos.api.v1.DeleteUserWebhookRequest
|
25, // 56: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest
|
||||||
4, // 57: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse
|
27, // 57: memos.api.v1.UserService.ListUserSessions:input_type -> memos.api.v1.ListUserSessionsRequest
|
||||||
2, // 58: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User
|
29, // 58: memos.api.v1.UserService.RevokeUserSession:input_type -> memos.api.v1.RevokeUserSessionRequest
|
||||||
2, // 59: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User
|
31, // 59: memos.api.v1.UserService.ListUserWebhooks:input_type -> memos.api.v1.ListUserWebhooksRequest
|
||||||
2, // 60: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User
|
33, // 60: memos.api.v1.UserService.CreateUserWebhook:input_type -> memos.api.v1.CreateUserWebhookRequest
|
||||||
44, // 61: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty
|
34, // 61: memos.api.v1.UserService.UpdateUserWebhook:input_type -> memos.api.v1.UpdateUserWebhookRequest
|
||||||
45, // 62: memos.api.v1.UserService.GetUserAvatar:output_type -> google.api.HttpBody
|
35, // 62: memos.api.v1.UserService.DeleteUserWebhook:input_type -> memos.api.v1.DeleteUserWebhookRequest
|
||||||
13, // 63: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse
|
37, // 63: memos.api.v1.UserService.ListUserNotifications:input_type -> memos.api.v1.ListUserNotificationsRequest
|
||||||
10, // 64: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats
|
39, // 64: memos.api.v1.UserService.UpdateUserNotification:input_type -> memos.api.v1.UpdateUserNotificationRequest
|
||||||
14, // 65: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting
|
40, // 65: memos.api.v1.UserService.DeleteUserNotification:input_type -> memos.api.v1.DeleteUserNotificationRequest
|
||||||
14, // 66: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting
|
6, // 66: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse
|
||||||
18, // 67: memos.api.v1.UserService.ListUserSettings:output_type -> memos.api.v1.ListUserSettingsResponse
|
4, // 67: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User
|
||||||
21, // 68: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse
|
4, // 68: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User
|
||||||
19, // 69: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken
|
4, // 69: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User
|
||||||
44, // 70: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty
|
51, // 70: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty
|
||||||
26, // 71: memos.api.v1.UserService.ListUserSessions:output_type -> memos.api.v1.ListUserSessionsResponse
|
52, // 71: memos.api.v1.UserService.GetUserAvatar:output_type -> google.api.HttpBody
|
||||||
44, // 72: memos.api.v1.UserService.RevokeUserSession:output_type -> google.protobuf.Empty
|
15, // 72: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse
|
||||||
30, // 73: memos.api.v1.UserService.ListUserWebhooks:output_type -> memos.api.v1.ListUserWebhooksResponse
|
12, // 73: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats
|
||||||
28, // 74: memos.api.v1.UserService.CreateUserWebhook:output_type -> memos.api.v1.UserWebhook
|
16, // 74: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting
|
||||||
28, // 75: memos.api.v1.UserService.UpdateUserWebhook:output_type -> memos.api.v1.UserWebhook
|
16, // 75: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting
|
||||||
44, // 76: memos.api.v1.UserService.DeleteUserWebhook:output_type -> google.protobuf.Empty
|
20, // 76: memos.api.v1.UserService.ListUserSettings:output_type -> memos.api.v1.ListUserSettingsResponse
|
||||||
57, // [57:77] is the sub-list for method output_type
|
23, // 77: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse
|
||||||
37, // [37:57] is the sub-list for method input_type
|
21, // 78: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken
|
||||||
37, // [37:37] is the sub-list for extension type_name
|
51, // 79: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty
|
||||||
37, // [37:37] is the sub-list for extension extendee
|
28, // 80: memos.api.v1.UserService.ListUserSessions:output_type -> memos.api.v1.ListUserSessionsResponse
|
||||||
0, // [0:37] is the sub-list for field type_name
|
51, // 81: memos.api.v1.UserService.RevokeUserSession:output_type -> google.protobuf.Empty
|
||||||
|
32, // 82: memos.api.v1.UserService.ListUserWebhooks:output_type -> memos.api.v1.ListUserWebhooksResponse
|
||||||
|
30, // 83: memos.api.v1.UserService.CreateUserWebhook:output_type -> memos.api.v1.UserWebhook
|
||||||
|
30, // 84: memos.api.v1.UserService.UpdateUserWebhook:output_type -> memos.api.v1.UserWebhook
|
||||||
|
51, // 85: memos.api.v1.UserService.DeleteUserWebhook:output_type -> google.protobuf.Empty
|
||||||
|
38, // 86: memos.api.v1.UserService.ListUserNotifications:output_type -> memos.api.v1.ListUserNotificationsResponse
|
||||||
|
36, // 87: memos.api.v1.UserService.UpdateUserNotification:output_type -> memos.api.v1.UserNotification
|
||||||
|
51, // 88: memos.api.v1.UserService.DeleteUserNotification:output_type -> google.protobuf.Empty
|
||||||
|
66, // [66:89] is the sub-list for method output_type
|
||||||
|
43, // [43:66] is the sub-list for method input_type
|
||||||
|
43, // [43:43] is the sub-list for extension type_name
|
||||||
|
43, // [43:43] is the sub-list for extension extendee
|
||||||
|
0, // [0:43] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_api_v1_user_service_proto_init() }
|
func init() { file_api_v1_user_service_proto_init() }
|
||||||
|
|
@ -2911,13 +3376,14 @@ func file_api_v1_user_service_proto_init() {
|
||||||
(*UserSetting_AccessTokensSetting_)(nil),
|
(*UserSetting_AccessTokensSetting_)(nil),
|
||||||
(*UserSetting_WebhooksSetting_)(nil),
|
(*UserSetting_WebhooksSetting_)(nil),
|
||||||
}
|
}
|
||||||
|
file_api_v1_user_service_proto_msgTypes[32].OneofWrappers = []any{}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_user_service_proto_rawDesc), len(file_api_v1_user_service_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_user_service_proto_rawDesc), len(file_api_v1_user_service_proto_rawDesc)),
|
||||||
NumEnums: 2,
|
NumEnums: 4,
|
||||||
NumMessages: 39,
|
NumMessages: 44,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1003,6 +1003,179 @@ func local_request_UserService_DeleteUserWebhook_0(ctx context.Context, marshale
|
||||||
return msg, metadata, err
|
return msg, metadata, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var filter_UserService_ListUserNotifications_0 = &utilities.DoubleArray{Encoding: map[string]int{"parent": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
|
||||||
|
|
||||||
|
func request_UserService_ListUserNotifications_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq ListUserNotificationsRequest
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if req.Body != nil {
|
||||||
|
_, _ = io.Copy(io.Discard, req.Body)
|
||||||
|
}
|
||||||
|
val, ok := pathParams["parent"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
|
||||||
|
}
|
||||||
|
protoReq.Parent, err = runtime.String(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
|
||||||
|
}
|
||||||
|
if err := req.ParseForm(); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_ListUserNotifications_0); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
msg, err := client.ListUserNotifications(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_UserService_ListUserNotifications_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq ListUserNotificationsRequest
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
val, ok := pathParams["parent"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
|
||||||
|
}
|
||||||
|
protoReq.Parent, err = runtime.String(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
|
||||||
|
}
|
||||||
|
if err := req.ParseForm(); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_ListUserNotifications_0); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
msg, err := server.ListUserNotifications(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var filter_UserService_UpdateUserNotification_0 = &utilities.DoubleArray{Encoding: map[string]int{"notification": 0, "name": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}}
|
||||||
|
|
||||||
|
func request_UserService_UpdateUserNotification_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq UpdateUserNotificationRequest
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||||
|
if berr != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||||
|
}
|
||||||
|
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Notification); err != nil && !errors.Is(err, io.EOF) {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if req.Body != nil {
|
||||||
|
_, _ = io.Copy(io.Discard, req.Body)
|
||||||
|
}
|
||||||
|
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
|
||||||
|
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Notification); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
} else {
|
||||||
|
protoReq.UpdateMask = fieldMask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val, ok := pathParams["notification.name"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "notification.name")
|
||||||
|
}
|
||||||
|
err = runtime.PopulateFieldFromPath(&protoReq, "notification.name", val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "notification.name", err)
|
||||||
|
}
|
||||||
|
if err := req.ParseForm(); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_UpdateUserNotification_0); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
msg, err := client.UpdateUserNotification(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_UserService_UpdateUserNotification_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq UpdateUserNotificationRequest
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||||
|
if berr != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||||
|
}
|
||||||
|
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Notification); err != nil && !errors.Is(err, io.EOF) {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
|
||||||
|
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Notification); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
} else {
|
||||||
|
protoReq.UpdateMask = fieldMask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val, ok := pathParams["notification.name"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "notification.name")
|
||||||
|
}
|
||||||
|
err = runtime.PopulateFieldFromPath(&protoReq, "notification.name", val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "notification.name", err)
|
||||||
|
}
|
||||||
|
if err := req.ParseForm(); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_UpdateUserNotification_0); err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
msg, err := server.UpdateUserNotification(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_UserService_DeleteUserNotification_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq DeleteUserNotificationRequest
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if req.Body != nil {
|
||||||
|
_, _ = io.Copy(io.Discard, req.Body)
|
||||||
|
}
|
||||||
|
val, ok := pathParams["name"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
|
||||||
|
}
|
||||||
|
protoReq.Name, err = runtime.String(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
|
||||||
|
}
|
||||||
|
msg, err := client.DeleteUserNotification(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_UserService_DeleteUserNotification_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq DeleteUserNotificationRequest
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
val, ok := pathParams["name"]
|
||||||
|
if !ok {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
|
||||||
|
}
|
||||||
|
protoReq.Name, err = runtime.String(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
|
||||||
|
}
|
||||||
|
msg, err := server.DeleteUserNotification(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterUserServiceHandlerServer registers the http handlers for service UserService to "mux".
|
// RegisterUserServiceHandlerServer registers the http handlers for service UserService to "mux".
|
||||||
// UnaryRPC :call UserServiceServer directly.
|
// UnaryRPC :call UserServiceServer directly.
|
||||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||||
|
|
@ -1409,6 +1582,66 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
|
||||||
}
|
}
|
||||||
forward_UserService_DeleteUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
forward_UserService_DeleteUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
})
|
})
|
||||||
|
mux.Handle(http.MethodGet, pattern_UserService_ListUserNotifications_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
var stream runtime.ServerTransportStream
|
||||||
|
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/ListUserNotifications", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/notifications"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_UserService_ListUserNotifications_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||||
|
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_UserService_ListUserNotifications_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
|
mux.Handle(http.MethodPatch, pattern_UserService_UpdateUserNotification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
var stream runtime.ServerTransportStream
|
||||||
|
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/UpdateUserNotification", runtime.WithHTTPPathPattern("/api/v1/{notification.name=users/*/notifications/*}"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_UserService_UpdateUserNotification_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||||
|
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_UserService_UpdateUserNotification_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
|
mux.Handle(http.MethodDelete, pattern_UserService_DeleteUserNotification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
var stream runtime.ServerTransportStream
|
||||||
|
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/DeleteUserNotification", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/notifications/*}"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_UserService_DeleteUserNotification_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||||
|
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_UserService_DeleteUserNotification_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1789,51 +2022,108 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
|
||||||
}
|
}
|
||||||
forward_UserService_DeleteUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
forward_UserService_DeleteUserWebhook_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
})
|
})
|
||||||
|
mux.Handle(http.MethodGet, pattern_UserService_ListUserNotifications_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/ListUserNotifications", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/notifications"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_UserService_ListUserNotifications_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_UserService_ListUserNotifications_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
|
mux.Handle(http.MethodPatch, pattern_UserService_UpdateUserNotification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/UpdateUserNotification", runtime.WithHTTPPathPattern("/api/v1/{notification.name=users/*/notifications/*}"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_UserService_UpdateUserNotification_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_UserService_UpdateUserNotification_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
|
mux.Handle(http.MethodDelete, pattern_UserService_DeleteUserNotification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/DeleteUserNotification", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/notifications/*}"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_UserService_DeleteUserNotification_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_UserService_DeleteUserNotification_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
pattern_UserService_ListUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, ""))
|
pattern_UserService_ListUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, ""))
|
||||||
pattern_UserService_GetUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, ""))
|
pattern_UserService_GetUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, ""))
|
||||||
pattern_UserService_CreateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, ""))
|
pattern_UserService_CreateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, ""))
|
||||||
pattern_UserService_UpdateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "user.name"}, ""))
|
pattern_UserService_UpdateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "user.name"}, ""))
|
||||||
pattern_UserService_DeleteUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, ""))
|
pattern_UserService_DeleteUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, ""))
|
||||||
pattern_UserService_GetUserAvatar_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "name", "avatar"}, ""))
|
pattern_UserService_GetUserAvatar_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "name", "avatar"}, ""))
|
||||||
pattern_UserService_ListAllUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, "stats"))
|
pattern_UserService_ListAllUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "users"}, "stats"))
|
||||||
pattern_UserService_GetUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, "getStats"))
|
pattern_UserService_GetUserStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "users", "name"}, "getStats"))
|
||||||
pattern_UserService_GetUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "settings", "name"}, ""))
|
pattern_UserService_GetUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "settings", "name"}, ""))
|
||||||
pattern_UserService_UpdateUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "settings", "setting.name"}, ""))
|
pattern_UserService_UpdateUserSetting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "settings", "setting.name"}, ""))
|
||||||
pattern_UserService_ListUserSettings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "settings"}, ""))
|
pattern_UserService_ListUserSettings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "settings"}, ""))
|
||||||
pattern_UserService_ListUserAccessTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "accessTokens"}, ""))
|
pattern_UserService_ListUserAccessTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "accessTokens"}, ""))
|
||||||
pattern_UserService_CreateUserAccessToken_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "accessTokens"}, ""))
|
pattern_UserService_CreateUserAccessToken_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "accessTokens"}, ""))
|
||||||
pattern_UserService_DeleteUserAccessToken_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "accessTokens", "name"}, ""))
|
pattern_UserService_DeleteUserAccessToken_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "accessTokens", "name"}, ""))
|
||||||
pattern_UserService_ListUserSessions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "sessions"}, ""))
|
pattern_UserService_ListUserSessions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "sessions"}, ""))
|
||||||
pattern_UserService_RevokeUserSession_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "sessions", "name"}, ""))
|
pattern_UserService_RevokeUserSession_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "sessions", "name"}, ""))
|
||||||
pattern_UserService_ListUserWebhooks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "webhooks"}, ""))
|
pattern_UserService_ListUserWebhooks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "webhooks"}, ""))
|
||||||
pattern_UserService_CreateUserWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "webhooks"}, ""))
|
pattern_UserService_CreateUserWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "webhooks"}, ""))
|
||||||
pattern_UserService_UpdateUserWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "webhooks", "webhook.name"}, ""))
|
pattern_UserService_UpdateUserWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "webhooks", "webhook.name"}, ""))
|
||||||
pattern_UserService_DeleteUserWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "webhooks", "name"}, ""))
|
pattern_UserService_DeleteUserWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "webhooks", "name"}, ""))
|
||||||
|
pattern_UserService_ListUserNotifications_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "notifications"}, ""))
|
||||||
|
pattern_UserService_UpdateUserNotification_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "notifications", "notification.name"}, ""))
|
||||||
|
pattern_UserService_DeleteUserNotification_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "notifications", "name"}, ""))
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
forward_UserService_ListUsers_0 = runtime.ForwardResponseMessage
|
forward_UserService_ListUsers_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_GetUser_0 = runtime.ForwardResponseMessage
|
forward_UserService_GetUser_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_CreateUser_0 = runtime.ForwardResponseMessage
|
forward_UserService_CreateUser_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_UpdateUser_0 = runtime.ForwardResponseMessage
|
forward_UserService_UpdateUser_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_DeleteUser_0 = runtime.ForwardResponseMessage
|
forward_UserService_DeleteUser_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_GetUserAvatar_0 = runtime.ForwardResponseMessage
|
forward_UserService_GetUserAvatar_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_ListAllUserStats_0 = runtime.ForwardResponseMessage
|
forward_UserService_ListAllUserStats_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_GetUserStats_0 = runtime.ForwardResponseMessage
|
forward_UserService_GetUserStats_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_GetUserSetting_0 = runtime.ForwardResponseMessage
|
forward_UserService_GetUserSetting_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_UpdateUserSetting_0 = runtime.ForwardResponseMessage
|
forward_UserService_UpdateUserSetting_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_ListUserSettings_0 = runtime.ForwardResponseMessage
|
forward_UserService_ListUserSettings_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_ListUserAccessTokens_0 = runtime.ForwardResponseMessage
|
forward_UserService_ListUserAccessTokens_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_CreateUserAccessToken_0 = runtime.ForwardResponseMessage
|
forward_UserService_CreateUserAccessToken_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_DeleteUserAccessToken_0 = runtime.ForwardResponseMessage
|
forward_UserService_DeleteUserAccessToken_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_ListUserSessions_0 = runtime.ForwardResponseMessage
|
forward_UserService_ListUserSessions_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_RevokeUserSession_0 = runtime.ForwardResponseMessage
|
forward_UserService_RevokeUserSession_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_ListUserWebhooks_0 = runtime.ForwardResponseMessage
|
forward_UserService_ListUserWebhooks_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_CreateUserWebhook_0 = runtime.ForwardResponseMessage
|
forward_UserService_CreateUserWebhook_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_UpdateUserWebhook_0 = runtime.ForwardResponseMessage
|
forward_UserService_UpdateUserWebhook_0 = runtime.ForwardResponseMessage
|
||||||
forward_UserService_DeleteUserWebhook_0 = runtime.ForwardResponseMessage
|
forward_UserService_DeleteUserWebhook_0 = runtime.ForwardResponseMessage
|
||||||
|
forward_UserService_ListUserNotifications_0 = runtime.ForwardResponseMessage
|
||||||
|
forward_UserService_UpdateUserNotification_0 = runtime.ForwardResponseMessage
|
||||||
|
forward_UserService_DeleteUserNotification_0 = runtime.ForwardResponseMessage
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -21,26 +21,29 @@ import (
|
||||||
const _ = grpc.SupportPackageIsVersion9
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UserService_ListUsers_FullMethodName = "/memos.api.v1.UserService/ListUsers"
|
UserService_ListUsers_FullMethodName = "/memos.api.v1.UserService/ListUsers"
|
||||||
UserService_GetUser_FullMethodName = "/memos.api.v1.UserService/GetUser"
|
UserService_GetUser_FullMethodName = "/memos.api.v1.UserService/GetUser"
|
||||||
UserService_CreateUser_FullMethodName = "/memos.api.v1.UserService/CreateUser"
|
UserService_CreateUser_FullMethodName = "/memos.api.v1.UserService/CreateUser"
|
||||||
UserService_UpdateUser_FullMethodName = "/memos.api.v1.UserService/UpdateUser"
|
UserService_UpdateUser_FullMethodName = "/memos.api.v1.UserService/UpdateUser"
|
||||||
UserService_DeleteUser_FullMethodName = "/memos.api.v1.UserService/DeleteUser"
|
UserService_DeleteUser_FullMethodName = "/memos.api.v1.UserService/DeleteUser"
|
||||||
UserService_GetUserAvatar_FullMethodName = "/memos.api.v1.UserService/GetUserAvatar"
|
UserService_GetUserAvatar_FullMethodName = "/memos.api.v1.UserService/GetUserAvatar"
|
||||||
UserService_ListAllUserStats_FullMethodName = "/memos.api.v1.UserService/ListAllUserStats"
|
UserService_ListAllUserStats_FullMethodName = "/memos.api.v1.UserService/ListAllUserStats"
|
||||||
UserService_GetUserStats_FullMethodName = "/memos.api.v1.UserService/GetUserStats"
|
UserService_GetUserStats_FullMethodName = "/memos.api.v1.UserService/GetUserStats"
|
||||||
UserService_GetUserSetting_FullMethodName = "/memos.api.v1.UserService/GetUserSetting"
|
UserService_GetUserSetting_FullMethodName = "/memos.api.v1.UserService/GetUserSetting"
|
||||||
UserService_UpdateUserSetting_FullMethodName = "/memos.api.v1.UserService/UpdateUserSetting"
|
UserService_UpdateUserSetting_FullMethodName = "/memos.api.v1.UserService/UpdateUserSetting"
|
||||||
UserService_ListUserSettings_FullMethodName = "/memos.api.v1.UserService/ListUserSettings"
|
UserService_ListUserSettings_FullMethodName = "/memos.api.v1.UserService/ListUserSettings"
|
||||||
UserService_ListUserAccessTokens_FullMethodName = "/memos.api.v1.UserService/ListUserAccessTokens"
|
UserService_ListUserAccessTokens_FullMethodName = "/memos.api.v1.UserService/ListUserAccessTokens"
|
||||||
UserService_CreateUserAccessToken_FullMethodName = "/memos.api.v1.UserService/CreateUserAccessToken"
|
UserService_CreateUserAccessToken_FullMethodName = "/memos.api.v1.UserService/CreateUserAccessToken"
|
||||||
UserService_DeleteUserAccessToken_FullMethodName = "/memos.api.v1.UserService/DeleteUserAccessToken"
|
UserService_DeleteUserAccessToken_FullMethodName = "/memos.api.v1.UserService/DeleteUserAccessToken"
|
||||||
UserService_ListUserSessions_FullMethodName = "/memos.api.v1.UserService/ListUserSessions"
|
UserService_ListUserSessions_FullMethodName = "/memos.api.v1.UserService/ListUserSessions"
|
||||||
UserService_RevokeUserSession_FullMethodName = "/memos.api.v1.UserService/RevokeUserSession"
|
UserService_RevokeUserSession_FullMethodName = "/memos.api.v1.UserService/RevokeUserSession"
|
||||||
UserService_ListUserWebhooks_FullMethodName = "/memos.api.v1.UserService/ListUserWebhooks"
|
UserService_ListUserWebhooks_FullMethodName = "/memos.api.v1.UserService/ListUserWebhooks"
|
||||||
UserService_CreateUserWebhook_FullMethodName = "/memos.api.v1.UserService/CreateUserWebhook"
|
UserService_CreateUserWebhook_FullMethodName = "/memos.api.v1.UserService/CreateUserWebhook"
|
||||||
UserService_UpdateUserWebhook_FullMethodName = "/memos.api.v1.UserService/UpdateUserWebhook"
|
UserService_UpdateUserWebhook_FullMethodName = "/memos.api.v1.UserService/UpdateUserWebhook"
|
||||||
UserService_DeleteUserWebhook_FullMethodName = "/memos.api.v1.UserService/DeleteUserWebhook"
|
UserService_DeleteUserWebhook_FullMethodName = "/memos.api.v1.UserService/DeleteUserWebhook"
|
||||||
|
UserService_ListUserNotifications_FullMethodName = "/memos.api.v1.UserService/ListUserNotifications"
|
||||||
|
UserService_UpdateUserNotification_FullMethodName = "/memos.api.v1.UserService/UpdateUserNotification"
|
||||||
|
UserService_DeleteUserNotification_FullMethodName = "/memos.api.v1.UserService/DeleteUserNotification"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserServiceClient is the client API for UserService service.
|
// UserServiceClient is the client API for UserService service.
|
||||||
|
|
@ -90,6 +93,12 @@ type UserServiceClient interface {
|
||||||
UpdateUserWebhook(ctx context.Context, in *UpdateUserWebhookRequest, opts ...grpc.CallOption) (*UserWebhook, error)
|
UpdateUserWebhook(ctx context.Context, in *UpdateUserWebhookRequest, opts ...grpc.CallOption) (*UserWebhook, error)
|
||||||
// DeleteUserWebhook deletes a webhook for a user.
|
// DeleteUserWebhook deletes a webhook for a user.
|
||||||
DeleteUserWebhook(ctx context.Context, in *DeleteUserWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
DeleteUserWebhook(ctx context.Context, in *DeleteUserWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||||
|
// ListUserNotifications lists notifications for a user.
|
||||||
|
ListUserNotifications(ctx context.Context, in *ListUserNotificationsRequest, opts ...grpc.CallOption) (*ListUserNotificationsResponse, error)
|
||||||
|
// UpdateUserNotification updates a notification.
|
||||||
|
UpdateUserNotification(ctx context.Context, in *UpdateUserNotificationRequest, opts ...grpc.CallOption) (*UserNotification, error)
|
||||||
|
// DeleteUserNotification deletes a notification.
|
||||||
|
DeleteUserNotification(ctx context.Context, in *DeleteUserNotificationRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type userServiceClient struct {
|
type userServiceClient struct {
|
||||||
|
|
@ -300,6 +309,36 @@ func (c *userServiceClient) DeleteUserWebhook(ctx context.Context, in *DeleteUse
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *userServiceClient) ListUserNotifications(ctx context.Context, in *ListUserNotificationsRequest, opts ...grpc.CallOption) (*ListUserNotificationsResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListUserNotificationsResponse)
|
||||||
|
err := c.cc.Invoke(ctx, UserService_ListUserNotifications_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userServiceClient) UpdateUserNotification(ctx context.Context, in *UpdateUserNotificationRequest, opts ...grpc.CallOption) (*UserNotification, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(UserNotification)
|
||||||
|
err := c.cc.Invoke(ctx, UserService_UpdateUserNotification_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userServiceClient) DeleteUserNotification(ctx context.Context, in *DeleteUserNotificationRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(emptypb.Empty)
|
||||||
|
err := c.cc.Invoke(ctx, UserService_DeleteUserNotification_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UserServiceServer is the server API for UserService service.
|
// UserServiceServer is the server API for UserService service.
|
||||||
// All implementations must embed UnimplementedUserServiceServer
|
// All implementations must embed UnimplementedUserServiceServer
|
||||||
// for forward compatibility.
|
// for forward compatibility.
|
||||||
|
|
@ -347,6 +386,12 @@ type UserServiceServer interface {
|
||||||
UpdateUserWebhook(context.Context, *UpdateUserWebhookRequest) (*UserWebhook, error)
|
UpdateUserWebhook(context.Context, *UpdateUserWebhookRequest) (*UserWebhook, error)
|
||||||
// DeleteUserWebhook deletes a webhook for a user.
|
// DeleteUserWebhook deletes a webhook for a user.
|
||||||
DeleteUserWebhook(context.Context, *DeleteUserWebhookRequest) (*emptypb.Empty, error)
|
DeleteUserWebhook(context.Context, *DeleteUserWebhookRequest) (*emptypb.Empty, error)
|
||||||
|
// ListUserNotifications lists notifications for a user.
|
||||||
|
ListUserNotifications(context.Context, *ListUserNotificationsRequest) (*ListUserNotificationsResponse, error)
|
||||||
|
// UpdateUserNotification updates a notification.
|
||||||
|
UpdateUserNotification(context.Context, *UpdateUserNotificationRequest) (*UserNotification, error)
|
||||||
|
// DeleteUserNotification deletes a notification.
|
||||||
|
DeleteUserNotification(context.Context, *DeleteUserNotificationRequest) (*emptypb.Empty, error)
|
||||||
mustEmbedUnimplementedUserServiceServer()
|
mustEmbedUnimplementedUserServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -417,6 +462,15 @@ func (UnimplementedUserServiceServer) UpdateUserWebhook(context.Context, *Update
|
||||||
func (UnimplementedUserServiceServer) DeleteUserWebhook(context.Context, *DeleteUserWebhookRequest) (*emptypb.Empty, error) {
|
func (UnimplementedUserServiceServer) DeleteUserWebhook(context.Context, *DeleteUserWebhookRequest) (*emptypb.Empty, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteUserWebhook not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method DeleteUserWebhook not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedUserServiceServer) ListUserNotifications(context.Context, *ListUserNotificationsRequest) (*ListUserNotificationsResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListUserNotifications not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedUserServiceServer) UpdateUserNotification(context.Context, *UpdateUserNotificationRequest) (*UserNotification, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method UpdateUserNotification not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedUserServiceServer) DeleteUserNotification(context.Context, *DeleteUserNotificationRequest) (*emptypb.Empty, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method DeleteUserNotification not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
|
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
|
||||||
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
|
|
@ -798,6 +852,60 @@ func _UserService_DeleteUserWebhook_Handler(srv interface{}, ctx context.Context
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _UserService_ListUserNotifications_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListUserNotificationsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(UserServiceServer).ListUserNotifications(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: UserService_ListUserNotifications_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(UserServiceServer).ListUserNotifications(ctx, req.(*ListUserNotificationsRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _UserService_UpdateUserNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(UpdateUserNotificationRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(UserServiceServer).UpdateUserNotification(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: UserService_UpdateUserNotification_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(UserServiceServer).UpdateUserNotification(ctx, req.(*UpdateUserNotificationRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _UserService_DeleteUserNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(DeleteUserNotificationRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(UserServiceServer).DeleteUserNotification(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: UserService_DeleteUserNotification_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(UserServiceServer).DeleteUserNotification(ctx, req.(*DeleteUserNotificationRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
|
// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
|
@ -885,6 +993,18 @@ var UserService_ServiceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "DeleteUserWebhook",
|
MethodName: "DeleteUserWebhook",
|
||||||
Handler: _UserService_DeleteUserWebhook_Handler,
|
Handler: _UserService_DeleteUserWebhook_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListUserNotifications",
|
||||||
|
Handler: _UserService_ListUserNotifications_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "UpdateUserNotification",
|
||||||
|
Handler: _UserService_UpdateUserNotification_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "DeleteUserNotification",
|
||||||
|
Handler: _UserService_DeleteUserNotification_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "api/v1/user_service.proto",
|
Metadata: "api/v1/user_service.proto",
|
||||||
|
|
|
||||||
|
|
@ -442,71 +442,6 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Status'
|
$ref: '#/components/schemas/Status'
|
||||||
/api/v1/inboxes/{inboxe}:
|
|
||||||
delete:
|
|
||||||
tags:
|
|
||||||
- InboxService
|
|
||||||
description: DeleteInbox deletes an inbox.
|
|
||||||
operationId: InboxService_DeleteInbox
|
|
||||||
parameters:
|
|
||||||
- name: inboxe
|
|
||||||
in: path
|
|
||||||
description: The inboxe id.
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
content: {}
|
|
||||||
default:
|
|
||||||
description: Default error response
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/Status'
|
|
||||||
patch:
|
|
||||||
tags:
|
|
||||||
- InboxService
|
|
||||||
description: UpdateInbox updates an inbox.
|
|
||||||
operationId: InboxService_UpdateInbox
|
|
||||||
parameters:
|
|
||||||
- name: inboxe
|
|
||||||
in: path
|
|
||||||
description: The inboxe id.
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- name: updateMask
|
|
||||||
in: query
|
|
||||||
description: Required. The list of fields to update.
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: field-mask
|
|
||||||
- name: allowMissing
|
|
||||||
in: query
|
|
||||||
description: Optional. If set to true, allows updating missing fields.
|
|
||||||
schema:
|
|
||||||
type: boolean
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/Inbox'
|
|
||||||
required: true
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/Inbox'
|
|
||||||
default:
|
|
||||||
description: Default error response
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/Status'
|
|
||||||
/api/v1/memos:
|
/api/v1/memos:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -1329,12 +1264,12 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Status'
|
$ref: '#/components/schemas/Status'
|
||||||
/api/v1/users/{user}/inboxes:
|
/api/v1/users/{user}/notifications:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- InboxService
|
- UserService
|
||||||
description: ListInboxes lists inboxes for a user.
|
description: ListUserNotifications lists notifications for a user.
|
||||||
operationId: InboxService_ListInboxes
|
operationId: UserService_ListUserNotifications
|
||||||
parameters:
|
parameters:
|
||||||
- name: user
|
- name: user
|
||||||
in: path
|
in: path
|
||||||
|
|
@ -1344,35 +1279,15 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
- name: pageSize
|
- name: pageSize
|
||||||
in: query
|
in: query
|
||||||
description: |-
|
|
||||||
Optional. The maximum number of inboxes to return.
|
|
||||||
The service may return fewer than this value.
|
|
||||||
If unspecified, at most 50 inboxes will be returned.
|
|
||||||
The maximum value is 1000; values above 1000 will be coerced to 1000.
|
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
- name: pageToken
|
- name: pageToken
|
||||||
in: query
|
in: query
|
||||||
description: |-
|
|
||||||
Optional. A page token, received from a previous `ListInboxes` call.
|
|
||||||
Provide this to retrieve the subsequent page.
|
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
- name: filter
|
- name: filter
|
||||||
in: query
|
in: query
|
||||||
description: |-
|
|
||||||
Optional. Filter to apply to the list results.
|
|
||||||
Example: "status=UNREAD" or "type=MEMO_COMMENT"
|
|
||||||
Supported operators: =, !=
|
|
||||||
Supported fields: status, type, sender, create_time
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- name: orderBy
|
|
||||||
in: query
|
|
||||||
description: |-
|
|
||||||
Optional. The order to sort results by.
|
|
||||||
Example: "create_time desc" or "status asc"
|
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
responses:
|
responses:
|
||||||
|
|
@ -1381,7 +1296,78 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ListInboxesResponse'
|
$ref: '#/components/schemas/ListUserNotificationsResponse'
|
||||||
|
default:
|
||||||
|
description: Default error response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
/api/v1/users/{user}/notifications/{notification}:
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- UserService
|
||||||
|
description: DeleteUserNotification deletes a notification.
|
||||||
|
operationId: UserService_DeleteUserNotification
|
||||||
|
parameters:
|
||||||
|
- name: user
|
||||||
|
in: path
|
||||||
|
description: The user id.
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: notification
|
||||||
|
in: path
|
||||||
|
description: The notification id.
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
content: {}
|
||||||
|
default:
|
||||||
|
description: Default error response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
patch:
|
||||||
|
tags:
|
||||||
|
- UserService
|
||||||
|
description: UpdateUserNotification updates a notification.
|
||||||
|
operationId: UserService_UpdateUserNotification
|
||||||
|
parameters:
|
||||||
|
- name: user
|
||||||
|
in: path
|
||||||
|
description: The user id.
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: notification
|
||||||
|
in: path
|
||||||
|
description: The notification id.
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: updateMask
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: field-mask
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UserNotification'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UserNotification'
|
||||||
default:
|
default:
|
||||||
description: Default error response
|
description: Default error response
|
||||||
content:
|
content:
|
||||||
|
|
@ -2039,7 +2025,6 @@ components:
|
||||||
enum:
|
enum:
|
||||||
- TYPE_UNSPECIFIED
|
- TYPE_UNSPECIFIED
|
||||||
- MEMO_COMMENT
|
- MEMO_COMMENT
|
||||||
- VERSION_UPDATE
|
|
||||||
type: string
|
type: string
|
||||||
description: The type of the activity.
|
description: The type of the activity.
|
||||||
format: enum
|
format: enum
|
||||||
|
|
@ -2264,52 +2249,6 @@ components:
|
||||||
properties:
|
properties:
|
||||||
oauth2Config:
|
oauth2Config:
|
||||||
$ref: '#/components/schemas/OAuth2Config'
|
$ref: '#/components/schemas/OAuth2Config'
|
||||||
Inbox:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The resource name of the inbox.
|
|
||||||
Format: inboxes/{inbox}
|
|
||||||
sender:
|
|
||||||
readOnly: true
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The sender of the inbox notification.
|
|
||||||
Format: users/{user}
|
|
||||||
receiver:
|
|
||||||
readOnly: true
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The receiver of the inbox notification.
|
|
||||||
Format: users/{user}
|
|
||||||
status:
|
|
||||||
enum:
|
|
||||||
- STATUS_UNSPECIFIED
|
|
||||||
- UNREAD
|
|
||||||
- ARCHIVED
|
|
||||||
type: string
|
|
||||||
description: The status of the inbox notification.
|
|
||||||
format: enum
|
|
||||||
createTime:
|
|
||||||
readOnly: true
|
|
||||||
type: string
|
|
||||||
description: Output only. The creation timestamp.
|
|
||||||
format: date-time
|
|
||||||
type:
|
|
||||||
readOnly: true
|
|
||||||
enum:
|
|
||||||
- TYPE_UNSPECIFIED
|
|
||||||
- MEMO_COMMENT
|
|
||||||
- VERSION_UPDATE
|
|
||||||
type: string
|
|
||||||
description: The type of the inbox notification.
|
|
||||||
format: enum
|
|
||||||
activityId:
|
|
||||||
type: integer
|
|
||||||
description: Optional. The activity ID associated with this inbox notification.
|
|
||||||
format: int32
|
|
||||||
ListActivitiesResponse:
|
ListActivitiesResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
@ -2357,23 +2296,6 @@ components:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/IdentityProvider'
|
$ref: '#/components/schemas/IdentityProvider'
|
||||||
description: The list of identity providers.
|
description: The list of identity providers.
|
||||||
ListInboxesResponse:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
inboxes:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/Inbox'
|
|
||||||
description: The list of inboxes.
|
|
||||||
nextPageToken:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
A token that can be sent as `page_token` to retrieve the next page.
|
|
||||||
If this field is omitted, there are no subsequent pages.
|
|
||||||
totalSize:
|
|
||||||
type: integer
|
|
||||||
description: The total count of inboxes (may be approximate).
|
|
||||||
format: int32
|
|
||||||
ListMemoAttachmentsResponse:
|
ListMemoAttachmentsResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
@ -2462,6 +2384,15 @@ components:
|
||||||
type: integer
|
type: integer
|
||||||
description: The total count of access tokens.
|
description: The total count of access tokens.
|
||||||
format: int32
|
format: int32
|
||||||
|
ListUserNotificationsResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
notifications:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/UserNotification'
|
||||||
|
nextPageToken:
|
||||||
|
type: string
|
||||||
ListUserSessionsResponse:
|
ListUserSessionsResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
@ -2903,6 +2834,46 @@ components:
|
||||||
description: Optional. The expiration timestamp.
|
description: Optional. The expiration timestamp.
|
||||||
format: date-time
|
format: date-time
|
||||||
description: User access token message
|
description: User access token message
|
||||||
|
UserNotification:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
readOnly: true
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The resource name of the notification.
|
||||||
|
Format: users/{user}/notifications/{notification}
|
||||||
|
sender:
|
||||||
|
readOnly: true
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The sender of the notification.
|
||||||
|
Format: users/{user}
|
||||||
|
status:
|
||||||
|
enum:
|
||||||
|
- STATUS_UNSPECIFIED
|
||||||
|
- UNREAD
|
||||||
|
- ARCHIVED
|
||||||
|
type: string
|
||||||
|
description: The status of the notification.
|
||||||
|
format: enum
|
||||||
|
createTime:
|
||||||
|
readOnly: true
|
||||||
|
type: string
|
||||||
|
description: The creation timestamp.
|
||||||
|
format: date-time
|
||||||
|
type:
|
||||||
|
readOnly: true
|
||||||
|
enum:
|
||||||
|
- TYPE_UNSPECIFIED
|
||||||
|
- MEMO_COMMENT
|
||||||
|
type: string
|
||||||
|
description: The type of the notification.
|
||||||
|
format: enum
|
||||||
|
activityId:
|
||||||
|
type: integer
|
||||||
|
description: The activity ID associated with this notification.
|
||||||
|
format: int32
|
||||||
UserSession:
|
UserSession:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
@ -3223,7 +3194,6 @@ tags:
|
||||||
- name: AttachmentService
|
- name: AttachmentService
|
||||||
- name: AuthService
|
- name: AuthService
|
||||||
- name: IdentityProviderService
|
- name: IdentityProviderService
|
||||||
- name: InboxService
|
|
||||||
- name: MemoService
|
- name: MemoService
|
||||||
- name: ShortcutService
|
- name: ShortcutService
|
||||||
- name: UserService
|
- name: UserService
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ type InboxMessage_Type int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
InboxMessage_TYPE_UNSPECIFIED InboxMessage_Type = 0
|
InboxMessage_TYPE_UNSPECIFIED InboxMessage_Type = 0
|
||||||
InboxMessage_MEMO_COMMENT InboxMessage_Type = 1
|
// Memo comment notification.
|
||||||
InboxMessage_VERSION_UPDATE InboxMessage_Type = 2
|
InboxMessage_MEMO_COMMENT InboxMessage_Type = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for InboxMessage_Type.
|
// Enum value maps for InboxMessage_Type.
|
||||||
|
|
@ -34,12 +34,10 @@ var (
|
||||||
InboxMessage_Type_name = map[int32]string{
|
InboxMessage_Type_name = map[int32]string{
|
||||||
0: "TYPE_UNSPECIFIED",
|
0: "TYPE_UNSPECIFIED",
|
||||||
1: "MEMO_COMMENT",
|
1: "MEMO_COMMENT",
|
||||||
2: "VERSION_UPDATE",
|
|
||||||
}
|
}
|
||||||
InboxMessage_Type_value = map[string]int32{
|
InboxMessage_Type_value = map[string]int32{
|
||||||
"TYPE_UNSPECIFIED": 0,
|
"TYPE_UNSPECIFIED": 0,
|
||||||
"MEMO_COMMENT": 1,
|
"MEMO_COMMENT": 1,
|
||||||
"VERSION_UPDATE": 2,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -71,9 +69,11 @@ func (InboxMessage_Type) EnumDescriptor() ([]byte, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type InboxMessage struct {
|
type InboxMessage struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Type InboxMessage_Type `protobuf:"varint,1,opt,name=type,proto3,enum=memos.store.InboxMessage_Type" json:"type,omitempty"`
|
// The type of the inbox message.
|
||||||
ActivityId *int32 `protobuf:"varint,2,opt,name=activity_id,json=activityId,proto3,oneof" json:"activity_id,omitempty"`
|
Type InboxMessage_Type `protobuf:"varint,1,opt,name=type,proto3,enum=memos.store.InboxMessage_Type" json:"type,omitempty"`
|
||||||
|
// The system-generated unique ID of related activity.
|
||||||
|
ActivityId *int32 `protobuf:"varint,2,opt,name=activity_id,json=activityId,proto3,oneof" json:"activity_id,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
@ -126,15 +126,14 @@ var File_store_inbox_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_store_inbox_proto_rawDesc = "" +
|
const file_store_inbox_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x11store/inbox.proto\x12\vmemos.store\"\xbc\x01\n" +
|
"\x11store/inbox.proto\x12\vmemos.store\"\xa8\x01\n" +
|
||||||
"\fInboxMessage\x122\n" +
|
"\fInboxMessage\x122\n" +
|
||||||
"\x04type\x18\x01 \x01(\x0e2\x1e.memos.store.InboxMessage.TypeR\x04type\x12$\n" +
|
"\x04type\x18\x01 \x01(\x0e2\x1e.memos.store.InboxMessage.TypeR\x04type\x12$\n" +
|
||||||
"\vactivity_id\x18\x02 \x01(\x05H\x00R\n" +
|
"\vactivity_id\x18\x02 \x01(\x05H\x00R\n" +
|
||||||
"activityId\x88\x01\x01\"B\n" +
|
"activityId\x88\x01\x01\".\n" +
|
||||||
"\x04Type\x12\x14\n" +
|
"\x04Type\x12\x14\n" +
|
||||||
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
|
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
|
||||||
"\fMEMO_COMMENT\x10\x01\x12\x12\n" +
|
"\fMEMO_COMMENT\x10\x01B\x0e\n" +
|
||||||
"\x0eVERSION_UPDATE\x10\x02B\x0e\n" +
|
|
||||||
"\f_activity_idB\x95\x01\n" +
|
"\f_activity_idB\x95\x01\n" +
|
||||||
"\x0fcom.memos.storeB\n" +
|
"\x0fcom.memos.storeB\n" +
|
||||||
"InboxProtoP\x01Z)github.com/usememos/memos/proto/gen/store\xa2\x02\x03MSX\xaa\x02\vMemos.Store\xca\x02\vMemos\\Store\xe2\x02\x17Memos\\Store\\GPBMetadata\xea\x02\fMemos::Storeb\x06proto3"
|
"InboxProtoP\x01Z)github.com/usememos/memos/proto/gen/store\xa2\x02\x03MSX\xaa\x02\vMemos.Store\xca\x02\vMemos\\Store\xe2\x02\x17Memos\\Store\\GPBMetadata\xea\x02\fMemos::Storeb\x06proto3"
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,14 @@ package memos.store;
|
||||||
option go_package = "gen/store";
|
option go_package = "gen/store";
|
||||||
|
|
||||||
message InboxMessage {
|
message InboxMessage {
|
||||||
|
// The type of the inbox message.
|
||||||
|
Type type = 1;
|
||||||
|
// The system-generated unique ID of related activity.
|
||||||
|
optional int32 activity_id = 2;
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
TYPE_UNSPECIFIED = 0;
|
TYPE_UNSPECIFIED = 0;
|
||||||
|
// Memo comment notification.
|
||||||
MEMO_COMMENT = 1;
|
MEMO_COMMENT = 1;
|
||||||
VERSION_UPDATE = 2;
|
|
||||||
}
|
}
|
||||||
Type type = 1;
|
|
||||||
optional int32 activity_id = 2;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,9 @@ func (s *APIV1Service) GetActivity(ctx context.Context, request *v1pb.GetActivit
|
||||||
return activityMessage, nil
|
return activityMessage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convertActivityFromStore converts a storage-layer activity to an API activity.
|
||||||
|
// This handles the mapping between internal activity representation and the public API,
|
||||||
|
// including proper type and level conversions.
|
||||||
func (s *APIV1Service) convertActivityFromStore(ctx context.Context, activity *store.Activity) (*v1pb.Activity, error) {
|
func (s *APIV1Service) convertActivityFromStore(ctx context.Context, activity *store.Activity) (*v1pb.Activity, error) {
|
||||||
payload, err := s.convertActivityPayloadFromStore(ctx, activity.Payload)
|
payload, err := s.convertActivityPayloadFromStore(ctx, activity.Payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -98,9 +101,12 @@ func (s *APIV1Service) convertActivityFromStore(ctx context.Context, activity *s
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convertActivityPayloadFromStore converts a storage-layer activity payload to an API payload.
|
||||||
|
// This resolves references (e.g., memo IDs) to resource names for the API.
|
||||||
func (s *APIV1Service) convertActivityPayloadFromStore(ctx context.Context, payload *storepb.ActivityPayload) (*v1pb.ActivityPayload, error) {
|
func (s *APIV1Service) convertActivityPayloadFromStore(ctx context.Context, payload *storepb.ActivityPayload) (*v1pb.ActivityPayload, error) {
|
||||||
v2Payload := &v1pb.ActivityPayload{}
|
v2Payload := &v1pb.ActivityPayload{}
|
||||||
if payload.MemoComment != nil {
|
if payload.MemoComment != nil {
|
||||||
|
// Fetch the comment memo
|
||||||
memo, err := s.Store.GetMemo(ctx, &store.FindMemo{
|
memo, err := s.Store.GetMemo(ctx, &store.FindMemo{
|
||||||
ID: &payload.MemoComment.MemoId,
|
ID: &payload.MemoComment.MemoId,
|
||||||
ExcludeContent: true,
|
ExcludeContent: true,
|
||||||
|
|
@ -111,6 +117,8 @@ func (s *APIV1Service) convertActivityPayloadFromStore(ctx context.Context, payl
|
||||||
if memo == nil {
|
if memo == nil {
|
||||||
return nil, status.Errorf(codes.NotFound, "memo does not exist")
|
return nil, status.Errorf(codes.NotFound, "memo does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch the related memo (the one being commented on)
|
||||||
relatedMemo, err := s.Store.GetMemo(ctx, &store.FindMemo{
|
relatedMemo, err := s.Store.GetMemo(ctx, &store.FindMemo{
|
||||||
ID: &payload.MemoComment.RelatedMemoId,
|
ID: &payload.MemoComment.RelatedMemoId,
|
||||||
ExcludeContent: true,
|
ExcludeContent: true,
|
||||||
|
|
@ -118,6 +126,7 @@ func (s *APIV1Service) convertActivityPayloadFromStore(ctx context.Context, payl
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get related memo: %v", err)
|
return nil, status.Errorf(codes.Internal, "failed to get related memo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v2Payload.Payload = &v1pb.ActivityPayload_MemoComment{
|
v2Payload.Payload = &v1pb.ActivityPayload_MemoComment{
|
||||||
MemoComment: &v1pb.ActivityMemoCommentPayload{
|
MemoComment: &v1pb.ActivityMemoCommentPayload{
|
||||||
Memo: fmt.Sprintf("%s%s", MemoNamePrefix, memo.UID),
|
Memo: fmt.Sprintf("%s%s", MemoNamePrefix, memo.UID),
|
||||||
|
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
|
||||||
|
|
||||||
v1pb "github.com/usememos/memos/proto/gen/api/v1"
|
|
||||||
"github.com/usememos/memos/store"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *APIV1Service) ListInboxes(ctx context.Context, request *v1pb.ListInboxesRequest) (*v1pb.ListInboxesResponse, error) {
|
|
||||||
// Extract user ID from parent resource name
|
|
||||||
userID, err := ExtractUserIDFromName(request.Parent)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "invalid parent name %q: %v", request.Parent, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current user for authorization
|
|
||||||
currentUser, err := s.GetCurrentUser(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get current user")
|
|
||||||
}
|
|
||||||
if currentUser == nil {
|
|
||||||
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if current user can access the requested user's inboxes
|
|
||||||
if currentUser.ID != userID {
|
|
||||||
// Only allow hosts and admins to access other users' inboxes
|
|
||||||
if currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
|
|
||||||
return nil, status.Errorf(codes.PermissionDenied, "cannot access inboxes for user %q", request.Parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var limit, offset int
|
|
||||||
if request.PageToken != "" {
|
|
||||||
var pageToken v1pb.PageToken
|
|
||||||
if err := unmarshalPageToken(request.PageToken, &pageToken); err != nil {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "invalid page token: %v", err)
|
|
||||||
}
|
|
||||||
limit = int(pageToken.Limit)
|
|
||||||
offset = int(pageToken.Offset)
|
|
||||||
} else {
|
|
||||||
limit = int(request.PageSize)
|
|
||||||
}
|
|
||||||
if limit <= 0 {
|
|
||||||
limit = DefaultPageSize
|
|
||||||
}
|
|
||||||
if limit > MaxPageSize {
|
|
||||||
limit = MaxPageSize
|
|
||||||
}
|
|
||||||
limitPlusOne := limit + 1
|
|
||||||
|
|
||||||
findInbox := &store.FindInbox{
|
|
||||||
ReceiverID: &userID,
|
|
||||||
Limit: &limitPlusOne,
|
|
||||||
Offset: &offset,
|
|
||||||
}
|
|
||||||
|
|
||||||
inboxes, err := s.Store.ListInboxes(ctx, findInbox)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to list inboxes: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
inboxMessages := []*v1pb.Inbox{}
|
|
||||||
nextPageToken := ""
|
|
||||||
if len(inboxes) == limitPlusOne {
|
|
||||||
inboxes = inboxes[:limit]
|
|
||||||
nextPageToken, err = getPageToken(limit, offset+limit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get next page token: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, inbox := range inboxes {
|
|
||||||
inboxMessage := convertInboxFromStore(inbox)
|
|
||||||
if inboxMessage.Type == v1pb.Inbox_TYPE_UNSPECIFIED {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inboxMessages = append(inboxMessages, inboxMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
response := &v1pb.ListInboxesResponse{
|
|
||||||
Inboxes: inboxMessages,
|
|
||||||
NextPageToken: nextPageToken,
|
|
||||||
TotalSize: int32(len(inboxMessages)), // For now, use actual returned count
|
|
||||||
}
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *APIV1Service) UpdateInbox(ctx context.Context, request *v1pb.UpdateInboxRequest) (*v1pb.Inbox, error) {
|
|
||||||
if request.UpdateMask == nil || len(request.UpdateMask.Paths) == 0 {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "update mask is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
inboxID, err := ExtractInboxIDFromName(request.Inbox.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "invalid inbox name %q: %v", request.Inbox.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current user for authorization
|
|
||||||
currentUser, err := s.GetCurrentUser(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get current user")
|
|
||||||
}
|
|
||||||
if currentUser == nil {
|
|
||||||
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the existing inbox to verify ownership
|
|
||||||
inboxes, err := s.Store.ListInboxes(ctx, &store.FindInbox{
|
|
||||||
ID: &inboxID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get inbox: %v", err)
|
|
||||||
}
|
|
||||||
if len(inboxes) == 0 {
|
|
||||||
return nil, status.Errorf(codes.NotFound, "inbox %q not found", request.Inbox.Name)
|
|
||||||
}
|
|
||||||
existingInbox := inboxes[0]
|
|
||||||
|
|
||||||
// Check if current user can update this inbox (must be the receiver)
|
|
||||||
if currentUser.ID != existingInbox.ReceiverID {
|
|
||||||
return nil, status.Errorf(codes.PermissionDenied, "cannot update inbox for another user")
|
|
||||||
}
|
|
||||||
|
|
||||||
update := &store.UpdateInbox{
|
|
||||||
ID: inboxID,
|
|
||||||
}
|
|
||||||
for _, field := range request.UpdateMask.Paths {
|
|
||||||
if field == "status" {
|
|
||||||
if request.Inbox.Status == v1pb.Inbox_STATUS_UNSPECIFIED {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "status cannot be unspecified")
|
|
||||||
}
|
|
||||||
update.Status = convertInboxStatusToStore(request.Inbox.Status)
|
|
||||||
} else {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "unsupported field in update mask: %q", field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inbox, err := s.Store.UpdateInbox(ctx, update)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to update inbox: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertInboxFromStore(inbox), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *APIV1Service) DeleteInbox(ctx context.Context, request *v1pb.DeleteInboxRequest) (*emptypb.Empty, error) {
|
|
||||||
inboxID, err := ExtractInboxIDFromName(request.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "invalid inbox name %q: %v", request.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current user for authorization
|
|
||||||
currentUser, err := s.GetCurrentUser(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get current user")
|
|
||||||
}
|
|
||||||
if currentUser == nil {
|
|
||||||
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the existing inbox to verify ownership
|
|
||||||
inboxes, err := s.Store.ListInboxes(ctx, &store.FindInbox{
|
|
||||||
ID: &inboxID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get inbox: %v", err)
|
|
||||||
}
|
|
||||||
if len(inboxes) == 0 {
|
|
||||||
return nil, status.Errorf(codes.NotFound, "inbox %q not found", request.Name)
|
|
||||||
}
|
|
||||||
existingInbox := inboxes[0]
|
|
||||||
|
|
||||||
// Check if current user can delete this inbox (must be the receiver)
|
|
||||||
if currentUser.ID != existingInbox.ReceiverID {
|
|
||||||
return nil, status.Errorf(codes.PermissionDenied, "cannot delete inbox for another user")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.Store.DeleteInbox(ctx, &store.DeleteInbox{
|
|
||||||
ID: inboxID,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to delete inbox: %v", err)
|
|
||||||
}
|
|
||||||
return &emptypb.Empty{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertInboxFromStore(inbox *store.Inbox) *v1pb.Inbox {
|
|
||||||
return &v1pb.Inbox{
|
|
||||||
Name: fmt.Sprintf("%s%d", InboxNamePrefix, inbox.ID),
|
|
||||||
Sender: fmt.Sprintf("%s%d", UserNamePrefix, inbox.SenderID),
|
|
||||||
Receiver: fmt.Sprintf("%s%d", UserNamePrefix, inbox.ReceiverID),
|
|
||||||
Status: convertInboxStatusFromStore(inbox.Status),
|
|
||||||
CreateTime: timestamppb.New(time.Unix(inbox.CreatedTs, 0)),
|
|
||||||
Type: v1pb.Inbox_Type(inbox.Message.Type),
|
|
||||||
ActivityId: inbox.Message.ActivityId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertInboxStatusFromStore(status store.InboxStatus) v1pb.Inbox_Status {
|
|
||||||
switch status {
|
|
||||||
case store.UNREAD:
|
|
||||||
return v1pb.Inbox_UNREAD
|
|
||||||
case store.ARCHIVED:
|
|
||||||
return v1pb.Inbox_ARCHIVED
|
|
||||||
default:
|
|
||||||
return v1pb.Inbox_STATUS_UNSPECIFIED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertInboxStatusToStore(status v1pb.Inbox_Status) store.InboxStatus {
|
|
||||||
switch status {
|
|
||||||
case v1pb.Inbox_ARCHIVED:
|
|
||||||
return store.ARCHIVED
|
|
||||||
default:
|
|
||||||
return store.UNREAD
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,559 +0,0 @@
|
||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
|
||||||
|
|
||||||
v1pb "github.com/usememos/memos/proto/gen/api/v1"
|
|
||||||
storepb "github.com/usememos/memos/proto/gen/store"
|
|
||||||
"github.com/usememos/memos/store"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestListInboxes(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
t.Run("ListInboxes success", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
// List inboxes (should be empty initially)
|
|
||||||
req := &v1pb.ListInboxesRequest{
|
|
||||||
Parent: fmt.Sprintf("users/%d", user.ID),
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ts.Service.ListInboxes(userCtx, req)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, resp)
|
|
||||||
require.Empty(t, resp.Inboxes)
|
|
||||||
require.Equal(t, int32(0), resp.TotalSize)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("ListInboxes with pagination", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create some inbox entries
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
_, err := ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: user.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
// List inboxes with page size limit
|
|
||||||
req := &v1pb.ListInboxesRequest{
|
|
||||||
Parent: fmt.Sprintf("users/%d", user.ID),
|
|
||||||
PageSize: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ts.Service.ListInboxes(userCtx, req)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, resp)
|
|
||||||
require.Equal(t, 2, len(resp.Inboxes))
|
|
||||||
require.NotEmpty(t, resp.NextPageToken)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("ListInboxes permission denied for different user", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create two users
|
|
||||||
user1, err := ts.CreateRegularUser(ctx, "user1")
|
|
||||||
require.NoError(t, err)
|
|
||||||
user2, err := ts.CreateRegularUser(ctx, "user2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user1 context but try to list user2's inboxes
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user1.ID)
|
|
||||||
|
|
||||||
req := &v1pb.ListInboxesRequest{
|
|
||||||
Parent: fmt.Sprintf("users/%d", user2.ID),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.ListInboxes(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "cannot access inboxes")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("ListInboxes host can access other users' inboxes", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a host user and a regular user
|
|
||||||
hostUser, err := ts.CreateHostUser(ctx, "hostuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
regularUser, err := ts.CreateRegularUser(ctx, "regularuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create an inbox for the regular user
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
_, err = ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: regularUser.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set host user context and try to list regular user's inboxes
|
|
||||||
hostCtx := ts.CreateUserContext(ctx, hostUser.ID)
|
|
||||||
|
|
||||||
req := &v1pb.ListInboxesRequest{
|
|
||||||
Parent: fmt.Sprintf("users/%d", regularUser.ID),
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ts.Service.ListInboxes(hostCtx, req)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, resp)
|
|
||||||
require.Equal(t, 1, len(resp.Inboxes))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("ListInboxes invalid parent format", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
req := &v1pb.ListInboxesRequest{
|
|
||||||
Parent: "invalid-parent-format",
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.ListInboxes(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "invalid parent name")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("ListInboxes unauthenticated", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
req := &v1pb.ListInboxesRequest{
|
|
||||||
Parent: "users/1",
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := ts.Service.ListInboxes(ctx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "user not authenticated")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateInbox(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
t.Run("UpdateInbox success", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create an inbox entry
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
inbox, err := ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: user.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
// Update inbox status
|
|
||||||
req := &v1pb.UpdateInboxRequest{
|
|
||||||
Inbox: &v1pb.Inbox{
|
|
||||||
Name: fmt.Sprintf("inboxes/%d", inbox.ID),
|
|
||||||
Status: v1pb.Inbox_ARCHIVED,
|
|
||||||
},
|
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{
|
|
||||||
Paths: []string{"status"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ts.Service.UpdateInbox(userCtx, req)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, resp)
|
|
||||||
require.Equal(t, v1pb.Inbox_ARCHIVED, resp.Status)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("UpdateInbox permission denied for different user", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create two users
|
|
||||||
user1, err := ts.CreateRegularUser(ctx, "user1")
|
|
||||||
require.NoError(t, err)
|
|
||||||
user2, err := ts.CreateRegularUser(ctx, "user2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create an inbox entry for user2
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
inbox, err := ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: user2.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user1 context but try to update user2's inbox
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user1.ID)
|
|
||||||
|
|
||||||
req := &v1pb.UpdateInboxRequest{
|
|
||||||
Inbox: &v1pb.Inbox{
|
|
||||||
Name: fmt.Sprintf("inboxes/%d", inbox.ID),
|
|
||||||
Status: v1pb.Inbox_ARCHIVED,
|
|
||||||
},
|
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{
|
|
||||||
Paths: []string{"status"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.UpdateInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "cannot update inbox")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("UpdateInbox missing update mask", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
req := &v1pb.UpdateInboxRequest{
|
|
||||||
Inbox: &v1pb.Inbox{
|
|
||||||
Name: "inboxes/1",
|
|
||||||
Status: v1pb.Inbox_ARCHIVED,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.UpdateInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "update mask is required")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("UpdateInbox invalid name format", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
req := &v1pb.UpdateInboxRequest{
|
|
||||||
Inbox: &v1pb.Inbox{
|
|
||||||
Name: "invalid-inbox-name",
|
|
||||||
Status: v1pb.Inbox_ARCHIVED,
|
|
||||||
},
|
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{
|
|
||||||
Paths: []string{"status"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.UpdateInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "invalid inbox name")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("UpdateInbox not found", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
req := &v1pb.UpdateInboxRequest{
|
|
||||||
Inbox: &v1pb.Inbox{
|
|
||||||
Name: "inboxes/99999", // Non-existent inbox
|
|
||||||
Status: v1pb.Inbox_ARCHIVED,
|
|
||||||
},
|
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{
|
|
||||||
Paths: []string{"status"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.UpdateInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
st, ok := status.FromError(err)
|
|
||||||
require.True(t, ok)
|
|
||||||
require.Equal(t, codes.NotFound, st.Code())
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("UpdateInbox unsupported field", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create an inbox entry
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
inbox, err := ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: user.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
req := &v1pb.UpdateInboxRequest{
|
|
||||||
Inbox: &v1pb.Inbox{
|
|
||||||
Name: fmt.Sprintf("inboxes/%d", inbox.ID),
|
|
||||||
Status: v1pb.Inbox_ARCHIVED,
|
|
||||||
},
|
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{
|
|
||||||
Paths: []string{"unsupported_field"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.UpdateInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "unsupported field")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteInbox(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
t.Run("DeleteInbox success", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create an inbox entry
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
inbox, err := ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: user.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
// Delete inbox
|
|
||||||
req := &v1pb.DeleteInboxRequest{
|
|
||||||
Name: fmt.Sprintf("inboxes/%d", inbox.ID),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.DeleteInbox(userCtx, req)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Verify inbox is deleted
|
|
||||||
inboxes, err := ts.Store.ListInboxes(ctx, &store.FindInbox{
|
|
||||||
ReceiverID: &user.ID,
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 0, len(inboxes))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("DeleteInbox permission denied for different user", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create two users
|
|
||||||
user1, err := ts.CreateRegularUser(ctx, "user1")
|
|
||||||
require.NoError(t, err)
|
|
||||||
user2, err := ts.CreateRegularUser(ctx, "user2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create an inbox entry for user2
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
inbox, err := ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: user2.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user1 context but try to delete user2's inbox
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user1.ID)
|
|
||||||
|
|
||||||
req := &v1pb.DeleteInboxRequest{
|
|
||||||
Name: fmt.Sprintf("inboxes/%d", inbox.ID),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.DeleteInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "cannot delete inbox")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("DeleteInbox invalid name format", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
req := &v1pb.DeleteInboxRequest{
|
|
||||||
Name: "invalid-inbox-name",
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.DeleteInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Contains(t, err.Error(), "invalid inbox name")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("DeleteInbox not found", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
req := &v1pb.DeleteInboxRequest{
|
|
||||||
Name: "inboxes/99999", // Non-existent inbox
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ts.Service.DeleteInbox(userCtx, req)
|
|
||||||
require.Error(t, err)
|
|
||||||
st, ok := status.FromError(err)
|
|
||||||
require.True(t, ok)
|
|
||||||
require.Equal(t, codes.NotFound, st.Code())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInboxCRUDComplete(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
t.Run("Complete CRUD lifecycle", func(t *testing.T) {
|
|
||||||
ts := NewTestService(t)
|
|
||||||
defer ts.Cleanup()
|
|
||||||
|
|
||||||
// Create a user
|
|
||||||
user, err := ts.CreateRegularUser(ctx, "testuser")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create an inbox entry directly in store
|
|
||||||
const systemBotID int32 = 0
|
|
||||||
inbox, err := ts.Store.CreateInbox(ctx, &store.Inbox{
|
|
||||||
SenderID: systemBotID,
|
|
||||||
ReceiverID: user.ID,
|
|
||||||
Status: store.UNREAD,
|
|
||||||
Message: &storepb.InboxMessage{
|
|
||||||
Type: storepb.InboxMessage_MEMO_COMMENT,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Set user context
|
|
||||||
userCtx := ts.CreateUserContext(ctx, user.ID)
|
|
||||||
|
|
||||||
// 1. List inboxes - should have 1
|
|
||||||
listReq := &v1pb.ListInboxesRequest{
|
|
||||||
Parent: fmt.Sprintf("users/%d", user.ID),
|
|
||||||
}
|
|
||||||
listResp, err := ts.Service.ListInboxes(userCtx, listReq)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 1, len(listResp.Inboxes))
|
|
||||||
require.Equal(t, v1pb.Inbox_UNREAD, listResp.Inboxes[0].Status)
|
|
||||||
|
|
||||||
// 2. Update inbox status to ARCHIVED
|
|
||||||
updateReq := &v1pb.UpdateInboxRequest{
|
|
||||||
Inbox: &v1pb.Inbox{
|
|
||||||
Name: fmt.Sprintf("inboxes/%d", inbox.ID),
|
|
||||||
Status: v1pb.Inbox_ARCHIVED,
|
|
||||||
},
|
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{
|
|
||||||
Paths: []string{"status"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
updateResp, err := ts.Service.UpdateInbox(userCtx, updateReq)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, v1pb.Inbox_ARCHIVED, updateResp.Status)
|
|
||||||
|
|
||||||
// 3. List inboxes again - should still have 1 but ARCHIVED
|
|
||||||
listResp, err = ts.Service.ListInboxes(userCtx, listReq)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 1, len(listResp.Inboxes))
|
|
||||||
require.Equal(t, v1pb.Inbox_ARCHIVED, listResp.Inboxes[0].Status)
|
|
||||||
|
|
||||||
// 4. Delete inbox
|
|
||||||
deleteReq := &v1pb.DeleteInboxRequest{
|
|
||||||
Name: fmt.Sprintf("inboxes/%d", inbox.ID),
|
|
||||||
}
|
|
||||||
_, err = ts.Service.DeleteInbox(userCtx, deleteReq)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// 5. List inboxes - should be empty
|
|
||||||
listResp, err = ts.Service.ListInboxes(userCtx, listReq)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 0, len(listResp.Inboxes))
|
|
||||||
require.Equal(t, int32(0), listResp.TotalSize)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1552,3 +1552,201 @@ func extractUsernameFromComparison(left, right ast.Expr) (string, bool) {
|
||||||
|
|
||||||
return str, true
|
return str, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListUserNotifications lists all notifications for a user.
|
||||||
|
// Notifications are backed by the inbox storage layer and represent activities
|
||||||
|
// that require user attention (e.g., memo comments).
|
||||||
|
func (s *APIV1Service) ListUserNotifications(ctx context.Context, request *v1pb.ListUserNotificationsRequest) (*v1pb.ListUserNotificationsResponse, error) {
|
||||||
|
userID, err := ExtractUserIDFromName(request.Parent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the requesting user has permission to view these notifications
|
||||||
|
currentUser, err := s.GetCurrentUser(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
|
||||||
|
}
|
||||||
|
if currentUser.ID != userID {
|
||||||
|
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch inbox items from storage
|
||||||
|
inboxes, err := s.Store.ListInboxes(ctx, &store.FindInbox{
|
||||||
|
ReceiverID: &userID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to list inboxes: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert storage layer inboxes to API notifications
|
||||||
|
notifications := []*v1pb.UserNotification{}
|
||||||
|
for _, inbox := range inboxes {
|
||||||
|
notification, err := s.convertInboxToUserNotification(ctx, inbox)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to convert inbox: %v", err)
|
||||||
|
}
|
||||||
|
notifications = append(notifications, notification)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1pb.ListUserNotificationsResponse{
|
||||||
|
Notifications: notifications,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUserNotification updates a notification's status (e.g., marking as read/archived).
|
||||||
|
// Only the notification owner can update their notifications.
|
||||||
|
func (s *APIV1Service) UpdateUserNotification(ctx context.Context, request *v1pb.UpdateUserNotificationRequest) (*v1pb.UserNotification, error) {
|
||||||
|
if request.Notification == nil {
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "notification is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationID, err := ExtractNotificationIDFromName(request.Notification.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "invalid notification name: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentUser, err := s.GetCurrentUser(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify ownership before updating
|
||||||
|
inboxes, err := s.Store.ListInboxes(ctx, &store.FindInbox{
|
||||||
|
ID: ¬ificationID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to get inbox: %v", err)
|
||||||
|
}
|
||||||
|
if len(inboxes) == 0 {
|
||||||
|
return nil, status.Errorf(codes.NotFound, "notification not found")
|
||||||
|
}
|
||||||
|
inbox := inboxes[0]
|
||||||
|
if inbox.ReceiverID != currentUser.ID {
|
||||||
|
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build update request based on field mask
|
||||||
|
update := &store.UpdateInbox{
|
||||||
|
ID: notificationID,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, path := range request.UpdateMask.Paths {
|
||||||
|
switch path {
|
||||||
|
case "status":
|
||||||
|
// Convert API status enum to storage enum
|
||||||
|
var inboxStatus store.InboxStatus
|
||||||
|
switch request.Notification.Status {
|
||||||
|
case v1pb.UserNotification_UNREAD:
|
||||||
|
inboxStatus = store.UNREAD
|
||||||
|
case v1pb.UserNotification_ARCHIVED:
|
||||||
|
inboxStatus = store.ARCHIVED
|
||||||
|
default:
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "invalid status")
|
||||||
|
}
|
||||||
|
update.Status = inboxStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedInbox, err := s.Store.UpdateInbox(ctx, update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to update inbox: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
notification, err := s.convertInboxToUserNotification(ctx, updatedInbox)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to convert inbox: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return notification, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUserNotification permanently deletes a notification.
|
||||||
|
// Only the notification owner can delete their notifications.
|
||||||
|
func (s *APIV1Service) DeleteUserNotification(ctx context.Context, request *v1pb.DeleteUserNotificationRequest) (*emptypb.Empty, error) {
|
||||||
|
notificationID, err := ExtractNotificationIDFromName(request.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "invalid notification name: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentUser, err := s.GetCurrentUser(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify ownership before deletion
|
||||||
|
inboxes, err := s.Store.ListInboxes(ctx, &store.FindInbox{
|
||||||
|
ID: ¬ificationID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to get inbox: %v", err)
|
||||||
|
}
|
||||||
|
if len(inboxes) == 0 {
|
||||||
|
return nil, status.Errorf(codes.NotFound, "notification not found")
|
||||||
|
}
|
||||||
|
inbox := inboxes[0]
|
||||||
|
if inbox.ReceiverID != currentUser.ID {
|
||||||
|
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.Store.DeleteInbox(ctx, &store.DeleteInbox{
|
||||||
|
ID: notificationID,
|
||||||
|
}); err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "failed to delete inbox: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &emptypb.Empty{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertInboxToUserNotification converts a storage-layer inbox to an API notification.
|
||||||
|
// This handles the mapping between the internal inbox representation and the public API.
|
||||||
|
func (s *APIV1Service) convertInboxToUserNotification(ctx context.Context, inbox *store.Inbox) (*v1pb.UserNotification, error) {
|
||||||
|
notification := &v1pb.UserNotification{
|
||||||
|
Name: fmt.Sprintf("users/%d/notifications/%d", inbox.ReceiverID, inbox.ID),
|
||||||
|
Sender: fmt.Sprintf("%s%d", UserNamePrefix, inbox.SenderID),
|
||||||
|
CreateTime: timestamppb.New(time.Unix(inbox.CreatedTs, 0)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert status from storage enum to API enum
|
||||||
|
switch inbox.Status {
|
||||||
|
case store.UNREAD:
|
||||||
|
notification.Status = v1pb.UserNotification_UNREAD
|
||||||
|
case store.ARCHIVED:
|
||||||
|
notification.Status = v1pb.UserNotification_ARCHIVED
|
||||||
|
default:
|
||||||
|
notification.Status = v1pb.UserNotification_STATUS_UNSPECIFIED
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract notification type and activity ID from inbox message
|
||||||
|
if inbox.Message != nil {
|
||||||
|
switch inbox.Message.Type {
|
||||||
|
case storepb.InboxMessage_MEMO_COMMENT:
|
||||||
|
notification.Type = v1pb.UserNotification_MEMO_COMMENT
|
||||||
|
default:
|
||||||
|
notification.Type = v1pb.UserNotification_TYPE_UNSPECIFIED
|
||||||
|
}
|
||||||
|
|
||||||
|
if inbox.Message.ActivityId != nil {
|
||||||
|
notification.ActivityId = inbox.Message.ActivityId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notification, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractNotificationIDFromName extracts the notification ID from a resource name.
|
||||||
|
// Expected format: users/{user_id}/notifications/{notification_id}
|
||||||
|
func ExtractNotificationIDFromName(name string) (int32, error) {
|
||||||
|
pattern := regexp.MustCompile(`^users/(\d+)/notifications/(\d+)$`)
|
||||||
|
matches := pattern.FindStringSubmatch(name)
|
||||||
|
if len(matches) != 3 {
|
||||||
|
return 0, errors.Errorf("invalid notification name: %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.Atoi(matches[2])
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Errorf("invalid notification id: %s", matches[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
return int32(id), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ type APIV1Service struct {
|
||||||
v1pb.UnimplementedMemoServiceServer
|
v1pb.UnimplementedMemoServiceServer
|
||||||
v1pb.UnimplementedAttachmentServiceServer
|
v1pb.UnimplementedAttachmentServiceServer
|
||||||
v1pb.UnimplementedShortcutServiceServer
|
v1pb.UnimplementedShortcutServiceServer
|
||||||
v1pb.UnimplementedInboxServiceServer
|
|
||||||
v1pb.UnimplementedActivityServiceServer
|
v1pb.UnimplementedActivityServiceServer
|
||||||
v1pb.UnimplementedIdentityProviderServiceServer
|
v1pb.UnimplementedIdentityProviderServiceServer
|
||||||
|
|
||||||
|
|
@ -60,7 +59,6 @@ func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store
|
||||||
v1pb.RegisterMemoServiceServer(grpcServer, apiv1Service)
|
v1pb.RegisterMemoServiceServer(grpcServer, apiv1Service)
|
||||||
v1pb.RegisterAttachmentServiceServer(grpcServer, apiv1Service)
|
v1pb.RegisterAttachmentServiceServer(grpcServer, apiv1Service)
|
||||||
v1pb.RegisterShortcutServiceServer(grpcServer, apiv1Service)
|
v1pb.RegisterShortcutServiceServer(grpcServer, apiv1Service)
|
||||||
v1pb.RegisterInboxServiceServer(grpcServer, apiv1Service)
|
|
||||||
v1pb.RegisterActivityServiceServer(grpcServer, apiv1Service)
|
v1pb.RegisterActivityServiceServer(grpcServer, apiv1Service)
|
||||||
v1pb.RegisterIdentityProviderServiceServer(grpcServer, apiv1Service)
|
v1pb.RegisterIdentityProviderServiceServer(grpcServer, apiv1Service)
|
||||||
reflection.Register(grpcServer)
|
reflection.Register(grpcServer)
|
||||||
|
|
@ -107,9 +105,6 @@ func (s *APIV1Service) RegisterGateway(ctx context.Context, echoServer *echo.Ech
|
||||||
if err := v1pb.RegisterShortcutServiceHandler(ctx, gwMux, conn); err != nil {
|
if err := v1pb.RegisterShortcutServiceHandler(ctx, gwMux, conn); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := v1pb.RegisterInboxServiceHandler(ctx, gwMux, conn); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := v1pb.RegisterActivityServiceHandler(ctx, gwMux, conn); err != nil {
|
if err := v1pb.RegisterActivityServiceHandler(ctx, gwMux, conn); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,13 @@ import (
|
||||||
storepb "github.com/usememos/memos/proto/gen/store"
|
storepb "github.com/usememos/memos/proto/gen/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InboxStatus is the status for an inbox.
|
// InboxStatus represents the status of an inbox notification.
|
||||||
type InboxStatus string
|
type InboxStatus string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UNREAD InboxStatus = "UNREAD"
|
// UNREAD indicates the notification has not been read by the user.
|
||||||
|
UNREAD InboxStatus = "UNREAD"
|
||||||
|
// ARCHIVED indicates the notification has been archived/dismissed by the user.
|
||||||
ARCHIVED InboxStatus = "ARCHIVED"
|
ARCHIVED InboxStatus = "ARCHIVED"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -18,20 +20,24 @@ func (s InboxStatus) String() string {
|
||||||
return string(s)
|
return string(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inbox represents a notification in a user's inbox.
|
||||||
|
// It connects activities to users who should be notified.
|
||||||
type Inbox struct {
|
type Inbox struct {
|
||||||
ID int32
|
ID int32
|
||||||
CreatedTs int64
|
CreatedTs int64
|
||||||
SenderID int32
|
SenderID int32 // The user who triggered the notification
|
||||||
ReceiverID int32
|
ReceiverID int32 // The user who receives the notification
|
||||||
Status InboxStatus
|
Status InboxStatus // Current status (unread/archived)
|
||||||
Message *storepb.InboxMessage
|
Message *storepb.InboxMessage // The notification message content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateInbox contains fields that can be updated for an inbox item.
|
||||||
type UpdateInbox struct {
|
type UpdateInbox struct {
|
||||||
ID int32
|
ID int32
|
||||||
Status InboxStatus
|
Status InboxStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindInbox specifies filter criteria for querying inbox items.
|
||||||
type FindInbox struct {
|
type FindInbox struct {
|
||||||
ID *int32
|
ID *int32
|
||||||
SenderID *int32
|
SenderID *int32
|
||||||
|
|
@ -43,22 +49,27 @@ type FindInbox struct {
|
||||||
Offset *int
|
Offset *int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteInbox specifies which inbox item to delete.
|
||||||
type DeleteInbox struct {
|
type DeleteInbox struct {
|
||||||
ID int32
|
ID int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateInbox creates a new inbox notification.
|
||||||
func (s *Store) CreateInbox(ctx context.Context, create *Inbox) (*Inbox, error) {
|
func (s *Store) CreateInbox(ctx context.Context, create *Inbox) (*Inbox, error) {
|
||||||
return s.driver.CreateInbox(ctx, create)
|
return s.driver.CreateInbox(ctx, create)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListInboxes retrieves inbox items matching the filter criteria.
|
||||||
func (s *Store) ListInboxes(ctx context.Context, find *FindInbox) ([]*Inbox, error) {
|
func (s *Store) ListInboxes(ctx context.Context, find *FindInbox) ([]*Inbox, error) {
|
||||||
return s.driver.ListInboxes(ctx, find)
|
return s.driver.ListInboxes(ctx, find)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateInbox updates an existing inbox item.
|
||||||
func (s *Store) UpdateInbox(ctx context.Context, update *UpdateInbox) (*Inbox, error) {
|
func (s *Store) UpdateInbox(ctx context.Context, update *UpdateInbox) (*Inbox, error) {
|
||||||
return s.driver.UpdateInbox(ctx, update)
|
return s.driver.UpdateInbox(ctx, update)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteInbox permanently removes an inbox item.
|
||||||
func (s *Store) DeleteInbox(ctx context.Context, delete *DeleteInbox) error {
|
func (s *Store) DeleteInbox(ctx context.Context, delete *DeleteInbox) error {
|
||||||
return s.driver.DeleteInbox(ctx, delete)
|
return s.driver.DeleteInbox(ctx, delete)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,39 @@
|
||||||
import { InboxIcon, LoaderIcon, MessageCircleIcon, TrashIcon } from "lucide-react";
|
import { CheckIcon, MessageCircleIcon, TrashIcon, XIcon } from "lucide-react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
import UserAvatar from "@/components/UserAvatar";
|
||||||
import { activityServiceClient } from "@/grpcweb";
|
import { activityServiceClient } from "@/grpcweb";
|
||||||
import useAsyncEffect from "@/hooks/useAsyncEffect";
|
import useAsyncEffect from "@/hooks/useAsyncEffect";
|
||||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { memoStore, userStore } from "@/store";
|
import { memoStore, userStore } from "@/store";
|
||||||
import { activityNamePrefix } from "@/store/common";
|
import { activityNamePrefix } from "@/store/common";
|
||||||
import { Inbox, Inbox_Status } from "@/types/proto/api/v1/inbox_service";
|
|
||||||
import { Memo } from "@/types/proto/api/v1/memo_service";
|
import { Memo } from "@/types/proto/api/v1/memo_service";
|
||||||
import { User } from "@/types/proto/api/v1/user_service";
|
import { User, UserNotification, UserNotification_Status } from "@/types/proto/api/v1/user_service";
|
||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
inbox: Inbox;
|
notification: UserNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MemoCommentMessage = observer(({ inbox }: Props) => {
|
const MemoCommentMessage = observer(({ notification }: Props) => {
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
const navigateTo = useNavigateTo();
|
const navigateTo = useNavigateTo();
|
||||||
const [relatedMemo, setRelatedMemo] = useState<Memo | undefined>(undefined);
|
const [relatedMemo, setRelatedMemo] = useState<Memo | undefined>(undefined);
|
||||||
|
const [commentMemo, setCommentMemo] = useState<Memo | undefined>(undefined);
|
||||||
const [sender, setSender] = useState<User | undefined>(undefined);
|
const [sender, setSender] = useState<User | undefined>(undefined);
|
||||||
const [initialized, setInitialized] = useState<boolean>(false);
|
const [initialized, setInitialized] = useState<boolean>(false);
|
||||||
const [hasError, setHasError] = useState<boolean>(false);
|
const [hasError, setHasError] = useState<boolean>(false);
|
||||||
|
|
||||||
useAsyncEffect(async () => {
|
useAsyncEffect(async () => {
|
||||||
if (!inbox.activityId) {
|
if (!notification.activityId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const activity = await activityServiceClient.getActivity({
|
const activity = await activityServiceClient.getActivity({
|
||||||
name: `${activityNamePrefix}${inbox.activityId}`,
|
name: `${activityNamePrefix}${notification.activityId}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (activity.payload?.memoComment) {
|
if (activity.payload?.memoComment) {
|
||||||
|
|
@ -42,7 +42,14 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
|
||||||
skipStore: true,
|
skipStore: true,
|
||||||
});
|
});
|
||||||
setRelatedMemo(memo);
|
setRelatedMemo(memo);
|
||||||
const sender = await userStore.getOrFetchUserByName(inbox.sender);
|
|
||||||
|
// Fetch the comment memo
|
||||||
|
const comment = await memoStore.getOrFetchMemoByName(memoCommentPayload.memo, {
|
||||||
|
skipStore: true,
|
||||||
|
});
|
||||||
|
setCommentMemo(comment);
|
||||||
|
|
||||||
|
const sender = await userStore.getOrFetchUserByName(notification.sender);
|
||||||
setSender(sender);
|
setSender(sender);
|
||||||
setInitialized(true);
|
setInitialized(true);
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +58,7 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
|
||||||
setHasError(true);
|
setHasError(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, [inbox.activityId]);
|
}, [notification.activityId]);
|
||||||
|
|
||||||
const handleNavigateToMemo = async () => {
|
const handleNavigateToMemo = async () => {
|
||||||
if (!relatedMemo) {
|
if (!relatedMemo) {
|
||||||
|
|
@ -59,16 +66,16 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateTo(`/${relatedMemo.name}`);
|
navigateTo(`/${relatedMemo.name}`);
|
||||||
if (inbox.status === Inbox_Status.UNREAD) {
|
if (notification.status === UserNotification_Status.UNREAD) {
|
||||||
handleArchiveMessage(true);
|
handleArchiveMessage(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleArchiveMessage = async (silence = false) => {
|
const handleArchiveMessage = async (silence = false) => {
|
||||||
await userStore.updateInbox(
|
await userStore.updateNotification(
|
||||||
{
|
{
|
||||||
name: inbox.name,
|
name: notification.name,
|
||||||
status: Inbox_Status.ARCHIVED,
|
status: UserNotification_Status.ARCHIVED,
|
||||||
},
|
},
|
||||||
["status"],
|
["status"],
|
||||||
);
|
);
|
||||||
|
|
@ -78,104 +85,120 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteMessage = async () => {
|
const handleDeleteMessage = async () => {
|
||||||
await userStore.deleteInbox(inbox.name);
|
await userStore.deleteNotification(notification.name);
|
||||||
toast.success(t("message.deleted-successfully"));
|
toast.success(t("message.deleted-successfully"));
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteButton = () => (
|
if (!initialized && !hasError) {
|
||||||
<>
|
return (
|
||||||
<div>
|
<div className="w-full px-4 py-3.5 border-b border-border last:border-b-0 bg-muted/20 animate-pulse">
|
||||||
<TooltipProvider>
|
<div className="flex items-start gap-3">
|
||||||
<Tooltip>
|
<div className="w-9 h-9 rounded-full bg-muted/60 shrink-0" />
|
||||||
<TooltipTrigger>
|
<div className="flex-1 space-y-2.5">
|
||||||
<TrashIcon
|
<div className="h-3.5 bg-muted/60 rounded w-2/5" />
|
||||||
className="w-4 h-auto cursor-pointer text-muted-foreground hover:text-primary"
|
<div className="h-16 bg-muted/40 rounded-md" />
|
||||||
onClick={() => handleDeleteMessage()}
|
</div>
|
||||||
/>
|
</div>
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>{t("common.delete")}</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
const archiveButton = () => (
|
if (hasError) {
|
||||||
<>
|
return (
|
||||||
<div>
|
<div className="w-full px-4 py-3.5 border-b border-border last:border-b-0 bg-destructive/[0.03]">
|
||||||
<TooltipProvider>
|
<div className="flex items-center justify-between">
|
||||||
<Tooltip>
|
<div className="flex items-center gap-3">
|
||||||
<TooltipTrigger>
|
<div className="w-9 h-9 rounded-full bg-destructive/10 flex items-center justify-center shrink-0">
|
||||||
<InboxIcon
|
<XIcon className="w-4 h-4 text-destructive" />
|
||||||
className="w-4 h-auto cursor-pointer text-muted-foreground hover:text-primary"
|
</div>
|
||||||
onClick={() => handleArchiveMessage()}
|
<span className="text-sm text-destructive/90">{t("inbox.failed-to-load")}</span>
|
||||||
/>
|
</div>
|
||||||
</TooltipTrigger>
|
<button
|
||||||
<TooltipContent>
|
onClick={handleDeleteMessage}
|
||||||
<p>{t("common.archive")}</p>
|
className="p-1.5 hover:bg-destructive/10 rounded-md transition-colors"
|
||||||
</TooltipContent>
|
title={t("common.delete")}
|
||||||
</Tooltip>
|
>
|
||||||
</TooltipProvider>
|
<TrashIcon className="w-3.5 h-3.5 text-destructive/70 hover:text-destructive" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
const isUnread = notification.status === UserNotification_Status.UNREAD;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full flex flex-row justify-start items-start gap-3">
|
<div
|
||||||
<div
|
className={cn(
|
||||||
className={cn(
|
"w-full px-4 py-3.5 border-b border-border last:border-b-0 transition-colors group relative",
|
||||||
"shrink-0 mt-2 p-2 rounded-full border",
|
isUnread ? "bg-primary/[0.02] hover:bg-primary/[0.04]" : "hover:bg-muted/40",
|
||||||
inbox.status === Inbox_Status.UNREAD
|
)}
|
||||||
? "border-primary text-primary bg-primary/10"
|
>
|
||||||
: "border-muted-foreground text-muted-foreground bg-muted",
|
{/* Unread indicator bar */}
|
||||||
)}
|
{isUnread && <div className="absolute left-0 top-0 bottom-0 w-1 bg-primary" />}
|
||||||
>
|
|
||||||
<TooltipProvider>
|
<div className="flex items-start gap-3">
|
||||||
<Tooltip>
|
{/* Avatar & Icon */}
|
||||||
<TooltipTrigger>
|
<div className="relative shrink-0 mt-0.5">
|
||||||
<MessageCircleIcon className="w-4 sm:w-5 h-auto" />
|
<UserAvatar className="w-9 h-9" avatarUrl={sender?.avatarUrl} />
|
||||||
</TooltipTrigger>
|
<div
|
||||||
<TooltipContent>
|
className={cn(
|
||||||
<p>Comment</p>
|
"absolute -bottom-0.5 -right-0.5 w-[18px] h-[18px] rounded-full border-[2px] border-background flex items-center justify-center shadow-sm",
|
||||||
</TooltipContent>
|
isUnread ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground",
|
||||||
</Tooltip>
|
)}
|
||||||
</TooltipProvider>
|
>
|
||||||
</div>
|
<MessageCircleIcon className="w-2.5 h-2.5" />
|
||||||
<div
|
</div>
|
||||||
className={cn(
|
</div>
|
||||||
"border w-full p-2 px-3 rounded-lg flex flex-col justify-start items-start gap-1 border-border hover:bg-background",
|
|
||||||
inbox.status !== Inbox_Status.UNREAD && "opacity-60",
|
{/* Content */}
|
||||||
)}
|
<div className="flex-1 min-w-0">
|
||||||
>
|
{/* Header */}
|
||||||
{initialized ? (
|
<div className="flex items-start justify-between gap-2">
|
||||||
<>
|
<div className="flex-1 min-w-0 flex items-baseline gap-1.5 flex-wrap">
|
||||||
<div className="w-full flex flex-row justify-between items-center">
|
<span className="font-semibold text-sm text-foreground">{sender?.displayName || sender?.username}</span>
|
||||||
<span className="text-sm text-muted-foreground">{inbox.createTime?.toLocaleString()}</span>
|
<span className="text-sm text-muted-foreground">commented on your memo</span>
|
||||||
{inbox.status === Inbox_Status.UNREAD ? archiveButton() : deleteButton()}
|
<span className="text-xs text-muted-foreground/80">
|
||||||
|
· {notification.createTime?.toLocaleDateString([], { month: "short", day: "numeric" })} at{" "}
|
||||||
|
{notification.createTime?.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p
|
<div className="flex items-center gap-0.5 shrink-0">
|
||||||
className="text-base leading-tight cursor-pointer text-muted-foreground hover:underline hover:text-primary"
|
{isUnread ? (
|
||||||
|
<button
|
||||||
|
onClick={() => handleArchiveMessage()}
|
||||||
|
className="p-1.5 hover:bg-background/80 rounded-md transition-all opacity-0 group-hover:opacity-100"
|
||||||
|
title={t("common.archive")}
|
||||||
|
>
|
||||||
|
<CheckIcon className="w-3.5 h-3.5 text-muted-foreground hover:text-primary" />
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
onClick={handleDeleteMessage}
|
||||||
|
className="p-1.5 hover:bg-background/80 rounded-md transition-all opacity-0 group-hover:opacity-100"
|
||||||
|
title={t("common.delete")}
|
||||||
|
>
|
||||||
|
<TrashIcon className="w-3.5 h-3.5 text-muted-foreground hover:text-destructive" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Comment Preview */}
|
||||||
|
{commentMemo && (
|
||||||
|
<div
|
||||||
onClick={handleNavigateToMemo}
|
onClick={handleNavigateToMemo}
|
||||||
|
className="mt-2 p-3 rounded-md bg-muted/40 hover:bg-muted/60 cursor-pointer border border-border/50 hover:border-border transition-all group/comment"
|
||||||
>
|
>
|
||||||
{t("inbox.memo-comment", {
|
<div className="flex items-start gap-2">
|
||||||
user: sender?.displayName || sender?.username,
|
<MessageCircleIcon className="w-3.5 h-3.5 text-muted-foreground/60 shrink-0 mt-0.5" />
|
||||||
memo: relatedMemo?.name,
|
<p className="text-[13px] text-foreground/90 line-clamp-2 leading-relaxed group-hover/comment:text-foreground transition-colors">
|
||||||
interpolation: { escapeValue: false },
|
{commentMemo.content || <span className="italic text-muted-foreground">Empty comment</span>}
|
||||||
})}
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</>
|
</div>
|
||||||
) : hasError ? (
|
)}
|
||||||
<div className="w-full flex flex-row justify-between items-center">
|
</div>
|
||||||
<span className="text-sm text-muted-foreground">{t("inbox.failed-to-load")}</span>
|
|
||||||
{deleteButton()}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="w-full flex flex-row justify-center items-center my-2">
|
|
||||||
<LoaderIcon className="animate-spin text-muted-foreground" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { EarthIcon, LibraryIcon, PaperclipIcon, UserCircleIcon } from "lucide-react";
|
import { BellIcon, EarthIcon, LibraryIcon, PaperclipIcon, UserCircleIcon } from "lucide-react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
|
|
@ -33,7 +33,7 @@ const Navigation = observer((props: Props) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
userStore.fetchInboxes();
|
userStore.fetchNotifications();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const homeNavLink: NavLinkItem = {
|
const homeNavLink: NavLinkItem = {
|
||||||
|
|
@ -54,6 +54,22 @@ const Navigation = observer((props: Props) => {
|
||||||
title: t("common.attachments"),
|
title: t("common.attachments"),
|
||||||
icon: <PaperclipIcon className="w-6 h-auto shrink-0" />,
|
icon: <PaperclipIcon className="w-6 h-auto shrink-0" />,
|
||||||
};
|
};
|
||||||
|
const unreadCount = userStore.state.notifications.filter((n) => n.status === "UNREAD").length;
|
||||||
|
const inboxNavLink: NavLinkItem = {
|
||||||
|
id: "header-inbox",
|
||||||
|
path: Routes.INBOX,
|
||||||
|
title: t("common.inbox"),
|
||||||
|
icon: (
|
||||||
|
<div className="relative">
|
||||||
|
<BellIcon className="w-6 h-auto shrink-0" />
|
||||||
|
{unreadCount > 0 && (
|
||||||
|
<span className="absolute -top-1 -right-1 min-w-[18px] h-[18px] px-1 flex items-center justify-center bg-primary text-primary-foreground text-[10px] font-semibold rounded-full border-2 border-background">
|
||||||
|
{unreadCount > 99 ? "99+" : unreadCount}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
};
|
||||||
const signInNavLink: NavLinkItem = {
|
const signInNavLink: NavLinkItem = {
|
||||||
id: "header-auth",
|
id: "header-auth",
|
||||||
path: Routes.AUTH,
|
path: Routes.AUTH,
|
||||||
|
|
@ -61,7 +77,9 @@ const Navigation = observer((props: Props) => {
|
||||||
icon: <UserCircleIcon className="w-6 h-auto shrink-0" />,
|
icon: <UserCircleIcon className="w-6 h-auto shrink-0" />,
|
||||||
};
|
};
|
||||||
|
|
||||||
const navLinks: NavLinkItem[] = currentUser ? [homeNavLink, exploreNavLink, attachmentsNavLink] : [exploreNavLink, signInNavLink];
|
const navLinks: NavLinkItem[] = currentUser
|
||||||
|
? [homeNavLink, exploreNavLink, attachmentsNavLink, inboxNavLink]
|
||||||
|
: [exploreNavLink, signInNavLink];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className={cn("w-full h-full overflow-auto flex flex-col justify-between items-start gap-4 hide-scrollbar", className)}>
|
<header className={cn("w-full h-full overflow-auto flex flex-col justify-between items-start gap-4 hide-scrollbar", className)}>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,4 @@
|
||||||
import {
|
import { ArchiveIcon, LogOutIcon, User2Icon, SquareUserIcon, SettingsIcon, GlobeIcon, PaletteIcon, CheckIcon } from "lucide-react";
|
||||||
ArchiveIcon,
|
|
||||||
LogOutIcon,
|
|
||||||
User2Icon,
|
|
||||||
SquareUserIcon,
|
|
||||||
SettingsIcon,
|
|
||||||
BellIcon,
|
|
||||||
GlobeIcon,
|
|
||||||
PaletteIcon,
|
|
||||||
CheckIcon,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { authServiceClient } from "@/grpcweb";
|
import { authServiceClient } from "@/grpcweb";
|
||||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||||
|
|
@ -99,10 +89,6 @@ const UserMenu = observer((props: Props) => {
|
||||||
<ArchiveIcon className="size-4 text-muted-foreground" />
|
<ArchiveIcon className="size-4 text-muted-foreground" />
|
||||||
{t("common.archived")}
|
{t("common.archived")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => navigateTo(Routes.INBOX)}>
|
|
||||||
<BellIcon className="size-4 text-muted-foreground" />
|
|
||||||
{t("common.inbox")}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSub>
|
<DropdownMenuSub>
|
||||||
<DropdownMenuSubTrigger>
|
<DropdownMenuSubTrigger>
|
||||||
<GlobeIcon className="size-4 text-muted-foreground" />
|
<GlobeIcon className="size-4 text-muted-foreground" />
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { ActivityServiceDefinition } from "./types/proto/api/v1/activity_service
|
||||||
import { AttachmentServiceDefinition } from "./types/proto/api/v1/attachment_service";
|
import { AttachmentServiceDefinition } from "./types/proto/api/v1/attachment_service";
|
||||||
import { AuthServiceDefinition } from "./types/proto/api/v1/auth_service";
|
import { AuthServiceDefinition } from "./types/proto/api/v1/auth_service";
|
||||||
import { IdentityProviderServiceDefinition } from "./types/proto/api/v1/idp_service";
|
import { IdentityProviderServiceDefinition } from "./types/proto/api/v1/idp_service";
|
||||||
import { InboxServiceDefinition } from "./types/proto/api/v1/inbox_service";
|
|
||||||
import { MemoServiceDefinition } from "./types/proto/api/v1/memo_service";
|
import { MemoServiceDefinition } from "./types/proto/api/v1/memo_service";
|
||||||
import { ShortcutServiceDefinition } from "./types/proto/api/v1/shortcut_service";
|
import { ShortcutServiceDefinition } from "./types/proto/api/v1/shortcut_service";
|
||||||
import { UserServiceDefinition } from "./types/proto/api/v1/user_service";
|
import { UserServiceDefinition } from "./types/proto/api/v1/user_service";
|
||||||
|
|
@ -30,8 +29,6 @@ export const attachmentServiceClient = clientFactory.create(AttachmentServiceDef
|
||||||
|
|
||||||
export const shortcutServiceClient = clientFactory.create(ShortcutServiceDefinition, channel);
|
export const shortcutServiceClient = clientFactory.create(ShortcutServiceDefinition, channel);
|
||||||
|
|
||||||
export const inboxServiceClient = clientFactory.create(InboxServiceDefinition, channel);
|
|
||||||
|
|
||||||
export const activityServiceClient = clientFactory.create(ActivityServiceDefinition, channel);
|
export const activityServiceClient = clientFactory.create(ActivityServiceDefinition, channel);
|
||||||
|
|
||||||
export const identityProviderServiceClient = clientFactory.create(IdentityProviderServiceDefinition, channel);
|
export const identityProviderServiceClient = clientFactory.create(IdentityProviderServiceDefinition, channel);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
"about": "About",
|
"about": "About",
|
||||||
"add": "Add",
|
"add": "Add",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
|
"all": "All",
|
||||||
"archive": "Archive",
|
"archive": "Archive",
|
||||||
"archived": "Archived",
|
"archived": "Archived",
|
||||||
"attachments": "Attachments",
|
"attachments": "Attachments",
|
||||||
|
|
@ -125,8 +126,10 @@
|
||||||
},
|
},
|
||||||
"inbox": {
|
"inbox": {
|
||||||
"memo-comment": "{{user}} has a comment on your {{memo}}.",
|
"memo-comment": "{{user}} has a comment on your {{memo}}.",
|
||||||
"version-update": "New version {{version}} is available now!",
|
"failed-to-load": "Failed to load inbox item",
|
||||||
"failed-to-load": "Failed to load inbox item"
|
"unread": "Unread",
|
||||||
|
"no-unread": "No unread notifications",
|
||||||
|
"no-archived": "No archived notifications"
|
||||||
},
|
},
|
||||||
"markdown": {
|
"markdown": {
|
||||||
"checkbox": "Checkbox",
|
"checkbox": "Checkbox",
|
||||||
|
|
|
||||||
|
|
@ -1,63 +1,126 @@
|
||||||
import { sortBy } from "lodash-es";
|
import { sortBy } from "lodash-es";
|
||||||
import { BellIcon } from "lucide-react";
|
import { ArchiveIcon, BellIcon, InboxIcon } from "lucide-react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useEffect } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Empty from "@/components/Empty";
|
import Empty from "@/components/Empty";
|
||||||
import MemoCommentMessage from "@/components/Inbox/MemoCommentMessage";
|
import MemoCommentMessage from "@/components/Inbox/MemoCommentMessage";
|
||||||
import MobileHeader from "@/components/MobileHeader";
|
import MobileHeader from "@/components/MobileHeader";
|
||||||
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
|
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
import { userStore } from "@/store";
|
import { userStore } from "@/store";
|
||||||
import { Inbox, Inbox_Status, Inbox_Type } from "@/types/proto/api/v1/inbox_service";
|
import { UserNotification, UserNotification_Status, UserNotification_Type } from "@/types/proto/api/v1/user_service";
|
||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
|
|
||||||
const Inboxes = observer(() => {
|
const Inboxes = observer(() => {
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
const { md } = useResponsiveWidth();
|
const { md } = useResponsiveWidth();
|
||||||
|
const [filter, setFilter] = useState<"all" | "unread" | "archived">("all");
|
||||||
|
|
||||||
const inboxes = sortBy(userStore.state.inboxes, (inbox: Inbox) => {
|
const allNotifications = sortBy(userStore.state.notifications, (notification: UserNotification) => {
|
||||||
if (inbox.status === Inbox_Status.UNREAD) return 0;
|
return -(notification.createTime?.getTime() || 0);
|
||||||
if (inbox.status === Inbox_Status.ARCHIVED) return 1;
|
|
||||||
return 2;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchInboxes = async () => {
|
const notifications = allNotifications.filter((notification) => {
|
||||||
|
if (filter === "unread") return notification.status === UserNotification_Status.UNREAD;
|
||||||
|
if (filter === "archived") return notification.status === UserNotification_Status.ARCHIVED;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const unreadCount = allNotifications.filter((n) => n.status === UserNotification_Status.UNREAD).length;
|
||||||
|
const archivedCount = allNotifications.filter((n) => n.status === UserNotification_Status.ARCHIVED).length;
|
||||||
|
|
||||||
|
const fetchNotifications = async () => {
|
||||||
try {
|
try {
|
||||||
await userStore.fetchInboxes();
|
await userStore.fetchNotifications();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch inboxes:", error);
|
console.error("Failed to fetch notifications:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchInboxes();
|
fetchNotifications();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
|
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
|
||||||
{!md && <MobileHeader />}
|
{!md && <MobileHeader />}
|
||||||
<div className="w-full px-4 sm:px-6">
|
<div className="w-full px-4 sm:px-6">
|
||||||
<div className="w-full border border-border flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-background text-foreground">
|
<div className="w-full border border-border flex flex-col justify-start items-start rounded-xl bg-background text-foreground overflow-hidden">
|
||||||
<div className="relative w-full flex flex-row justify-between items-center">
|
{/* Header */}
|
||||||
<p className="py-1 flex flex-row justify-start items-center select-none opacity-80">
|
<div className="w-full px-4 py-4 border-b border-border">
|
||||||
<BellIcon className="w-6 h-auto mr-1 opacity-80" />
|
<div className="flex flex-row justify-between items-center">
|
||||||
<span className="text-lg">{t("common.inbox")}</span>
|
<div className="flex flex-row items-center gap-2">
|
||||||
</p>
|
<BellIcon className="w-5 h-auto text-muted-foreground" />
|
||||||
|
<h1 className="text-xl font-semibold">{t("common.inbox")}</h1>
|
||||||
|
{unreadCount > 0 && (
|
||||||
|
<span className="ml-1 px-2 py-0.5 text-xs font-medium rounded-full bg-primary text-primary-foreground">
|
||||||
|
{unreadCount}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full h-auto flex flex-col justify-start items-start px-2 pb-4">
|
|
||||||
{inboxes.length === 0 && (
|
{/* Filter Tabs */}
|
||||||
<div className="w-full mt-4 mb-8 flex flex-col justify-center items-center italic">
|
<div className="w-full px-4 py-2 border-b border-border bg-muted/30">
|
||||||
|
<div className="flex flex-row gap-1">
|
||||||
|
<button
|
||||||
|
onClick={() => setFilter("all")}
|
||||||
|
className={cn(
|
||||||
|
"px-3 py-1.5 text-sm font-medium rounded-md transition-colors",
|
||||||
|
filter === "all"
|
||||||
|
? "bg-background text-foreground shadow-sm"
|
||||||
|
: "text-muted-foreground hover:text-foreground hover:bg-background/50",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{t("common.all")} ({allNotifications.length})
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setFilter("unread")}
|
||||||
|
className={cn(
|
||||||
|
"px-3 py-1.5 text-sm font-medium rounded-md transition-colors flex items-center gap-1.5",
|
||||||
|
filter === "unread"
|
||||||
|
? "bg-background text-foreground shadow-sm"
|
||||||
|
: "text-muted-foreground hover:text-foreground hover:bg-background/50",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<InboxIcon className="w-3.5 h-auto" />
|
||||||
|
{t("inbox.unread")} ({unreadCount})
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setFilter("archived")}
|
||||||
|
className={cn(
|
||||||
|
"px-3 py-1.5 text-sm font-medium rounded-md transition-colors flex items-center gap-1.5",
|
||||||
|
filter === "archived"
|
||||||
|
? "bg-background text-foreground shadow-sm"
|
||||||
|
: "text-muted-foreground hover:text-foreground hover:bg-background/50",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ArchiveIcon className="w-3.5 h-auto" />
|
||||||
|
{t("common.archived")} ({archivedCount})
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Notifications List */}
|
||||||
|
<div className="w-full">
|
||||||
|
{notifications.length === 0 ? (
|
||||||
|
<div className="w-full py-16 flex flex-col justify-center items-center">
|
||||||
<Empty />
|
<Empty />
|
||||||
<p className="mt-4 text-muted-foreground">{t("message.no-data")}</p>
|
<p className="mt-4 text-sm text-muted-foreground">
|
||||||
|
{filter === "unread" ? t("inbox.no-unread") : filter === "archived" ? t("inbox.no-archived") : t("message.no-data")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{notifications.map((notification: UserNotification) => {
|
||||||
|
if (notification.type === UserNotification_Type.MEMO_COMMENT) {
|
||||||
|
return <MemoCommentMessage key={notification.name} notification={notification} />;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-col justify-start items-start w-full mt-4 gap-4">
|
|
||||||
{inboxes.map((inbox: Inbox) => {
|
|
||||||
if (inbox.type === Inbox_Type.MEMO_COMMENT) {
|
|
||||||
return <MemoCommentMessage key={`${inbox.name}-${inbox.status}`} inbox={inbox} />;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { uniqueId } from "lodash-es";
|
import { uniqueId } from "lodash-es";
|
||||||
import { makeAutoObservable, computed } from "mobx";
|
import { makeAutoObservable, computed } from "mobx";
|
||||||
import { authServiceClient, inboxServiceClient, userServiceClient, shortcutServiceClient } from "@/grpcweb";
|
import { authServiceClient, userServiceClient, shortcutServiceClient } from "@/grpcweb";
|
||||||
import { Inbox } from "@/types/proto/api/v1/inbox_service";
|
|
||||||
import { Shortcut } from "@/types/proto/api/v1/shortcut_service";
|
import { Shortcut } from "@/types/proto/api/v1/shortcut_service";
|
||||||
import {
|
import {
|
||||||
User,
|
User,
|
||||||
|
UserNotification,
|
||||||
UserSetting,
|
UserSetting,
|
||||||
UserSetting_Key,
|
UserSetting_Key,
|
||||||
UserSetting_GeneralSetting,
|
UserSetting_GeneralSetting,
|
||||||
|
|
@ -24,7 +24,7 @@ class LocalState {
|
||||||
userAccessTokensSetting?: UserSetting_AccessTokensSetting;
|
userAccessTokensSetting?: UserSetting_AccessTokensSetting;
|
||||||
userWebhooksSetting?: UserSetting_WebhooksSetting;
|
userWebhooksSetting?: UserSetting_WebhooksSetting;
|
||||||
shortcuts: Shortcut[] = [];
|
shortcuts: Shortcut[] = [];
|
||||||
inboxes: Inbox[] = [];
|
notifications: UserNotification[] = [];
|
||||||
userMapByName: Record<string, User> = {};
|
userMapByName: Record<string, User> = {};
|
||||||
userStatsByName: Record<string, UserStats> = {};
|
userStatsByName: Record<string, UserStats> = {};
|
||||||
|
|
||||||
|
|
@ -218,40 +218,40 @@ const userStore = (() => {
|
||||||
// Note: fetchShortcuts is now handled by fetchUserSettings
|
// Note: fetchShortcuts is now handled by fetchUserSettings
|
||||||
// The shortcuts are extracted from the user shortcuts setting
|
// The shortcuts are extracted from the user shortcuts setting
|
||||||
|
|
||||||
const fetchInboxes = async () => {
|
const fetchNotifications = async () => {
|
||||||
if (!state.currentUser) {
|
if (!state.currentUser) {
|
||||||
throw new Error("No current user available");
|
throw new Error("No current user available");
|
||||||
}
|
}
|
||||||
|
|
||||||
const { inboxes } = await inboxServiceClient.listInboxes({
|
const { notifications } = await userServiceClient.listUserNotifications({
|
||||||
parent: state.currentUser,
|
parent: state.currentUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
state.setPartial({
|
state.setPartial({
|
||||||
inboxes,
|
notifications,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateInbox = async (inbox: Partial<Inbox>, updateMask: string[]) => {
|
const updateNotification = async (notification: Partial<UserNotification>, updateMask: string[]) => {
|
||||||
const updatedInbox = await inboxServiceClient.updateInbox({
|
const updatedNotification = await userServiceClient.updateUserNotification({
|
||||||
inbox,
|
notification,
|
||||||
updateMask,
|
updateMask,
|
||||||
});
|
});
|
||||||
state.setPartial({
|
state.setPartial({
|
||||||
inboxes: state.inboxes.map((i) => {
|
notifications: state.notifications.map((n) => {
|
||||||
if (i.name === updatedInbox.name) {
|
if (n.name === updatedNotification.name) {
|
||||||
return updatedInbox;
|
return updatedNotification;
|
||||||
}
|
}
|
||||||
return i;
|
return n;
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
return updatedInbox;
|
return updatedNotification;
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteInbox = async (name: string) => {
|
const deleteNotification = async (name: string) => {
|
||||||
await inboxServiceClient.deleteInbox({ name });
|
await userServiceClient.deleteUserNotification({ name });
|
||||||
state.setPartial({
|
state.setPartial({
|
||||||
inboxes: state.inboxes.filter((i) => i.name !== name),
|
notifications: state.notifications.filter((n) => n.name !== name),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -296,9 +296,9 @@ const userStore = (() => {
|
||||||
updateUserGeneralSetting,
|
updateUserGeneralSetting,
|
||||||
getUserGeneralSetting,
|
getUserGeneralSetting,
|
||||||
fetchUserSettings,
|
fetchUserSettings,
|
||||||
fetchInboxes,
|
fetchNotifications,
|
||||||
updateInbox,
|
updateNotification,
|
||||||
deleteInbox,
|
deleteNotification,
|
||||||
fetchUserStats,
|
fetchUserStats,
|
||||||
setStatsStateId,
|
setStatsStateId,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,6 @@ export enum Activity_Type {
|
||||||
TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED",
|
TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED",
|
||||||
/** MEMO_COMMENT - Memo comment activity. */
|
/** MEMO_COMMENT - Memo comment activity. */
|
||||||
MEMO_COMMENT = "MEMO_COMMENT",
|
MEMO_COMMENT = "MEMO_COMMENT",
|
||||||
/** VERSION_UPDATE - Version update activity. */
|
|
||||||
VERSION_UPDATE = "VERSION_UPDATE",
|
|
||||||
UNRECOGNIZED = "UNRECOGNIZED",
|
UNRECOGNIZED = "UNRECOGNIZED",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,9 +50,6 @@ export function activity_TypeFromJSON(object: any): Activity_Type {
|
||||||
case 1:
|
case 1:
|
||||||
case "MEMO_COMMENT":
|
case "MEMO_COMMENT":
|
||||||
return Activity_Type.MEMO_COMMENT;
|
return Activity_Type.MEMO_COMMENT;
|
||||||
case 2:
|
|
||||||
case "VERSION_UPDATE":
|
|
||||||
return Activity_Type.VERSION_UPDATE;
|
|
||||||
case -1:
|
case -1:
|
||||||
case "UNRECOGNIZED":
|
case "UNRECOGNIZED":
|
||||||
default:
|
default:
|
||||||
|
|
@ -68,8 +63,6 @@ export function activity_TypeToNumber(object: Activity_Type): number {
|
||||||
return 0;
|
return 0;
|
||||||
case Activity_Type.MEMO_COMMENT:
|
case Activity_Type.MEMO_COMMENT:
|
||||||
return 1;
|
return 1;
|
||||||
case Activity_Type.VERSION_UPDATE:
|
|
||||||
return 2;
|
|
||||||
case Activity_Type.UNRECOGNIZED:
|
case Activity_Type.UNRECOGNIZED:
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,6 @@ export enum Inbox_Type {
|
||||||
TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED",
|
TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED",
|
||||||
/** MEMO_COMMENT - Memo comment notification. */
|
/** MEMO_COMMENT - Memo comment notification. */
|
||||||
MEMO_COMMENT = "MEMO_COMMENT",
|
MEMO_COMMENT = "MEMO_COMMENT",
|
||||||
/** VERSION_UPDATE - Version update notification. */
|
|
||||||
VERSION_UPDATE = "VERSION_UPDATE",
|
|
||||||
UNRECOGNIZED = "UNRECOGNIZED",
|
UNRECOGNIZED = "UNRECOGNIZED",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,9 +100,6 @@ export function inbox_TypeFromJSON(object: any): Inbox_Type {
|
||||||
case 1:
|
case 1:
|
||||||
case "MEMO_COMMENT":
|
case "MEMO_COMMENT":
|
||||||
return Inbox_Type.MEMO_COMMENT;
|
return Inbox_Type.MEMO_COMMENT;
|
||||||
case 2:
|
|
||||||
case "VERSION_UPDATE":
|
|
||||||
return Inbox_Type.VERSION_UPDATE;
|
|
||||||
case -1:
|
case -1:
|
||||||
case "UNRECOGNIZED":
|
case "UNRECOGNIZED":
|
||||||
default:
|
default:
|
||||||
|
|
@ -118,8 +113,6 @@ export function inbox_TypeToNumber(object: Inbox_Type): number {
|
||||||
return 0;
|
return 0;
|
||||||
case Inbox_Type.MEMO_COMMENT:
|
case Inbox_Type.MEMO_COMMENT:
|
||||||
return 1;
|
return 1;
|
||||||
case Inbox_Type.VERSION_UPDATE:
|
|
||||||
return 2;
|
|
||||||
case Inbox_Type.UNRECOGNIZED:
|
case Inbox_Type.UNRECOGNIZED:
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -579,6 +579,127 @@ export interface DeleteUserWebhookRequest {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UserNotification {
|
||||||
|
/**
|
||||||
|
* The resource name of the notification.
|
||||||
|
* Format: users/{user}/notifications/{notification}
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* The sender of the notification.
|
||||||
|
* Format: users/{user}
|
||||||
|
*/
|
||||||
|
sender: string;
|
||||||
|
/** The status of the notification. */
|
||||||
|
status: UserNotification_Status;
|
||||||
|
/** The creation timestamp. */
|
||||||
|
createTime?:
|
||||||
|
| Date
|
||||||
|
| undefined;
|
||||||
|
/** The type of the notification. */
|
||||||
|
type: UserNotification_Type;
|
||||||
|
/** The activity ID associated with this notification. */
|
||||||
|
activityId?: number | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum UserNotification_Status {
|
||||||
|
STATUS_UNSPECIFIED = "STATUS_UNSPECIFIED",
|
||||||
|
UNREAD = "UNREAD",
|
||||||
|
ARCHIVED = "ARCHIVED",
|
||||||
|
UNRECOGNIZED = "UNRECOGNIZED",
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userNotification_StatusFromJSON(object: any): UserNotification_Status {
|
||||||
|
switch (object) {
|
||||||
|
case 0:
|
||||||
|
case "STATUS_UNSPECIFIED":
|
||||||
|
return UserNotification_Status.STATUS_UNSPECIFIED;
|
||||||
|
case 1:
|
||||||
|
case "UNREAD":
|
||||||
|
return UserNotification_Status.UNREAD;
|
||||||
|
case 2:
|
||||||
|
case "ARCHIVED":
|
||||||
|
return UserNotification_Status.ARCHIVED;
|
||||||
|
case -1:
|
||||||
|
case "UNRECOGNIZED":
|
||||||
|
default:
|
||||||
|
return UserNotification_Status.UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userNotification_StatusToNumber(object: UserNotification_Status): number {
|
||||||
|
switch (object) {
|
||||||
|
case UserNotification_Status.STATUS_UNSPECIFIED:
|
||||||
|
return 0;
|
||||||
|
case UserNotification_Status.UNREAD:
|
||||||
|
return 1;
|
||||||
|
case UserNotification_Status.ARCHIVED:
|
||||||
|
return 2;
|
||||||
|
case UserNotification_Status.UNRECOGNIZED:
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum UserNotification_Type {
|
||||||
|
TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED",
|
||||||
|
MEMO_COMMENT = "MEMO_COMMENT",
|
||||||
|
UNRECOGNIZED = "UNRECOGNIZED",
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userNotification_TypeFromJSON(object: any): UserNotification_Type {
|
||||||
|
switch (object) {
|
||||||
|
case 0:
|
||||||
|
case "TYPE_UNSPECIFIED":
|
||||||
|
return UserNotification_Type.TYPE_UNSPECIFIED;
|
||||||
|
case 1:
|
||||||
|
case "MEMO_COMMENT":
|
||||||
|
return UserNotification_Type.MEMO_COMMENT;
|
||||||
|
case -1:
|
||||||
|
case "UNRECOGNIZED":
|
||||||
|
default:
|
||||||
|
return UserNotification_Type.UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userNotification_TypeToNumber(object: UserNotification_Type): number {
|
||||||
|
switch (object) {
|
||||||
|
case UserNotification_Type.TYPE_UNSPECIFIED:
|
||||||
|
return 0;
|
||||||
|
case UserNotification_Type.MEMO_COMMENT:
|
||||||
|
return 1;
|
||||||
|
case UserNotification_Type.UNRECOGNIZED:
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListUserNotificationsRequest {
|
||||||
|
/**
|
||||||
|
* The parent user resource.
|
||||||
|
* Format: users/{user}
|
||||||
|
*/
|
||||||
|
parent: string;
|
||||||
|
pageSize: number;
|
||||||
|
pageToken: string;
|
||||||
|
filter: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListUserNotificationsResponse {
|
||||||
|
notifications: UserNotification[];
|
||||||
|
nextPageToken: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateUserNotificationRequest {
|
||||||
|
notification?: UserNotification | undefined;
|
||||||
|
updateMask?: string[] | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteUserNotificationRequest {
|
||||||
|
/** Format: users/{user}/notifications/{notification} */
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
function createBaseUser(): User {
|
function createBaseUser(): User {
|
||||||
return {
|
return {
|
||||||
name: "",
|
name: "",
|
||||||
|
|
@ -3206,6 +3327,365 @@ export const DeleteUserWebhookRequest: MessageFns<DeleteUserWebhookRequest> = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function createBaseUserNotification(): UserNotification {
|
||||||
|
return {
|
||||||
|
name: "",
|
||||||
|
sender: "",
|
||||||
|
status: UserNotification_Status.STATUS_UNSPECIFIED,
|
||||||
|
createTime: undefined,
|
||||||
|
type: UserNotification_Type.TYPE_UNSPECIFIED,
|
||||||
|
activityId: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UserNotification: MessageFns<UserNotification> = {
|
||||||
|
encode(message: UserNotification, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||||
|
if (message.name !== "") {
|
||||||
|
writer.uint32(10).string(message.name);
|
||||||
|
}
|
||||||
|
if (message.sender !== "") {
|
||||||
|
writer.uint32(18).string(message.sender);
|
||||||
|
}
|
||||||
|
if (message.status !== UserNotification_Status.STATUS_UNSPECIFIED) {
|
||||||
|
writer.uint32(24).int32(userNotification_StatusToNumber(message.status));
|
||||||
|
}
|
||||||
|
if (message.createTime !== undefined) {
|
||||||
|
Timestamp.encode(toTimestamp(message.createTime), writer.uint32(34).fork()).join();
|
||||||
|
}
|
||||||
|
if (message.type !== UserNotification_Type.TYPE_UNSPECIFIED) {
|
||||||
|
writer.uint32(40).int32(userNotification_TypeToNumber(message.type));
|
||||||
|
}
|
||||||
|
if (message.activityId !== undefined) {
|
||||||
|
writer.uint32(48).int32(message.activityId);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: BinaryReader | Uint8Array, length?: number): UserNotification {
|
||||||
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseUserNotification();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1: {
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.name = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
if (tag !== 18) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.sender = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
if (tag !== 24) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.status = userNotification_StatusFromJSON(reader.int32());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
if (tag !== 34) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.createTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
|
if (tag !== 40) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.type = userNotification_TypeFromJSON(reader.int32());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 6: {
|
||||||
|
if (tag !== 48) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.activityId = reader.int32();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skip(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<UserNotification>): UserNotification {
|
||||||
|
return UserNotification.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<UserNotification>): UserNotification {
|
||||||
|
const message = createBaseUserNotification();
|
||||||
|
message.name = object.name ?? "";
|
||||||
|
message.sender = object.sender ?? "";
|
||||||
|
message.status = object.status ?? UserNotification_Status.STATUS_UNSPECIFIED;
|
||||||
|
message.createTime = object.createTime ?? undefined;
|
||||||
|
message.type = object.type ?? UserNotification_Type.TYPE_UNSPECIFIED;
|
||||||
|
message.activityId = object.activityId ?? undefined;
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseListUserNotificationsRequest(): ListUserNotificationsRequest {
|
||||||
|
return { parent: "", pageSize: 0, pageToken: "", filter: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ListUserNotificationsRequest: MessageFns<ListUserNotificationsRequest> = {
|
||||||
|
encode(message: ListUserNotificationsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||||
|
if (message.parent !== "") {
|
||||||
|
writer.uint32(10).string(message.parent);
|
||||||
|
}
|
||||||
|
if (message.pageSize !== 0) {
|
||||||
|
writer.uint32(16).int32(message.pageSize);
|
||||||
|
}
|
||||||
|
if (message.pageToken !== "") {
|
||||||
|
writer.uint32(26).string(message.pageToken);
|
||||||
|
}
|
||||||
|
if (message.filter !== "") {
|
||||||
|
writer.uint32(34).string(message.filter);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: BinaryReader | Uint8Array, length?: number): ListUserNotificationsRequest {
|
||||||
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseListUserNotificationsRequest();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1: {
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.parent = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
if (tag !== 16) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.pageSize = reader.int32();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
if (tag !== 26) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.pageToken = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
if (tag !== 34) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.filter = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skip(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<ListUserNotificationsRequest>): ListUserNotificationsRequest {
|
||||||
|
return ListUserNotificationsRequest.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<ListUserNotificationsRequest>): ListUserNotificationsRequest {
|
||||||
|
const message = createBaseListUserNotificationsRequest();
|
||||||
|
message.parent = object.parent ?? "";
|
||||||
|
message.pageSize = object.pageSize ?? 0;
|
||||||
|
message.pageToken = object.pageToken ?? "";
|
||||||
|
message.filter = object.filter ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseListUserNotificationsResponse(): ListUserNotificationsResponse {
|
||||||
|
return { notifications: [], nextPageToken: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ListUserNotificationsResponse: MessageFns<ListUserNotificationsResponse> = {
|
||||||
|
encode(message: ListUserNotificationsResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||||
|
for (const v of message.notifications) {
|
||||||
|
UserNotification.encode(v!, writer.uint32(10).fork()).join();
|
||||||
|
}
|
||||||
|
if (message.nextPageToken !== "") {
|
||||||
|
writer.uint32(18).string(message.nextPageToken);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: BinaryReader | Uint8Array, length?: number): ListUserNotificationsResponse {
|
||||||
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseListUserNotificationsResponse();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1: {
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.notifications.push(UserNotification.decode(reader, reader.uint32()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
if (tag !== 18) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.nextPageToken = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skip(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<ListUserNotificationsResponse>): ListUserNotificationsResponse {
|
||||||
|
return ListUserNotificationsResponse.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<ListUserNotificationsResponse>): ListUserNotificationsResponse {
|
||||||
|
const message = createBaseListUserNotificationsResponse();
|
||||||
|
message.notifications = object.notifications?.map((e) => UserNotification.fromPartial(e)) || [];
|
||||||
|
message.nextPageToken = object.nextPageToken ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseUpdateUserNotificationRequest(): UpdateUserNotificationRequest {
|
||||||
|
return { notification: undefined, updateMask: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UpdateUserNotificationRequest: MessageFns<UpdateUserNotificationRequest> = {
|
||||||
|
encode(message: UpdateUserNotificationRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||||
|
if (message.notification !== undefined) {
|
||||||
|
UserNotification.encode(message.notification, writer.uint32(10).fork()).join();
|
||||||
|
}
|
||||||
|
if (message.updateMask !== undefined) {
|
||||||
|
FieldMask.encode(FieldMask.wrap(message.updateMask), writer.uint32(18).fork()).join();
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: BinaryReader | Uint8Array, length?: number): UpdateUserNotificationRequest {
|
||||||
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseUpdateUserNotificationRequest();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1: {
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.notification = UserNotification.decode(reader, reader.uint32());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
if (tag !== 18) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.updateMask = FieldMask.unwrap(FieldMask.decode(reader, reader.uint32()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skip(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<UpdateUserNotificationRequest>): UpdateUserNotificationRequest {
|
||||||
|
return UpdateUserNotificationRequest.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<UpdateUserNotificationRequest>): UpdateUserNotificationRequest {
|
||||||
|
const message = createBaseUpdateUserNotificationRequest();
|
||||||
|
message.notification = (object.notification !== undefined && object.notification !== null)
|
||||||
|
? UserNotification.fromPartial(object.notification)
|
||||||
|
: undefined;
|
||||||
|
message.updateMask = object.updateMask ?? undefined;
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseDeleteUserNotificationRequest(): DeleteUserNotificationRequest {
|
||||||
|
return { name: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DeleteUserNotificationRequest: MessageFns<DeleteUserNotificationRequest> = {
|
||||||
|
encode(message: DeleteUserNotificationRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||||
|
if (message.name !== "") {
|
||||||
|
writer.uint32(10).string(message.name);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: BinaryReader | Uint8Array, length?: number): DeleteUserNotificationRequest {
|
||||||
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseDeleteUserNotificationRequest();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1: {
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.name = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skip(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<DeleteUserNotificationRequest>): DeleteUserNotificationRequest {
|
||||||
|
return DeleteUserNotificationRequest.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<DeleteUserNotificationRequest>): DeleteUserNotificationRequest {
|
||||||
|
const message = createBaseDeleteUserNotificationRequest();
|
||||||
|
message.name = object.name ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export type UserServiceDefinition = typeof UserServiceDefinition;
|
export type UserServiceDefinition = typeof UserServiceDefinition;
|
||||||
export const UserServiceDefinition = {
|
export const UserServiceDefinition = {
|
||||||
name: "UserService",
|
name: "UserService",
|
||||||
|
|
@ -4317,6 +4797,235 @@ export const UserServiceDefinition = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
/** ListUserNotifications lists notifications for a user. */
|
||||||
|
listUserNotifications: {
|
||||||
|
name: "ListUserNotifications",
|
||||||
|
requestType: ListUserNotificationsRequest,
|
||||||
|
requestStream: false,
|
||||||
|
responseType: ListUserNotificationsResponse,
|
||||||
|
responseStream: false,
|
||||||
|
options: {
|
||||||
|
_unknownFields: {
|
||||||
|
8410: [new Uint8Array([6, 112, 97, 114, 101, 110, 116])],
|
||||||
|
578365826: [
|
||||||
|
new Uint8Array([
|
||||||
|
40,
|
||||||
|
18,
|
||||||
|
38,
|
||||||
|
47,
|
||||||
|
97,
|
||||||
|
112,
|
||||||
|
105,
|
||||||
|
47,
|
||||||
|
118,
|
||||||
|
49,
|
||||||
|
47,
|
||||||
|
123,
|
||||||
|
112,
|
||||||
|
97,
|
||||||
|
114,
|
||||||
|
101,
|
||||||
|
110,
|
||||||
|
116,
|
||||||
|
61,
|
||||||
|
117,
|
||||||
|
115,
|
||||||
|
101,
|
||||||
|
114,
|
||||||
|
115,
|
||||||
|
47,
|
||||||
|
42,
|
||||||
|
125,
|
||||||
|
47,
|
||||||
|
110,
|
||||||
|
111,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
102,
|
||||||
|
105,
|
||||||
|
99,
|
||||||
|
97,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
111,
|
||||||
|
110,
|
||||||
|
115,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/** UpdateUserNotification updates a notification. */
|
||||||
|
updateUserNotification: {
|
||||||
|
name: "UpdateUserNotification",
|
||||||
|
requestType: UpdateUserNotificationRequest,
|
||||||
|
requestStream: false,
|
||||||
|
responseType: UserNotification,
|
||||||
|
responseStream: false,
|
||||||
|
options: {
|
||||||
|
_unknownFields: {
|
||||||
|
8410: [
|
||||||
|
new Uint8Array([
|
||||||
|
24,
|
||||||
|
110,
|
||||||
|
111,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
102,
|
||||||
|
105,
|
||||||
|
99,
|
||||||
|
97,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
111,
|
||||||
|
110,
|
||||||
|
44,
|
||||||
|
117,
|
||||||
|
112,
|
||||||
|
100,
|
||||||
|
97,
|
||||||
|
116,
|
||||||
|
101,
|
||||||
|
95,
|
||||||
|
109,
|
||||||
|
97,
|
||||||
|
115,
|
||||||
|
107,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
578365826: [
|
||||||
|
new Uint8Array([
|
||||||
|
67,
|
||||||
|
58,
|
||||||
|
12,
|
||||||
|
110,
|
||||||
|
111,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
102,
|
||||||
|
105,
|
||||||
|
99,
|
||||||
|
97,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
111,
|
||||||
|
110,
|
||||||
|
50,
|
||||||
|
51,
|
||||||
|
47,
|
||||||
|
97,
|
||||||
|
112,
|
||||||
|
105,
|
||||||
|
47,
|
||||||
|
118,
|
||||||
|
49,
|
||||||
|
47,
|
||||||
|
123,
|
||||||
|
110,
|
||||||
|
111,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
102,
|
||||||
|
105,
|
||||||
|
99,
|
||||||
|
97,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
111,
|
||||||
|
110,
|
||||||
|
46,
|
||||||
|
110,
|
||||||
|
97,
|
||||||
|
109,
|
||||||
|
101,
|
||||||
|
61,
|
||||||
|
117,
|
||||||
|
115,
|
||||||
|
101,
|
||||||
|
114,
|
||||||
|
115,
|
||||||
|
47,
|
||||||
|
42,
|
||||||
|
47,
|
||||||
|
110,
|
||||||
|
111,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
102,
|
||||||
|
105,
|
||||||
|
99,
|
||||||
|
97,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
111,
|
||||||
|
110,
|
||||||
|
115,
|
||||||
|
47,
|
||||||
|
42,
|
||||||
|
125,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/** DeleteUserNotification deletes a notification. */
|
||||||
|
deleteUserNotification: {
|
||||||
|
name: "DeleteUserNotification",
|
||||||
|
requestType: DeleteUserNotificationRequest,
|
||||||
|
requestStream: false,
|
||||||
|
responseType: Empty,
|
||||||
|
responseStream: false,
|
||||||
|
options: {
|
||||||
|
_unknownFields: {
|
||||||
|
8410: [new Uint8Array([4, 110, 97, 109, 101])],
|
||||||
|
578365826: [
|
||||||
|
new Uint8Array([
|
||||||
|
40,
|
||||||
|
42,
|
||||||
|
38,
|
||||||
|
47,
|
||||||
|
97,
|
||||||
|
112,
|
||||||
|
105,
|
||||||
|
47,
|
||||||
|
118,
|
||||||
|
49,
|
||||||
|
47,
|
||||||
|
123,
|
||||||
|
110,
|
||||||
|
97,
|
||||||
|
109,
|
||||||
|
101,
|
||||||
|
61,
|
||||||
|
117,
|
||||||
|
115,
|
||||||
|
101,
|
||||||
|
114,
|
||||||
|
115,
|
||||||
|
47,
|
||||||
|
42,
|
||||||
|
47,
|
||||||
|
110,
|
||||||
|
111,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
102,
|
||||||
|
105,
|
||||||
|
99,
|
||||||
|
97,
|
||||||
|
116,
|
||||||
|
105,
|
||||||
|
111,
|
||||||
|
110,
|
||||||
|
115,
|
||||||
|
47,
|
||||||
|
42,
|
||||||
|
125,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue