Commit d6a75bba authored by johnnyjoy's avatar johnnyjoy

refactor: webhook service

parent 03399a60
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"google.golang.org/protobuf/encoding/protojson"
v1pb "github.com/usememos/memos/proto/gen/api/v1" v1pb "github.com/usememos/memos/proto/gen/api/v1"
) )
...@@ -19,9 +18,20 @@ var ( ...@@ -19,9 +18,20 @@ var (
timeout = 30 * time.Second timeout = 30 * time.Second
) )
type WebhookRequestPayload struct {
// The target URL for the webhook request.
Url string `json:"url"`
// The type of activity that triggered this webhook.
ActivityType string `json:"activityType"`
// The resource name of the creator. Format: users/{user}
Creator string `json:"creator"`
// The memo that triggered this webhook (if applicable).
Memo *v1pb.Memo `json:"memo"`
}
// Post posts the message to webhook endpoint. // Post posts the message to webhook endpoint.
func Post(requestPayload *v1pb.WebhookRequestPayload) error { func Post(requestPayload *WebhookRequestPayload) error {
body, err := protojson.Marshal(requestPayload) body, err := json.Marshal(requestPayload)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to marshal webhook request to %s", requestPayload.Url) return errors.Wrapf(err, "failed to marshal webhook request to %s", requestPayload.Url)
} }
...@@ -67,7 +77,7 @@ func Post(requestPayload *v1pb.WebhookRequestPayload) error { ...@@ -67,7 +77,7 @@ func Post(requestPayload *v1pb.WebhookRequestPayload) error {
// PostAsync posts the message to webhook endpoint asynchronously. // PostAsync posts the message to webhook endpoint asynchronously.
// It spawns a new goroutine to handle the request and does not wait for the response. // It spawns a new goroutine to handle the request and does not wait for the response.
func PostAsync(requestPayload *v1pb.WebhookRequestPayload) { func PostAsync(requestPayload *WebhookRequestPayload) {
go func() { go func() {
if err := Post(requestPayload); err != nil { if err := Post(requestPayload); err != nil {
// Since we're in a goroutine, we can only log the error // Since we're in a goroutine, we can only log the error
......
...@@ -2,7 +2,6 @@ syntax = "proto3"; ...@@ -2,7 +2,6 @@ syntax = "proto3";
package memos.api.v1; package memos.api.v1;
import "api/v1/common.proto";
import "api/v1/memo_service.proto"; import "api/v1/memo_service.proto";
import "google/api/annotations.proto"; import "google/api/annotations.proto";
import "google/api/client.proto"; import "google/api/client.proto";
...@@ -10,43 +9,43 @@ import "google/api/field_behavior.proto"; ...@@ -10,43 +9,43 @@ import "google/api/field_behavior.proto";
import "google/api/resource.proto"; import "google/api/resource.proto";
import "google/protobuf/empty.proto"; import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto"; import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
option go_package = "gen/api/v1"; option go_package = "gen/api/v1";
service WebhookService { service WebhookService {
// ListWebhooks returns a list of webhooks. // ListWebhooks returns a list of webhooks for a user.
rpc ListWebhooks(ListWebhooksRequest) returns (ListWebhooksResponse) { rpc ListWebhooks(ListWebhooksRequest) returns (ListWebhooksResponse) {
option (google.api.http) = {get: "/api/v1/webhooks"}; option (google.api.http) = {get: "/api/v1/{parent=users/*}/webhooks"};
option (google.api.method_signature) = "parent";
} }
// GetWebhook gets a webhook by name. // GetWebhook gets a webhook by name.
rpc GetWebhook(GetWebhookRequest) returns (Webhook) { rpc GetWebhook(GetWebhookRequest) returns (Webhook) {
option (google.api.http) = {get: "/api/v1/{name=webhooks/*}"}; option (google.api.http) = {get: "/api/v1/{name=users/*/webhooks/*}"};
option (google.api.method_signature) = "name"; option (google.api.method_signature) = "name";
} }
// CreateWebhook creates a new webhook. // CreateWebhook creates a new webhook for a user.
rpc CreateWebhook(CreateWebhookRequest) returns (Webhook) { rpc CreateWebhook(CreateWebhookRequest) returns (Webhook) {
option (google.api.http) = { option (google.api.http) = {
post: "/api/v1/webhooks" post: "/api/v1/{parent=users/*}/webhooks"
body: "webhook" body: "webhook"
}; };
option (google.api.method_signature) = "webhook"; option (google.api.method_signature) = "parent,webhook";
} }
// UpdateWebhook updates a webhook. // UpdateWebhook updates a webhook for a user.
rpc UpdateWebhook(UpdateWebhookRequest) returns (Webhook) { rpc UpdateWebhook(UpdateWebhookRequest) returns (Webhook) {
option (google.api.http) = { option (google.api.http) = {
patch: "/api/v1/{webhook.name=webhooks/*}" patch: "/api/v1/{webhook.name=users/*/webhooks/*}"
body: "webhook" body: "webhook"
}; };
option (google.api.method_signature) = "webhook,update_mask"; option (google.api.method_signature) = "webhook,update_mask";
} }
// DeleteWebhook deletes a webhook. // DeleteWebhook deletes a webhook for a user.
rpc DeleteWebhook(DeleteWebhookRequest) returns (google.protobuf.Empty) { rpc DeleteWebhook(DeleteWebhookRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=webhooks/*}"}; option (google.api.http) = {delete: "/api/v1/{name=users/*/webhooks/*}"};
option (google.api.method_signature) = "name"; option (google.api.method_signature) = "name";
} }
} }
...@@ -54,46 +53,39 @@ service WebhookService { ...@@ -54,46 +53,39 @@ service WebhookService {
message Webhook { message Webhook {
option (google.api.resource) = { option (google.api.resource) = {
type: "memos.api.v1/Webhook" type: "memos.api.v1/Webhook"
pattern: "webhooks/{webhook}" pattern: "users/{user}/webhooks/{webhook}"
name_field: "name"
singular: "webhook" singular: "webhook"
plural: "webhooks" plural: "webhooks"
}; };
// The resource name of the webhook. // The resource name of the webhook.
// Format: webhooks/{webhook} // Format: users/{user}/webhooks/{webhook}
string name = 1 [(google.api.field_behavior) = IDENTIFIER]; string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// Required. The display name of the webhook. // The display name of the webhook.
string display_name = 2 [(google.api.field_behavior) = REQUIRED]; string display_name = 2 [(google.api.field_behavior) = REQUIRED];
// Required. The target URL for the webhook. // The target URL for the webhook.
string url = 3 [(google.api.field_behavior) = REQUIRED]; string url = 3 [(google.api.field_behavior) = REQUIRED];
}
// Output only. The resource name of the creator. message ListWebhooksRequest {
// Required. The parent resource where webhooks are listed.
// Format: users/{user} // Format: users/{user}
string creator = 4 [(google.api.field_behavior) = OUTPUT_ONLY]; string parent = 1 [
(google.api.field_behavior) = REQUIRED,
// The state of the webhook. (google.api.resource_reference) = {child_type: "memos.api.v1/Webhook"}
State state = 5 [(google.api.field_behavior) = REQUIRED]; ];
// Output only. The creation timestamp.
google.protobuf.Timestamp create_time = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The last update timestamp.
google.protobuf.Timestamp update_time = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
} }
message ListWebhooksRequest {}
message ListWebhooksResponse { message ListWebhooksResponse {
// The list of webhooks. // The list of webhooks.
repeated Webhook webhooks = 1; repeated Webhook webhooks = 1;
} }
message GetWebhookRequest { message GetWebhookRequest {
// Required. The resource name of the webhook. // Required. The resource name of the webhook to retrieve.
// Format: webhooks/{webhook} // Format: users/{user}/webhooks/{webhook}
string name = 1 [ string name = 1 [
(google.api.field_behavior) = REQUIRED, (google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Webhook"} (google.api.resource_reference) = {type: "memos.api.v1/Webhook"}
...@@ -101,55 +93,33 @@ message GetWebhookRequest { ...@@ -101,55 +93,33 @@ message GetWebhookRequest {
} }
message CreateWebhookRequest { message CreateWebhookRequest {
// Required. The webhook to create. // Required. The parent resource where this webhook will be created.
Webhook webhook = 1 [ // Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED, (google.api.field_behavior) = REQUIRED,
(google.api.field_behavior) = INPUT_ONLY (google.api.resource_reference) = {child_type: "memos.api.v1/Webhook"}
]; ];
// Optional. The webhook ID to use for this webhook. // Required. The webhook to create.
// If empty, a unique ID will be generated. Webhook webhook = 2 [(google.api.field_behavior) = REQUIRED];
// Must match the pattern [a-z0-9-]+
string webhook_id = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. If set, validate the request but don't actually create the webhook. // Optional. If set, validate the request, but do not actually create the webhook.
bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL]; bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
} }
message UpdateWebhookRequest { message UpdateWebhookRequest {
// Required. The webhook to update. // Required. The webhook resource which replaces the resource on the server.
Webhook webhook = 1 [(google.api.field_behavior) = REQUIRED]; Webhook webhook = 1 [(google.api.field_behavior) = REQUIRED];
// Required. The list of fields to update. // Optional. The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED]; google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = OPTIONAL];
} }
message DeleteWebhookRequest { message DeleteWebhookRequest {
// Required. The resource name of the webhook to delete. // Required. The resource name of the webhook to delete.
// Format: webhooks/{webhook} // Format: users/{user}/webhooks/{webhook}
string name = 1 [ string name = 1 [
(google.api.field_behavior) = REQUIRED, (google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Webhook"} (google.api.resource_reference) = {type: "memos.api.v1/Webhook"}
]; ];
} }
message WebhookRequestPayload {
// The target URL for the webhook request.
string url = 1 [(google.api.field_behavior) = REQUIRED];
// The type of activity that triggered this webhook.
string activity_type = 2 [(google.api.field_behavior) = REQUIRED];
// The resource name of the creator.
// Format: users/{user}
string creator = 3 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// The creation timestamp of the activity.
google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
// The memo that triggered this webhook (if applicable).
Memo memo = 5 [(google.api.field_behavior) = OPTIONAL];
}
...@@ -12,7 +12,6 @@ import ( ...@@ -12,7 +12,6 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb" emptypb "google.golang.org/protobuf/types/known/emptypb"
fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect" reflect "reflect"
sync "sync" sync "sync"
unsafe "unsafe" unsafe "unsafe"
...@@ -28,21 +27,12 @@ const ( ...@@ -28,21 +27,12 @@ const (
type Webhook struct { type Webhook struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// The resource name of the webhook. // The resource name of the webhook.
// Format: webhooks/{webhook} // Format: users/{user}/webhooks/{webhook}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// Required. The display name of the webhook. // The display name of the webhook.
DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"`
// Required. The target URL for the webhook. // The target URL for the webhook.
Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"` Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"`
// Output only. The resource name of the creator.
// Format: users/{user}
Creator string `protobuf:"bytes,4,opt,name=creator,proto3" json:"creator,omitempty"`
// The state of the webhook.
State State `protobuf:"varint,5,opt,name=state,proto3,enum=memos.api.v1.State" json:"state,omitempty"`
// Output only. The creation timestamp.
CreateTime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
// Output only. The last update timestamp.
UpdateTime *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
...@@ -98,36 +88,11 @@ func (x *Webhook) GetUrl() string { ...@@ -98,36 +88,11 @@ func (x *Webhook) GetUrl() string {
return "" return ""
} }
func (x *Webhook) GetCreator() string {
if x != nil {
return x.Creator
}
return ""
}
func (x *Webhook) GetState() State {
if x != nil {
return x.State
}
return State_STATE_UNSPECIFIED
}
func (x *Webhook) GetCreateTime() *timestamppb.Timestamp {
if x != nil {
return x.CreateTime
}
return nil
}
func (x *Webhook) GetUpdateTime() *timestamppb.Timestamp {
if x != nil {
return x.UpdateTime
}
return nil
}
type ListWebhooksRequest struct { type ListWebhooksRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// Required. The parent resource where webhooks are listed.
// Format: users/{user}
Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
...@@ -162,6 +127,13 @@ func (*ListWebhooksRequest) Descriptor() ([]byte, []int) { ...@@ -162,6 +127,13 @@ func (*ListWebhooksRequest) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{1} return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{1}
} }
func (x *ListWebhooksRequest) GetParent() string {
if x != nil {
return x.Parent
}
return ""
}
type ListWebhooksResponse struct { type ListWebhooksResponse struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// The list of webhooks. // The list of webhooks.
...@@ -209,8 +181,8 @@ func (x *ListWebhooksResponse) GetWebhooks() []*Webhook { ...@@ -209,8 +181,8 @@ func (x *ListWebhooksResponse) GetWebhooks() []*Webhook {
type GetWebhookRequest struct { type GetWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// Required. The resource name of the webhook. // Required. The resource name of the webhook to retrieve.
// Format: webhooks/{webhook} // Format: users/{user}/webhooks/{webhook}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
...@@ -255,13 +227,12 @@ func (x *GetWebhookRequest) GetName() string { ...@@ -255,13 +227,12 @@ func (x *GetWebhookRequest) GetName() string {
type CreateWebhookRequest struct { type CreateWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// Required. The parent resource where this webhook will be created.
// Format: users/{user}
Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"`
// Required. The webhook to create. // Required. The webhook to create.
Webhook *Webhook `protobuf:"bytes,1,opt,name=webhook,proto3" json:"webhook,omitempty"` Webhook *Webhook `protobuf:"bytes,2,opt,name=webhook,proto3" json:"webhook,omitempty"`
// Optional. The webhook ID to use for this webhook. // Optional. If set, validate the request, but do not actually create the webhook.
// If empty, a unique ID will be generated.
// Must match the pattern [a-z0-9-]+
WebhookId string `protobuf:"bytes,2,opt,name=webhook_id,json=webhookId,proto3" json:"webhook_id,omitempty"`
// Optional. If set, validate the request but don't actually create the webhook.
ValidateOnly bool `protobuf:"varint,3,opt,name=validate_only,json=validateOnly,proto3" json:"validate_only,omitempty"` ValidateOnly bool `protobuf:"varint,3,opt,name=validate_only,json=validateOnly,proto3" json:"validate_only,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
...@@ -297,18 +268,18 @@ func (*CreateWebhookRequest) Descriptor() ([]byte, []int) { ...@@ -297,18 +268,18 @@ func (*CreateWebhookRequest) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{4} return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{4}
} }
func (x *CreateWebhookRequest) GetWebhook() *Webhook { func (x *CreateWebhookRequest) GetParent() string {
if x != nil { if x != nil {
return x.Webhook return x.Parent
} }
return nil return ""
} }
func (x *CreateWebhookRequest) GetWebhookId() string { func (x *CreateWebhookRequest) GetWebhook() *Webhook {
if x != nil { if x != nil {
return x.WebhookId return x.Webhook
} }
return "" return nil
} }
func (x *CreateWebhookRequest) GetValidateOnly() bool { func (x *CreateWebhookRequest) GetValidateOnly() bool {
...@@ -320,9 +291,9 @@ func (x *CreateWebhookRequest) GetValidateOnly() bool { ...@@ -320,9 +291,9 @@ func (x *CreateWebhookRequest) GetValidateOnly() bool {
type UpdateWebhookRequest struct { type UpdateWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// Required. The webhook to update. // Required. The webhook resource which replaces the resource on the server.
Webhook *Webhook `protobuf:"bytes,1,opt,name=webhook,proto3" json:"webhook,omitempty"` Webhook *Webhook `protobuf:"bytes,1,opt,name=webhook,proto3" json:"webhook,omitempty"`
// Required. The list of fields to update. // Optional. The list of fields to update.
UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
...@@ -375,7 +346,7 @@ func (x *UpdateWebhookRequest) GetUpdateMask() *fieldmaskpb.FieldMask { ...@@ -375,7 +346,7 @@ func (x *UpdateWebhookRequest) GetUpdateMask() *fieldmaskpb.FieldMask {
type DeleteWebhookRequest struct { type DeleteWebhookRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// Required. The resource name of the webhook to delete. // Required. The resource name of the webhook to delete.
// Format: webhooks/{webhook} // Format: users/{user}/webhooks/{webhook}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
...@@ -418,137 +389,41 @@ func (x *DeleteWebhookRequest) GetName() string { ...@@ -418,137 +389,41 @@ func (x *DeleteWebhookRequest) GetName() string {
return "" return ""
} }
type WebhookRequestPayload struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The target URL for the webhook request.
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
// The type of activity that triggered this webhook.
ActivityType string `protobuf:"bytes,2,opt,name=activity_type,json=activityType,proto3" json:"activity_type,omitempty"`
// The resource name of the creator.
// Format: users/{user}
Creator string `protobuf:"bytes,3,opt,name=creator,proto3" json:"creator,omitempty"`
// The creation timestamp of the activity.
CreateTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
// The memo that triggered this webhook (if applicable).
Memo *Memo `protobuf:"bytes,5,opt,name=memo,proto3" json:"memo,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *WebhookRequestPayload) Reset() {
*x = WebhookRequestPayload{}
mi := &file_api_v1_webhook_service_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WebhookRequestPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WebhookRequestPayload) ProtoMessage() {}
func (x *WebhookRequestPayload) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_webhook_service_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WebhookRequestPayload.ProtoReflect.Descriptor instead.
func (*WebhookRequestPayload) Descriptor() ([]byte, []int) {
return file_api_v1_webhook_service_proto_rawDescGZIP(), []int{7}
}
func (x *WebhookRequestPayload) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
func (x *WebhookRequestPayload) GetActivityType() string {
if x != nil {
return x.ActivityType
}
return ""
}
func (x *WebhookRequestPayload) GetCreator() string {
if x != nil {
return x.Creator
}
return ""
}
func (x *WebhookRequestPayload) GetCreateTime() *timestamppb.Timestamp {
if x != nil {
return x.CreateTime
}
return nil
}
func (x *WebhookRequestPayload) GetMemo() *Memo {
if x != nil {
return x.Memo
}
return nil
}
var File_api_v1_webhook_service_proto protoreflect.FileDescriptor var File_api_v1_webhook_service_proto protoreflect.FileDescriptor
const file_api_v1_webhook_service_proto_rawDesc = "" + const file_api_v1_webhook_service_proto_rawDesc = "" +
"\n" + "\n" +
"\x1capi/v1/webhook_service.proto\x12\fmemos.api.v1\x1a\x13api/v1/common.proto\x1a\x19api/v1/memo_service.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xfc\x02\n" + "\x1capi/v1/webhook_service.proto\x12\fmemos.api.v1\x1a\x19api/v1/memo_service.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\"\xb0\x01\n" +
"\aWebhook\x12\x17\n" + "\aWebhook\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12&\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12&\n" +
"\fdisplay_name\x18\x02 \x01(\tB\x03\xe0A\x02R\vdisplayName\x12\x15\n" + "\fdisplay_name\x18\x02 \x01(\tB\x03\xe0A\x02R\vdisplayName\x12\x15\n" +
"\x03url\x18\x03 \x01(\tB\x03\xe0A\x02R\x03url\x12\x1d\n" + "\x03url\x18\x03 \x01(\tB\x03\xe0A\x02R\x03url:M\xeaAJ\n" +
"\acreator\x18\x04 \x01(\tB\x03\xe0A\x03R\acreator\x12.\n" + "\x14memos.api.v1/Webhook\x12\x1fusers/{user}/webhooks/{webhook}*\bwebhooks2\awebhook\"K\n" +
"\x05state\x18\x05 \x01(\x0e2\x13.memos.api.v1.StateB\x03\xe0A\x02R\x05state\x12@\n" + "\x13ListWebhooksRequest\x124\n" +
"\vcreate_time\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" + "\x06parent\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\x12\x14memos.api.v1/WebhookR\x06parent\"I\n" +
"createTime\x12@\n" +
"\vupdate_time\x18\a \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
"updateTime:F\xeaAC\n" +
"\x14memos.api.v1/Webhook\x12\x12webhooks/{webhook}\x1a\x04name*\bwebhooks2\awebhook\"\x15\n" +
"\x13ListWebhooksRequest\"I\n" +
"\x14ListWebhooksResponse\x121\n" + "\x14ListWebhooksResponse\x121\n" +
"\bwebhooks\x18\x01 \x03(\v2\x15.memos.api.v1.WebhookR\bwebhooks\"E\n" + "\bwebhooks\x18\x01 \x03(\v2\x15.memos.api.v1.WebhookR\bwebhooks\"E\n" +
"\x11GetWebhookRequest\x120\n" + "\x11GetWebhookRequest\x120\n" +
"\x04name\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\n" + "\x04name\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\n" +
"\x14memos.api.v1/WebhookR\x04name\"\x9d\x01\n" + "\x14memos.api.v1/WebhookR\x04name\"\xac\x01\n" +
"\x14CreateWebhookRequest\x127\n" + "\x14CreateWebhookRequest\x124\n" +
"\awebhook\x18\x01 \x01(\v2\x15.memos.api.v1.WebhookB\x06\xe0A\x02\xe0A\x04R\awebhook\x12\"\n" + "\x06parent\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\x12\x14memos.api.v1/WebhookR\x06parent\x124\n" +
"\n" + "\awebhook\x18\x02 \x01(\v2\x15.memos.api.v1.WebhookB\x03\xe0A\x02R\awebhook\x12(\n" +
"webhook_id\x18\x02 \x01(\tB\x03\xe0A\x01R\twebhookId\x12(\n" +
"\rvalidate_only\x18\x03 \x01(\bB\x03\xe0A\x01R\fvalidateOnly\"\x8e\x01\n" + "\rvalidate_only\x18\x03 \x01(\bB\x03\xe0A\x01R\fvalidateOnly\"\x8e\x01\n" +
"\x14UpdateWebhookRequest\x124\n" + "\x14UpdateWebhookRequest\x124\n" +
"\awebhook\x18\x01 \x01(\v2\x15.memos.api.v1.WebhookB\x03\xe0A\x02R\awebhook\x12@\n" + "\awebhook\x18\x01 \x01(\v2\x15.memos.api.v1.WebhookB\x03\xe0A\x02R\awebhook\x12@\n" +
"\vupdate_mask\x18\x02 \x01(\v2\x1a.google.protobuf.FieldMaskB\x03\xe0A\x02R\n" + "\vupdate_mask\x18\x02 \x01(\v2\x1a.google.protobuf.FieldMaskB\x03\xe0A\x01R\n" +
"updateMask\"H\n" + "updateMask\"H\n" +
"\x14DeleteWebhookRequest\x120\n" + "\x14DeleteWebhookRequest\x120\n" +
"\x04name\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\n" + "\x04name\x18\x01 \x01(\tB\x1c\xe0A\x02\xfaA\x16\n" +
"\x14memos.api.v1/WebhookR\x04name\"\xfc\x01\n" + "\x14memos.api.v1/WebhookR\x04name2\xc4\x05\n" +
"\x15WebhookRequestPayload\x12\x15\n" + "\x0eWebhookService\x12\x89\x01\n" +
"\x03url\x18\x01 \x01(\tB\x03\xe0A\x02R\x03url\x12(\n" + "\fListWebhooks\x12!.memos.api.v1.ListWebhooksRequest\x1a\".memos.api.v1.ListWebhooksResponse\"2\xdaA\x06parent\x82\xd3\xe4\x93\x02#\x12!/api/v1/{parent=users/*}/webhooks\x12v\n" +
"\ractivity_type\x18\x02 \x01(\tB\x03\xe0A\x02R\factivityType\x123\n" +
"\acreator\x18\x03 \x01(\tB\x19\xe0A\x03\xfaA\x13\n" +
"\x11memos.api.v1/UserR\acreator\x12@\n" +
"\vcreate_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
"createTime\x12+\n" +
"\x04memo\x18\x05 \x01(\v2\x12.memos.api.v1.MemoB\x03\xe0A\x01R\x04memo2\xf8\x04\n" +
"\x0eWebhookService\x12o\n" +
"\fListWebhooks\x12!.memos.api.v1.ListWebhooksRequest\x1a\".memos.api.v1.ListWebhooksResponse\"\x18\x82\xd3\xe4\x93\x02\x12\x12\x10/api/v1/webhooks\x12n\n" +
"\n" + "\n" +
"GetWebhook\x12\x1f.memos.api.v1.GetWebhookRequest\x1a\x15.memos.api.v1.Webhook\"(\xdaA\x04name\x82\xd3\xe4\x93\x02\x1b\x12\x19/api/v1/{name=webhooks/*}\x12w\n" + "GetWebhook\x12\x1f.memos.api.v1.GetWebhookRequest\x1a\x15.memos.api.v1.Webhook\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#\x12!/api/v1/{name=users/*/webhooks/*}\x12\x8f\x01\n" +
"\rCreateWebhook\x12\".memos.api.v1.CreateWebhookRequest\x1a\x15.memos.api.v1.Webhook\"+\xdaA\awebhook\x82\xd3\xe4\x93\x02\x1b:\awebhook\"\x10/api/v1/webhooks\x12\x94\x01\n" + "\rCreateWebhook\x12\".memos.api.v1.CreateWebhookRequest\x1a\x15.memos.api.v1.Webhook\"C\xdaA\x0eparent,webhook\x82\xd3\xe4\x93\x02,:\awebhook\"!/api/v1/{parent=users/*}/webhooks\x12\x9c\x01\n" +
"\rUpdateWebhook\x12\".memos.api.v1.UpdateWebhookRequest\x1a\x15.memos.api.v1.Webhook\"H\xdaA\x13webhook,update_mask\x82\xd3\xe4\x93\x02,:\awebhook2!/api/v1/{webhook.name=webhooks/*}\x12u\n" + "\rUpdateWebhook\x12\".memos.api.v1.UpdateWebhookRequest\x1a\x15.memos.api.v1.Webhook\"P\xdaA\x13webhook,update_mask\x82\xd3\xe4\x93\x024:\awebhook2)/api/v1/{webhook.name=users/*/webhooks/*}\x12}\n" +
"\rDeleteWebhook\x12\".memos.api.v1.DeleteWebhookRequest\x1a\x16.google.protobuf.Empty\"(\xdaA\x04name\x82\xd3\xe4\x93\x02\x1b*\x19/api/v1/{name=webhooks/*}B\xab\x01\n" + "\rDeleteWebhook\x12\".memos.api.v1.DeleteWebhookRequest\x1a\x16.google.protobuf.Empty\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#*!/api/v1/{name=users/*/webhooks/*}B\xab\x01\n" +
"\x10com.memos.api.v1B\x13WebhookServiceProtoP\x01Z0github.com/usememos/memos/proto/gen/api/v1;apiv1\xa2\x02\x03MAX\xaa\x02\fMemos.Api.V1\xca\x02\fMemos\\Api\\V1\xe2\x02\x18Memos\\Api\\V1\\GPBMetadata\xea\x02\x0eMemos::Api::V1b\x06proto3" "\x10com.memos.api.v1B\x13WebhookServiceProtoP\x01Z0github.com/usememos/memos/proto/gen/api/v1;apiv1\xa2\x02\x03MAX\xaa\x02\fMemos.Api.V1\xca\x02\fMemos\\Api\\V1\xe2\x02\x18Memos\\Api\\V1\\GPBMetadata\xea\x02\x0eMemos::Api::V1b\x06proto3"
var ( var (
...@@ -563,7 +438,7 @@ func file_api_v1_webhook_service_proto_rawDescGZIP() []byte { ...@@ -563,7 +438,7 @@ func file_api_v1_webhook_service_proto_rawDescGZIP() []byte {
return file_api_v1_webhook_service_proto_rawDescData return file_api_v1_webhook_service_proto_rawDescData
} }
var file_api_v1_webhook_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_api_v1_webhook_service_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_api_v1_webhook_service_proto_goTypes = []any{ var file_api_v1_webhook_service_proto_goTypes = []any{
(*Webhook)(nil), // 0: memos.api.v1.Webhook (*Webhook)(nil), // 0: memos.api.v1.Webhook
(*ListWebhooksRequest)(nil), // 1: memos.api.v1.ListWebhooksRequest (*ListWebhooksRequest)(nil), // 1: memos.api.v1.ListWebhooksRequest
...@@ -572,38 +447,29 @@ var file_api_v1_webhook_service_proto_goTypes = []any{ ...@@ -572,38 +447,29 @@ var file_api_v1_webhook_service_proto_goTypes = []any{
(*CreateWebhookRequest)(nil), // 4: memos.api.v1.CreateWebhookRequest (*CreateWebhookRequest)(nil), // 4: memos.api.v1.CreateWebhookRequest
(*UpdateWebhookRequest)(nil), // 5: memos.api.v1.UpdateWebhookRequest (*UpdateWebhookRequest)(nil), // 5: memos.api.v1.UpdateWebhookRequest
(*DeleteWebhookRequest)(nil), // 6: memos.api.v1.DeleteWebhookRequest (*DeleteWebhookRequest)(nil), // 6: memos.api.v1.DeleteWebhookRequest
(*WebhookRequestPayload)(nil), // 7: memos.api.v1.WebhookRequestPayload (*fieldmaskpb.FieldMask)(nil), // 7: google.protobuf.FieldMask
(State)(0), // 8: memos.api.v1.State (*emptypb.Empty)(nil), // 8: google.protobuf.Empty
(*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp
(*fieldmaskpb.FieldMask)(nil), // 10: google.protobuf.FieldMask
(*Memo)(nil), // 11: memos.api.v1.Memo
(*emptypb.Empty)(nil), // 12: google.protobuf.Empty
} }
var file_api_v1_webhook_service_proto_depIdxs = []int32{ var file_api_v1_webhook_service_proto_depIdxs = []int32{
8, // 0: memos.api.v1.Webhook.state:type_name -> memos.api.v1.State 0, // 0: memos.api.v1.ListWebhooksResponse.webhooks:type_name -> memos.api.v1.Webhook
9, // 1: memos.api.v1.Webhook.create_time:type_name -> google.protobuf.Timestamp 0, // 1: memos.api.v1.CreateWebhookRequest.webhook:type_name -> memos.api.v1.Webhook
9, // 2: memos.api.v1.Webhook.update_time:type_name -> google.protobuf.Timestamp 0, // 2: memos.api.v1.UpdateWebhookRequest.webhook:type_name -> memos.api.v1.Webhook
0, // 3: memos.api.v1.ListWebhooksResponse.webhooks:type_name -> memos.api.v1.Webhook 7, // 3: memos.api.v1.UpdateWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask
0, // 4: memos.api.v1.CreateWebhookRequest.webhook:type_name -> memos.api.v1.Webhook 1, // 4: memos.api.v1.WebhookService.ListWebhooks:input_type -> memos.api.v1.ListWebhooksRequest
0, // 5: memos.api.v1.UpdateWebhookRequest.webhook:type_name -> memos.api.v1.Webhook 3, // 5: memos.api.v1.WebhookService.GetWebhook:input_type -> memos.api.v1.GetWebhookRequest
10, // 6: memos.api.v1.UpdateWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask 4, // 6: memos.api.v1.WebhookService.CreateWebhook:input_type -> memos.api.v1.CreateWebhookRequest
9, // 7: memos.api.v1.WebhookRequestPayload.create_time:type_name -> google.protobuf.Timestamp 5, // 7: memos.api.v1.WebhookService.UpdateWebhook:input_type -> memos.api.v1.UpdateWebhookRequest
11, // 8: memos.api.v1.WebhookRequestPayload.memo:type_name -> memos.api.v1.Memo 6, // 8: memos.api.v1.WebhookService.DeleteWebhook:input_type -> memos.api.v1.DeleteWebhookRequest
1, // 9: memos.api.v1.WebhookService.ListWebhooks:input_type -> memos.api.v1.ListWebhooksRequest 2, // 9: memos.api.v1.WebhookService.ListWebhooks:output_type -> memos.api.v1.ListWebhooksResponse
3, // 10: memos.api.v1.WebhookService.GetWebhook:input_type -> memos.api.v1.GetWebhookRequest 0, // 10: memos.api.v1.WebhookService.GetWebhook:output_type -> memos.api.v1.Webhook
4, // 11: memos.api.v1.WebhookService.CreateWebhook:input_type -> memos.api.v1.CreateWebhookRequest 0, // 11: memos.api.v1.WebhookService.CreateWebhook:output_type -> memos.api.v1.Webhook
5, // 12: memos.api.v1.WebhookService.UpdateWebhook:input_type -> memos.api.v1.UpdateWebhookRequest 0, // 12: memos.api.v1.WebhookService.UpdateWebhook:output_type -> memos.api.v1.Webhook
6, // 13: memos.api.v1.WebhookService.DeleteWebhook:input_type -> memos.api.v1.DeleteWebhookRequest 8, // 13: memos.api.v1.WebhookService.DeleteWebhook:output_type -> google.protobuf.Empty
2, // 14: memos.api.v1.WebhookService.ListWebhooks:output_type -> memos.api.v1.ListWebhooksResponse 9, // [9:14] is the sub-list for method output_type
0, // 15: memos.api.v1.WebhookService.GetWebhook:output_type -> memos.api.v1.Webhook 4, // [4:9] is the sub-list for method input_type
0, // 16: memos.api.v1.WebhookService.CreateWebhook:output_type -> memos.api.v1.Webhook 4, // [4:4] is the sub-list for extension type_name
0, // 17: memos.api.v1.WebhookService.UpdateWebhook:output_type -> memos.api.v1.Webhook 4, // [4:4] is the sub-list for extension extendee
12, // 18: memos.api.v1.WebhookService.DeleteWebhook:output_type -> google.protobuf.Empty 0, // [0:4] is the sub-list for field type_name
14, // [14:19] is the sub-list for method output_type
9, // [9:14] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
} }
func init() { file_api_v1_webhook_service_proto_init() } func init() { file_api_v1_webhook_service_proto_init() }
...@@ -611,7 +477,6 @@ func file_api_v1_webhook_service_proto_init() { ...@@ -611,7 +477,6 @@ func file_api_v1_webhook_service_proto_init() {
if File_api_v1_webhook_service_proto != nil { if File_api_v1_webhook_service_proto != nil {
return return
} }
file_api_v1_common_proto_init()
file_api_v1_memo_service_proto_init() file_api_v1_memo_service_proto_init()
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
...@@ -619,7 +484,7 @@ func file_api_v1_webhook_service_proto_init() { ...@@ -619,7 +484,7 @@ func file_api_v1_webhook_service_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_webhook_service_proto_rawDesc), len(file_api_v1_webhook_service_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_webhook_service_proto_rawDesc), len(file_api_v1_webhook_service_proto_rawDesc)),
NumEnums: 0, NumEnums: 0,
NumMessages: 8, NumMessages: 7,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },
......
...@@ -39,10 +39,19 @@ func request_WebhookService_ListWebhooks_0(ctx context.Context, marshaler runtim ...@@ -39,10 +39,19 @@ func request_WebhookService_ListWebhooks_0(ctx context.Context, marshaler runtim
var ( var (
protoReq ListWebhooksRequest protoReq ListWebhooksRequest
metadata runtime.ServerMetadata metadata runtime.ServerMetadata
err error
) )
if req.Body != nil { if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body) _, _ = io.Copy(io.Discard, req.Body)
} }
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := client.ListWebhooks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.ListWebhooks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err return msg, metadata, err
} }
...@@ -51,7 +60,16 @@ func local_request_WebhookService_ListWebhooks_0(ctx context.Context, marshaler ...@@ -51,7 +60,16 @@ func local_request_WebhookService_ListWebhooks_0(ctx context.Context, marshaler
var ( var (
protoReq ListWebhooksRequest protoReq ListWebhooksRequest
metadata runtime.ServerMetadata metadata runtime.ServerMetadata
err error
) )
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
msg, err := server.ListWebhooks(ctx, &protoReq) msg, err := server.ListWebhooks(ctx, &protoReq)
return msg, metadata, err return msg, metadata, err
} }
...@@ -95,12 +113,13 @@ func local_request_WebhookService_GetWebhook_0(ctx context.Context, marshaler ru ...@@ -95,12 +113,13 @@ func local_request_WebhookService_GetWebhook_0(ctx context.Context, marshaler ru
return msg, metadata, err return msg, metadata, err
} }
var filter_WebhookService_CreateWebhook_0 = &utilities.DoubleArray{Encoding: map[string]int{"webhook": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} var filter_WebhookService_CreateWebhook_0 = &utilities.DoubleArray{Encoding: map[string]int{"webhook": 0, "parent": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
func request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client WebhookServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler runtime.Marshaler, client WebhookServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var ( var (
protoReq CreateWebhookRequest protoReq CreateWebhookRequest
metadata runtime.ServerMetadata metadata runtime.ServerMetadata
err error
) )
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
...@@ -108,6 +127,14 @@ func request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler runti ...@@ -108,6 +127,14 @@ func request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler runti
if req.Body != nil { if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body) _, _ = 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 { if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
...@@ -122,10 +149,19 @@ func local_request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler ...@@ -122,10 +149,19 @@ func local_request_WebhookService_CreateWebhook_0(ctx context.Context, marshaler
var ( var (
protoReq CreateWebhookRequest protoReq CreateWebhookRequest
metadata runtime.ServerMetadata metadata runtime.ServerMetadata
err error
) )
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Webhook); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
if err := req.ParseForm(); err != nil { if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
...@@ -268,7 +304,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve ...@@ -268,7 +304,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve
var stream runtime.ServerTransportStream var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/ListWebhooks", runtime.WithHTTPPathPattern("/api/v1/webhooks")) annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/ListWebhooks", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -288,7 +324,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve ...@@ -288,7 +324,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve
var stream runtime.ServerTransportStream var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/GetWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=webhooks/*}")) annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/GetWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -308,7 +344,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve ...@@ -308,7 +344,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve
var stream runtime.ServerTransportStream var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/CreateWebhook", runtime.WithHTTPPathPattern("/api/v1/webhooks")) annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/CreateWebhook", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -328,7 +364,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve ...@@ -328,7 +364,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve
var stream runtime.ServerTransportStream var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/UpdateWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=webhooks/*}")) annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/UpdateWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=users/*/webhooks/*}"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -348,7 +384,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve ...@@ -348,7 +384,7 @@ func RegisterWebhookServiceHandlerServer(ctx context.Context, mux *runtime.Serve
var stream runtime.ServerTransportStream var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/DeleteWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=webhooks/*}")) annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.WebhookService/DeleteWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -406,7 +442,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve ...@@ -406,7 +442,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/ListWebhooks", runtime.WithHTTPPathPattern("/api/v1/webhooks")) annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/ListWebhooks", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -423,7 +459,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve ...@@ -423,7 +459,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/GetWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=webhooks/*}")) annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/GetWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -440,7 +476,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve ...@@ -440,7 +476,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/CreateWebhook", runtime.WithHTTPPathPattern("/api/v1/webhooks")) annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/CreateWebhook", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/webhooks"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -457,7 +493,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve ...@@ -457,7 +493,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/UpdateWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=webhooks/*}")) annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/UpdateWebhook", runtime.WithHTTPPathPattern("/api/v1/{webhook.name=users/*/webhooks/*}"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -474,7 +510,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve ...@@ -474,7 +510,7 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/DeleteWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=webhooks/*}")) annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.WebhookService/DeleteWebhook", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/webhooks/*}"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
...@@ -491,11 +527,11 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve ...@@ -491,11 +527,11 @@ func RegisterWebhookServiceHandlerClient(ctx context.Context, mux *runtime.Serve
} }
var ( var (
pattern_WebhookService_ListWebhooks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "webhooks"}, "")) pattern_WebhookService_ListWebhooks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "webhooks"}, ""))
pattern_WebhookService_GetWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "webhooks", "name"}, "")) pattern_WebhookService_GetWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "webhooks", "name"}, ""))
pattern_WebhookService_CreateWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "webhooks"}, "")) pattern_WebhookService_CreateWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "webhooks"}, ""))
pattern_WebhookService_UpdateWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "webhooks", "webhook.name"}, "")) pattern_WebhookService_UpdateWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "webhooks", "webhook.name"}, ""))
pattern_WebhookService_DeleteWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "webhooks", "name"}, "")) pattern_WebhookService_DeleteWebhook_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 2, 3, 1, 0, 4, 4, 5, 4}, []string{"api", "v1", "users", "webhooks", "name"}, ""))
) )
var ( var (
......
...@@ -31,15 +31,15 @@ const ( ...@@ -31,15 +31,15 @@ const (
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type WebhookServiceClient interface { type WebhookServiceClient interface {
// ListWebhooks returns a list of webhooks. // ListWebhooks returns a list of webhooks for a user.
ListWebhooks(ctx context.Context, in *ListWebhooksRequest, opts ...grpc.CallOption) (*ListWebhooksResponse, error) ListWebhooks(ctx context.Context, in *ListWebhooksRequest, opts ...grpc.CallOption) (*ListWebhooksResponse, error)
// GetWebhook gets a webhook by name. // GetWebhook gets a webhook by name.
GetWebhook(ctx context.Context, in *GetWebhookRequest, opts ...grpc.CallOption) (*Webhook, error) GetWebhook(ctx context.Context, in *GetWebhookRequest, opts ...grpc.CallOption) (*Webhook, error)
// CreateWebhook creates a new webhook. // CreateWebhook creates a new webhook for a user.
CreateWebhook(ctx context.Context, in *CreateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error) CreateWebhook(ctx context.Context, in *CreateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error)
// UpdateWebhook updates a webhook. // UpdateWebhook updates a webhook for a user.
UpdateWebhook(ctx context.Context, in *UpdateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error) UpdateWebhook(ctx context.Context, in *UpdateWebhookRequest, opts ...grpc.CallOption) (*Webhook, error)
// DeleteWebhook deletes a webhook. // DeleteWebhook deletes a webhook for a user.
DeleteWebhook(ctx context.Context, in *DeleteWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) DeleteWebhook(ctx context.Context, in *DeleteWebhookRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
} }
...@@ -105,15 +105,15 @@ func (c *webhookServiceClient) DeleteWebhook(ctx context.Context, in *DeleteWebh ...@@ -105,15 +105,15 @@ func (c *webhookServiceClient) DeleteWebhook(ctx context.Context, in *DeleteWebh
// All implementations must embed UnimplementedWebhookServiceServer // All implementations must embed UnimplementedWebhookServiceServer
// for forward compatibility. // for forward compatibility.
type WebhookServiceServer interface { type WebhookServiceServer interface {
// ListWebhooks returns a list of webhooks. // ListWebhooks returns a list of webhooks for a user.
ListWebhooks(context.Context, *ListWebhooksRequest) (*ListWebhooksResponse, error) ListWebhooks(context.Context, *ListWebhooksRequest) (*ListWebhooksResponse, error)
// GetWebhook gets a webhook by name. // GetWebhook gets a webhook by name.
GetWebhook(context.Context, *GetWebhookRequest) (*Webhook, error) GetWebhook(context.Context, *GetWebhookRequest) (*Webhook, error)
// CreateWebhook creates a new webhook. // CreateWebhook creates a new webhook for a user.
CreateWebhook(context.Context, *CreateWebhookRequest) (*Webhook, error) CreateWebhook(context.Context, *CreateWebhookRequest) (*Webhook, error)
// UpdateWebhook updates a webhook. // UpdateWebhook updates a webhook for a user.
UpdateWebhook(context.Context, *UpdateWebhookRequest) (*Webhook, error) UpdateWebhook(context.Context, *UpdateWebhookRequest) (*Webhook, error)
// DeleteWebhook deletes a webhook. // DeleteWebhook deletes a webhook for a user.
DeleteWebhook(context.Context, *DeleteWebhookRequest) (*emptypb.Empty, error) DeleteWebhook(context.Context, *DeleteWebhookRequest) (*emptypb.Empty, error)
mustEmbedUnimplementedWebhookServiceServer() mustEmbedUnimplementedWebhookServiceServer()
} }
......
...@@ -602,57 +602,6 @@ paths: ...@@ -602,57 +602,6 @@ paths:
type: string type: string
tags: tags:
- UserService - UserService
/api/v1/webhooks:
get:
summary: ListWebhooks returns a list of webhooks.
operationId: WebhookService_ListWebhooks
responses:
"200":
description: A successful response.
schema:
$ref: '#/definitions/v1ListWebhooksResponse'
default:
description: An unexpected error response.
schema:
$ref: '#/definitions/googlerpcStatus'
tags:
- WebhookService
post:
summary: CreateWebhook creates a new webhook.
operationId: WebhookService_CreateWebhook
responses:
"200":
description: A successful response.
schema:
$ref: '#/definitions/v1Webhook'
default:
description: An unexpected error response.
schema:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: webhook
description: Required. The webhook to create.
in: body
required: true
schema:
$ref: '#/definitions/v1Webhook'
required:
- webhook
- name: webhookId
description: |-
Optional. The webhook ID to use for this webhook.
If empty, a unique ID will be generated.
Must match the pattern [a-z0-9-]+
in: query
required: false
type: string
- name: validateOnly
description: Optional. If set, validate the request but don't actually create the webhook.
in: query
required: false
type: boolean
tags:
- WebhookService
/api/v1/workspace/profile: /api/v1/workspace/profile:
get: get:
summary: Gets the workspace profile. summary: Gets the workspace profile.
...@@ -1242,7 +1191,7 @@ paths: ...@@ -1242,7 +1191,7 @@ paths:
"200": "200":
description: A successful response. description: A successful response.
schema: schema:
$ref: '#/definitions/v1Webhook' $ref: '#/definitions/apiv1Webhook'
default: default:
description: An unexpected error response. description: An unexpected error response.
schema: schema:
...@@ -1250,12 +1199,12 @@ paths: ...@@ -1250,12 +1199,12 @@ paths:
parameters: parameters:
- name: name_6 - name: name_6
description: |- description: |-
Required. The resource name of the webhook. Required. The resource name of the webhook to retrieve.
Format: webhooks/{webhook} Format: users/{user}/webhooks/{webhook}
in: path in: path
required: true required: true
type: string type: string
pattern: webhooks/[^/]+ pattern: users/[^/]+/webhooks/[^/]+
tags: tags:
- WebhookService - WebhookService
delete: delete:
...@@ -1362,7 +1311,7 @@ paths: ...@@ -1362,7 +1311,7 @@ paths:
- ShortcutService - ShortcutService
/api/v1/{name_9}: /api/v1/{name_9}:
delete: delete:
summary: DeleteWebhook deletes a webhook. summary: DeleteWebhook deletes a webhook for a user.
operationId: WebhookService_DeleteWebhook operationId: WebhookService_DeleteWebhook
responses: responses:
"200": "200":
...@@ -1378,11 +1327,11 @@ paths: ...@@ -1378,11 +1327,11 @@ paths:
- name: name_9 - name: name_9
description: |- description: |-
Required. The resource name of the webhook to delete. Required. The resource name of the webhook to delete.
Format: webhooks/{webhook} Format: users/{user}/webhooks/{webhook}
in: path in: path
required: true required: true
type: string type: string
pattern: webhooks/[^/]+ pattern: users/[^/]+/webhooks/[^/]+
tags: tags:
- WebhookService - WebhookService
/api/v1/{name}: /api/v1/{name}:
...@@ -2131,6 +2080,66 @@ paths: ...@@ -2131,6 +2080,66 @@ paths:
$ref: '#/definitions/MemoServiceRenameMemoTagBody' $ref: '#/definitions/MemoServiceRenameMemoTagBody'
tags: tags:
- MemoService - MemoService
/api/v1/{parent}/webhooks:
get:
summary: ListWebhooks returns a list of webhooks for a user.
operationId: WebhookService_ListWebhooks
responses:
"200":
description: A successful response.
schema:
$ref: '#/definitions/v1ListWebhooksResponse'
default:
description: An unexpected error response.
schema:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: parent
description: |-
Required. The parent resource where webhooks are listed.
Format: users/{user}
in: path
required: true
type: string
pattern: users/[^/]+
tags:
- WebhookService
post:
summary: CreateWebhook creates a new webhook for a user.
operationId: WebhookService_CreateWebhook
responses:
"200":
description: A successful response.
schema:
$ref: '#/definitions/apiv1Webhook'
default:
description: An unexpected error response.
schema:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: parent
description: |-
Required. The parent resource where this webhook will be created.
Format: users/{user}
in: path
required: true
type: string
pattern: users/[^/]+
- name: webhook
description: Required. The webhook to create.
in: body
required: true
schema:
$ref: '#/definitions/apiv1Webhook'
required:
- webhook
- name: validateOnly
description: Optional. If set, validate the request, but do not actually create the webhook.
in: query
required: false
type: boolean
tags:
- WebhookService
/api/v1/{setting.name}: /api/v1/{setting.name}:
patch: patch:
summary: Updates a workspace setting. summary: Updates a workspace setting.
...@@ -2333,13 +2342,13 @@ paths: ...@@ -2333,13 +2342,13 @@ paths:
- UserService - UserService
/api/v1/{webhook.name}: /api/v1/{webhook.name}:
patch: patch:
summary: UpdateWebhook updates a webhook. summary: UpdateWebhook updates a webhook for a user.
operationId: WebhookService_UpdateWebhook operationId: WebhookService_UpdateWebhook
responses: responses:
"200": "200":
description: A successful response. description: A successful response.
schema: schema:
$ref: '#/definitions/v1Webhook' $ref: '#/definitions/apiv1Webhook'
default: default:
description: An unexpected error response. description: An unexpected error response.
schema: schema:
...@@ -2348,13 +2357,13 @@ paths: ...@@ -2348,13 +2357,13 @@ paths:
- name: webhook.name - name: webhook.name
description: |- description: |-
The resource name of the webhook. The resource name of the webhook.
Format: webhooks/{webhook} Format: users/{user}/webhooks/{webhook}
in: path in: path
required: true required: true
type: string type: string
pattern: webhooks/[^/]+ pattern: users/[^/]+/webhooks/[^/]+
- name: webhook - name: webhook
description: Required. The webhook to update. description: Required. The webhook resource which replaces the resource on the server.
in: body in: body
required: true required: true
schema: schema:
...@@ -2362,34 +2371,14 @@ paths: ...@@ -2362,34 +2371,14 @@ paths:
properties: properties:
displayName: displayName:
type: string type: string
description: Required. The display name of the webhook. description: The display name of the webhook.
url: url:
type: string type: string
description: Required. The target URL for the webhook. description: The target URL for the webhook.
creator: title: Required. The webhook resource which replaces the resource on the server.
type: string
title: |-
Output only. The resource name of the creator.
Format: users/{user}
readOnly: true
state:
$ref: '#/definitions/v1State'
description: The state of the webhook.
createTime:
type: string
format: date-time
description: Output only. The creation timestamp.
readOnly: true
updateTime:
type: string
format: date-time
description: Output only. The last update timestamp.
readOnly: true
title: Required. The webhook to update.
required: required:
- displayName - displayName
- url - url
- state
- webhook - webhook
tags: tags:
- WebhookService - WebhookService
...@@ -2878,6 +2867,23 @@ definitions: ...@@ -2878,6 +2867,23 @@ definitions:
type: string type: string
description: The default visibility of the memo. description: The default visibility of the memo.
title: User settings message title: User settings message
apiv1Webhook:
type: object
properties:
name:
type: string
title: |-
The resource name of the webhook.
Format: users/{user}/webhooks/{webhook}
displayName:
type: string
description: The display name of the webhook.
url:
type: string
description: The target URL for the webhook.
required:
- displayName
- url
apiv1WorkspaceCustomProfile: apiv1WorkspaceCustomProfile:
type: object type: object
properties: properties:
...@@ -3658,7 +3664,7 @@ definitions: ...@@ -3658,7 +3664,7 @@ definitions:
type: array type: array
items: items:
type: object type: object
$ref: '#/definitions/v1Webhook' $ref: '#/definitions/apiv1Webhook'
description: The list of webhooks. description: The list of webhooks.
v1MathBlockNode: v1MathBlockNode:
type: object type: object
...@@ -4200,43 +4206,6 @@ definitions: ...@@ -4200,43 +4206,6 @@ definitions:
- PROTECTED - PROTECTED
- PUBLIC - PUBLIC
default: VISIBILITY_UNSPECIFIED default: VISIBILITY_UNSPECIFIED
v1Webhook:
type: object
properties:
name:
type: string
title: |-
The resource name of the webhook.
Format: webhooks/{webhook}
displayName:
type: string
description: Required. The display name of the webhook.
url:
type: string
description: Required. The target URL for the webhook.
creator:
type: string
title: |-
Output only. The resource name of the creator.
Format: users/{user}
readOnly: true
state:
$ref: '#/definitions/v1State'
description: The state of the webhook.
createTime:
type: string
format: date-time
description: Output only. The creation timestamp.
readOnly: true
updateTime:
type: string
format: date-time
description: Output only. The last update timestamp.
readOnly: true
required:
- displayName
- url
- state
v1WorkspaceProfile: v1WorkspaceProfile:
type: object type: object
properties: properties:
......
...@@ -34,6 +34,8 @@ const ( ...@@ -34,6 +34,8 @@ const (
UserSetting_ACCESS_TOKENS UserSetting_Key = 3 UserSetting_ACCESS_TOKENS UserSetting_Key = 3
// The shortcuts of the user. // The shortcuts of the user.
UserSetting_SHORTCUTS UserSetting_Key = 4 UserSetting_SHORTCUTS UserSetting_Key = 4
// The webhooks of the user.
UserSetting_WEBHOOKS UserSetting_Key = 5
) )
// Enum value maps for UserSetting_Key. // Enum value maps for UserSetting_Key.
...@@ -44,6 +46,7 @@ var ( ...@@ -44,6 +46,7 @@ var (
2: "SESSIONS", 2: "SESSIONS",
3: "ACCESS_TOKENS", 3: "ACCESS_TOKENS",
4: "SHORTCUTS", 4: "SHORTCUTS",
5: "WEBHOOKS",
} }
UserSetting_Key_value = map[string]int32{ UserSetting_Key_value = map[string]int32{
"KEY_UNSPECIFIED": 0, "KEY_UNSPECIFIED": 0,
...@@ -51,6 +54,7 @@ var ( ...@@ -51,6 +54,7 @@ var (
"SESSIONS": 2, "SESSIONS": 2,
"ACCESS_TOKENS": 3, "ACCESS_TOKENS": 3,
"SHORTCUTS": 4, "SHORTCUTS": 4,
"WEBHOOKS": 5,
} }
) )
...@@ -91,6 +95,7 @@ type UserSetting struct { ...@@ -91,6 +95,7 @@ type UserSetting struct {
// *UserSetting_Sessions // *UserSetting_Sessions
// *UserSetting_AccessTokens // *UserSetting_AccessTokens
// *UserSetting_Shortcuts // *UserSetting_Shortcuts
// *UserSetting_Webhooks
Value isUserSetting_Value `protobuf_oneof:"value"` Value isUserSetting_Value `protobuf_oneof:"value"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
...@@ -183,6 +188,15 @@ func (x *UserSetting) GetShortcuts() *ShortcutsUserSetting { ...@@ -183,6 +188,15 @@ func (x *UserSetting) GetShortcuts() *ShortcutsUserSetting {
return nil return nil
} }
func (x *UserSetting) GetWebhooks() *WebhooksUserSetting {
if x != nil {
if x, ok := x.Value.(*UserSetting_Webhooks); ok {
return x.Webhooks
}
}
return nil
}
type isUserSetting_Value interface { type isUserSetting_Value interface {
isUserSetting_Value() isUserSetting_Value()
} }
...@@ -203,6 +217,10 @@ type UserSetting_Shortcuts struct { ...@@ -203,6 +217,10 @@ type UserSetting_Shortcuts struct {
Shortcuts *ShortcutsUserSetting `protobuf:"bytes,6,opt,name=shortcuts,proto3,oneof"` Shortcuts *ShortcutsUserSetting `protobuf:"bytes,6,opt,name=shortcuts,proto3,oneof"`
} }
type UserSetting_Webhooks struct {
Webhooks *WebhooksUserSetting `protobuf:"bytes,7,opt,name=webhooks,proto3,oneof"`
}
func (*UserSetting_General) isUserSetting_Value() {} func (*UserSetting_General) isUserSetting_Value() {}
func (*UserSetting_Sessions) isUserSetting_Value() {} func (*UserSetting_Sessions) isUserSetting_Value() {}
...@@ -211,6 +229,8 @@ func (*UserSetting_AccessTokens) isUserSetting_Value() {} ...@@ -211,6 +229,8 @@ func (*UserSetting_AccessTokens) isUserSetting_Value() {}
func (*UserSetting_Shortcuts) isUserSetting_Value() {} func (*UserSetting_Shortcuts) isUserSetting_Value() {}
func (*UserSetting_Webhooks) isUserSetting_Value() {}
type GeneralUserSetting struct { type GeneralUserSetting struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// The user's locale. // The user's locale.
...@@ -406,6 +426,50 @@ func (x *ShortcutsUserSetting) GetShortcuts() []*ShortcutsUserSetting_Shortcut { ...@@ -406,6 +426,50 @@ func (x *ShortcutsUserSetting) GetShortcuts() []*ShortcutsUserSetting_Shortcut {
return nil return nil
} }
type WebhooksUserSetting struct {
state protoimpl.MessageState `protogen:"open.v1"`
Webhooks []*WebhooksUserSetting_Webhook `protobuf:"bytes,1,rep,name=webhooks,proto3" json:"webhooks,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *WebhooksUserSetting) Reset() {
*x = WebhooksUserSetting{}
mi := &file_store_user_setting_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WebhooksUserSetting) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WebhooksUserSetting) ProtoMessage() {}
func (x *WebhooksUserSetting) ProtoReflect() protoreflect.Message {
mi := &file_store_user_setting_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WebhooksUserSetting.ProtoReflect.Descriptor instead.
func (*WebhooksUserSetting) Descriptor() ([]byte, []int) {
return file_store_user_setting_proto_rawDescGZIP(), []int{5}
}
func (x *WebhooksUserSetting) GetWebhooks() []*WebhooksUserSetting_Webhook {
if x != nil {
return x.Webhooks
}
return nil
}
type SessionsUserSetting_Session struct { type SessionsUserSetting_Session struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
// Unique session identifier. // Unique session identifier.
...@@ -424,7 +488,7 @@ type SessionsUserSetting_Session struct { ...@@ -424,7 +488,7 @@ type SessionsUserSetting_Session struct {
func (x *SessionsUserSetting_Session) Reset() { func (x *SessionsUserSetting_Session) Reset() {
*x = SessionsUserSetting_Session{} *x = SessionsUserSetting_Session{}
mi := &file_store_user_setting_proto_msgTypes[5] mi := &file_store_user_setting_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
...@@ -436,7 +500,7 @@ func (x *SessionsUserSetting_Session) String() string { ...@@ -436,7 +500,7 @@ func (x *SessionsUserSetting_Session) String() string {
func (*SessionsUserSetting_Session) ProtoMessage() {} func (*SessionsUserSetting_Session) ProtoMessage() {}
func (x *SessionsUserSetting_Session) ProtoReflect() protoreflect.Message { func (x *SessionsUserSetting_Session) ProtoReflect() protoreflect.Message {
mi := &file_store_user_setting_proto_msgTypes[5] mi := &file_store_user_setting_proto_msgTypes[6]
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 {
...@@ -505,7 +569,7 @@ type SessionsUserSetting_ClientInfo struct { ...@@ -505,7 +569,7 @@ type SessionsUserSetting_ClientInfo struct {
func (x *SessionsUserSetting_ClientInfo) Reset() { func (x *SessionsUserSetting_ClientInfo) Reset() {
*x = SessionsUserSetting_ClientInfo{} *x = SessionsUserSetting_ClientInfo{}
mi := &file_store_user_setting_proto_msgTypes[6] mi := &file_store_user_setting_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
...@@ -517,7 +581,7 @@ func (x *SessionsUserSetting_ClientInfo) String() string { ...@@ -517,7 +581,7 @@ func (x *SessionsUserSetting_ClientInfo) String() string {
func (*SessionsUserSetting_ClientInfo) ProtoMessage() {} func (*SessionsUserSetting_ClientInfo) ProtoMessage() {}
func (x *SessionsUserSetting_ClientInfo) ProtoReflect() protoreflect.Message { func (x *SessionsUserSetting_ClientInfo) ProtoReflect() protoreflect.Message {
mi := &file_store_user_setting_proto_msgTypes[6] mi := &file_store_user_setting_proto_msgTypes[7]
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 {
...@@ -581,7 +645,7 @@ type AccessTokensUserSetting_AccessToken struct { ...@@ -581,7 +645,7 @@ type AccessTokensUserSetting_AccessToken struct {
func (x *AccessTokensUserSetting_AccessToken) Reset() { func (x *AccessTokensUserSetting_AccessToken) Reset() {
*x = AccessTokensUserSetting_AccessToken{} *x = AccessTokensUserSetting_AccessToken{}
mi := &file_store_user_setting_proto_msgTypes[7] mi := &file_store_user_setting_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
...@@ -593,7 +657,7 @@ func (x *AccessTokensUserSetting_AccessToken) String() string { ...@@ -593,7 +657,7 @@ func (x *AccessTokensUserSetting_AccessToken) String() string {
func (*AccessTokensUserSetting_AccessToken) ProtoMessage() {} func (*AccessTokensUserSetting_AccessToken) ProtoMessage() {}
func (x *AccessTokensUserSetting_AccessToken) ProtoReflect() protoreflect.Message { func (x *AccessTokensUserSetting_AccessToken) ProtoReflect() protoreflect.Message {
mi := &file_store_user_setting_proto_msgTypes[7] mi := &file_store_user_setting_proto_msgTypes[8]
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 {
...@@ -634,7 +698,7 @@ type ShortcutsUserSetting_Shortcut struct { ...@@ -634,7 +698,7 @@ type ShortcutsUserSetting_Shortcut struct {
func (x *ShortcutsUserSetting_Shortcut) Reset() { func (x *ShortcutsUserSetting_Shortcut) Reset() {
*x = ShortcutsUserSetting_Shortcut{} *x = ShortcutsUserSetting_Shortcut{}
mi := &file_store_user_setting_proto_msgTypes[8] mi := &file_store_user_setting_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
...@@ -646,7 +710,7 @@ func (x *ShortcutsUserSetting_Shortcut) String() string { ...@@ -646,7 +710,7 @@ func (x *ShortcutsUserSetting_Shortcut) String() string {
func (*ShortcutsUserSetting_Shortcut) ProtoMessage() {} func (*ShortcutsUserSetting_Shortcut) ProtoMessage() {}
func (x *ShortcutsUserSetting_Shortcut) ProtoReflect() protoreflect.Message { func (x *ShortcutsUserSetting_Shortcut) ProtoReflect() protoreflect.Message {
mi := &file_store_user_setting_proto_msgTypes[8] mi := &file_store_user_setting_proto_msgTypes[9]
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 {
...@@ -683,24 +747,89 @@ func (x *ShortcutsUserSetting_Shortcut) GetFilter() string { ...@@ -683,24 +747,89 @@ func (x *ShortcutsUserSetting_Shortcut) GetFilter() string {
return "" return ""
} }
type WebhooksUserSetting_Webhook struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Unique identifier for the webhook
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// Descriptive title for the webhook
Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`
// The webhook URL endpoint
Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *WebhooksUserSetting_Webhook) Reset() {
*x = WebhooksUserSetting_Webhook{}
mi := &file_store_user_setting_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WebhooksUserSetting_Webhook) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WebhooksUserSetting_Webhook) ProtoMessage() {}
func (x *WebhooksUserSetting_Webhook) ProtoReflect() protoreflect.Message {
mi := &file_store_user_setting_proto_msgTypes[10]
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 WebhooksUserSetting_Webhook.ProtoReflect.Descriptor instead.
func (*WebhooksUserSetting_Webhook) Descriptor() ([]byte, []int) {
return file_store_user_setting_proto_rawDescGZIP(), []int{5, 0}
}
func (x *WebhooksUserSetting_Webhook) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *WebhooksUserSetting_Webhook) GetTitle() string {
if x != nil {
return x.Title
}
return ""
}
func (x *WebhooksUserSetting_Webhook) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
var File_store_user_setting_proto protoreflect.FileDescriptor var File_store_user_setting_proto protoreflect.FileDescriptor
const file_store_user_setting_proto_rawDesc = "" + const file_store_user_setting_proto_rawDesc = "" +
"\n" + "\n" +
"\x18store/user_setting.proto\x12\vmemos.store\x1a\x1fgoogle/protobuf/timestamp.proto\"\xc5\x03\n" + "\x18store/user_setting.proto\x12\vmemos.store\x1a\x1fgoogle/protobuf/timestamp.proto\"\x93\x04\n" +
"\vUserSetting\x12\x17\n" + "\vUserSetting\x12\x17\n" +
"\auser_id\x18\x01 \x01(\x05R\x06userId\x12.\n" + "\auser_id\x18\x01 \x01(\x05R\x06userId\x12.\n" +
"\x03key\x18\x02 \x01(\x0e2\x1c.memos.store.UserSetting.KeyR\x03key\x12;\n" + "\x03key\x18\x02 \x01(\x0e2\x1c.memos.store.UserSetting.KeyR\x03key\x12;\n" +
"\ageneral\x18\x03 \x01(\v2\x1f.memos.store.GeneralUserSettingH\x00R\ageneral\x12>\n" + "\ageneral\x18\x03 \x01(\v2\x1f.memos.store.GeneralUserSettingH\x00R\ageneral\x12>\n" +
"\bsessions\x18\x04 \x01(\v2 .memos.store.SessionsUserSettingH\x00R\bsessions\x12K\n" + "\bsessions\x18\x04 \x01(\v2 .memos.store.SessionsUserSettingH\x00R\bsessions\x12K\n" +
"\raccess_tokens\x18\x05 \x01(\v2$.memos.store.AccessTokensUserSettingH\x00R\faccessTokens\x12A\n" + "\raccess_tokens\x18\x05 \x01(\v2$.memos.store.AccessTokensUserSettingH\x00R\faccessTokens\x12A\n" +
"\tshortcuts\x18\x06 \x01(\v2!.memos.store.ShortcutsUserSettingH\x00R\tshortcuts\"W\n" + "\tshortcuts\x18\x06 \x01(\v2!.memos.store.ShortcutsUserSettingH\x00R\tshortcuts\x12>\n" +
"\bwebhooks\x18\a \x01(\v2 .memos.store.WebhooksUserSettingH\x00R\bwebhooks\"e\n" +
"\x03Key\x12\x13\n" + "\x03Key\x12\x13\n" +
"\x0fKEY_UNSPECIFIED\x10\x00\x12\v\n" + "\x0fKEY_UNSPECIFIED\x10\x00\x12\v\n" +
"\aGENERAL\x10\x01\x12\f\n" + "\aGENERAL\x10\x01\x12\f\n" +
"\bSESSIONS\x10\x02\x12\x11\n" + "\bSESSIONS\x10\x02\x12\x11\n" +
"\rACCESS_TOKENS\x10\x03\x12\r\n" + "\rACCESS_TOKENS\x10\x03\x12\r\n" +
"\tSHORTCUTS\x10\x04B\a\n" + "\tSHORTCUTS\x10\x04\x12\f\n" +
"\bWEBHOOKS\x10\x05B\a\n" +
"\x05value\"u\n" + "\x05value\"u\n" +
"\x12GeneralUserSetting\x12\x16\n" + "\x12GeneralUserSetting\x12\x16\n" +
"\x06locale\x18\x01 \x01(\tR\x06locale\x12\x1e\n" + "\x06locale\x18\x01 \x01(\tR\x06locale\x12\x1e\n" +
...@@ -740,7 +869,13 @@ const file_store_user_setting_proto_rawDesc = "" + ...@@ -740,7 +869,13 @@ const file_store_user_setting_proto_rawDesc = "" +
"\bShortcut\x12\x0e\n" + "\bShortcut\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" +
"\x05title\x18\x02 \x01(\tR\x05title\x12\x16\n" + "\x05title\x18\x02 \x01(\tR\x05title\x12\x16\n" +
"\x06filter\x18\x03 \x01(\tR\x06filterB\x9b\x01\n" + "\x06filter\x18\x03 \x01(\tR\x06filter\"\x9e\x01\n" +
"\x13WebhooksUserSetting\x12D\n" +
"\bwebhooks\x18\x01 \x03(\v2(.memos.store.WebhooksUserSetting.WebhookR\bwebhooks\x1aA\n" +
"\aWebhook\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" +
"\x05title\x18\x02 \x01(\tR\x05title\x12\x10\n" +
"\x03url\x18\x03 \x01(\tR\x03urlB\x9b\x01\n" +
"\x0fcom.memos.storeB\x10UserSettingProtoP\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" "\x0fcom.memos.storeB\x10UserSettingProtoP\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"
var ( var (
...@@ -756,7 +891,7 @@ func file_store_user_setting_proto_rawDescGZIP() []byte { ...@@ -756,7 +891,7 @@ func file_store_user_setting_proto_rawDescGZIP() []byte {
} }
var file_store_user_setting_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_store_user_setting_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_store_user_setting_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_store_user_setting_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_store_user_setting_proto_goTypes = []any{ var file_store_user_setting_proto_goTypes = []any{
(UserSetting_Key)(0), // 0: memos.store.UserSetting.Key (UserSetting_Key)(0), // 0: memos.store.UserSetting.Key
(*UserSetting)(nil), // 1: memos.store.UserSetting (*UserSetting)(nil), // 1: memos.store.UserSetting
...@@ -764,11 +899,13 @@ var file_store_user_setting_proto_goTypes = []any{ ...@@ -764,11 +899,13 @@ var file_store_user_setting_proto_goTypes = []any{
(*SessionsUserSetting)(nil), // 3: memos.store.SessionsUserSetting (*SessionsUserSetting)(nil), // 3: memos.store.SessionsUserSetting
(*AccessTokensUserSetting)(nil), // 4: memos.store.AccessTokensUserSetting (*AccessTokensUserSetting)(nil), // 4: memos.store.AccessTokensUserSetting
(*ShortcutsUserSetting)(nil), // 5: memos.store.ShortcutsUserSetting (*ShortcutsUserSetting)(nil), // 5: memos.store.ShortcutsUserSetting
(*SessionsUserSetting_Session)(nil), // 6: memos.store.SessionsUserSetting.Session (*WebhooksUserSetting)(nil), // 6: memos.store.WebhooksUserSetting
(*SessionsUserSetting_ClientInfo)(nil), // 7: memos.store.SessionsUserSetting.ClientInfo (*SessionsUserSetting_Session)(nil), // 7: memos.store.SessionsUserSetting.Session
(*AccessTokensUserSetting_AccessToken)(nil), // 8: memos.store.AccessTokensUserSetting.AccessToken (*SessionsUserSetting_ClientInfo)(nil), // 8: memos.store.SessionsUserSetting.ClientInfo
(*ShortcutsUserSetting_Shortcut)(nil), // 9: memos.store.ShortcutsUserSetting.Shortcut (*AccessTokensUserSetting_AccessToken)(nil), // 9: memos.store.AccessTokensUserSetting.AccessToken
(*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp (*ShortcutsUserSetting_Shortcut)(nil), // 10: memos.store.ShortcutsUserSetting.Shortcut
(*WebhooksUserSetting_Webhook)(nil), // 11: memos.store.WebhooksUserSetting.Webhook
(*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp
} }
var file_store_user_setting_proto_depIdxs = []int32{ var file_store_user_setting_proto_depIdxs = []int32{
0, // 0: memos.store.UserSetting.key:type_name -> memos.store.UserSetting.Key 0, // 0: memos.store.UserSetting.key:type_name -> memos.store.UserSetting.Key
...@@ -776,18 +913,20 @@ var file_store_user_setting_proto_depIdxs = []int32{ ...@@ -776,18 +913,20 @@ var file_store_user_setting_proto_depIdxs = []int32{
3, // 2: memos.store.UserSetting.sessions:type_name -> memos.store.SessionsUserSetting 3, // 2: memos.store.UserSetting.sessions:type_name -> memos.store.SessionsUserSetting
4, // 3: memos.store.UserSetting.access_tokens:type_name -> memos.store.AccessTokensUserSetting 4, // 3: memos.store.UserSetting.access_tokens:type_name -> memos.store.AccessTokensUserSetting
5, // 4: memos.store.UserSetting.shortcuts:type_name -> memos.store.ShortcutsUserSetting 5, // 4: memos.store.UserSetting.shortcuts:type_name -> memos.store.ShortcutsUserSetting
6, // 5: memos.store.SessionsUserSetting.sessions:type_name -> memos.store.SessionsUserSetting.Session 6, // 5: memos.store.UserSetting.webhooks:type_name -> memos.store.WebhooksUserSetting
8, // 6: memos.store.AccessTokensUserSetting.access_tokens:type_name -> memos.store.AccessTokensUserSetting.AccessToken 7, // 6: memos.store.SessionsUserSetting.sessions:type_name -> memos.store.SessionsUserSetting.Session
9, // 7: memos.store.ShortcutsUserSetting.shortcuts:type_name -> memos.store.ShortcutsUserSetting.Shortcut 9, // 7: memos.store.AccessTokensUserSetting.access_tokens:type_name -> memos.store.AccessTokensUserSetting.AccessToken
10, // 8: memos.store.SessionsUserSetting.Session.create_time:type_name -> google.protobuf.Timestamp 10, // 8: memos.store.ShortcutsUserSetting.shortcuts:type_name -> memos.store.ShortcutsUserSetting.Shortcut
10, // 9: memos.store.SessionsUserSetting.Session.expire_time:type_name -> google.protobuf.Timestamp 11, // 9: memos.store.WebhooksUserSetting.webhooks:type_name -> memos.store.WebhooksUserSetting.Webhook
10, // 10: memos.store.SessionsUserSetting.Session.last_accessed_time:type_name -> google.protobuf.Timestamp 12, // 10: memos.store.SessionsUserSetting.Session.create_time:type_name -> google.protobuf.Timestamp
7, // 11: memos.store.SessionsUserSetting.Session.client_info:type_name -> memos.store.SessionsUserSetting.ClientInfo 12, // 11: memos.store.SessionsUserSetting.Session.expire_time:type_name -> google.protobuf.Timestamp
12, // [12:12] is the sub-list for method output_type 12, // 12: memos.store.SessionsUserSetting.Session.last_accessed_time:type_name -> google.protobuf.Timestamp
12, // [12:12] is the sub-list for method input_type 8, // 13: memos.store.SessionsUserSetting.Session.client_info:type_name -> memos.store.SessionsUserSetting.ClientInfo
12, // [12:12] is the sub-list for extension type_name 14, // [14:14] is the sub-list for method output_type
12, // [12:12] is the sub-list for extension extendee 14, // [14:14] is the sub-list for method input_type
0, // [0:12] is the sub-list for field type_name 14, // [14:14] is the sub-list for extension type_name
14, // [14:14] is the sub-list for extension extendee
0, // [0:14] is the sub-list for field type_name
} }
func init() { file_store_user_setting_proto_init() } func init() { file_store_user_setting_proto_init() }
...@@ -800,6 +939,7 @@ func file_store_user_setting_proto_init() { ...@@ -800,6 +939,7 @@ func file_store_user_setting_proto_init() {
(*UserSetting_Sessions)(nil), (*UserSetting_Sessions)(nil),
(*UserSetting_AccessTokens)(nil), (*UserSetting_AccessTokens)(nil),
(*UserSetting_Shortcuts)(nil), (*UserSetting_Shortcuts)(nil),
(*UserSetting_Webhooks)(nil),
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
...@@ -807,7 +947,7 @@ func file_store_user_setting_proto_init() { ...@@ -807,7 +947,7 @@ func file_store_user_setting_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_store_user_setting_proto_rawDesc), len(file_store_user_setting_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_store_user_setting_proto_rawDesc), len(file_store_user_setting_proto_rawDesc)),
NumEnums: 1, NumEnums: 1,
NumMessages: 9, NumMessages: 11,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },
......
...@@ -17,17 +17,19 @@ message UserSetting { ...@@ -17,17 +17,19 @@ message UserSetting {
ACCESS_TOKENS = 3; ACCESS_TOKENS = 3;
// The shortcuts of the user. // The shortcuts of the user.
SHORTCUTS = 4; SHORTCUTS = 4;
// The webhooks of the user.
WEBHOOKS = 5;
} }
int32 user_id = 1; int32 user_id = 1;
Key key = 2; Key key = 2;
oneof value { oneof value {
GeneralUserSetting general = 3; GeneralUserSetting general = 3;
SessionsUserSetting sessions = 4; SessionsUserSetting sessions = 4;
AccessTokensUserSetting access_tokens = 5; AccessTokensUserSetting access_tokens = 5;
ShortcutsUserSetting shortcuts = 6; ShortcutsUserSetting shortcuts = 6;
WebhooksUserSetting webhooks = 7;
} }
} }
...@@ -89,3 +91,15 @@ message ShortcutsUserSetting { ...@@ -89,3 +91,15 @@ message ShortcutsUserSetting {
} }
repeated Shortcut shortcuts = 1; repeated Shortcut shortcuts = 1;
} }
message WebhooksUserSetting {
message Webhook {
// Unique identifier for the webhook
string id = 1;
// Descriptive title for the webhook
string title = 2;
// The webhook URL endpoint
string url = 3;
}
repeated Webhook webhooks = 1;
}
...@@ -18,7 +18,6 @@ import ( ...@@ -18,7 +18,6 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/usememos/memos/plugin/webhook" "github.com/usememos/memos/plugin/webhook"
v1pb "github.com/usememos/memos/proto/gen/api/v1" v1pb "github.com/usememos/memos/proto/gen/api/v1"
...@@ -689,9 +688,7 @@ func (s *APIV1Service) dispatchMemoRelatedWebhook(ctx context.Context, memo *v1p ...@@ -689,9 +688,7 @@ func (s *APIV1Service) dispatchMemoRelatedWebhook(ctx context.Context, memo *v1p
if err != nil { if err != nil {
return status.Errorf(codes.InvalidArgument, "invalid memo creator") return status.Errorf(codes.InvalidArgument, "invalid memo creator")
} }
webhooks, err := s.Store.ListWebhooks(ctx, &store.FindWebhook{ webhooks, err := s.Store.GetUserWebhooks(ctx, creatorID)
CreatorID: &creatorID,
})
if err != nil { if err != nil {
return err return err
} }
...@@ -701,7 +698,7 @@ func (s *APIV1Service) dispatchMemoRelatedWebhook(ctx context.Context, memo *v1p ...@@ -701,7 +698,7 @@ func (s *APIV1Service) dispatchMemoRelatedWebhook(ctx context.Context, memo *v1p
return errors.Wrap(err, "failed to convert memo to webhook payload") return errors.Wrap(err, "failed to convert memo to webhook payload")
} }
payload.ActivityType = activityType payload.ActivityType = activityType
payload.Url = hook.URL payload.Url = hook.Url
// Use asynchronous webhook dispatch // Use asynchronous webhook dispatch
webhook.PostAsync(payload) webhook.PostAsync(payload)
...@@ -709,14 +706,13 @@ func (s *APIV1Service) dispatchMemoRelatedWebhook(ctx context.Context, memo *v1p ...@@ -709,14 +706,13 @@ func (s *APIV1Service) dispatchMemoRelatedWebhook(ctx context.Context, memo *v1p
return nil return nil
} }
func convertMemoToWebhookPayload(memo *v1pb.Memo) (*v1pb.WebhookRequestPayload, error) { func convertMemoToWebhookPayload(memo *v1pb.Memo) (*webhook.WebhookRequestPayload, error) {
creatorID, err := ExtractUserIDFromName(memo.Creator) creatorID, err := ExtractUserIDFromName(memo.Creator)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "invalid memo creator") return nil, errors.Wrap(err, "invalid memo creator")
} }
return &v1pb.WebhookRequestPayload{ return &webhook.WebhookRequestPayload{
Creator: fmt.Sprintf("%s%d", UserNamePrefix, creatorID), Creator: fmt.Sprintf("%s%d", UserNamePrefix, creatorID),
CreateTime: timestamppb.New(time.Now()),
Memo: memo, Memo: memo,
}, nil }, nil
} }
......
...@@ -146,14 +146,18 @@ func ExtractActivityIDFromName(name string) (int32, error) { ...@@ -146,14 +146,18 @@ func ExtractActivityIDFromName(name string) (int32, error) {
} }
// ExtractWebhookIDFromName returns the webhook ID from a resource name. // ExtractWebhookIDFromName returns the webhook ID from a resource name.
func ExtractWebhookIDFromName(name string) (int32, error) { // Expected format: users/{user}/webhooks/{webhook}
tokens, err := GetNameParentTokens(name, WebhookNamePrefix) func ExtractWebhookIDFromName(name string) (string, error) {
tokens, err := GetNameParentTokens(name, UserNamePrefix, WebhookNamePrefix)
if err != nil { if err != nil {
return 0, err return "", err
} }
id, err := util.ConvertStringToInt32(tokens[0]) if len(tokens) != 2 {
if err != nil { return "", errors.Errorf("invalid webhook name format: %q", name)
return 0, errors.Errorf("invalid webhook ID %q", tokens[0])
} }
return id, nil webhookID := tokens[1]
if webhookID == "" {
return "", errors.Errorf("invalid webhook ID %q", webhookID)
}
return webhookID, nil
} }
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ import (
func TestCreateWebhook(t *testing.T) { func TestCreateWebhook(t *testing.T) {
ctx := context.Background() ctx := context.Background()
t.Run("CreateWebhook with host user", func(t *testing.T) { t.Run("CreateWebhook with host user", func(t *testing.T) {
// Create test service for this specific test // Create test service for this specific test
ts := NewTestService(t) ts := NewTestService(t)
...@@ -27,6 +26,7 @@ func TestCreateWebhook(t *testing.T) { ...@@ -27,6 +26,7 @@ func TestCreateWebhook(t *testing.T) {
// Create a webhook // Create a webhook
req := &v1pb.CreateWebhookRequest{ req := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook", DisplayName: "Test Webhook",
Url: "https://example.com/webhook", Url: "https://example.com/webhook",
...@@ -41,16 +41,16 @@ func TestCreateWebhook(t *testing.T) { ...@@ -41,16 +41,16 @@ func TestCreateWebhook(t *testing.T) {
require.Equal(t, "Test Webhook", resp.DisplayName) require.Equal(t, "Test Webhook", resp.DisplayName)
require.Equal(t, "https://example.com/webhook", resp.Url) require.Equal(t, "https://example.com/webhook", resp.Url)
require.Contains(t, resp.Name, "webhooks/") require.Contains(t, resp.Name, "webhooks/")
require.Equal(t, fmt.Sprintf("users/%d", hostUser.ID), resp.Creator) require.Contains(t, resp.Name, fmt.Sprintf("users/%d", hostUser.ID))
}) })
t.Run("CreateWebhook fails without authentication", func(t *testing.T) { t.Run("CreateWebhook fails without authentication", func(t *testing.T) {
// Create test service for this specific test // Create test service for this specific test
ts := NewTestService(t) ts := NewTestService(t)
defer ts.Cleanup() defer ts.Cleanup()
// Try to create webhook without authentication // Try to create webhook without authentication
req := &v1pb.CreateWebhookRequest{ req := &v1pb.CreateWebhookRequest{
Parent: "users/1", // Dummy parent since we don't have a real user
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook", DisplayName: "Test Webhook",
Url: "https://example.com/webhook", Url: "https://example.com/webhook",
...@@ -73,9 +73,9 @@ func TestCreateWebhook(t *testing.T) { ...@@ -73,9 +73,9 @@ func TestCreateWebhook(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, regularUser.ID) userCtx := ts.CreateUserContext(ctx, regularUser.ID)
// Try to create webhook as regular user // Try to create webhook as regular user
req := &v1pb.CreateWebhookRequest{ req := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", regularUser.ID),
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook", DisplayName: "Test Webhook",
Url: "https://example.com/webhook", Url: "https://example.com/webhook",
...@@ -99,9 +99,9 @@ func TestCreateWebhook(t *testing.T) { ...@@ -99,9 +99,9 @@ func TestCreateWebhook(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID) userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Try to create webhook with missing URL // Try to create webhook with missing URL
req := &v1pb.CreateWebhookRequest{ req := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook", DisplayName: "Test Webhook",
// URL missing // URL missing
...@@ -128,9 +128,10 @@ func TestListWebhooks(t *testing.T) { ...@@ -128,9 +128,10 @@ func TestListWebhooks(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID) userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// List webhooks // List webhooks
req := &v1pb.ListWebhooksRequest{} req := &v1pb.ListWebhooksRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
}
resp, err := ts.Service.ListWebhooks(userCtx, req) resp, err := ts.Service.ListWebhooks(userCtx, req)
// Verify response // Verify response
...@@ -148,9 +149,9 @@ func TestListWebhooks(t *testing.T) { ...@@ -148,9 +149,9 @@ func TestListWebhooks(t *testing.T) {
hostUser, err := ts.CreateHostUser(ctx, "admin") hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID) userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook // Create a webhook
createReq := &v1pb.CreateWebhookRequest{ createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook", DisplayName: "Test Webhook",
Url: "https://example.com/webhook", Url: "https://example.com/webhook",
...@@ -160,7 +161,9 @@ func TestListWebhooks(t *testing.T) { ...@@ -160,7 +161,9 @@ func TestListWebhooks(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// List webhooks // List webhooks
listReq := &v1pb.ListWebhooksRequest{} listReq := &v1pb.ListWebhooksRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
}
resp, err := ts.Service.ListWebhooks(userCtx, listReq) resp, err := ts.Service.ListWebhooks(userCtx, listReq)
// Verify response // Verify response
...@@ -175,9 +178,10 @@ func TestListWebhooks(t *testing.T) { ...@@ -175,9 +178,10 @@ func TestListWebhooks(t *testing.T) {
// Create test service for this specific test // Create test service for this specific test
ts := NewTestService(t) ts := NewTestService(t)
defer ts.Cleanup() defer ts.Cleanup()
// Try to list webhooks without authentication // Try to list webhooks without authentication
req := &v1pb.ListWebhooksRequest{} req := &v1pb.ListWebhooksRequest{
Parent: "users/1", // Dummy parent since we don't have a real user
}
_, err := ts.Service.ListWebhooks(ctx, req) _, err := ts.Service.ListWebhooks(ctx, req)
// Should fail with permission denied or unauthenticated // Should fail with permission denied or unauthenticated
...@@ -197,9 +201,9 @@ func TestGetWebhook(t *testing.T) { ...@@ -197,9 +201,9 @@ func TestGetWebhook(t *testing.T) {
hostUser, err := ts.CreateHostUser(ctx, "admin") hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID) userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook // Create a webhook
createReq := &v1pb.CreateWebhookRequest{ createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook", DisplayName: "Test Webhook",
Url: "https://example.com/webhook", Url: "https://example.com/webhook",
...@@ -213,13 +217,11 @@ func TestGetWebhook(t *testing.T) { ...@@ -213,13 +217,11 @@ func TestGetWebhook(t *testing.T) {
Name: createdWebhook.Name, Name: createdWebhook.Name,
} }
resp, err := ts.Service.GetWebhook(userCtx, getReq) resp, err := ts.Service.GetWebhook(userCtx, getReq)
// Verify response // Verify response
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, resp) require.NotNil(t, resp)
require.Equal(t, createdWebhook.Name, resp.Name) require.Equal(t, createdWebhook.Name, resp.Name)
require.Equal(t, createdWebhook.Url, resp.Url) require.Equal(t, createdWebhook.Url, resp.Url)
require.Equal(t, createdWebhook.Creator, resp.Creator)
}) })
t.Run("GetWebhook fails with invalid name", func(t *testing.T) { t.Run("GetWebhook fails with invalid name", func(t *testing.T) {
...@@ -251,10 +253,9 @@ func TestGetWebhook(t *testing.T) { ...@@ -251,10 +253,9 @@ func TestGetWebhook(t *testing.T) {
hostUser, err := ts.CreateHostUser(ctx, "admin") hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID) userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Try to get non-existent webhook // Try to get non-existent webhook
req := &v1pb.GetWebhookRequest{ req := &v1pb.GetWebhookRequest{
Name: "webhooks/999", Name: fmt.Sprintf("users/%d/webhooks/999", hostUser.ID),
} }
_, err = ts.Service.GetWebhook(userCtx, req) _, err = ts.Service.GetWebhook(userCtx, req)
...@@ -276,11 +277,11 @@ func TestUpdateWebhook(t *testing.T) { ...@@ -276,11 +277,11 @@ func TestUpdateWebhook(t *testing.T) {
hostUser, err := ts.CreateHostUser(ctx, "admin") hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID) userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Create a webhook // Create a webhook
createReq := &v1pb.CreateWebhookRequest{ createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
Name: "Original Webhook", DisplayName: "Original Webhook",
Url: "https://example.com/webhook", Url: "https://example.com/webhook",
}, },
} }
...@@ -310,11 +311,10 @@ func TestUpdateWebhook(t *testing.T) { ...@@ -310,11 +311,10 @@ func TestUpdateWebhook(t *testing.T) {
// Create test service for this specific test // Create test service for this specific test
ts := NewTestService(t) ts := NewTestService(t)
defer ts.Cleanup() defer ts.Cleanup()
// Try to update webhook without authentication // Try to update webhook without authentication
req := &v1pb.UpdateWebhookRequest{ req := &v1pb.UpdateWebhookRequest{
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
Name: "webhooks/1", Name: "users/1/webhooks/1",
Url: "https://updated.example.com/webhook", Url: "https://updated.example.com/webhook",
}, },
} }
...@@ -328,7 +328,6 @@ func TestUpdateWebhook(t *testing.T) { ...@@ -328,7 +328,6 @@ func TestUpdateWebhook(t *testing.T) {
func TestDeleteWebhook(t *testing.T) { func TestDeleteWebhook(t *testing.T) {
ctx := context.Background() ctx := context.Background()
t.Run("DeleteWebhook removes webhook", func(t *testing.T) { t.Run("DeleteWebhook removes webhook", func(t *testing.T) {
// Create test service for this specific test // Create test service for this specific test
ts := NewTestService(t) ts := NewTestService(t)
...@@ -341,6 +340,7 @@ func TestDeleteWebhook(t *testing.T) { ...@@ -341,6 +340,7 @@ func TestDeleteWebhook(t *testing.T) {
// Create a webhook // Create a webhook
createReq := &v1pb.CreateWebhookRequest{ createReq := &v1pb.CreateWebhookRequest{
Parent: fmt.Sprintf("users/%d", hostUser.ID),
Webhook: &v1pb.Webhook{ Webhook: &v1pb.Webhook{
DisplayName: "Test Webhook", DisplayName: "Test Webhook",
Url: "https://example.com/webhook", Url: "https://example.com/webhook",
...@@ -373,10 +373,9 @@ func TestDeleteWebhook(t *testing.T) { ...@@ -373,10 +373,9 @@ func TestDeleteWebhook(t *testing.T) {
// Create test service for this specific test // Create test service for this specific test
ts := NewTestService(t) ts := NewTestService(t)
defer ts.Cleanup() defer ts.Cleanup()
// Try to delete webhook without authentication // Try to delete webhook without authentication
req := &v1pb.DeleteWebhookRequest{ req := &v1pb.DeleteWebhookRequest{
Name: "webhooks/1", Name: "users/1/webhooks/1",
} }
_, err := ts.Service.DeleteWebhook(ctx, req) _, err := ts.Service.DeleteWebhook(ctx, req)
...@@ -394,10 +393,9 @@ func TestDeleteWebhook(t *testing.T) { ...@@ -394,10 +393,9 @@ func TestDeleteWebhook(t *testing.T) {
hostUser, err := ts.CreateHostUser(ctx, "admin") hostUser, err := ts.CreateHostUser(ctx, "admin")
require.NoError(t, err) require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, hostUser.ID) userCtx := ts.CreateUserContext(ctx, hostUser.ID)
// Try to delete non-existent webhook // Try to delete non-existent webhook
req := &v1pb.DeleteWebhookRequest{ req := &v1pb.DeleteWebhookRequest{
Name: "webhooks/999", Name: fmt.Sprintf("users/%d/webhooks/999", hostUser.ID),
} }
_, err = ts.Service.DeleteWebhook(userCtx, req) _, err = ts.Service.DeleteWebhook(userCtx, req)
......
...@@ -2,17 +2,18 @@ package v1 ...@@ -2,17 +2,18 @@ package v1
import ( import (
"context" "context"
"crypto/rand"
"encoding/hex"
"fmt" "fmt"
"strings" "strings"
"time"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/usememos/memos/internal/util"
v1pb "github.com/usememos/memos/proto/gen/api/v1" v1pb "github.com/usememos/memos/proto/gen/api/v1"
"github.com/usememos/memos/store" storepb "github.com/usememos/memos/proto/gen/store"
) )
func (s *APIV1Service) CreateWebhook(ctx context.Context, request *v1pb.CreateWebhookRequest) (*v1pb.Webhook, error) { func (s *APIV1Service) CreateWebhook(ctx context.Context, request *v1pb.CreateWebhookRequest) (*v1pb.Webhook, error) {
...@@ -24,6 +25,17 @@ func (s *APIV1Service) CreateWebhook(ctx context.Context, request *v1pb.CreateWe ...@@ -24,6 +25,17 @@ func (s *APIV1Service) CreateWebhook(ctx context.Context, request *v1pb.CreateWe
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated") return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
} }
// Extract user ID from parent (format: users/{user})
parentUserID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}
// Users can only create webhooks for themselves
if parentUserID != currentUser.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
// Only host users can create webhooks // Only host users can create webhooks
if !isSuperUser(currentUser) { if !isSuperUser(currentUser) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied") return nil, status.Errorf(codes.PermissionDenied, "permission denied")
...@@ -37,29 +49,42 @@ func (s *APIV1Service) CreateWebhook(ctx context.Context, request *v1pb.CreateWe ...@@ -37,29 +49,42 @@ func (s *APIV1Service) CreateWebhook(ctx context.Context, request *v1pb.CreateWe
return nil, status.Errorf(codes.InvalidArgument, "webhook URL is required") return nil, status.Errorf(codes.InvalidArgument, "webhook URL is required")
} }
// TODO: Handle webhook_id, validate_only, and request_id fields // Handle validate_only field
if request.ValidateOnly { if request.ValidateOnly {
// Perform validation checks without actually creating the webhook // Perform validation checks without actually creating the webhook
return &v1pb.Webhook{ return &v1pb.Webhook{
Name: fmt.Sprintf("users/%d/webhooks/validate", currentUser.ID),
DisplayName: request.Webhook.DisplayName, DisplayName: request.Webhook.DisplayName,
Url: request.Webhook.Url, Url: request.Webhook.Url,
Creator: fmt.Sprintf("users/%d", currentUser.ID),
State: request.Webhook.State,
}, nil }, nil
} }
webhook, err := s.Store.CreateWebhook(ctx, &store.Webhook{ err = s.Store.AddUserWebhook(ctx, currentUser.ID, &storepb.WebhooksUserSetting_Webhook{
CreatorID: currentUser.ID, Id: generateWebhookID(),
Name: request.Webhook.DisplayName, Title: request.Webhook.DisplayName,
URL: strings.TrimSpace(request.Webhook.Url), Url: strings.TrimSpace(request.Webhook.Url),
}) })
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create webhook, error: %+v", err) return nil, status.Errorf(codes.Internal, "failed to create webhook, error: %+v", err)
} }
return convertWebhookFromStore(webhook), nil
// Return the newly created webhook
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user webhooks, error: %+v", err)
}
// Find the webhook we just created
for _, webhook := range webhooks {
if webhook.Title == request.Webhook.DisplayName && webhook.Url == strings.TrimSpace(request.Webhook.Url) {
return convertWebhookFromUserSetting(webhook, currentUser.ID), nil
}
}
return nil, status.Errorf(codes.Internal, "failed to find created webhook")
} }
func (s *APIV1Service) ListWebhooks(ctx context.Context, _ *v1pb.ListWebhooksRequest) (*v1pb.ListWebhooksResponse, error) { func (s *APIV1Service) ListWebhooks(ctx context.Context, request *v1pb.ListWebhooksRequest) (*v1pb.ListWebhooksResponse, error) {
currentUser, err := s.GetCurrentUser(ctx) currentUser, err := s.GetCurrentUser(ctx)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err) return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
...@@ -68,11 +93,18 @@ func (s *APIV1Service) ListWebhooks(ctx context.Context, _ *v1pb.ListWebhooksReq ...@@ -68,11 +93,18 @@ func (s *APIV1Service) ListWebhooks(ctx context.Context, _ *v1pb.ListWebhooksReq
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated") return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
} }
// TODO: Implement proper filtering, ordering, and pagination // Extract user ID from parent (format: users/{user})
// For now, list webhooks for the current user parentUserID, err := ExtractUserIDFromName(request.Parent)
webhooks, err := s.Store.ListWebhooks(ctx, &store.FindWebhook{ if err != nil {
CreatorID: &currentUser.ID, return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}) }
// Users can only list their own webhooks
if parentUserID != currentUser.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list webhooks, error: %+v", err) return nil, status.Errorf(codes.Internal, "failed to list webhooks, error: %+v", err)
} }
...@@ -81,16 +113,28 @@ func (s *APIV1Service) ListWebhooks(ctx context.Context, _ *v1pb.ListWebhooksReq ...@@ -81,16 +113,28 @@ func (s *APIV1Service) ListWebhooks(ctx context.Context, _ *v1pb.ListWebhooksReq
Webhooks: []*v1pb.Webhook{}, Webhooks: []*v1pb.Webhook{},
} }
for _, webhook := range webhooks { for _, webhook := range webhooks {
response.Webhooks = append(response.Webhooks, convertWebhookFromStore(webhook)) response.Webhooks = append(response.Webhooks, convertWebhookFromUserSetting(webhook, currentUser.ID))
} }
return response, nil return response, nil
} }
func (s *APIV1Service) GetWebhook(ctx context.Context, request *v1pb.GetWebhookRequest) (*v1pb.Webhook, error) { func (s *APIV1Service) GetWebhook(ctx context.Context, request *v1pb.GetWebhookRequest) (*v1pb.Webhook, error) {
webhookID, err := ExtractWebhookIDFromName(request.Name) // Extract user ID and webhook ID from name (format: users/{user}/webhooks/{webhook})
tokens, err := GetNameParentTokens(request.Name, UserNamePrefix, WebhookNamePrefix)
if err != nil { if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err) return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
} }
if len(tokens) != 2 {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name format")
}
userIDStr := tokens[0]
webhookID := tokens[1]
requestedUserID, err := util.ConvertStringToInt32(userIDStr)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user ID in webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx) currentUser, err := s.GetCurrentUser(ctx)
if err != nil { if err != nil {
...@@ -100,22 +144,23 @@ func (s *APIV1Service) GetWebhook(ctx context.Context, request *v1pb.GetWebhookR ...@@ -100,22 +144,23 @@ func (s *APIV1Service) GetWebhook(ctx context.Context, request *v1pb.GetWebhookR
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated") return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
} }
webhook, err := s.Store.GetWebhook(ctx, &store.FindWebhook{ // Users can only access their own webhooks
ID: &webhookID, if requestedUserID != currentUser.ID {
CreatorID: &currentUser.ID, return nil, status.Errorf(codes.PermissionDenied, "permission denied")
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get webhook, error: %+v", err)
}
if webhook == nil {
return nil, status.Errorf(codes.NotFound, "webhook not found")
} }
webhookPb := convertWebhookFromStore(webhook) webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil {
// TODO: Implement read_mask field filtering return nil, status.Errorf(codes.Internal, "failed to get webhooks, error: %+v", err)
}
return webhookPb, nil // Find webhook by ID
for _, webhook := range webhooks {
if webhook.Id == webhookID {
return convertWebhookFromUserSetting(webhook, currentUser.ID), nil
}
}
return nil, status.Errorf(codes.NotFound, "webhook not found")
} }
func (s *APIV1Service) UpdateWebhook(ctx context.Context, request *v1pb.UpdateWebhookRequest) (*v1pb.Webhook, error) { func (s *APIV1Service) UpdateWebhook(ctx context.Context, request *v1pb.UpdateWebhookRequest) (*v1pb.Webhook, error) {
...@@ -123,10 +168,22 @@ func (s *APIV1Service) UpdateWebhook(ctx context.Context, request *v1pb.UpdateWe ...@@ -123,10 +168,22 @@ func (s *APIV1Service) UpdateWebhook(ctx context.Context, request *v1pb.UpdateWe
return nil, status.Errorf(codes.InvalidArgument, "update_mask is required") return nil, status.Errorf(codes.InvalidArgument, "update_mask is required")
} }
webhookID, err := ExtractWebhookIDFromName(request.Webhook.Name) // Extract user ID and webhook ID from name (format: users/{user}/webhooks/{webhook})
tokens, err := GetNameParentTokens(request.Webhook.Name, UserNamePrefix, WebhookNamePrefix)
if err != nil { if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err) return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
} }
if len(tokens) != 2 {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name format")
}
userIDStr := tokens[0]
webhookID := tokens[1]
requestedUserID, err := util.ConvertStringToInt32(userIDStr)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user ID in webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx) currentUser, err := s.GetCurrentUser(ctx)
if err != nil { if err != nil {
...@@ -136,44 +193,75 @@ func (s *APIV1Service) UpdateWebhook(ctx context.Context, request *v1pb.UpdateWe ...@@ -136,44 +193,75 @@ func (s *APIV1Service) UpdateWebhook(ctx context.Context, request *v1pb.UpdateWe
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated") return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
} }
// Check if webhook exists and user has permission // Users can only update their own webhooks
existingWebhook, err := s.Store.GetWebhook(ctx, &store.FindWebhook{ if requestedUserID != currentUser.ID {
ID: &webhookID, return nil, status.Errorf(codes.PermissionDenied, "permission denied")
CreatorID: &currentUser.ID, }
})
// Get existing webhooks from user settings
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get webhook: %v", err) return nil, status.Errorf(codes.Internal, "failed to get webhooks: %v", err)
}
// Find the webhook to update
var existingWebhook *storepb.WebhooksUserSetting_Webhook
for _, webhook := range webhooks {
if webhook.Id == webhookID {
existingWebhook = webhook
break
} }
}
if existingWebhook == nil { if existingWebhook == nil {
return nil, status.Errorf(codes.NotFound, "webhook not found") return nil, status.Errorf(codes.NotFound, "webhook not found")
} }
update := &store.UpdateWebhook{ // Create updated webhook
ID: webhookID, updatedWebhook := &storepb.WebhooksUserSetting_Webhook{
Id: existingWebhook.Id,
Title: existingWebhook.Title,
Url: existingWebhook.Url,
} }
// Apply updates based on update mask
for _, field := range request.UpdateMask.Paths { for _, field := range request.UpdateMask.Paths {
switch field { switch field {
case "display_name": case "display_name":
update.Name = &request.Webhook.DisplayName updatedWebhook.Title = request.Webhook.DisplayName
case "url": case "url":
update.URL = &request.Webhook.Url updatedWebhook.Url = request.Webhook.Url
default: default:
return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field) return nil, status.Errorf(codes.InvalidArgument, "invalid update path: %s", field)
} }
} }
webhook, err := s.Store.UpdateWebhook(ctx, update) // Update the webhook in user settings
err = s.Store.UpdateUserWebhook(ctx, currentUser.ID, updatedWebhook)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to update webhook, error: %+v", err) return nil, status.Errorf(codes.Internal, "failed to update webhook: %v", err)
} }
return convertWebhookFromStore(webhook), nil
return convertWebhookFromUserSetting(updatedWebhook, currentUser.ID), nil
} }
func (s *APIV1Service) DeleteWebhook(ctx context.Context, request *v1pb.DeleteWebhookRequest) (*emptypb.Empty, error) { func (s *APIV1Service) DeleteWebhook(ctx context.Context, request *v1pb.DeleteWebhookRequest) (*emptypb.Empty, error) {
webhookID, err := ExtractWebhookIDFromName(request.Name) // Extract user ID and webhook ID from name (format: users/{user}/webhooks/{webhook})
tokens, err := GetNameParentTokens(request.Name, UserNamePrefix, WebhookNamePrefix)
if err != nil { if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err) return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name: %v", err)
} }
if len(tokens) != 2 {
return nil, status.Errorf(codes.InvalidArgument, "invalid webhook name format")
}
userIDStr := tokens[0]
webhookID := tokens[1]
requestedUserID, err := util.ConvertStringToInt32(userIDStr)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid user ID in webhook name: %v", err)
}
currentUser, err := s.GetCurrentUser(ctx) currentUser, err := s.GetCurrentUser(ctx)
if err != nil { if err != nil {
...@@ -183,37 +271,47 @@ func (s *APIV1Service) DeleteWebhook(ctx context.Context, request *v1pb.DeleteWe ...@@ -183,37 +271,47 @@ func (s *APIV1Service) DeleteWebhook(ctx context.Context, request *v1pb.DeleteWe
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated") return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
} }
// Check if webhook exists and user has permission // Users can only delete their own webhooks
webhook, err := s.Store.GetWebhook(ctx, &store.FindWebhook{ if requestedUserID != currentUser.ID {
ID: &webhookID, return nil, status.Errorf(codes.PermissionDenied, "permission denied")
CreatorID: &currentUser.ID, }
})
// Get existing webhooks from user settings to verify it exists
webhooks, err := s.Store.GetUserWebhooks(ctx, currentUser.ID)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get webhook: %v", err) return nil, status.Errorf(codes.Internal, "failed to get webhooks: %v", err)
}
// Check if webhook exists
webhookExists := false
for _, webhook := range webhooks {
if webhook.Id == webhookID {
webhookExists = true
break
} }
if webhook == nil {
return nil, status.Errorf(codes.NotFound, "webhook not found")
} }
// TODO: Handle force field properly if !webhookExists {
return nil, status.Errorf(codes.NotFound, "webhook not found")
}
err = s.Store.DeleteWebhook(ctx, &store.DeleteWebhook{ err = s.Store.RemoveUserWebhook(ctx, currentUser.ID, webhookID)
ID: webhookID,
})
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to delete webhook, error: %+v", err) return nil, status.Errorf(codes.Internal, "failed to delete webhook: %v", err)
} }
return &emptypb.Empty{}, nil return &emptypb.Empty{}, nil
} }
func convertWebhookFromStore(webhook *store.Webhook) *v1pb.Webhook { func convertWebhookFromUserSetting(webhook *storepb.WebhooksUserSetting_Webhook, userID int32) *v1pb.Webhook {
return &v1pb.Webhook{ return &v1pb.Webhook{
Name: fmt.Sprintf("webhooks/%d", webhook.ID), Name: fmt.Sprintf("users/%d/webhooks/%s", userID, webhook.Id),
DisplayName: webhook.Name, DisplayName: webhook.Title,
Url: webhook.URL, Url: webhook.Url,
Creator: fmt.Sprintf("users/%d", webhook.CreatorID),
State: v1pb.State_NORMAL, // Default to NORMAL state for webhooks
CreateTime: timestamppb.New(time.Unix(webhook.CreatedTs, 0)),
UpdateTime: timestamppb.New(time.Unix(webhook.UpdatedTs, 0)),
} }
} }
func generateWebhookID() string {
b := make([]byte, 8)
rand.Read(b)
return hex.EncodeToString(b)
}
package mysql
import (
"context"
"strings"
"github.com/usememos/memos/store"
)
func (d *DB) CreateWebhook(ctx context.Context, create *store.Webhook) (*store.Webhook, error) {
fields := []string{"`name`", "`url`", "`creator_id`"}
placeholder := []string{"?", "?", "?"}
args := []any{create.Name, create.URL, create.CreatorID}
stmt := "INSERT INTO `webhook` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ")"
result, err := d.db.ExecContext(ctx, stmt, args...)
if err != nil {
return nil, err
}
id, err := result.LastInsertId()
if err != nil {
return nil, err
}
create.ID = int32(id)
return d.GetWebhook(ctx, &store.FindWebhook{ID: &create.ID})
}
func (d *DB) ListWebhooks(ctx context.Context, find *store.FindWebhook) ([]*store.Webhook, error) {
where, args := []string{"1 = 1"}, []any{}
if find.ID != nil {
where, args = append(where, "`id` = ?"), append(args, *find.ID)
}
if find.CreatorID != nil {
where, args = append(where, "`creator_id` = ?"), append(args, *find.CreatorID)
}
rows, err := d.db.QueryContext(ctx, "SELECT `id`, UNIX_TIMESTAMP(`created_ts`), UNIX_TIMESTAMP(`updated_ts`), `creator_id`, `name`, `url` FROM `webhook` WHERE "+strings.Join(where, " AND ")+" ORDER BY `id` DESC",
args...,
)
if err != nil {
return nil, err
}
defer rows.Close()
list := []*store.Webhook{}
for rows.Next() {
webhook := &store.Webhook{}
if err := rows.Scan(
&webhook.ID,
&webhook.CreatedTs,
&webhook.UpdatedTs,
&webhook.CreatorID,
&webhook.Name,
&webhook.URL,
); err != nil {
return nil, err
}
list = append(list, webhook)
}
if err := rows.Err(); err != nil {
return nil, err
}
return list, nil
}
func (d *DB) GetWebhook(ctx context.Context, find *store.FindWebhook) (*store.Webhook, error) {
list, err := d.ListWebhooks(ctx, find)
if err != nil {
return nil, err
}
if len(list) == 0 {
return nil, nil
}
return list[0], nil
}
func (d *DB) UpdateWebhook(ctx context.Context, update *store.UpdateWebhook) (*store.Webhook, error) {
set, args := []string{}, []any{}
if update.Name != nil {
set, args = append(set, "`name` = ?"), append(args, *update.Name)
}
if update.URL != nil {
set, args = append(set, "`url` = ?"), append(args, *update.URL)
}
args = append(args, update.ID)
stmt := "UPDATE `webhook` SET " + strings.Join(set, ", ") + " WHERE `id` = ?"
_, err := d.db.ExecContext(ctx, stmt, args...)
if err != nil {
return nil, err
}
webhook, err := d.GetWebhook(ctx, &store.FindWebhook{ID: &update.ID})
if err != nil {
return nil, err
}
return webhook, nil
}
func (d *DB) DeleteWebhook(ctx context.Context, delete *store.DeleteWebhook) error {
_, err := d.db.ExecContext(ctx, "DELETE FROM `webhook` WHERE `id` = ?", delete.ID)
return err
}
package postgres
import (
"context"
"strings"
"github.com/usememos/memos/store"
)
func (d *DB) CreateWebhook(ctx context.Context, create *store.Webhook) (*store.Webhook, error) {
fields := []string{"name", "url", "creator_id"}
args := []any{create.Name, create.URL, create.CreatorID}
stmt := "INSERT INTO webhook (" + strings.Join(fields, ", ") + ") VALUES (" + placeholders(len(args)) + ") RETURNING id, created_ts, updated_ts"
if err := d.db.QueryRowContext(ctx, stmt, args...).Scan(
&create.ID,
&create.CreatedTs,
&create.UpdatedTs,
); err != nil {
return nil, err
}
webhook := create
return webhook, nil
}
func (d *DB) ListWebhooks(ctx context.Context, find *store.FindWebhook) ([]*store.Webhook, error) {
where, args := []string{"1 = 1"}, []any{}
if find.ID != nil {
where, args = append(where, "id = "+placeholder(len(args)+1)), append(args, *find.ID)
}
if find.CreatorID != nil {
where, args = append(where, "creator_id = "+placeholder(len(args)+1)), append(args, *find.CreatorID)
}
rows, err := d.db.QueryContext(ctx, `
SELECT
id,
created_ts,
updated_ts,
creator_id,
name,
url
FROM webhook
WHERE `+strings.Join(where, " AND ")+`
ORDER BY id DESC`,
args...,
)
if err != nil {
return nil, err
}
defer rows.Close()
list := []*store.Webhook{}
for rows.Next() {
webhook := &store.Webhook{}
if err := rows.Scan(
&webhook.ID,
&webhook.CreatedTs,
&webhook.UpdatedTs,
&webhook.CreatorID,
&webhook.Name,
&webhook.URL,
); err != nil {
return nil, err
}
list = append(list, webhook)
}
if err := rows.Err(); err != nil {
return nil, err
}
return list, nil
}
func (d *DB) UpdateWebhook(ctx context.Context, update *store.UpdateWebhook) (*store.Webhook, error) {
set, args := []string{}, []any{}
if update.Name != nil {
set, args = append(set, "name = "+placeholder(len(args)+1)), append(args, *update.Name)
}
if update.URL != nil {
set, args = append(set, "url = "+placeholder(len(args)+1)), append(args, *update.URL)
}
stmt := "UPDATE webhook SET " + strings.Join(set, ", ") + " WHERE id = " + placeholder(len(args)+1) + " RETURNING id, created_ts, updated_ts, creator_id, name, url"
args = append(args, update.ID)
webhook := &store.Webhook{}
if err := d.db.QueryRowContext(ctx, stmt, args...).Scan(
&webhook.ID,
&webhook.CreatedTs,
&webhook.UpdatedTs,
&webhook.CreatorID,
&webhook.Name,
&webhook.URL,
); err != nil {
return nil, err
}
return webhook, nil
}
func (d *DB) DeleteWebhook(ctx context.Context, delete *store.DeleteWebhook) error {
_, err := d.db.ExecContext(ctx, "DELETE FROM webhook WHERE id = $1", delete.ID)
return err
}
package sqlite
import (
"context"
"strings"
"github.com/usememos/memos/store"
)
func (d *DB) CreateWebhook(ctx context.Context, create *store.Webhook) (*store.Webhook, error) {
fields := []string{"`name`", "`url`", "`creator_id`"}
placeholder := []string{"?", "?", "?"}
args := []any{create.Name, create.URL, create.CreatorID}
stmt := "INSERT INTO `webhook` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ") RETURNING `id`, `created_ts`, `updated_ts`"
if err := d.db.QueryRowContext(ctx, stmt, args...).Scan(
&create.ID,
&create.CreatedTs,
&create.UpdatedTs,
); err != nil {
return nil, err
}
webhook := create
return webhook, nil
}
func (d *DB) ListWebhooks(ctx context.Context, find *store.FindWebhook) ([]*store.Webhook, error) {
where, args := []string{"1 = 1"}, []any{}
if find.ID != nil {
where, args = append(where, "`id` = ?"), append(args, *find.ID)
}
if find.CreatorID != nil {
where, args = append(where, "`creator_id` = ?"), append(args, *find.CreatorID)
}
rows, err := d.db.QueryContext(ctx, `
SELECT
id,
created_ts,
updated_ts,
creator_id,
name,
url
FROM webhook
WHERE `+strings.Join(where, " AND ")+`
ORDER BY id DESC`,
args...,
)
if err != nil {
return nil, err
}
defer rows.Close()
list := []*store.Webhook{}
for rows.Next() {
webhook := &store.Webhook{}
if err := rows.Scan(
&webhook.ID,
&webhook.CreatedTs,
&webhook.UpdatedTs,
&webhook.CreatorID,
&webhook.Name,
&webhook.URL,
); err != nil {
return nil, err
}
list = append(list, webhook)
}
if err := rows.Err(); err != nil {
return nil, err
}
return list, nil
}
func (d *DB) UpdateWebhook(ctx context.Context, update *store.UpdateWebhook) (*store.Webhook, error) {
set, args := []string{}, []any{}
if update.Name != nil {
set, args = append(set, "name = ?"), append(args, *update.Name)
}
if update.URL != nil {
set, args = append(set, "url = ?"), append(args, *update.URL)
}
args = append(args, update.ID)
stmt := "UPDATE `webhook` SET " + strings.Join(set, ", ") + " WHERE `id` = ? RETURNING `id`, `created_ts`, `updated_ts`, `creator_id`, `name`, `url`"
webhook := &store.Webhook{}
if err := d.db.QueryRowContext(ctx, stmt, args...).Scan(
&webhook.ID,
&webhook.CreatedTs,
&webhook.UpdatedTs,
&webhook.CreatorID,
&webhook.Name,
&webhook.URL,
); err != nil {
return nil, err
}
return webhook, nil
}
func (d *DB) DeleteWebhook(ctx context.Context, delete *store.DeleteWebhook) error {
_, err := d.db.ExecContext(ctx, "DELETE FROM `webhook` WHERE `id` = ?", delete.ID)
return err
}
...@@ -69,12 +69,6 @@ type Driver interface { ...@@ -69,12 +69,6 @@ type Driver interface {
UpdateInbox(ctx context.Context, update *UpdateInbox) (*Inbox, error) UpdateInbox(ctx context.Context, update *UpdateInbox) (*Inbox, error)
DeleteInbox(ctx context.Context, delete *DeleteInbox) error DeleteInbox(ctx context.Context, delete *DeleteInbox) error
// Webhook model related methods.
CreateWebhook(ctx context.Context, create *Webhook) (*Webhook, error)
ListWebhooks(ctx context.Context, find *FindWebhook) ([]*Webhook, error)
UpdateWebhook(ctx context.Context, update *UpdateWebhook) (*Webhook, error)
DeleteWebhook(ctx context.Context, delete *DeleteWebhook) error
// Reaction model related methods. // Reaction model related methods.
UpsertReaction(ctx context.Context, create *Reaction) (*Reaction, error) UpsertReaction(ctx context.Context, create *Reaction) (*Reaction, error)
ListReactions(ctx context.Context, find *FindReaction) ([]*Reaction, error) ListReactions(ctx context.Context, find *FindReaction) ([]*Reaction, error)
......
package teststore
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/usememos/memos/store"
)
func TestWebhookStore(t *testing.T) {
ctx := context.Background()
ts := NewTestingStore(ctx, t)
user, err := createTestingHostUser(ctx, ts)
require.NoError(t, err)
webhook, err := ts.CreateWebhook(ctx, &store.Webhook{
CreatorID: user.ID,
Name: "test_webhook",
URL: "https://example.com",
})
require.NoError(t, err)
require.Equal(t, "test_webhook", webhook.Name)
require.Equal(t, user.ID, webhook.CreatorID)
webhooks, err := ts.ListWebhooks(ctx, &store.FindWebhook{
CreatorID: &user.ID,
})
require.NoError(t, err)
require.Equal(t, 1, len(webhooks))
require.Equal(t, webhook, webhooks[0])
newName := "test_webhook_new"
updatedWebhook, err := ts.UpdateWebhook(ctx, &store.UpdateWebhook{
ID: webhook.ID,
Name: &newName,
})
require.NoError(t, err)
require.Equal(t, newName, updatedWebhook.Name)
require.Equal(t, webhook.CreatorID, updatedWebhook.CreatorID)
err = ts.DeleteWebhook(ctx, &store.DeleteWebhook{
ID: webhook.ID,
})
require.NoError(t, err)
webhooks, err = ts.ListWebhooks(ctx, &store.FindWebhook{
CreatorID: &user.ID,
})
require.NoError(t, err)
require.Equal(t, 0, len(webhooks))
ts.Close()
}
...@@ -241,6 +241,114 @@ func (s *Store) UpdateUserSessionLastAccessed(ctx context.Context, userID int32, ...@@ -241,6 +241,114 @@ func (s *Store) UpdateUserSessionLastAccessed(ctx context.Context, userID int32,
return err return err
} }
// GetUserWebhooks returns the webhooks of the user.
func (s *Store) GetUserWebhooks(ctx context.Context, userID int32) ([]*storepb.WebhooksUserSetting_Webhook, error) {
userSetting, err := s.GetUserSetting(ctx, &FindUserSetting{
UserID: &userID,
Key: storepb.UserSetting_WEBHOOKS,
})
if err != nil {
return nil, err
}
if userSetting == nil {
return []*storepb.WebhooksUserSetting_Webhook{}, nil
}
webhooksUserSetting := userSetting.GetWebhooks()
return webhooksUserSetting.Webhooks, nil
}
// AddUserWebhook adds a new webhook for the user.
func (s *Store) AddUserWebhook(ctx context.Context, userID int32, webhook *storepb.WebhooksUserSetting_Webhook) error {
existingWebhooks, err := s.GetUserWebhooks(ctx, userID)
if err != nil {
return err
}
// Check if webhook already exists, update if it does
var updatedWebhooks []*storepb.WebhooksUserSetting_Webhook
webhookExists := false
for _, existing := range existingWebhooks {
if existing.Id == webhook.Id {
updatedWebhooks = append(updatedWebhooks, webhook)
webhookExists = true
} else {
updatedWebhooks = append(updatedWebhooks, existing)
}
}
// If webhook doesn't exist, add it
if !webhookExists {
updatedWebhooks = append(updatedWebhooks, webhook)
}
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSetting_WEBHOOKS,
Value: &storepb.UserSetting_Webhooks{
Webhooks: &storepb.WebhooksUserSetting{
Webhooks: updatedWebhooks,
},
},
})
return err
}
// RemoveUserWebhook removes the webhook of the user.
func (s *Store) RemoveUserWebhook(ctx context.Context, userID int32, webhookID string) error {
oldWebhooks, err := s.GetUserWebhooks(ctx, userID)
if err != nil {
return err
}
newWebhooks := make([]*storepb.WebhooksUserSetting_Webhook, 0, len(oldWebhooks))
for _, webhook := range oldWebhooks {
if webhookID != webhook.Id {
newWebhooks = append(newWebhooks, webhook)
}
}
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSetting_WEBHOOKS,
Value: &storepb.UserSetting_Webhooks{
Webhooks: &storepb.WebhooksUserSetting{
Webhooks: newWebhooks,
},
},
})
return err
}
// UpdateUserWebhook updates an existing webhook for the user.
func (s *Store) UpdateUserWebhook(ctx context.Context, userID int32, webhook *storepb.WebhooksUserSetting_Webhook) error {
webhooks, err := s.GetUserWebhooks(ctx, userID)
if err != nil {
return err
}
for i, existing := range webhooks {
if existing.Id == webhook.Id {
webhooks[i] = webhook
break
}
}
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSetting_WEBHOOKS,
Value: &storepb.UserSetting_Webhooks{
Webhooks: &storepb.WebhooksUserSetting{
Webhooks: webhooks,
},
},
})
return err
}
func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) { func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) {
userSetting := &storepb.UserSetting{ userSetting := &storepb.UserSetting{
UserId: raw.UserID, UserId: raw.UserID,
...@@ -272,6 +380,12 @@ func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) { ...@@ -272,6 +380,12 @@ func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) {
return nil, err return nil, err
} }
userSetting.Value = &storepb.UserSetting_General{General: generalUserSetting} userSetting.Value = &storepb.UserSetting_General{General: generalUserSetting}
case storepb.UserSetting_WEBHOOKS:
webhooksUserSetting := &storepb.WebhooksUserSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(raw.Value), webhooksUserSetting); err != nil {
return nil, err
}
userSetting.Value = &storepb.UserSetting_Webhooks{Webhooks: webhooksUserSetting}
default: default:
return nil, nil return nil, nil
} }
...@@ -313,6 +427,13 @@ func convertUserSettingToRaw(userSetting *storepb.UserSetting) (*UserSetting, er ...@@ -313,6 +427,13 @@ func convertUserSettingToRaw(userSetting *storepb.UserSetting) (*UserSetting, er
return nil, err return nil, err
} }
raw.Value = string(value) raw.Value = string(value)
case storepb.UserSetting_WEBHOOKS:
webhooksUserSetting := userSetting.GetWebhooks()
value, err := protojson.Marshal(webhooksUserSetting)
if err != nil {
return nil, err
}
raw.Value = string(value)
default: default:
return nil, errors.Errorf("unsupported user setting key: %v", userSetting.Key) return nil, errors.Errorf("unsupported user setting key: %v", userSetting.Key)
} }
......
package store
import (
"context"
)
type Webhook struct {
ID int32
CreatedTs int64
UpdatedTs int64
CreatorID int32
Name string
URL string
}
type FindWebhook struct {
ID *int32
CreatorID *int32
}
type UpdateWebhook struct {
ID int32
Name *string
URL *string
}
type DeleteWebhook struct {
ID int32
}
func (s *Store) CreateWebhook(ctx context.Context, create *Webhook) (*Webhook, error) {
return s.driver.CreateWebhook(ctx, create)
}
func (s *Store) ListWebhooks(ctx context.Context, find *FindWebhook) ([]*Webhook, error) {
return s.driver.ListWebhooks(ctx, find)
}
func (s *Store) GetWebhook(ctx context.Context, find *FindWebhook) (*Webhook, error) {
list, err := s.ListWebhooks(ctx, find)
if err != nil {
return nil, err
}
if len(list) == 0 {
return nil, nil
}
return list[0], nil
}
func (s *Store) UpdateWebhook(ctx context.Context, update *UpdateWebhook) (*Webhook, error) {
return s.driver.UpdateWebhook(ctx, update)
}
func (s *Store) DeleteWebhook(ctx context.Context, delete *DeleteWebhook) error {
return s.driver.DeleteWebhook(ctx, delete)
}
...@@ -3,6 +3,7 @@ import { XIcon } from "lucide-react"; ...@@ -3,6 +3,7 @@ import { XIcon } from "lucide-react";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { toast } from "react-hot-toast"; import { toast } from "react-hot-toast";
import { webhookServiceClient } from "@/grpcweb"; import { webhookServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
import useLoading from "@/hooks/useLoading"; import useLoading from "@/hooks/useLoading";
import { useTranslate } from "@/utils/i18n"; import { useTranslate } from "@/utils/i18n";
import { generateDialog } from "./Dialog"; import { generateDialog } from "./Dialog";
...@@ -20,6 +21,7 @@ interface State { ...@@ -20,6 +21,7 @@ interface State {
const CreateWebhookDialog: React.FC<Props> = (props: Props) => { const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
const { webhookName, destroy, onConfirm } = props; const { webhookName, destroy, onConfirm } = props;
const t = useTranslate(); const t = useTranslate();
const currentUser = useCurrentUser();
const [state, setState] = useState({ const [state, setState] = useState({
displayName: "", displayName: "",
url: "", url: "",
...@@ -67,9 +69,15 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => { ...@@ -67,9 +69,15 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
return; return;
} }
if (!currentUser) {
toast.error("User not authenticated");
return;
}
try { try {
if (isCreating) { if (isCreating) {
await webhookServiceClient.createWebhook({ await webhookServiceClient.createWebhook({
parent: currentUser.name,
webhook: { webhook: {
displayName: state.displayName, displayName: state.displayName,
url: state.url, url: state.url,
......
...@@ -3,26 +3,31 @@ import { ExternalLinkIcon, TrashIcon } from "lucide-react"; ...@@ -3,26 +3,31 @@ import { ExternalLinkIcon, TrashIcon } from "lucide-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { webhookServiceClient } from "@/grpcweb"; import { webhookServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
import { Webhook } from "@/types/proto/api/v1/webhook_service"; import { Webhook } from "@/types/proto/api/v1/webhook_service";
import { useTranslate } from "@/utils/i18n"; import { useTranslate } from "@/utils/i18n";
import showCreateWebhookDialog from "../CreateWebhookDialog"; import showCreateWebhookDialog from "../CreateWebhookDialog";
const listWebhooks = async () => {
const { webhooks } = await webhookServiceClient.listWebhooks({});
return webhooks;
};
const WebhookSection = () => { const WebhookSection = () => {
const t = useTranslate(); const t = useTranslate();
const currentUser = useCurrentUser();
const [webhooks, setWebhooks] = useState<Webhook[]>([]); const [webhooks, setWebhooks] = useState<Webhook[]>([]);
const listWebhooks = async () => {
if (!currentUser) return [];
const { webhooks } = await webhookServiceClient.listWebhooks({
parent: currentUser.name,
});
return webhooks;
};
useEffect(() => { useEffect(() => {
listWebhooks().then((webhooks) => { listWebhooks().then((webhooks) => {
setWebhooks(webhooks); setWebhooks(webhooks);
}); });
}, []); }, [currentUser]);
const handleCreateAccessTokenDialogConfirm = async () => { const handleCreateWebhookDialogConfirm = async () => {
const webhooks = await listWebhooks(); const webhooks = await listWebhooks();
setWebhooks(webhooks); setWebhooks(webhooks);
}; };
...@@ -47,7 +52,7 @@ const WebhookSection = () => { ...@@ -47,7 +52,7 @@ const WebhookSection = () => {
<Button <Button
color="primary" color="primary"
onClick={() => { onClick={() => {
showCreateWebhookDialog(handleCreateAccessTokenDialogConfirm); showCreateWebhookDialog(handleCreateWebhookDialogConfirm);
}} }}
> >
{t("common.create")} {t("common.create")}
......
...@@ -8,38 +8,27 @@ ...@@ -8,38 +8,27 @@
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import { Empty } from "../../google/protobuf/empty"; import { Empty } from "../../google/protobuf/empty";
import { FieldMask } from "../../google/protobuf/field_mask"; import { FieldMask } from "../../google/protobuf/field_mask";
import { Timestamp } from "../../google/protobuf/timestamp";
import { State, stateFromJSON, stateToNumber } from "./common";
import { Memo } from "./memo_service";
export const protobufPackage = "memos.api.v1"; export const protobufPackage = "memos.api.v1";
export interface Webhook { export interface Webhook {
/** /**
* The resource name of the webhook. * The resource name of the webhook.
* Format: webhooks/{webhook} * Format: users/{user}/webhooks/{webhook}
*/ */
name: string; name: string;
/** Required. The display name of the webhook. */ /** The display name of the webhook. */
displayName: string; displayName: string;
/** Required. The target URL for the webhook. */ /** The target URL for the webhook. */
url: string; url: string;
/**
* Output only. The resource name of the creator.
* Format: users/{user}
*/
creator: string;
/** The state of the webhook. */
state: State;
/** Output only. The creation timestamp. */
createTime?:
| Date
| undefined;
/** Output only. The last update timestamp. */
updateTime?: Date | undefined;
} }
export interface ListWebhooksRequest { export interface ListWebhooksRequest {
/**
* Required. The parent resource where webhooks are listed.
* Format: users/{user}
*/
parent: string;
} }
export interface ListWebhooksResponse { export interface ListWebhooksResponse {
...@@ -49,72 +38,45 @@ export interface ListWebhooksResponse { ...@@ -49,72 +38,45 @@ export interface ListWebhooksResponse {
export interface GetWebhookRequest { export interface GetWebhookRequest {
/** /**
* Required. The resource name of the webhook. * Required. The resource name of the webhook to retrieve.
* Format: webhooks/{webhook} * Format: users/{user}/webhooks/{webhook}
*/ */
name: string; name: string;
} }
export interface CreateWebhookRequest { export interface CreateWebhookRequest {
/**
* Required. The parent resource where this webhook will be created.
* Format: users/{user}
*/
parent: string;
/** Required. The webhook to create. */ /** Required. The webhook to create. */
webhook?: webhook?:
| Webhook | Webhook
| undefined; | undefined;
/** /** Optional. If set, validate the request, but do not actually create the webhook. */
* Optional. The webhook ID to use for this webhook.
* If empty, a unique ID will be generated.
* Must match the pattern [a-z0-9-]+
*/
webhookId: string;
/** Optional. If set, validate the request but don't actually create the webhook. */
validateOnly: boolean; validateOnly: boolean;
} }
export interface UpdateWebhookRequest { export interface UpdateWebhookRequest {
/** Required. The webhook to update. */ /** Required. The webhook resource which replaces the resource on the server. */
webhook?: webhook?:
| Webhook | Webhook
| undefined; | undefined;
/** Required. The list of fields to update. */ /** Optional. The list of fields to update. */
updateMask?: string[] | undefined; updateMask?: string[] | undefined;
} }
export interface DeleteWebhookRequest { export interface DeleteWebhookRequest {
/** /**
* Required. The resource name of the webhook to delete. * Required. The resource name of the webhook to delete.
* Format: webhooks/{webhook} * Format: users/{user}/webhooks/{webhook}
*/ */
name: string; name: string;
} }
export interface WebhookRequestPayload {
/** The target URL for the webhook request. */
url: string;
/** The type of activity that triggered this webhook. */
activityType: string;
/**
* The resource name of the creator.
* Format: users/{user}
*/
creator: string;
/** The creation timestamp of the activity. */
createTime?:
| Date
| undefined;
/** The memo that triggered this webhook (if applicable). */
memo?: Memo | undefined;
}
function createBaseWebhook(): Webhook { function createBaseWebhook(): Webhook {
return { return { name: "", displayName: "", url: "" };
name: "",
displayName: "",
url: "",
creator: "",
state: State.STATE_UNSPECIFIED,
createTime: undefined,
updateTime: undefined,
};
} }
export const Webhook: MessageFns<Webhook> = { export const Webhook: MessageFns<Webhook> = {
...@@ -128,18 +90,6 @@ export const Webhook: MessageFns<Webhook> = { ...@@ -128,18 +90,6 @@ export const Webhook: MessageFns<Webhook> = {
if (message.url !== "") { if (message.url !== "") {
writer.uint32(26).string(message.url); writer.uint32(26).string(message.url);
} }
if (message.creator !== "") {
writer.uint32(34).string(message.creator);
}
if (message.state !== State.STATE_UNSPECIFIED) {
writer.uint32(40).int32(stateToNumber(message.state));
}
if (message.createTime !== undefined) {
Timestamp.encode(toTimestamp(message.createTime), writer.uint32(50).fork()).join();
}
if (message.updateTime !== undefined) {
Timestamp.encode(toTimestamp(message.updateTime), writer.uint32(58).fork()).join();
}
return writer; return writer;
}, },
...@@ -174,38 +124,6 @@ export const Webhook: MessageFns<Webhook> = { ...@@ -174,38 +124,6 @@ export const Webhook: MessageFns<Webhook> = {
message.url = reader.string(); message.url = reader.string();
continue; continue;
} }
case 4: {
if (tag !== 34) {
break;
}
message.creator = reader.string();
continue;
}
case 5: {
if (tag !== 40) {
break;
}
message.state = stateFromJSON(reader.int32());
continue;
}
case 6: {
if (tag !== 50) {
break;
}
message.createTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
continue;
}
case 7: {
if (tag !== 58) {
break;
}
message.updateTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
continue;
}
} }
if ((tag & 7) === 4 || tag === 0) { if ((tag & 7) === 4 || tag === 0) {
break; break;
...@@ -223,20 +141,19 @@ export const Webhook: MessageFns<Webhook> = { ...@@ -223,20 +141,19 @@ export const Webhook: MessageFns<Webhook> = {
message.name = object.name ?? ""; message.name = object.name ?? "";
message.displayName = object.displayName ?? ""; message.displayName = object.displayName ?? "";
message.url = object.url ?? ""; message.url = object.url ?? "";
message.creator = object.creator ?? "";
message.state = object.state ?? State.STATE_UNSPECIFIED;
message.createTime = object.createTime ?? undefined;
message.updateTime = object.updateTime ?? undefined;
return message; return message;
}, },
}; };
function createBaseListWebhooksRequest(): ListWebhooksRequest { function createBaseListWebhooksRequest(): ListWebhooksRequest {
return {}; return { parent: "" };
} }
export const ListWebhooksRequest: MessageFns<ListWebhooksRequest> = { export const ListWebhooksRequest: MessageFns<ListWebhooksRequest> = {
encode(_: ListWebhooksRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { encode(message: ListWebhooksRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.parent !== "") {
writer.uint32(10).string(message.parent);
}
return writer; return writer;
}, },
...@@ -247,6 +164,14 @@ export const ListWebhooksRequest: MessageFns<ListWebhooksRequest> = { ...@@ -247,6 +164,14 @@ export const ListWebhooksRequest: MessageFns<ListWebhooksRequest> = {
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32();
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.parent = reader.string();
continue;
}
} }
if ((tag & 7) === 4 || tag === 0) { if ((tag & 7) === 4 || tag === 0) {
break; break;
...@@ -259,8 +184,9 @@ export const ListWebhooksRequest: MessageFns<ListWebhooksRequest> = { ...@@ -259,8 +184,9 @@ export const ListWebhooksRequest: MessageFns<ListWebhooksRequest> = {
create(base?: DeepPartial<ListWebhooksRequest>): ListWebhooksRequest { create(base?: DeepPartial<ListWebhooksRequest>): ListWebhooksRequest {
return ListWebhooksRequest.fromPartial(base ?? {}); return ListWebhooksRequest.fromPartial(base ?? {});
}, },
fromPartial(_: DeepPartial<ListWebhooksRequest>): ListWebhooksRequest { fromPartial(object: DeepPartial<ListWebhooksRequest>): ListWebhooksRequest {
const message = createBaseListWebhooksRequest(); const message = createBaseListWebhooksRequest();
message.parent = object.parent ?? "";
return message; return message;
}, },
}; };
...@@ -358,16 +284,16 @@ export const GetWebhookRequest: MessageFns<GetWebhookRequest> = { ...@@ -358,16 +284,16 @@ export const GetWebhookRequest: MessageFns<GetWebhookRequest> = {
}; };
function createBaseCreateWebhookRequest(): CreateWebhookRequest { function createBaseCreateWebhookRequest(): CreateWebhookRequest {
return { webhook: undefined, webhookId: "", validateOnly: false }; return { parent: "", webhook: undefined, validateOnly: false };
} }
export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = { export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = {
encode(message: CreateWebhookRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { encode(message: CreateWebhookRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.webhook !== undefined) { if (message.parent !== "") {
Webhook.encode(message.webhook, writer.uint32(10).fork()).join(); writer.uint32(10).string(message.parent);
} }
if (message.webhookId !== "") { if (message.webhook !== undefined) {
writer.uint32(18).string(message.webhookId); Webhook.encode(message.webhook, writer.uint32(18).fork()).join();
} }
if (message.validateOnly !== false) { if (message.validateOnly !== false) {
writer.uint32(24).bool(message.validateOnly); writer.uint32(24).bool(message.validateOnly);
...@@ -387,7 +313,7 @@ export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = { ...@@ -387,7 +313,7 @@ export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = {
break; break;
} }
message.webhook = Webhook.decode(reader, reader.uint32()); message.parent = reader.string();
continue; continue;
} }
case 2: { case 2: {
...@@ -395,7 +321,7 @@ export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = { ...@@ -395,7 +321,7 @@ export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = {
break; break;
} }
message.webhookId = reader.string(); message.webhook = Webhook.decode(reader, reader.uint32());
continue; continue;
} }
case 3: { case 3: {
...@@ -420,10 +346,10 @@ export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = { ...@@ -420,10 +346,10 @@ export const CreateWebhookRequest: MessageFns<CreateWebhookRequest> = {
}, },
fromPartial(object: DeepPartial<CreateWebhookRequest>): CreateWebhookRequest { fromPartial(object: DeepPartial<CreateWebhookRequest>): CreateWebhookRequest {
const message = createBaseCreateWebhookRequest(); const message = createBaseCreateWebhookRequest();
message.parent = object.parent ?? "";
message.webhook = (object.webhook !== undefined && object.webhook !== null) message.webhook = (object.webhook !== undefined && object.webhook !== null)
? Webhook.fromPartial(object.webhook) ? Webhook.fromPartial(object.webhook)
: undefined; : undefined;
message.webhookId = object.webhookId ?? "";
message.validateOnly = object.validateOnly ?? false; message.validateOnly = object.validateOnly ?? false;
return message; return message;
}, },
...@@ -535,106 +461,12 @@ export const DeleteWebhookRequest: MessageFns<DeleteWebhookRequest> = { ...@@ -535,106 +461,12 @@ export const DeleteWebhookRequest: MessageFns<DeleteWebhookRequest> = {
}, },
}; };
function createBaseWebhookRequestPayload(): WebhookRequestPayload {
return { url: "", activityType: "", creator: "", createTime: undefined, memo: undefined };
}
export const WebhookRequestPayload: MessageFns<WebhookRequestPayload> = {
encode(message: WebhookRequestPayload, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.url !== "") {
writer.uint32(10).string(message.url);
}
if (message.activityType !== "") {
writer.uint32(18).string(message.activityType);
}
if (message.creator !== "") {
writer.uint32(26).string(message.creator);
}
if (message.createTime !== undefined) {
Timestamp.encode(toTimestamp(message.createTime), writer.uint32(34).fork()).join();
}
if (message.memo !== undefined) {
Memo.encode(message.memo, writer.uint32(42).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): WebhookRequestPayload {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseWebhookRequestPayload();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.url = reader.string();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.activityType = reader.string();
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.creator = reader.string();
continue;
}
case 4: {
if (tag !== 34) {
break;
}
message.createTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
continue;
}
case 5: {
if (tag !== 42) {
break;
}
message.memo = Memo.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
create(base?: DeepPartial<WebhookRequestPayload>): WebhookRequestPayload {
return WebhookRequestPayload.fromPartial(base ?? {});
},
fromPartial(object: DeepPartial<WebhookRequestPayload>): WebhookRequestPayload {
const message = createBaseWebhookRequestPayload();
message.url = object.url ?? "";
message.activityType = object.activityType ?? "";
message.creator = object.creator ?? "";
message.createTime = object.createTime ?? undefined;
message.memo = (object.memo !== undefined && object.memo !== null) ? Memo.fromPartial(object.memo) : undefined;
return message;
},
};
export type WebhookServiceDefinition = typeof WebhookServiceDefinition; export type WebhookServiceDefinition = typeof WebhookServiceDefinition;
export const WebhookServiceDefinition = { export const WebhookServiceDefinition = {
name: "WebhookService", name: "WebhookService",
fullName: "memos.api.v1.WebhookService", fullName: "memos.api.v1.WebhookService",
methods: { methods: {
/** ListWebhooks returns a list of webhooks. */ /** ListWebhooks returns a list of webhooks for a user. */
listWebhooks: { listWebhooks: {
name: "ListWebhooks", name: "ListWebhooks",
requestType: ListWebhooksRequest, requestType: ListWebhooksRequest,
...@@ -643,8 +475,46 @@ export const WebhookServiceDefinition = { ...@@ -643,8 +475,46 @@ export const WebhookServiceDefinition = {
responseStream: false, responseStream: false,
options: { options: {
_unknownFields: { _unknownFields: {
8410: [new Uint8Array([6, 112, 97, 114, 101, 110, 116])],
578365826: [ 578365826: [
new Uint8Array([18, 18, 16, 47, 97, 112, 105, 47, 118, 49, 47, 119, 101, 98, 104, 111, 111, 107, 115]), new Uint8Array([
35,
18,
33,
47,
97,
112,
105,
47,
118,
49,
47,
123,
112,
97,
114,
101,
110,
116,
61,
117,
115,
101,
114,
115,
47,
42,
125,
47,
119,
101,
98,
104,
111,
111,
107,
115,
]),
], ],
}, },
}, },
...@@ -661,9 +531,9 @@ export const WebhookServiceDefinition = { ...@@ -661,9 +531,9 @@ export const WebhookServiceDefinition = {
8410: [new Uint8Array([4, 110, 97, 109, 101])], 8410: [new Uint8Array([4, 110, 97, 109, 101])],
578365826: [ 578365826: [
new Uint8Array([ new Uint8Array([
27, 35,
18, 18,
25, 33,
47, 47,
97, 97,
112, 112,
...@@ -678,6 +548,14 @@ export const WebhookServiceDefinition = { ...@@ -678,6 +548,14 @@ export const WebhookServiceDefinition = {
109, 109,
101, 101,
61, 61,
117,
115,
101,
114,
115,
47,
42,
47,
119, 119,
101, 101,
98, 98,
...@@ -694,7 +572,7 @@ export const WebhookServiceDefinition = { ...@@ -694,7 +572,7 @@ export const WebhookServiceDefinition = {
}, },
}, },
}, },
/** CreateWebhook creates a new webhook. */ /** CreateWebhook creates a new webhook for a user. */
createWebhook: { createWebhook: {
name: "CreateWebhook", name: "CreateWebhook",
requestType: CreateWebhookRequest, requestType: CreateWebhookRequest,
...@@ -703,10 +581,10 @@ export const WebhookServiceDefinition = { ...@@ -703,10 +581,10 @@ export const WebhookServiceDefinition = {
responseStream: false, responseStream: false,
options: { options: {
_unknownFields: { _unknownFields: {
8410: [new Uint8Array([7, 119, 101, 98, 104, 111, 111, 107])], 8410: [new Uint8Array([14, 112, 97, 114, 101, 110, 116, 44, 119, 101, 98, 104, 111, 111, 107])],
578365826: [ 578365826: [
new Uint8Array([ new Uint8Array([
27, 44,
58, 58,
7, 7,
119, 119,
...@@ -717,7 +595,7 @@ export const WebhookServiceDefinition = { ...@@ -717,7 +595,7 @@ export const WebhookServiceDefinition = {
111, 111,
107, 107,
34, 34,
16, 33,
47, 47,
97, 97,
112, 112,
...@@ -726,6 +604,23 @@ export const WebhookServiceDefinition = { ...@@ -726,6 +604,23 @@ export const WebhookServiceDefinition = {
118, 118,
49, 49,
47, 47,
123,
112,
97,
114,
101,
110,
116,
61,
117,
115,
101,
114,
115,
47,
42,
125,
47,
119, 119,
101, 101,
98, 98,
...@@ -739,7 +634,7 @@ export const WebhookServiceDefinition = { ...@@ -739,7 +634,7 @@ export const WebhookServiceDefinition = {
}, },
}, },
}, },
/** UpdateWebhook updates a webhook. */ /** UpdateWebhook updates a webhook for a user. */
updateWebhook: { updateWebhook: {
name: "UpdateWebhook", name: "UpdateWebhook",
requestType: UpdateWebhookRequest, requestType: UpdateWebhookRequest,
...@@ -774,7 +669,7 @@ export const WebhookServiceDefinition = { ...@@ -774,7 +669,7 @@ export const WebhookServiceDefinition = {
], ],
578365826: [ 578365826: [
new Uint8Array([ new Uint8Array([
44, 52,
58, 58,
7, 7,
119, 119,
...@@ -785,7 +680,7 @@ export const WebhookServiceDefinition = { ...@@ -785,7 +680,7 @@ export const WebhookServiceDefinition = {
111, 111,
107, 107,
50, 50,
33, 41,
47, 47,
97, 97,
112, 112,
...@@ -808,6 +703,14 @@ export const WebhookServiceDefinition = { ...@@ -808,6 +703,14 @@ export const WebhookServiceDefinition = {
109, 109,
101, 101,
61, 61,
117,
115,
101,
114,
115,
47,
42,
47,
119, 119,
101, 101,
98, 98,
...@@ -824,7 +727,7 @@ export const WebhookServiceDefinition = { ...@@ -824,7 +727,7 @@ export const WebhookServiceDefinition = {
}, },
}, },
}, },
/** DeleteWebhook deletes a webhook. */ /** DeleteWebhook deletes a webhook for a user. */
deleteWebhook: { deleteWebhook: {
name: "DeleteWebhook", name: "DeleteWebhook",
requestType: DeleteWebhookRequest, requestType: DeleteWebhookRequest,
...@@ -836,9 +739,9 @@ export const WebhookServiceDefinition = { ...@@ -836,9 +739,9 @@ export const WebhookServiceDefinition = {
8410: [new Uint8Array([4, 110, 97, 109, 101])], 8410: [new Uint8Array([4, 110, 97, 109, 101])],
578365826: [ 578365826: [
new Uint8Array([ new Uint8Array([
27, 35,
42, 42,
25, 33,
47, 47,
97, 97,
112, 112,
...@@ -853,6 +756,14 @@ export const WebhookServiceDefinition = { ...@@ -853,6 +756,14 @@ export const WebhookServiceDefinition = {
109, 109,
101, 101,
61, 61,
117,
115,
101,
114,
115,
47,
42,
47,
119, 119,
101, 101,
98, 98,
...@@ -880,18 +791,6 @@ export type DeepPartial<T> = T extends Builtin ? T ...@@ -880,18 +791,6 @@ export type DeepPartial<T> = T extends Builtin ? T
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> } : T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>; : Partial<T>;
function toTimestamp(date: Date): Timestamp {
const seconds = Math.trunc(date.getTime() / 1_000);
const nanos = (date.getTime() % 1_000) * 1_000_000;
return { seconds, nanos };
}
function fromTimestamp(t: Timestamp): Date {
let millis = (t.seconds || 0) * 1_000;
millis += (t.nanos || 0) / 1_000_000;
return new globalThis.Date(millis);
}
export interface MessageFns<T> { export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter; encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T; decode(input: BinaryReader | Uint8Array, length?: number): T;
......
...@@ -35,7 +35,7 @@ export enum Edition { ...@@ -35,7 +35,7 @@ export enum Edition {
EDITION_2024 = "EDITION_2024", EDITION_2024 = "EDITION_2024",
/** /**
* EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be * EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be
* used or relied on outside of tests. * used or relyed on outside of tests.
*/ */
EDITION_1_TEST_ONLY = "EDITION_1_TEST_ONLY", EDITION_1_TEST_ONLY = "EDITION_1_TEST_ONLY",
EDITION_2_TEST_ONLY = "EDITION_2_TEST_ONLY", EDITION_2_TEST_ONLY = "EDITION_2_TEST_ONLY",
...@@ -177,19 +177,11 @@ export interface FileDescriptorProto { ...@@ -177,19 +177,11 @@ export interface FileDescriptorProto {
* The supported values are "proto2", "proto3", and "editions". * The supported values are "proto2", "proto3", and "editions".
* *
* If `edition` is present, this value must be "editions". * If `edition` is present, this value must be "editions".
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/ */
syntax?: syntax?:
| string | string
| undefined; | undefined;
/** /** The edition of the proto file. */
* The edition of the proto file.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
edition?: Edition | undefined; edition?: Edition | undefined;
} }
...@@ -836,12 +828,7 @@ export interface FileOptions { ...@@ -836,12 +828,7 @@ export interface FileOptions {
rubyPackage?: rubyPackage?:
| string | string
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
...@@ -979,12 +966,7 @@ export interface MessageOptions { ...@@ -979,12 +966,7 @@ export interface MessageOptions {
deprecatedLegacyJsonFieldConflicts?: deprecatedLegacyJsonFieldConflicts?:
| boolean | boolean
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
...@@ -994,13 +976,12 @@ export interface MessageOptions { ...@@ -994,13 +976,12 @@ export interface MessageOptions {
export interface FieldOptions { export interface FieldOptions {
/** /**
* NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead.
* The ctype option instructs the C++ code generator to use a different * The ctype option instructs the C++ code generator to use a different
* representation of the field than it normally would. See the specific * representation of the field than it normally would. See the specific
* options below. This option is only implemented to support use of * options below. This option is only implemented to support use of
* [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of
* type "bytes" in the open source release. * type "bytes" in the open source release -- sorry, we'll try to include
* TODO: make ctype actually deprecated. * other types in a future version!
*/ */
ctype?: ctype?:
| FieldOptions_CType | FieldOptions_CType
...@@ -1089,12 +1070,7 @@ export interface FieldOptions { ...@@ -1089,12 +1070,7 @@ export interface FieldOptions {
retention?: FieldOptions_OptionRetention | undefined; retention?: FieldOptions_OptionRetention | undefined;
targets: FieldOptions_OptionTargetType[]; targets: FieldOptions_OptionTargetType[];
editionDefaults: FieldOptions_EditionDefault[]; editionDefaults: FieldOptions_EditionDefault[];
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: FeatureSet | undefined; features?: FeatureSet | undefined;
featureSupport?: featureSupport?:
| FieldOptions_FeatureSupport | FieldOptions_FeatureSupport
...@@ -1193,7 +1169,11 @@ export function fieldOptions_JSTypeToNumber(object: FieldOptions_JSType): number ...@@ -1193,7 +1169,11 @@ export function fieldOptions_JSTypeToNumber(object: FieldOptions_JSType): number
} }
} }
/** If set to RETENTION_SOURCE, the option will be omitted from the binary. */ /**
* If set to RETENTION_SOURCE, the option will be omitted from the binary.
* Note: as of January 2023, support for this is in progress and does not yet
* have an effect (b/264593489).
*/
export enum FieldOptions_OptionRetention { export enum FieldOptions_OptionRetention {
RETENTION_UNKNOWN = "RETENTION_UNKNOWN", RETENTION_UNKNOWN = "RETENTION_UNKNOWN",
RETENTION_RUNTIME = "RETENTION_RUNTIME", RETENTION_RUNTIME = "RETENTION_RUNTIME",
...@@ -1236,7 +1216,8 @@ export function fieldOptions_OptionRetentionToNumber(object: FieldOptions_Option ...@@ -1236,7 +1216,8 @@ export function fieldOptions_OptionRetentionToNumber(object: FieldOptions_Option
/** /**
* This indicates the types of entities that the field may apply to when used * This indicates the types of entities that the field may apply to when used
* as an option. If it is unset, then the field may be freely used as an * as an option. If it is unset, then the field may be freely used as an
* option on any kind of entity. * option on any kind of entity. Note: as of January 2023, support for this is
* in progress and does not yet have an effect (b/264593489).
*/ */
export enum FieldOptions_OptionTargetType { export enum FieldOptions_OptionTargetType {
TARGET_TYPE_UNKNOWN = "TARGET_TYPE_UNKNOWN", TARGET_TYPE_UNKNOWN = "TARGET_TYPE_UNKNOWN",
...@@ -1360,12 +1341,7 @@ export interface FieldOptions_FeatureSupport { ...@@ -1360,12 +1341,7 @@ export interface FieldOptions_FeatureSupport {
} }
export interface OneofOptions { export interface OneofOptions {
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
...@@ -1403,12 +1379,7 @@ export interface EnumOptions { ...@@ -1403,12 +1379,7 @@ export interface EnumOptions {
deprecatedLegacyJsonFieldConflicts?: deprecatedLegacyJsonFieldConflicts?:
| boolean | boolean
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
...@@ -1426,12 +1397,7 @@ export interface EnumValueOptions { ...@@ -1426,12 +1397,7 @@ export interface EnumValueOptions {
deprecated?: deprecated?:
| boolean | boolean
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
...@@ -1452,12 +1418,7 @@ export interface EnumValueOptions { ...@@ -1452,12 +1418,7 @@ export interface EnumValueOptions {
} }
export interface ServiceOptions { export interface ServiceOptions {
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
...@@ -1485,12 +1446,7 @@ export interface MethodOptions { ...@@ -1485,12 +1446,7 @@ export interface MethodOptions {
idempotencyLevel?: idempotencyLevel?:
| MethodOptions_IdempotencyLevel | MethodOptions_IdempotencyLevel
| undefined; | undefined;
/** /** Any features defined in the specific edition. */
* Any features defined in the specific edition.
* WARNING: This field should only be used by protobuf plugins or special
* cases like the proto compiler. Other uses are discouraged and
* developers should rely on the protoreflect APIs for their client language.
*/
features?: features?:
| FeatureSet | FeatureSet
| undefined; | undefined;
...@@ -1593,7 +1549,6 @@ export interface FeatureSet { ...@@ -1593,7 +1549,6 @@ export interface FeatureSet {
utf8Validation?: FeatureSet_Utf8Validation | undefined; utf8Validation?: FeatureSet_Utf8Validation | undefined;
messageEncoding?: FeatureSet_MessageEncoding | undefined; messageEncoding?: FeatureSet_MessageEncoding | undefined;
jsonFormat?: FeatureSet_JsonFormat | undefined; jsonFormat?: FeatureSet_JsonFormat | undefined;
enforceNamingStyle?: FeatureSet_EnforceNamingStyle | undefined;
} }
export enum FeatureSet_FieldPresence { export enum FeatureSet_FieldPresence {
...@@ -1836,45 +1791,6 @@ export function featureSet_JsonFormatToNumber(object: FeatureSet_JsonFormat): nu ...@@ -1836,45 +1791,6 @@ export function featureSet_JsonFormatToNumber(object: FeatureSet_JsonFormat): nu
} }
} }
export enum FeatureSet_EnforceNamingStyle {
ENFORCE_NAMING_STYLE_UNKNOWN = "ENFORCE_NAMING_STYLE_UNKNOWN",
STYLE2024 = "STYLE2024",
STYLE_LEGACY = "STYLE_LEGACY",
UNRECOGNIZED = "UNRECOGNIZED",
}
export function featureSet_EnforceNamingStyleFromJSON(object: any): FeatureSet_EnforceNamingStyle {
switch (object) {
case 0:
case "ENFORCE_NAMING_STYLE_UNKNOWN":
return FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN;
case 1:
case "STYLE2024":
return FeatureSet_EnforceNamingStyle.STYLE2024;
case 2:
case "STYLE_LEGACY":
return FeatureSet_EnforceNamingStyle.STYLE_LEGACY;
case -1:
case "UNRECOGNIZED":
default:
return FeatureSet_EnforceNamingStyle.UNRECOGNIZED;
}
}
export function featureSet_EnforceNamingStyleToNumber(object: FeatureSet_EnforceNamingStyle): number {
switch (object) {
case FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN:
return 0;
case FeatureSet_EnforceNamingStyle.STYLE2024:
return 1;
case FeatureSet_EnforceNamingStyle.STYLE_LEGACY:
return 2;
case FeatureSet_EnforceNamingStyle.UNRECOGNIZED:
default:
return -1;
}
}
/** /**
* A compiled specification for the defaults of a set of features. These * A compiled specification for the defaults of a set of features. These
* messages are generated from FeatureSet extensions and can be used to seed * messages are generated from FeatureSet extensions and can be used to seed
...@@ -4998,7 +4914,6 @@ function createBaseFeatureSet(): FeatureSet { ...@@ -4998,7 +4914,6 @@ function createBaseFeatureSet(): FeatureSet {
utf8Validation: FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN, utf8Validation: FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN,
messageEncoding: FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN, messageEncoding: FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN,
jsonFormat: FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN, jsonFormat: FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN,
enforceNamingStyle: FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN,
}; };
} }
...@@ -5033,12 +4948,6 @@ export const FeatureSet: MessageFns<FeatureSet> = { ...@@ -5033,12 +4948,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
if (message.jsonFormat !== undefined && message.jsonFormat !== FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN) { if (message.jsonFormat !== undefined && message.jsonFormat !== FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN) {
writer.uint32(48).int32(featureSet_JsonFormatToNumber(message.jsonFormat)); writer.uint32(48).int32(featureSet_JsonFormatToNumber(message.jsonFormat));
} }
if (
message.enforceNamingStyle !== undefined &&
message.enforceNamingStyle !== FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN
) {
writer.uint32(56).int32(featureSet_EnforceNamingStyleToNumber(message.enforceNamingStyle));
}
return writer; return writer;
}, },
...@@ -5097,14 +5006,6 @@ export const FeatureSet: MessageFns<FeatureSet> = { ...@@ -5097,14 +5006,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
message.jsonFormat = featureSet_JsonFormatFromJSON(reader.int32()); message.jsonFormat = featureSet_JsonFormatFromJSON(reader.int32());
continue; continue;
} }
case 7: {
if (tag !== 56) {
break;
}
message.enforceNamingStyle = featureSet_EnforceNamingStyleFromJSON(reader.int32());
continue;
}
} }
if ((tag & 7) === 4 || tag === 0) { if ((tag & 7) === 4 || tag === 0) {
break; break;
...@@ -5126,8 +5027,6 @@ export const FeatureSet: MessageFns<FeatureSet> = { ...@@ -5126,8 +5027,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
message.utf8Validation = object.utf8Validation ?? FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN; message.utf8Validation = object.utf8Validation ?? FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN;
message.messageEncoding = object.messageEncoding ?? FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN; message.messageEncoding = object.messageEncoding ?? FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN;
message.jsonFormat = object.jsonFormat ?? FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN; message.jsonFormat = object.jsonFormat ?? FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN;
message.enforceNamingStyle = object.enforceNamingStyle ??
FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN;
return message; return message;
}, },
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment