diff --git a/proto/api/v1/instance_service.proto b/proto/api/v1/instance_service.proto index b2e6c641a..b9c096ad6 100644 --- a/proto/api/v1/instance_service.proto +++ b/proto/api/v1/instance_service.proto @@ -71,6 +71,7 @@ message InstanceSetting { StorageSetting storage_setting = 3; MemoRelatedSetting memo_related_setting = 4; TagsSetting tags_setting = 5; + NotificationSetting notification_setting = 6; } // Enumeration of instance setting keys. @@ -84,6 +85,8 @@ message InstanceSetting { MEMO_RELATED = 3; // TAGS is the key for tag metadata. TAGS = 4; + // NOTIFICATION is the key for notification transport settings. + NOTIFICATION = 5; } // General instance settings configuration. @@ -174,6 +177,25 @@ message InstanceSetting { message TagsSetting { map tags = 1; } + + // Notification transport configuration. + message NotificationSetting { + EmailSetting email = 1; + + // Email delivery configuration for notifications. + message EmailSetting { + bool enabled = 1; + string smtp_host = 2; + int32 smtp_port = 3; + string smtp_username = 4; + string smtp_password = 5; + string from_email = 6; + string from_name = 7; + string reply_to = 8; + bool use_tls = 9; + bool use_ssl = 10; + } + } } // Request message for GetInstanceSetting method. diff --git a/proto/gen/api/v1/instance_service.pb.go b/proto/gen/api/v1/instance_service.pb.go index 2dc3e0094..0ffbfd228 100644 --- a/proto/gen/api/v1/instance_service.pb.go +++ b/proto/gen/api/v1/instance_service.pb.go @@ -37,6 +37,8 @@ const ( InstanceSetting_MEMO_RELATED InstanceSetting_Key = 3 // TAGS is the key for tag metadata. InstanceSetting_TAGS InstanceSetting_Key = 4 + // NOTIFICATION is the key for notification transport settings. + InstanceSetting_NOTIFICATION InstanceSetting_Key = 5 ) // Enum value maps for InstanceSetting_Key. @@ -47,6 +49,7 @@ var ( 2: "STORAGE", 3: "MEMO_RELATED", 4: "TAGS", + 5: "NOTIFICATION", } InstanceSetting_Key_value = map[string]int32{ "KEY_UNSPECIFIED": 0, @@ -54,6 +57,7 @@ var ( "STORAGE": 2, "MEMO_RELATED": 3, "TAGS": 4, + "NOTIFICATION": 5, } ) @@ -263,6 +267,7 @@ type InstanceSetting struct { // *InstanceSetting_StorageSetting_ // *InstanceSetting_MemoRelatedSetting_ // *InstanceSetting_TagsSetting_ + // *InstanceSetting_NotificationSetting_ Value isInstanceSetting_Value `protobuf_oneof:"value"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -348,6 +353,15 @@ func (x *InstanceSetting) GetTagsSetting() *InstanceSetting_TagsSetting { return nil } +func (x *InstanceSetting) GetNotificationSetting() *InstanceSetting_NotificationSetting { + if x != nil { + if x, ok := x.Value.(*InstanceSetting_NotificationSetting_); ok { + return x.NotificationSetting + } + } + return nil +} + type isInstanceSetting_Value interface { isInstanceSetting_Value() } @@ -368,6 +382,10 @@ type InstanceSetting_TagsSetting_ struct { TagsSetting *InstanceSetting_TagsSetting `protobuf:"bytes,5,opt,name=tags_setting,json=tagsSetting,proto3,oneof"` } +type InstanceSetting_NotificationSetting_ struct { + NotificationSetting *InstanceSetting_NotificationSetting `protobuf:"bytes,6,opt,name=notification_setting,json=notificationSetting,proto3,oneof"` +} + func (*InstanceSetting_GeneralSetting_) isInstanceSetting_Value() {} func (*InstanceSetting_StorageSetting_) isInstanceSetting_Value() {} @@ -376,6 +394,8 @@ func (*InstanceSetting_MemoRelatedSetting_) isInstanceSetting_Value() {} func (*InstanceSetting_TagsSetting_) isInstanceSetting_Value() {} +func (*InstanceSetting_NotificationSetting_) isInstanceSetting_Value() {} + // Request message for GetInstanceSetting method. type GetInstanceSettingRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -836,6 +856,51 @@ func (x *InstanceSetting_TagsSetting) GetTags() map[string]*InstanceSetting_TagM return nil } +// Notification transport configuration. +type InstanceSetting_NotificationSetting struct { + state protoimpl.MessageState `protogen:"open.v1"` + Email *InstanceSetting_NotificationSetting_EmailSetting `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InstanceSetting_NotificationSetting) Reset() { + *x = InstanceSetting_NotificationSetting{} + mi := &file_api_v1_instance_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InstanceSetting_NotificationSetting) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstanceSetting_NotificationSetting) ProtoMessage() {} + +func (x *InstanceSetting_NotificationSetting) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_instance_service_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 InstanceSetting_NotificationSetting.ProtoReflect.Descriptor instead. +func (*InstanceSetting_NotificationSetting) Descriptor() ([]byte, []int) { + return file_api_v1_instance_service_proto_rawDescGZIP(), []int{2, 5} +} + +func (x *InstanceSetting_NotificationSetting) GetEmail() *InstanceSetting_NotificationSetting_EmailSetting { + if x != nil { + return x.Email + } + return nil +} + // Custom profile configuration for instance branding. type InstanceSetting_GeneralSetting_CustomProfile struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -848,7 +913,7 @@ type InstanceSetting_GeneralSetting_CustomProfile struct { func (x *InstanceSetting_GeneralSetting_CustomProfile) Reset() { *x = InstanceSetting_GeneralSetting_CustomProfile{} - mi := &file_api_v1_instance_service_proto_msgTypes[10] + mi := &file_api_v1_instance_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -860,7 +925,7 @@ func (x *InstanceSetting_GeneralSetting_CustomProfile) String() string { func (*InstanceSetting_GeneralSetting_CustomProfile) ProtoMessage() {} func (x *InstanceSetting_GeneralSetting_CustomProfile) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_instance_service_proto_msgTypes[10] + mi := &file_api_v1_instance_service_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -913,7 +978,7 @@ type InstanceSetting_StorageSetting_S3Config struct { func (x *InstanceSetting_StorageSetting_S3Config) Reset() { *x = InstanceSetting_StorageSetting_S3Config{} - mi := &file_api_v1_instance_service_proto_msgTypes[11] + mi := &file_api_v1_instance_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -925,7 +990,7 @@ func (x *InstanceSetting_StorageSetting_S3Config) String() string { func (*InstanceSetting_StorageSetting_S3Config) ProtoMessage() {} func (x *InstanceSetting_StorageSetting_S3Config) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_instance_service_proto_msgTypes[11] + mi := &file_api_v1_instance_service_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -983,23 +1048,141 @@ func (x *InstanceSetting_StorageSetting_S3Config) GetUsePathStyle() bool { return false } +// Email delivery configuration for notifications. +type InstanceSetting_NotificationSetting_EmailSetting struct { + state protoimpl.MessageState `protogen:"open.v1"` + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + SmtpHost string `protobuf:"bytes,2,opt,name=smtp_host,json=smtpHost,proto3" json:"smtp_host,omitempty"` + SmtpPort int32 `protobuf:"varint,3,opt,name=smtp_port,json=smtpPort,proto3" json:"smtp_port,omitempty"` + SmtpUsername string `protobuf:"bytes,4,opt,name=smtp_username,json=smtpUsername,proto3" json:"smtp_username,omitempty"` + SmtpPassword string `protobuf:"bytes,5,opt,name=smtp_password,json=smtpPassword,proto3" json:"smtp_password,omitempty"` + FromEmail string `protobuf:"bytes,6,opt,name=from_email,json=fromEmail,proto3" json:"from_email,omitempty"` + FromName string `protobuf:"bytes,7,opt,name=from_name,json=fromName,proto3" json:"from_name,omitempty"` + ReplyTo string `protobuf:"bytes,8,opt,name=reply_to,json=replyTo,proto3" json:"reply_to,omitempty"` + UseTls bool `protobuf:"varint,9,opt,name=use_tls,json=useTls,proto3" json:"use_tls,omitempty"` + UseSsl bool `protobuf:"varint,10,opt,name=use_ssl,json=useSsl,proto3" json:"use_ssl,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) Reset() { + *x = InstanceSetting_NotificationSetting_EmailSetting{} + mi := &file_api_v1_instance_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstanceSetting_NotificationSetting_EmailSetting) ProtoMessage() {} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_instance_service_proto_msgTypes[14] + 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 InstanceSetting_NotificationSetting_EmailSetting.ProtoReflect.Descriptor instead. +func (*InstanceSetting_NotificationSetting_EmailSetting) Descriptor() ([]byte, []int) { + return file_api_v1_instance_service_proto_rawDescGZIP(), []int{2, 5, 0} +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetSmtpHost() string { + if x != nil { + return x.SmtpHost + } + return "" +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetSmtpPort() int32 { + if x != nil { + return x.SmtpPort + } + return 0 +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetSmtpUsername() string { + if x != nil { + return x.SmtpUsername + } + return "" +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetSmtpPassword() string { + if x != nil { + return x.SmtpPassword + } + return "" +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetFromEmail() string { + if x != nil { + return x.FromEmail + } + return "" +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetFromName() string { + if x != nil { + return x.FromName + } + return "" +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetReplyTo() string { + if x != nil { + return x.ReplyTo + } + return "" +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetUseTls() bool { + if x != nil { + return x.UseTls + } + return false +} + +func (x *InstanceSetting_NotificationSetting_EmailSetting) GetUseSsl() bool { + if x != nil { + return x.UseSsl + } + return false +} + var File_api_v1_instance_service_proto protoreflect.FileDescriptor const file_api_v1_instance_service_proto_rawDesc = "" + "\n" + - "\x1dapi/v1/instance_service.proto\x12\fmemos.api.v1\x1a\x19api/v1/user_service.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x17google/type/color.proto\x1a google/protobuf/field_mask.proto\"\x8c\x01\n" + + "\x1dapi/v1/instance_service.proto\x12\fmemos.api.v1\x1a\x19api/v1/user_service.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a google/protobuf/field_mask.proto\x1a\x17google/type/color.proto\"\x8c\x01\n" + "\x0fInstanceProfile\x12\x18\n" + "\aversion\x18\x02 \x01(\tR\aversion\x12\x12\n" + "\x04demo\x18\x03 \x01(\bR\x04demo\x12!\n" + "\finstance_url\x18\x06 \x01(\tR\vinstanceUrl\x12(\n" + "\x05admin\x18\a \x01(\v2\x12.memos.api.v1.UserR\x05admin\"\x1b\n" + - "\x19GetInstanceProfileRequest\"\xfe\x11\n" + + "\x19GetInstanceProfileRequest\"\x9e\x16\n" + "\x0fInstanceSetting\x12\x17\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12W\n" + "\x0fgeneral_setting\x18\x02 \x01(\v2,.memos.api.v1.InstanceSetting.GeneralSettingH\x00R\x0egeneralSetting\x12W\n" + "\x0fstorage_setting\x18\x03 \x01(\v2,.memos.api.v1.InstanceSetting.StorageSettingH\x00R\x0estorageSetting\x12d\n" + "\x14memo_related_setting\x18\x04 \x01(\v20.memos.api.v1.InstanceSetting.MemoRelatedSettingH\x00R\x12memoRelatedSetting\x12N\n" + - "\ftags_setting\x18\x05 \x01(\v2).memos.api.v1.InstanceSetting.TagsSettingH\x00R\vtagsSetting\x1a\xca\x04\n" + + "\ftags_setting\x18\x05 \x01(\v2).memos.api.v1.InstanceSetting.TagsSettingH\x00R\vtagsSetting\x12f\n" + + "\x14notification_setting\x18\x06 \x01(\v21.memos.api.v1.InstanceSetting.NotificationSettingH\x00R\x13notificationSetting\x1a\xca\x04\n" + "\x0eGeneralSetting\x12<\n" + "\x1adisallow_user_registration\x18\x02 \x01(\bR\x18disallowUserRegistration\x124\n" + "\x16disallow_password_auth\x18\x03 \x01(\bR\x14disallowPasswordAuth\x12+\n" + @@ -1042,13 +1225,29 @@ const file_api_v1_instance_service_proto_rawDesc = "" + "\x04tags\x18\x01 \x03(\v23.memos.api.v1.InstanceSetting.TagsSetting.TagsEntryR\x04tags\x1ab\n" + "\tTagsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12?\n" + - "\x05value\x18\x02 \x01(\v2).memos.api.v1.InstanceSetting.TagMetadataR\x05value:\x028\x01\"P\n" + + "\x05value\x18\x02 \x01(\v2).memos.api.v1.InstanceSetting.TagMetadataR\x05value:\x028\x01\x1a\xa3\x03\n" + + "\x13NotificationSetting\x12T\n" + + "\x05email\x18\x01 \x01(\v2>.memos.api.v1.InstanceSetting.NotificationSetting.EmailSettingR\x05email\x1a\xb5\x02\n" + + "\fEmailSetting\x12\x18\n" + + "\aenabled\x18\x01 \x01(\bR\aenabled\x12\x1b\n" + + "\tsmtp_host\x18\x02 \x01(\tR\bsmtpHost\x12\x1b\n" + + "\tsmtp_port\x18\x03 \x01(\x05R\bsmtpPort\x12#\n" + + "\rsmtp_username\x18\x04 \x01(\tR\fsmtpUsername\x12#\n" + + "\rsmtp_password\x18\x05 \x01(\tR\fsmtpPassword\x12\x1d\n" + + "\n" + + "from_email\x18\x06 \x01(\tR\tfromEmail\x12\x1b\n" + + "\tfrom_name\x18\a \x01(\tR\bfromName\x12\x19\n" + + "\breply_to\x18\b \x01(\tR\areplyTo\x12\x17\n" + + "\ause_tls\x18\t \x01(\bR\x06useTls\x12\x17\n" + + "\ause_ssl\x18\n" + + " \x01(\bR\x06useSsl\"b\n" + "\x03Key\x12\x13\n" + "\x0fKEY_UNSPECIFIED\x10\x00\x12\v\n" + "\aGENERAL\x10\x01\x12\v\n" + "\aSTORAGE\x10\x02\x12\x10\n" + "\fMEMO_RELATED\x10\x03\x12\b\n" + - "\x04TAGS\x10\x04:a\xeaA^\n" + + "\x04TAGS\x10\x04\x12\x10\n" + + "\fNOTIFICATION\x10\x05:a\xeaA^\n" + "\x1cmemos.api.v1/InstanceSetting\x12\x1binstance/settings/{setting}*\x10instanceSettings2\x0finstanceSettingB\a\n" + "\x05value\"U\n" + "\x19GetInstanceSettingRequest\x128\n" + @@ -1077,7 +1276,7 @@ func file_api_v1_instance_service_proto_rawDescGZIP() []byte { } var file_api_v1_instance_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_api_v1_instance_service_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_api_v1_instance_service_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_api_v1_instance_service_proto_goTypes = []any{ (InstanceSetting_Key)(0), // 0: memos.api.v1.InstanceSetting.Key (InstanceSetting_StorageSetting_StorageType)(0), // 1: memos.api.v1.InstanceSetting.StorageSetting.StorageType @@ -1091,38 +1290,42 @@ var file_api_v1_instance_service_proto_goTypes = []any{ (*InstanceSetting_MemoRelatedSetting)(nil), // 9: memos.api.v1.InstanceSetting.MemoRelatedSetting (*InstanceSetting_TagMetadata)(nil), // 10: memos.api.v1.InstanceSetting.TagMetadata (*InstanceSetting_TagsSetting)(nil), // 11: memos.api.v1.InstanceSetting.TagsSetting - (*InstanceSetting_GeneralSetting_CustomProfile)(nil), // 12: memos.api.v1.InstanceSetting.GeneralSetting.CustomProfile - (*InstanceSetting_StorageSetting_S3Config)(nil), // 13: memos.api.v1.InstanceSetting.StorageSetting.S3Config - nil, // 14: memos.api.v1.InstanceSetting.TagsSetting.TagsEntry - (*User)(nil), // 15: memos.api.v1.User - (*fieldmaskpb.FieldMask)(nil), // 16: google.protobuf.FieldMask - (*color.Color)(nil), // 17: google.type.Color + (*InstanceSetting_NotificationSetting)(nil), // 12: memos.api.v1.InstanceSetting.NotificationSetting + (*InstanceSetting_GeneralSetting_CustomProfile)(nil), // 13: memos.api.v1.InstanceSetting.GeneralSetting.CustomProfile + (*InstanceSetting_StorageSetting_S3Config)(nil), // 14: memos.api.v1.InstanceSetting.StorageSetting.S3Config + nil, // 15: memos.api.v1.InstanceSetting.TagsSetting.TagsEntry + (*InstanceSetting_NotificationSetting_EmailSetting)(nil), // 16: memos.api.v1.InstanceSetting.NotificationSetting.EmailSetting + (*User)(nil), // 17: memos.api.v1.User + (*fieldmaskpb.FieldMask)(nil), // 18: google.protobuf.FieldMask + (*color.Color)(nil), // 19: google.type.Color } var file_api_v1_instance_service_proto_depIdxs = []int32{ - 15, // 0: memos.api.v1.InstanceProfile.admin:type_name -> memos.api.v1.User + 17, // 0: memos.api.v1.InstanceProfile.admin:type_name -> memos.api.v1.User 7, // 1: memos.api.v1.InstanceSetting.general_setting:type_name -> memos.api.v1.InstanceSetting.GeneralSetting 8, // 2: memos.api.v1.InstanceSetting.storage_setting:type_name -> memos.api.v1.InstanceSetting.StorageSetting 9, // 3: memos.api.v1.InstanceSetting.memo_related_setting:type_name -> memos.api.v1.InstanceSetting.MemoRelatedSetting 11, // 4: memos.api.v1.InstanceSetting.tags_setting:type_name -> memos.api.v1.InstanceSetting.TagsSetting - 4, // 5: memos.api.v1.UpdateInstanceSettingRequest.setting:type_name -> memos.api.v1.InstanceSetting - 16, // 6: memos.api.v1.UpdateInstanceSettingRequest.update_mask:type_name -> google.protobuf.FieldMask - 12, // 7: memos.api.v1.InstanceSetting.GeneralSetting.custom_profile:type_name -> memos.api.v1.InstanceSetting.GeneralSetting.CustomProfile - 1, // 8: memos.api.v1.InstanceSetting.StorageSetting.storage_type:type_name -> memos.api.v1.InstanceSetting.StorageSetting.StorageType - 13, // 9: memos.api.v1.InstanceSetting.StorageSetting.s3_config:type_name -> memos.api.v1.InstanceSetting.StorageSetting.S3Config - 17, // 10: memos.api.v1.InstanceSetting.TagMetadata.background_color:type_name -> google.type.Color - 14, // 11: memos.api.v1.InstanceSetting.TagsSetting.tags:type_name -> memos.api.v1.InstanceSetting.TagsSetting.TagsEntry - 10, // 12: memos.api.v1.InstanceSetting.TagsSetting.TagsEntry.value:type_name -> memos.api.v1.InstanceSetting.TagMetadata - 3, // 13: memos.api.v1.InstanceService.GetInstanceProfile:input_type -> memos.api.v1.GetInstanceProfileRequest - 5, // 14: memos.api.v1.InstanceService.GetInstanceSetting:input_type -> memos.api.v1.GetInstanceSettingRequest - 6, // 15: memos.api.v1.InstanceService.UpdateInstanceSetting:input_type -> memos.api.v1.UpdateInstanceSettingRequest - 2, // 16: memos.api.v1.InstanceService.GetInstanceProfile:output_type -> memos.api.v1.InstanceProfile - 4, // 17: memos.api.v1.InstanceService.GetInstanceSetting:output_type -> memos.api.v1.InstanceSetting - 4, // 18: memos.api.v1.InstanceService.UpdateInstanceSetting:output_type -> memos.api.v1.InstanceSetting - 16, // [16:19] is the sub-list for method output_type - 13, // [13:16] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 12, // 5: memos.api.v1.InstanceSetting.notification_setting:type_name -> memos.api.v1.InstanceSetting.NotificationSetting + 4, // 6: memos.api.v1.UpdateInstanceSettingRequest.setting:type_name -> memos.api.v1.InstanceSetting + 18, // 7: memos.api.v1.UpdateInstanceSettingRequest.update_mask:type_name -> google.protobuf.FieldMask + 13, // 8: memos.api.v1.InstanceSetting.GeneralSetting.custom_profile:type_name -> memos.api.v1.InstanceSetting.GeneralSetting.CustomProfile + 1, // 9: memos.api.v1.InstanceSetting.StorageSetting.storage_type:type_name -> memos.api.v1.InstanceSetting.StorageSetting.StorageType + 14, // 10: memos.api.v1.InstanceSetting.StorageSetting.s3_config:type_name -> memos.api.v1.InstanceSetting.StorageSetting.S3Config + 19, // 11: memos.api.v1.InstanceSetting.TagMetadata.background_color:type_name -> google.type.Color + 15, // 12: memos.api.v1.InstanceSetting.TagsSetting.tags:type_name -> memos.api.v1.InstanceSetting.TagsSetting.TagsEntry + 16, // 13: memos.api.v1.InstanceSetting.NotificationSetting.email:type_name -> memos.api.v1.InstanceSetting.NotificationSetting.EmailSetting + 10, // 14: memos.api.v1.InstanceSetting.TagsSetting.TagsEntry.value:type_name -> memos.api.v1.InstanceSetting.TagMetadata + 3, // 15: memos.api.v1.InstanceService.GetInstanceProfile:input_type -> memos.api.v1.GetInstanceProfileRequest + 5, // 16: memos.api.v1.InstanceService.GetInstanceSetting:input_type -> memos.api.v1.GetInstanceSettingRequest + 6, // 17: memos.api.v1.InstanceService.UpdateInstanceSetting:input_type -> memos.api.v1.UpdateInstanceSettingRequest + 2, // 18: memos.api.v1.InstanceService.GetInstanceProfile:output_type -> memos.api.v1.InstanceProfile + 4, // 19: memos.api.v1.InstanceService.GetInstanceSetting:output_type -> memos.api.v1.InstanceSetting + 4, // 20: memos.api.v1.InstanceService.UpdateInstanceSetting:output_type -> memos.api.v1.InstanceSetting + 18, // [18:21] is the sub-list for method output_type + 15, // [15:18] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_api_v1_instance_service_proto_init() } @@ -1136,6 +1339,7 @@ func file_api_v1_instance_service_proto_init() { (*InstanceSetting_StorageSetting_)(nil), (*InstanceSetting_MemoRelatedSetting_)(nil), (*InstanceSetting_TagsSetting_)(nil), + (*InstanceSetting_NotificationSetting_)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -1143,7 +1347,7 @@ func file_api_v1_instance_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_instance_service_proto_rawDesc), len(file_api_v1_instance_service_proto_rawDesc)), NumEnums: 2, - NumMessages: 13, + NumMessages: 15, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/openapi.yaml b/proto/gen/openapi.yaml index 5dd207279..7983a4097 100644 --- a/proto/gen/openapi.yaml +++ b/proto/gen/openapi.yaml @@ -2192,6 +2192,8 @@ components: $ref: '#/components/schemas/InstanceSetting_MemoRelatedSetting' tagsSetting: $ref: '#/components/schemas/InstanceSetting_TagsSetting' + notificationSetting: + $ref: '#/components/schemas/InstanceSetting_NotificationSetting' description: An instance setting resource. InstanceSetting_GeneralSetting: type: object @@ -2248,6 +2250,12 @@ components: type: string description: reactions is the list of reactions. description: Memo-related instance settings and policies. + InstanceSetting_NotificationSetting: + type: object + properties: + email: + $ref: '#/components/schemas/NotificationSetting_EmailSetting' + description: Notification transport configuration. InstanceSetting_StorageSetting: type: object properties: @@ -2626,6 +2634,31 @@ components: type: string description: The title extracted from the first H1 heading, if present. description: Computed properties of a memo. + NotificationSetting_EmailSetting: + type: object + properties: + enabled: + type: boolean + smtpHost: + type: string + smtpPort: + type: integer + format: int32 + smtpUsername: + type: string + smtpPassword: + type: string + fromEmail: + type: string + fromName: + type: string + replyTo: + type: string + useTls: + type: boolean + useSsl: + type: boolean + description: Email delivery configuration for notifications. OAuth2Config: type: object properties: diff --git a/proto/gen/store/instance_setting.pb.go b/proto/gen/store/instance_setting.pb.go index c3a9e325c..26bd5fcd4 100644 --- a/proto/gen/store/instance_setting.pb.go +++ b/proto/gen/store/instance_setting.pb.go @@ -36,6 +36,8 @@ const ( InstanceSettingKey_MEMO_RELATED InstanceSettingKey = 4 // TAGS is the key for tag metadata. InstanceSettingKey_TAGS InstanceSettingKey = 5 + // NOTIFICATION is the key for notification transport settings. + InstanceSettingKey_NOTIFICATION InstanceSettingKey = 6 ) // Enum value maps for InstanceSettingKey. @@ -47,6 +49,7 @@ var ( 3: "STORAGE", 4: "MEMO_RELATED", 5: "TAGS", + 6: "NOTIFICATION", } InstanceSettingKey_value = map[string]int32{ "INSTANCE_SETTING_KEY_UNSPECIFIED": 0, @@ -55,6 +58,7 @@ var ( "STORAGE": 3, "MEMO_RELATED": 4, "TAGS": 5, + "NOTIFICATION": 6, } ) @@ -150,6 +154,7 @@ type InstanceSetting struct { // *InstanceSetting_StorageSetting // *InstanceSetting_MemoRelatedSetting // *InstanceSetting_TagsSetting + // *InstanceSetting_NotificationSetting Value isInstanceSetting_Value `protobuf_oneof:"value"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -244,6 +249,15 @@ func (x *InstanceSetting) GetTagsSetting() *InstanceTagsSetting { return nil } +func (x *InstanceSetting) GetNotificationSetting() *InstanceNotificationSetting { + if x != nil { + if x, ok := x.Value.(*InstanceSetting_NotificationSetting); ok { + return x.NotificationSetting + } + } + return nil +} + type isInstanceSetting_Value interface { isInstanceSetting_Value() } @@ -268,6 +282,10 @@ type InstanceSetting_TagsSetting struct { TagsSetting *InstanceTagsSetting `protobuf:"bytes,6,opt,name=tags_setting,json=tagsSetting,proto3,oneof"` } +type InstanceSetting_NotificationSetting struct { + NotificationSetting *InstanceNotificationSetting `protobuf:"bytes,7,opt,name=notification_setting,json=notificationSetting,proto3,oneof"` +} + func (*InstanceSetting_BasicSetting) isInstanceSetting_Value() {} func (*InstanceSetting_GeneralSetting) isInstanceSetting_Value() {} @@ -278,6 +296,8 @@ func (*InstanceSetting_MemoRelatedSetting) isInstanceSetting_Value() {} func (*InstanceSetting_TagsSetting) isInstanceSetting_Value() {} +func (*InstanceSetting_NotificationSetting) isInstanceSetting_Value() {} + type InstanceBasicSetting struct { state protoimpl.MessageState `protogen:"open.v1"` // The secret key for instance. Mainly used for session management. @@ -830,18 +850,179 @@ func (x *InstanceTagsSetting) GetTags() map[string]*InstanceTagMetadata { return nil } +type InstanceNotificationSetting struct { + state protoimpl.MessageState `protogen:"open.v1"` + Email *InstanceNotificationSetting_EmailSetting `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InstanceNotificationSetting) Reset() { + *x = InstanceNotificationSetting{} + mi := &file_store_instance_setting_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InstanceNotificationSetting) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstanceNotificationSetting) ProtoMessage() {} + +func (x *InstanceNotificationSetting) ProtoReflect() protoreflect.Message { + mi := &file_store_instance_setting_proto_msgTypes[9] + 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 InstanceNotificationSetting.ProtoReflect.Descriptor instead. +func (*InstanceNotificationSetting) Descriptor() ([]byte, []int) { + return file_store_instance_setting_proto_rawDescGZIP(), []int{9} +} + +func (x *InstanceNotificationSetting) GetEmail() *InstanceNotificationSetting_EmailSetting { + if x != nil { + return x.Email + } + return nil +} + +type InstanceNotificationSetting_EmailSetting struct { + state protoimpl.MessageState `protogen:"open.v1"` + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + SmtpHost string `protobuf:"bytes,2,opt,name=smtp_host,json=smtpHost,proto3" json:"smtp_host,omitempty"` + SmtpPort int32 `protobuf:"varint,3,opt,name=smtp_port,json=smtpPort,proto3" json:"smtp_port,omitempty"` + SmtpUsername string `protobuf:"bytes,4,opt,name=smtp_username,json=smtpUsername,proto3" json:"smtp_username,omitempty"` + SmtpPassword string `protobuf:"bytes,5,opt,name=smtp_password,json=smtpPassword,proto3" json:"smtp_password,omitempty"` + FromEmail string `protobuf:"bytes,6,opt,name=from_email,json=fromEmail,proto3" json:"from_email,omitempty"` + FromName string `protobuf:"bytes,7,opt,name=from_name,json=fromName,proto3" json:"from_name,omitempty"` + ReplyTo string `protobuf:"bytes,8,opt,name=reply_to,json=replyTo,proto3" json:"reply_to,omitempty"` + UseTls bool `protobuf:"varint,9,opt,name=use_tls,json=useTls,proto3" json:"use_tls,omitempty"` + UseSsl bool `protobuf:"varint,10,opt,name=use_ssl,json=useSsl,proto3" json:"use_ssl,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InstanceNotificationSetting_EmailSetting) Reset() { + *x = InstanceNotificationSetting_EmailSetting{} + mi := &file_store_instance_setting_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InstanceNotificationSetting_EmailSetting) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstanceNotificationSetting_EmailSetting) ProtoMessage() {} + +func (x *InstanceNotificationSetting_EmailSetting) ProtoReflect() protoreflect.Message { + mi := &file_store_instance_setting_proto_msgTypes[11] + 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 InstanceNotificationSetting_EmailSetting.ProtoReflect.Descriptor instead. +func (*InstanceNotificationSetting_EmailSetting) Descriptor() ([]byte, []int) { + return file_store_instance_setting_proto_rawDescGZIP(), []int{9, 0} +} + +func (x *InstanceNotificationSetting_EmailSetting) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *InstanceNotificationSetting_EmailSetting) GetSmtpHost() string { + if x != nil { + return x.SmtpHost + } + return "" +} + +func (x *InstanceNotificationSetting_EmailSetting) GetSmtpPort() int32 { + if x != nil { + return x.SmtpPort + } + return 0 +} + +func (x *InstanceNotificationSetting_EmailSetting) GetSmtpUsername() string { + if x != nil { + return x.SmtpUsername + } + return "" +} + +func (x *InstanceNotificationSetting_EmailSetting) GetSmtpPassword() string { + if x != nil { + return x.SmtpPassword + } + return "" +} + +func (x *InstanceNotificationSetting_EmailSetting) GetFromEmail() string { + if x != nil { + return x.FromEmail + } + return "" +} + +func (x *InstanceNotificationSetting_EmailSetting) GetFromName() string { + if x != nil { + return x.FromName + } + return "" +} + +func (x *InstanceNotificationSetting_EmailSetting) GetReplyTo() string { + if x != nil { + return x.ReplyTo + } + return "" +} + +func (x *InstanceNotificationSetting_EmailSetting) GetUseTls() bool { + if x != nil { + return x.UseTls + } + return false +} + +func (x *InstanceNotificationSetting_EmailSetting) GetUseSsl() bool { + if x != nil { + return x.UseSsl + } + return false +} + var File_store_instance_setting_proto protoreflect.FileDescriptor const file_store_instance_setting_proto_rawDesc = "" + "\n" + - "\x1cstore/instance_setting.proto\x12\vmemos.store\x1a\x17google/type/color.proto\"\xdb\x03\n" + + "\x1cstore/instance_setting.proto\x12\vmemos.store\x1a\x17google/type/color.proto\"\xba\x04\n" + "\x0fInstanceSetting\x121\n" + "\x03key\x18\x01 \x01(\x0e2\x1f.memos.store.InstanceSettingKeyR\x03key\x12H\n" + "\rbasic_setting\x18\x02 \x01(\v2!.memos.store.InstanceBasicSettingH\x00R\fbasicSetting\x12N\n" + "\x0fgeneral_setting\x18\x03 \x01(\v2#.memos.store.InstanceGeneralSettingH\x00R\x0egeneralSetting\x12N\n" + "\x0fstorage_setting\x18\x04 \x01(\v2#.memos.store.InstanceStorageSettingH\x00R\x0estorageSetting\x12[\n" + "\x14memo_related_setting\x18\x05 \x01(\v2'.memos.store.InstanceMemoRelatedSettingH\x00R\x12memoRelatedSetting\x12E\n" + - "\ftags_setting\x18\x06 \x01(\v2 .memos.store.InstanceTagsSettingH\x00R\vtagsSettingB\a\n" + + "\ftags_setting\x18\x06 \x01(\v2 .memos.store.InstanceTagsSettingH\x00R\vtagsSetting\x12]\n" + + "\x14notification_setting\x18\a \x01(\v2(.memos.store.InstanceNotificationSettingH\x00R\x13notificationSettingB\a\n" + "\x05value\"\\\n" + "\x14InstanceBasicSetting\x12\x1d\n" + "\n" + @@ -889,14 +1070,30 @@ const file_store_instance_setting_proto_rawDesc = "" + "\x04tags\x18\x01 \x03(\v2*.memos.store.InstanceTagsSetting.TagsEntryR\x04tags\x1aY\n" + "\tTagsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x126\n" + - "\x05value\x18\x02 \x01(\v2 .memos.store.InstanceTagMetadataR\x05value:\x028\x01*{\n" + + "\x05value\x18\x02 \x01(\v2 .memos.store.InstanceTagMetadataR\x05value:\x028\x01\"\xa2\x03\n" + + "\x1bInstanceNotificationSetting\x12K\n" + + "\x05email\x18\x01 \x01(\v25.memos.store.InstanceNotificationSetting.EmailSettingR\x05email\x1a\xb5\x02\n" + + "\fEmailSetting\x12\x18\n" + + "\aenabled\x18\x01 \x01(\bR\aenabled\x12\x1b\n" + + "\tsmtp_host\x18\x02 \x01(\tR\bsmtpHost\x12\x1b\n" + + "\tsmtp_port\x18\x03 \x01(\x05R\bsmtpPort\x12#\n" + + "\rsmtp_username\x18\x04 \x01(\tR\fsmtpUsername\x12#\n" + + "\rsmtp_password\x18\x05 \x01(\tR\fsmtpPassword\x12\x1d\n" + + "\n" + + "from_email\x18\x06 \x01(\tR\tfromEmail\x12\x1b\n" + + "\tfrom_name\x18\a \x01(\tR\bfromName\x12\x19\n" + + "\breply_to\x18\b \x01(\tR\areplyTo\x12\x17\n" + + "\ause_tls\x18\t \x01(\bR\x06useTls\x12\x17\n" + + "\ause_ssl\x18\n" + + " \x01(\bR\x06useSsl*\x8d\x01\n" + "\x12InstanceSettingKey\x12$\n" + " INSTANCE_SETTING_KEY_UNSPECIFIED\x10\x00\x12\t\n" + "\x05BASIC\x10\x01\x12\v\n" + "\aGENERAL\x10\x02\x12\v\n" + "\aSTORAGE\x10\x03\x12\x10\n" + "\fMEMO_RELATED\x10\x04\x12\b\n" + - "\x04TAGS\x10\x05B\x9f\x01\n" + + "\x04TAGS\x10\x05\x12\x10\n" + + "\fNOTIFICATION\x10\x06B\x9f\x01\n" + "\x0fcom.memos.storeB\x14InstanceSettingProtoP\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 ( @@ -912,21 +1109,23 @@ func file_store_instance_setting_proto_rawDescGZIP() []byte { } var file_store_instance_setting_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_store_instance_setting_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_store_instance_setting_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_store_instance_setting_proto_goTypes = []any{ - (InstanceSettingKey)(0), // 0: memos.store.InstanceSettingKey - (InstanceStorageSetting_StorageType)(0), // 1: memos.store.InstanceStorageSetting.StorageType - (*InstanceSetting)(nil), // 2: memos.store.InstanceSetting - (*InstanceBasicSetting)(nil), // 3: memos.store.InstanceBasicSetting - (*InstanceGeneralSetting)(nil), // 4: memos.store.InstanceGeneralSetting - (*InstanceCustomProfile)(nil), // 5: memos.store.InstanceCustomProfile - (*InstanceStorageSetting)(nil), // 6: memos.store.InstanceStorageSetting - (*StorageS3Config)(nil), // 7: memos.store.StorageS3Config - (*InstanceMemoRelatedSetting)(nil), // 8: memos.store.InstanceMemoRelatedSetting - (*InstanceTagMetadata)(nil), // 9: memos.store.InstanceTagMetadata - (*InstanceTagsSetting)(nil), // 10: memos.store.InstanceTagsSetting - nil, // 11: memos.store.InstanceTagsSetting.TagsEntry - (*color.Color)(nil), // 12: google.type.Color + (InstanceSettingKey)(0), // 0: memos.store.InstanceSettingKey + (InstanceStorageSetting_StorageType)(0), // 1: memos.store.InstanceStorageSetting.StorageType + (*InstanceSetting)(nil), // 2: memos.store.InstanceSetting + (*InstanceBasicSetting)(nil), // 3: memos.store.InstanceBasicSetting + (*InstanceGeneralSetting)(nil), // 4: memos.store.InstanceGeneralSetting + (*InstanceCustomProfile)(nil), // 5: memos.store.InstanceCustomProfile + (*InstanceStorageSetting)(nil), // 6: memos.store.InstanceStorageSetting + (*StorageS3Config)(nil), // 7: memos.store.StorageS3Config + (*InstanceMemoRelatedSetting)(nil), // 8: memos.store.InstanceMemoRelatedSetting + (*InstanceTagMetadata)(nil), // 9: memos.store.InstanceTagMetadata + (*InstanceTagsSetting)(nil), // 10: memos.store.InstanceTagsSetting + (*InstanceNotificationSetting)(nil), // 11: memos.store.InstanceNotificationSetting + nil, // 12: memos.store.InstanceTagsSetting.TagsEntry + (*InstanceNotificationSetting_EmailSetting)(nil), // 13: memos.store.InstanceNotificationSetting.EmailSetting + (*color.Color)(nil), // 14: google.type.Color } var file_store_instance_setting_proto_depIdxs = []int32{ 0, // 0: memos.store.InstanceSetting.key:type_name -> memos.store.InstanceSettingKey @@ -935,17 +1134,19 @@ var file_store_instance_setting_proto_depIdxs = []int32{ 6, // 3: memos.store.InstanceSetting.storage_setting:type_name -> memos.store.InstanceStorageSetting 8, // 4: memos.store.InstanceSetting.memo_related_setting:type_name -> memos.store.InstanceMemoRelatedSetting 10, // 5: memos.store.InstanceSetting.tags_setting:type_name -> memos.store.InstanceTagsSetting - 5, // 6: memos.store.InstanceGeneralSetting.custom_profile:type_name -> memos.store.InstanceCustomProfile - 1, // 7: memos.store.InstanceStorageSetting.storage_type:type_name -> memos.store.InstanceStorageSetting.StorageType - 7, // 8: memos.store.InstanceStorageSetting.s3_config:type_name -> memos.store.StorageS3Config - 12, // 9: memos.store.InstanceTagMetadata.background_color:type_name -> google.type.Color - 11, // 10: memos.store.InstanceTagsSetting.tags:type_name -> memos.store.InstanceTagsSetting.TagsEntry - 9, // 11: memos.store.InstanceTagsSetting.TagsEntry.value:type_name -> memos.store.InstanceTagMetadata - 12, // [12:12] is the sub-list for method output_type - 12, // [12:12] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 11, // 6: memos.store.InstanceSetting.notification_setting:type_name -> memos.store.InstanceNotificationSetting + 5, // 7: memos.store.InstanceGeneralSetting.custom_profile:type_name -> memos.store.InstanceCustomProfile + 1, // 8: memos.store.InstanceStorageSetting.storage_type:type_name -> memos.store.InstanceStorageSetting.StorageType + 7, // 9: memos.store.InstanceStorageSetting.s3_config:type_name -> memos.store.StorageS3Config + 14, // 10: memos.store.InstanceTagMetadata.background_color:type_name -> google.type.Color + 12, // 11: memos.store.InstanceTagsSetting.tags:type_name -> memos.store.InstanceTagsSetting.TagsEntry + 13, // 12: memos.store.InstanceNotificationSetting.email:type_name -> memos.store.InstanceNotificationSetting.EmailSetting + 9, // 13: memos.store.InstanceTagsSetting.TagsEntry.value:type_name -> memos.store.InstanceTagMetadata + 14, // [14:14] is the sub-list for method output_type + 14, // [14:14] is the sub-list for method input_type + 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_instance_setting_proto_init() } @@ -959,6 +1160,7 @@ func file_store_instance_setting_proto_init() { (*InstanceSetting_StorageSetting)(nil), (*InstanceSetting_MemoRelatedSetting)(nil), (*InstanceSetting_TagsSetting)(nil), + (*InstanceSetting_NotificationSetting)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -966,7 +1168,7 @@ func file_store_instance_setting_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_store_instance_setting_proto_rawDesc), len(file_store_instance_setting_proto_rawDesc)), NumEnums: 2, - NumMessages: 10, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/store/instance_setting.proto b/proto/store/instance_setting.proto index 62bb3db44..b0ab9a4b2 100644 --- a/proto/store/instance_setting.proto +++ b/proto/store/instance_setting.proto @@ -18,6 +18,8 @@ enum InstanceSettingKey { MEMO_RELATED = 4; // TAGS is the key for tag metadata. TAGS = 5; + // NOTIFICATION is the key for notification transport settings. + NOTIFICATION = 6; } message InstanceSetting { @@ -28,6 +30,7 @@ message InstanceSetting { InstanceStorageSetting storage_setting = 4; InstanceMemoRelatedSetting memo_related_setting = 5; InstanceTagsSetting tags_setting = 6; + InstanceNotificationSetting notification_setting = 7; } } @@ -117,3 +120,20 @@ message InstanceTagMetadata { message InstanceTagsSetting { map tags = 1; } + +message InstanceNotificationSetting { + EmailSetting email = 1; + + message EmailSetting { + bool enabled = 1; + string smtp_host = 2; + int32 smtp_port = 3; + string smtp_username = 4; + string smtp_password = 5; + string from_email = 6; + string from_name = 7; + string reply_to = 8; + bool use_tls = 9; + bool use_ssl = 10; + } +} diff --git a/server/router/api/v1/instance_service.go b/server/router/api/v1/instance_service.go index dcee7f301..042df9d34 100644 --- a/server/router/api/v1/instance_service.go +++ b/server/router/api/v1/instance_service.go @@ -51,6 +51,8 @@ func (s *APIV1Service) GetInstanceSetting(ctx context.Context, request *v1pb.Get _, err = s.Store.GetInstanceStorageSetting(ctx) case storepb.InstanceSettingKey_TAGS: _, err = s.Store.GetInstanceTagsSetting(ctx) + case storepb.InstanceSettingKey_NOTIFICATION: + _, err = s.Store.GetInstanceNotificationSetting(ctx) default: return nil, status.Errorf(codes.InvalidArgument, "unsupported instance setting key: %v", instanceSettingKey) } @@ -134,6 +136,10 @@ func convertInstanceSettingFromStore(setting *storepb.InstanceSetting) *v1pb.Ins instanceSetting.Value = &v1pb.InstanceSetting_TagsSetting_{ TagsSetting: convertInstanceTagsSettingFromStore(setting.GetTagsSetting()), } + case *storepb.InstanceSetting_NotificationSetting: + instanceSetting.Value = &v1pb.InstanceSetting_NotificationSetting_{ + NotificationSetting: convertInstanceNotificationSettingFromStore(setting.GetNotificationSetting()), + } default: // Leave Value unset for unsupported setting variants. } @@ -165,6 +171,10 @@ func convertInstanceSettingToStore(setting *v1pb.InstanceSetting) *storepb.Insta instanceSetting.Value = &storepb.InstanceSetting_TagsSetting{ TagsSetting: convertInstanceTagsSettingToStore(setting.GetTagsSetting()), } + case storepb.InstanceSettingKey_NOTIFICATION: + instanceSetting.Value = &storepb.InstanceSetting_NotificationSetting{ + NotificationSetting: convertInstanceNotificationSettingToStore(setting.GetNotificationSetting()), + } default: // Keep the default GeneralSetting value } @@ -318,6 +328,52 @@ func convertInstanceTagsSettingToStore(setting *v1pb.InstanceSetting_TagsSetting } } +func convertInstanceNotificationSettingFromStore(setting *storepb.InstanceNotificationSetting) *v1pb.InstanceSetting_NotificationSetting { + if setting == nil { + return nil + } + + notificationSetting := &v1pb.InstanceSetting_NotificationSetting{} + if setting.Email != nil { + notificationSetting.Email = &v1pb.InstanceSetting_NotificationSetting_EmailSetting{ + Enabled: setting.Email.Enabled, + SmtpHost: setting.Email.SmtpHost, + SmtpPort: setting.Email.SmtpPort, + SmtpUsername: setting.Email.SmtpUsername, + SmtpPassword: setting.Email.SmtpPassword, + FromEmail: setting.Email.FromEmail, + FromName: setting.Email.FromName, + ReplyTo: setting.Email.ReplyTo, + UseTls: setting.Email.UseTls, + UseSsl: setting.Email.UseSsl, + } + } + return notificationSetting +} + +func convertInstanceNotificationSettingToStore(setting *v1pb.InstanceSetting_NotificationSetting) *storepb.InstanceNotificationSetting { + if setting == nil { + return nil + } + + notificationSetting := &storepb.InstanceNotificationSetting{} + if setting.Email != nil { + notificationSetting.Email = &storepb.InstanceNotificationSetting_EmailSetting{ + Enabled: setting.Email.Enabled, + SmtpHost: setting.Email.SmtpHost, + SmtpPort: setting.Email.SmtpPort, + SmtpUsername: setting.Email.SmtpUsername, + SmtpPassword: setting.Email.SmtpPassword, + FromEmail: setting.Email.FromEmail, + FromName: setting.Email.FromName, + ReplyTo: setting.Email.ReplyTo, + UseTls: setting.Email.UseTls, + UseSsl: setting.Email.UseSsl, + } + } + return notificationSetting +} + func validateInstanceSetting(setting *v1pb.InstanceSetting) error { key, err := ExtractInstanceSettingKeyFromName(setting.Name) if err != nil { diff --git a/server/router/api/v1/test/instance_service_test.go b/server/router/api/v1/test/instance_service_test.go index 2fb9ff6e4..609989dab 100644 --- a/server/router/api/v1/test/instance_service_test.go +++ b/server/router/api/v1/test/instance_service_test.go @@ -204,6 +204,23 @@ func TestGetInstanceSetting(t *testing.T) { require.Empty(t, resp.GetTagsSetting().GetTags()) }) + t.Run("GetInstanceSetting - notification setting", func(t *testing.T) { + ts := NewTestService(t) + defer ts.Cleanup() + + req := &v1pb.GetInstanceSettingRequest{ + Name: "instance/settings/NOTIFICATION", + } + resp, err := ts.Service.GetInstanceSetting(ctx, req) + + require.NoError(t, err) + require.NotNil(t, resp) + require.Equal(t, "instance/settings/NOTIFICATION", resp.Name) + require.NotNil(t, resp.GetNotificationSetting()) + require.NotNil(t, resp.GetNotificationSetting().GetEmail()) + require.False(t, resp.GetNotificationSetting().GetEmail().GetEnabled()) + }) + t.Run("GetInstanceSetting - invalid setting name", func(t *testing.T) { // Create test service for this specific test ts := NewTestService(t) @@ -283,4 +300,39 @@ func TestUpdateInstanceSetting(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "invalid instance setting") }) + + t.Run("UpdateInstanceSetting - notification setting", func(t *testing.T) { + ts := NewTestService(t) + defer ts.Cleanup() + + hostUser, err := ts.CreateHostUser(ctx, "admin") + require.NoError(t, err) + + resp, err := ts.Service.UpdateInstanceSetting(ts.CreateUserContext(ctx, hostUser.ID), &v1pb.UpdateInstanceSettingRequest{ + Setting: &v1pb.InstanceSetting{ + Name: "instance/settings/NOTIFICATION", + Value: &v1pb.InstanceSetting_NotificationSetting_{ + NotificationSetting: &v1pb.InstanceSetting_NotificationSetting{ + Email: &v1pb.InstanceSetting_NotificationSetting_EmailSetting{ + Enabled: true, + SmtpHost: "smtp.example.com", + SmtpPort: 587, + SmtpUsername: "bot@example.com", + SmtpPassword: "secret", + FromEmail: "bot@example.com", + FromName: "Memos Bot", + ReplyTo: "support@example.com", + UseTls: true, + }, + }, + }, + }, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"notification_setting"}}, + }) + require.NoError(t, err) + require.NotNil(t, resp.GetNotificationSetting()) + require.NotNil(t, resp.GetNotificationSetting().GetEmail()) + require.True(t, resp.GetNotificationSetting().GetEmail().GetEnabled()) + require.Equal(t, "smtp.example.com", resp.GetNotificationSetting().GetEmail().GetSmtpHost()) + }) } diff --git a/store/instance_setting.go b/store/instance_setting.go index 2acc91fa1..4f24ebeec 100644 --- a/store/instance_setting.go +++ b/store/instance_setting.go @@ -39,6 +39,8 @@ func (s *Store) UpsertInstanceSetting(ctx context.Context, upsert *storepb.Insta valueBytes, err = protojson.Marshal(upsert.GetMemoRelatedSetting()) } else if upsert.Key == storepb.InstanceSettingKey_TAGS { valueBytes, err = protojson.Marshal(upsert.GetTagsSetting()) + } else if upsert.Key == storepb.InstanceSettingKey_NOTIFICATION { + valueBytes, err = protojson.Marshal(upsert.GetNotificationSetting()) } else { return nil, errors.Errorf("unsupported instance setting key: %v", upsert.Key) } @@ -192,6 +194,28 @@ func (s *Store) GetInstanceTagsSetting(ctx context.Context) (*storepb.InstanceTa return instanceTagsSetting, nil } +func (s *Store) GetInstanceNotificationSetting(ctx context.Context) (*storepb.InstanceNotificationSetting, error) { + instanceSetting, err := s.GetInstanceSetting(ctx, &FindInstanceSetting{ + Name: storepb.InstanceSettingKey_NOTIFICATION.String(), + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get instance notification setting") + } + + instanceNotificationSetting := &storepb.InstanceNotificationSetting{} + if instanceSetting != nil { + instanceNotificationSetting = instanceSetting.GetNotificationSetting() + } + if instanceNotificationSetting.Email == nil { + instanceNotificationSetting.Email = &storepb.InstanceNotificationSetting_EmailSetting{} + } + s.instanceSettingCache.Set(ctx, storepb.InstanceSettingKey_NOTIFICATION.String(), &storepb.InstanceSetting{ + Key: storepb.InstanceSettingKey_NOTIFICATION, + Value: &storepb.InstanceSetting_NotificationSetting{NotificationSetting: instanceNotificationSetting}, + }) + return instanceNotificationSetting, nil +} + const ( defaultInstanceStorageType = storepb.InstanceStorageSetting_LOCAL defaultInstanceUploadSizeLimitMb = 30 @@ -261,6 +285,12 @@ func convertInstanceSettingFromRaw(instanceSettingRaw *InstanceSetting) (*storep return nil, err } instanceSetting.Value = &storepb.InstanceSetting_TagsSetting{TagsSetting: tagsSetting} + case storepb.InstanceSettingKey_NOTIFICATION.String(): + notificationSetting := &storepb.InstanceNotificationSetting{} + if err := protojsonUnmarshaler.Unmarshal([]byte(instanceSettingRaw.Value), notificationSetting); err != nil { + return nil, err + } + instanceSetting.Value = &storepb.InstanceSetting_NotificationSetting{NotificationSetting: notificationSetting} default: // Skip unsupported instance setting key. return nil, nil diff --git a/store/test/instance_setting_test.go b/store/test/instance_setting_test.go index 7c4c97758..618396da1 100644 --- a/store/test/instance_setting_test.go +++ b/store/test/instance_setting_test.go @@ -257,6 +257,47 @@ func TestInstanceSettingTagsSetting(t *testing.T) { ts.Close() } +func TestInstanceSettingNotificationSetting(t *testing.T) { + t.Parallel() + ctx := context.Background() + ts := NewTestingStore(ctx, t) + + notificationSetting, err := ts.GetInstanceNotificationSetting(ctx) + require.NoError(t, err) + require.NotNil(t, notificationSetting) + require.NotNil(t, notificationSetting.Email) + require.False(t, notificationSetting.Email.Enabled) + + _, err = ts.UpsertInstanceSetting(ctx, &storepb.InstanceSetting{ + Key: storepb.InstanceSettingKey_NOTIFICATION, + Value: &storepb.InstanceSetting_NotificationSetting{ + NotificationSetting: &storepb.InstanceNotificationSetting{ + Email: &storepb.InstanceNotificationSetting_EmailSetting{ + Enabled: true, + SmtpHost: "smtp.example.com", + SmtpPort: 587, + SmtpUsername: "bot@example.com", + SmtpPassword: "secret", + FromEmail: "bot@example.com", + FromName: "Memos Bot", + ReplyTo: "support@example.com", + UseTls: true, + }, + }, + }, + }) + require.NoError(t, err) + + notificationSetting, err = ts.GetInstanceNotificationSetting(ctx) + require.NoError(t, err) + require.True(t, notificationSetting.Email.Enabled) + require.Equal(t, "smtp.example.com", notificationSetting.Email.SmtpHost) + require.Equal(t, int32(587), notificationSetting.Email.SmtpPort) + require.Equal(t, "bot@example.com", notificationSetting.Email.FromEmail) + + ts.Close() +} + func TestInstanceSettingListAll(t *testing.T) { t.Parallel() ctx := context.Background() @@ -284,10 +325,18 @@ func TestInstanceSettingListAll(t *testing.T) { }) require.NoError(t, err) - // List all - should have 2 more than initial + _, err = ts.UpsertInstanceSetting(ctx, &storepb.InstanceSetting{ + Key: storepb.InstanceSettingKey_NOTIFICATION, + Value: &storepb.InstanceSetting_NotificationSetting{ + NotificationSetting: &storepb.InstanceNotificationSetting{}, + }, + }) + require.NoError(t, err) + + // List all - should have 3 more than initial list, err := ts.ListInstanceSettings(ctx, &store.FindInstanceSetting{}) require.NoError(t, err) - require.Equal(t, initialCount+2, len(list)) + require.Equal(t, initialCount+3, len(list)) ts.Close() } diff --git a/web/src/types/proto/api/v1/instance_service_pb.ts b/web/src/types/proto/api/v1/instance_service_pb.ts index b3311189f..49ddea554 100644 --- a/web/src/types/proto/api/v1/instance_service_pb.ts +++ b/web/src/types/proto/api/v1/instance_service_pb.ts @@ -10,17 +10,17 @@ import { file_google_api_annotations } from "../../google/api/annotations_pb"; import { file_google_api_client } from "../../google/api/client_pb"; import { file_google_api_field_behavior } from "../../google/api/field_behavior_pb"; import { file_google_api_resource } from "../../google/api/resource_pb"; -import type { Color } from "../../google/type/color_pb"; -import { file_google_type_color } from "../../google/type/color_pb"; import type { FieldMask } from "@bufbuild/protobuf/wkt"; import { file_google_protobuf_field_mask } from "@bufbuild/protobuf/wkt"; +import type { Color } from "../../google/type/color_pb"; +import { file_google_type_color } from "../../google/type/color_pb"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file api/v1/instance_service.proto. */ export const file_api_v1_instance_service: GenFile = /*@__PURE__*/ - fileDesc("Ch1hcGkvdjEvaW5zdGFuY2Vfc2VydmljZS5wcm90bxIMbWVtb3MuYXBpLnYxImkKD0luc3RhbmNlUHJvZmlsZRIPCgd2ZXJzaW9uGAIgASgJEgwKBGRlbW8YAyABKAgSFAoMaW5zdGFuY2VfdXJsGAYgASgJEiEKBWFkbWluGAcgASgLMhIubWVtb3MuYXBpLnYxLlVzZXIiGwoZR2V0SW5zdGFuY2VQcm9maWxlUmVxdWVzdCLoDQoPSW5zdGFuY2VTZXR0aW5nEhEKBG5hbWUYASABKAlCA+BBCBJHCg9nZW5lcmFsX3NldHRpbmcYAiABKAsyLC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLkdlbmVyYWxTZXR0aW5nSAASRwoPc3RvcmFnZV9zZXR0aW5nGAMgASgLMiwubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZ0gAElAKFG1lbW9fcmVsYXRlZF9zZXR0aW5nGAQgASgLMjAubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5NZW1vUmVsYXRlZFNldHRpbmdIABJBCgx0YWdzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ3NTZXR0aW5nSAAahwMKDkdlbmVyYWxTZXR0aW5nEiIKGmRpc2FsbG93X3VzZXJfcmVnaXN0cmF0aW9uGAIgASgIEh4KFmRpc2FsbG93X3Bhc3N3b3JkX2F1dGgYAyABKAgSGQoRYWRkaXRpb25hbF9zY3JpcHQYBCABKAkSGAoQYWRkaXRpb25hbF9zdHlsZRgFIAEoCRJSCg5jdXN0b21fcHJvZmlsZRgGIAEoCzI6Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuR2VuZXJhbFNldHRpbmcuQ3VzdG9tUHJvZmlsZRIdChV3ZWVrX3N0YXJ0X2RheV9vZmZzZXQYByABKAUSIAoYZGlzYWxsb3dfY2hhbmdlX3VzZXJuYW1lGAggASgIEiAKGGRpc2FsbG93X2NoYW5nZV9uaWNrbmFtZRgJIAEoCBpFCg1DdXN0b21Qcm9maWxlEg0KBXRpdGxlGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEhAKCGxvZ29fdXJsGAMgASgJGroDCg5TdG9yYWdlU2V0dGluZxJOCgxzdG9yYWdlX3R5cGUYASABKA4yOC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlN0b3JhZ2VTZXR0aW5nLlN0b3JhZ2VUeXBlEhkKEWZpbGVwYXRoX3RlbXBsYXRlGAIgASgJEhwKFHVwbG9hZF9zaXplX2xpbWl0X21iGAMgASgDEkgKCXMzX2NvbmZpZxgEIAEoCzI1Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuU3RvcmFnZVNldHRpbmcuUzNDb25maWcahgEKCFMzQ29uZmlnEhUKDWFjY2Vzc19rZXlfaWQYASABKAkSGQoRYWNjZXNzX2tleV9zZWNyZXQYAiABKAkSEAoIZW5kcG9pbnQYAyABKAkSDgoGcmVnaW9uGAQgASgJEg4KBmJ1Y2tldBgFIAEoCRIWCg51c2VfcGF0aF9zdHlsZRgGIAEoCCJMCgtTdG9yYWdlVHlwZRIcChhTVE9SQUdFX1RZUEVfVU5TUEVDSUZJRUQQABIMCghEQVRBQkFTRRABEgkKBUxPQ0FMEAISBgoCUzMQAxqtAQoSTWVtb1JlbGF0ZWRTZXR0aW5nEiIKGmRpc2FsbG93X3B1YmxpY192aXNpYmlsaXR5GAEgASgIEiAKGGRpc3BsYXlfd2l0aF91cGRhdGVfdGltZRgCIAEoCBIcChRjb250ZW50X2xlbmd0aF9saW1pdBgDIAEoBRIgChhlbmFibGVfZG91YmxlX2NsaWNrX2VkaXQYBCABKAgSEQoJcmVhY3Rpb25zGAcgAygJGjsKC1RhZ01ldGFkYXRhEiwKEGJhY2tncm91bmRfY29sb3IYASABKAsyEi5nb29nbGUudHlwZS5Db2xvchqoAQoLVGFnc1NldHRpbmcSQQoEdGFncxgBIAMoCzIzLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuVGFnc1NldHRpbmcuVGFnc0VudHJ5GlYKCVRhZ3NFbnRyeRILCgNrZXkYASABKAkSOAoFdmFsdWUYAiABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ01ldGFkYXRhOgI4ASJQCgNLZXkSEwoPS0VZX1VOU1BFQ0lGSUVEEAASCwoHR0VORVJBTBABEgsKB1NUT1JBR0UQAhIQCgxNRU1PX1JFTEFURUQQAxIICgRUQUdTEAQ6YepBXgocbWVtb3MuYXBpLnYxL0luc3RhbmNlU2V0dGluZxIbaW5zdGFuY2Uvc2V0dGluZ3Mve3NldHRpbmd9KhBpbnN0YW5jZVNldHRpbmdzMg9pbnN0YW5jZVNldHRpbmdCBwoFdmFsdWUiTwoZR2V0SW5zdGFuY2VTZXR0aW5nUmVxdWVzdBIyCgRuYW1lGAEgASgJQiTgQQL6QR4KHG1lbW9zLmFwaS52MS9JbnN0YW5jZVNldHRpbmciiQEKHFVwZGF0ZUluc3RhbmNlU2V0dGluZ1JlcXVlc3QSMwoHc2V0dGluZxgBIAEoCzIdLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmdCA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBATLbAwoPSW5zdGFuY2VTZXJ2aWNlEn4KEkdldEluc3RhbmNlUHJvZmlsZRInLm1lbW9zLmFwaS52MS5HZXRJbnN0YW5jZVByb2ZpbGVSZXF1ZXN0Gh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlUHJvZmlsZSIggtPkkwIaEhgvYXBpL3YxL2luc3RhbmNlL3Byb2ZpbGUSjwEKEkdldEluc3RhbmNlU2V0dGluZxInLm1lbW9zLmFwaS52MS5HZXRJbnN0YW5jZVNldHRpbmdSZXF1ZXN0Gh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZyIx2kEEbmFtZYLT5JMCJBIiL2FwaS92MS97bmFtZT1pbnN0YW5jZS9zZXR0aW5ncy8qfRK1AQoVVXBkYXRlSW5zdGFuY2VTZXR0aW5nEioubWVtb3MuYXBpLnYxLlVwZGF0ZUluc3RhbmNlU2V0dGluZ1JlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nIlHaQRNzZXR0aW5nLHVwZGF0ZV9tYXNrgtPkkwI1OgdzZXR0aW5nMiovYXBpL3YxL3tzZXR0aW5nLm5hbWU9aW5zdGFuY2Uvc2V0dGluZ3MvKn1CrAEKEGNvbS5tZW1vcy5hcGkudjFCFEluc3RhbmNlU2VydmljZVByb3RvUAFaMGdpdGh1Yi5jb20vdXNlbWVtb3MvbWVtb3MvcHJvdG8vZ2VuL2FwaS92MTthcGl2MaICA01BWKoCDE1lbW9zLkFwaS5WMcoCDE1lbW9zXEFwaVxWMeICGE1lbW9zXEFwaVxWMVxHUEJNZXRhZGF0YeoCDk1lbW9zOjpBcGk6OlYxYgZwcm90bzM", [file_api_v1_user_service, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_type_color, file_google_protobuf_field_mask]); + fileDesc("Ch1hcGkvdjEvaW5zdGFuY2Vfc2VydmljZS5wcm90bxIMbWVtb3MuYXBpLnYxImkKD0luc3RhbmNlUHJvZmlsZRIPCgd2ZXJzaW9uGAIgASgJEgwKBGRlbW8YAyABKAgSFAoMaW5zdGFuY2VfdXJsGAYgASgJEiEKBWFkbWluGAcgASgLMhIubWVtb3MuYXBpLnYxLlVzZXIiGwoZR2V0SW5zdGFuY2VQcm9maWxlUmVxdWVzdCKFEQoPSW5zdGFuY2VTZXR0aW5nEhEKBG5hbWUYASABKAlCA+BBCBJHCg9nZW5lcmFsX3NldHRpbmcYAiABKAsyLC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLkdlbmVyYWxTZXR0aW5nSAASRwoPc3RvcmFnZV9zZXR0aW5nGAMgASgLMiwubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZ0gAElAKFG1lbW9fcmVsYXRlZF9zZXR0aW5nGAQgASgLMjAubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5NZW1vUmVsYXRlZFNldHRpbmdIABJBCgx0YWdzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ3NTZXR0aW5nSAASUQoUbm90aWZpY2F0aW9uX3NldHRpbmcYBiABKAsyMS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLk5vdGlmaWNhdGlvblNldHRpbmdIABqHAwoOR2VuZXJhbFNldHRpbmcSIgoaZGlzYWxsb3dfdXNlcl9yZWdpc3RyYXRpb24YAiABKAgSHgoWZGlzYWxsb3dfcGFzc3dvcmRfYXV0aBgDIAEoCBIZChFhZGRpdGlvbmFsX3NjcmlwdBgEIAEoCRIYChBhZGRpdGlvbmFsX3N0eWxlGAUgASgJElIKDmN1c3RvbV9wcm9maWxlGAYgASgLMjoubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5HZW5lcmFsU2V0dGluZy5DdXN0b21Qcm9maWxlEh0KFXdlZWtfc3RhcnRfZGF5X29mZnNldBgHIAEoBRIgChhkaXNhbGxvd19jaGFuZ2VfdXNlcm5hbWUYCCABKAgSIAoYZGlzYWxsb3dfY2hhbmdlX25pY2tuYW1lGAkgASgIGkUKDUN1c3RvbVByb2ZpbGUSDQoFdGl0bGUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSEAoIbG9nb191cmwYAyABKAkaugMKDlN0b3JhZ2VTZXR0aW5nEk4KDHN0b3JhZ2VfdHlwZRgBIAEoDjI4Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuU3RvcmFnZVNldHRpbmcuU3RvcmFnZVR5cGUSGQoRZmlsZXBhdGhfdGVtcGxhdGUYAiABKAkSHAoUdXBsb2FkX3NpemVfbGltaXRfbWIYAyABKAMSSAoJczNfY29uZmlnGAQgASgLMjUubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZy5TM0NvbmZpZxqGAQoIUzNDb25maWcSFQoNYWNjZXNzX2tleV9pZBgBIAEoCRIZChFhY2Nlc3Nfa2V5X3NlY3JldBgCIAEoCRIQCghlbmRwb2ludBgDIAEoCRIOCgZyZWdpb24YBCABKAkSDgoGYnVja2V0GAUgASgJEhYKDnVzZV9wYXRoX3N0eWxlGAYgASgIIkwKC1N0b3JhZ2VUeXBlEhwKGFNUT1JBR0VfVFlQRV9VTlNQRUNJRklFRBAAEgwKCERBVEFCQVNFEAESCQoFTE9DQUwQAhIGCgJTMxADGq0BChJNZW1vUmVsYXRlZFNldHRpbmcSIgoaZGlzYWxsb3dfcHVibGljX3Zpc2liaWxpdHkYASABKAgSIAoYZGlzcGxheV93aXRoX3VwZGF0ZV90aW1lGAIgASgIEhwKFGNvbnRlbnRfbGVuZ3RoX2xpbWl0GAMgASgFEiAKGGVuYWJsZV9kb3VibGVfY2xpY2tfZWRpdBgEIAEoCBIRCglyZWFjdGlvbnMYByADKAkaOwoLVGFnTWV0YWRhdGESLAoQYmFja2dyb3VuZF9jb2xvchgBIAEoCzISLmdvb2dsZS50eXBlLkNvbG9yGqgBCgtUYWdzU2V0dGluZxJBCgR0YWdzGAEgAygLMjMubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5UYWdzU2V0dGluZy5UYWdzRW50cnkaVgoJVGFnc0VudHJ5EgsKA2tleRgBIAEoCRI4CgV2YWx1ZRgCIAEoCzIpLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuVGFnTWV0YWRhdGE6AjgBGrUCChNOb3RpZmljYXRpb25TZXR0aW5nEk0KBWVtYWlsGAEgASgLMj4ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5Ob3RpZmljYXRpb25TZXR0aW5nLkVtYWlsU2V0dGluZxrOAQoMRW1haWxTZXR0aW5nEg8KB2VuYWJsZWQYASABKAgSEQoJc210cF9ob3N0GAIgASgJEhEKCXNtdHBfcG9ydBgDIAEoBRIVCg1zbXRwX3VzZXJuYW1lGAQgASgJEhUKDXNtdHBfcGFzc3dvcmQYBSABKAkSEgoKZnJvbV9lbWFpbBgGIAEoCRIRCglmcm9tX25hbWUYByABKAkSEAoIcmVwbHlfdG8YCCABKAkSDwoHdXNlX3RscxgJIAEoCBIPCgd1c2Vfc3NsGAogASgIImIKA0tleRITCg9LRVlfVU5TUEVDSUZJRUQQABILCgdHRU5FUkFMEAESCwoHU1RPUkFHRRACEhAKDE1FTU9fUkVMQVRFRBADEggKBFRBR1MQBBIQCgxOT1RJRklDQVRJT04QBTph6kFeChxtZW1vcy5hcGkudjEvSW5zdGFuY2VTZXR0aW5nEhtpbnN0YW5jZS9zZXR0aW5ncy97c2V0dGluZ30qEGluc3RhbmNlU2V0dGluZ3MyD2luc3RhbmNlU2V0dGluZ0IHCgV2YWx1ZSJPChlHZXRJbnN0YW5jZVNldHRpbmdSZXF1ZXN0EjIKBG5hbWUYASABKAlCJOBBAvpBHgocbWVtb3MuYXBpLnYxL0luc3RhbmNlU2V0dGluZyKJAQocVXBkYXRlSW5zdGFuY2VTZXR0aW5nUmVxdWVzdBIzCgdzZXR0aW5nGAEgASgLMh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZ0ID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EEBMtsDCg9JbnN0YW5jZVNlcnZpY2USfgoSR2V0SW5zdGFuY2VQcm9maWxlEicubWVtb3MuYXBpLnYxLkdldEluc3RhbmNlUHJvZmlsZVJlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VQcm9maWxlIiCC0+STAhoSGC9hcGkvdjEvaW5zdGFuY2UvcHJvZmlsZRKPAQoSR2V0SW5zdGFuY2VTZXR0aW5nEicubWVtb3MuYXBpLnYxLkdldEluc3RhbmNlU2V0dGluZ1JlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nIjHaQQRuYW1lgtPkkwIkEiIvYXBpL3YxL3tuYW1lPWluc3RhbmNlL3NldHRpbmdzLyp9ErUBChVVcGRhdGVJbnN0YW5jZVNldHRpbmcSKi5tZW1vcy5hcGkudjEuVXBkYXRlSW5zdGFuY2VTZXR0aW5nUmVxdWVzdBodLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmciUdpBE3NldHRpbmcsdXBkYXRlX21hc2uC0+STAjU6B3NldHRpbmcyKi9hcGkvdjEve3NldHRpbmcubmFtZT1pbnN0YW5jZS9zZXR0aW5ncy8qfUKsAQoQY29tLm1lbW9zLmFwaS52MUIUSW5zdGFuY2VTZXJ2aWNlUHJvdG9QAVowZ2l0aHViLmNvbS91c2VtZW1vcy9tZW1vcy9wcm90by9nZW4vYXBpL3YxO2FwaXYxogIDTUFYqgIMTWVtb3MuQXBpLlYxygIMTWVtb3NcQXBpXFYx4gIYTWVtb3NcQXBpXFYxXEdQQk1ldGFkYXRh6gIOTWVtb3M6OkFwaTo6VjFiBnByb3RvMw", [file_api_v1_user_service, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_field_mask, file_google_type_color]); /** * Instance profile message containing basic instance information. @@ -121,6 +121,12 @@ export type InstanceSetting = Message<"memos.api.v1.InstanceSetting"> & { */ value: InstanceSetting_TagsSetting; case: "tagsSetting"; + } | { + /** + * @generated from field: memos.api.v1.InstanceSetting.NotificationSetting notification_setting = 6; + */ + value: InstanceSetting_NotificationSetting; + case: "notificationSetting"; } | { case: undefined; value?: undefined }; }; @@ -448,6 +454,89 @@ export type InstanceSetting_TagsSetting = Message<"memos.api.v1.InstanceSetting. export const InstanceSetting_TagsSettingSchema: GenMessage = /*@__PURE__*/ messageDesc(file_api_v1_instance_service, 2, 4); +/** + * Notification transport configuration. + * + * @generated from message memos.api.v1.InstanceSetting.NotificationSetting + */ +export type InstanceSetting_NotificationSetting = Message<"memos.api.v1.InstanceSetting.NotificationSetting"> & { + /** + * @generated from field: memos.api.v1.InstanceSetting.NotificationSetting.EmailSetting email = 1; + */ + email?: InstanceSetting_NotificationSetting_EmailSetting; +}; + +/** + * Describes the message memos.api.v1.InstanceSetting.NotificationSetting. + * Use `create(InstanceSetting_NotificationSettingSchema)` to create a new message. + */ +export const InstanceSetting_NotificationSettingSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_instance_service, 2, 5); + +/** + * Email delivery configuration for notifications. + * + * @generated from message memos.api.v1.InstanceSetting.NotificationSetting.EmailSetting + */ +export type InstanceSetting_NotificationSetting_EmailSetting = Message<"memos.api.v1.InstanceSetting.NotificationSetting.EmailSetting"> & { + /** + * @generated from field: bool enabled = 1; + */ + enabled: boolean; + + /** + * @generated from field: string smtp_host = 2; + */ + smtpHost: string; + + /** + * @generated from field: int32 smtp_port = 3; + */ + smtpPort: number; + + /** + * @generated from field: string smtp_username = 4; + */ + smtpUsername: string; + + /** + * @generated from field: string smtp_password = 5; + */ + smtpPassword: string; + + /** + * @generated from field: string from_email = 6; + */ + fromEmail: string; + + /** + * @generated from field: string from_name = 7; + */ + fromName: string; + + /** + * @generated from field: string reply_to = 8; + */ + replyTo: string; + + /** + * @generated from field: bool use_tls = 9; + */ + useTls: boolean; + + /** + * @generated from field: bool use_ssl = 10; + */ + useSsl: boolean; +}; + +/** + * Describes the message memos.api.v1.InstanceSetting.NotificationSetting.EmailSetting. + * Use `create(InstanceSetting_NotificationSetting_EmailSettingSchema)` to create a new message. + */ +export const InstanceSetting_NotificationSetting_EmailSettingSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_instance_service, 2, 5, 0); + /** * Enumeration of instance setting keys. * @@ -486,6 +575,13 @@ export enum InstanceSetting_Key { * @generated from enum value: TAGS = 4; */ TAGS = 4, + + /** + * NOTIFICATION is the key for notification transport settings. + * + * @generated from enum value: NOTIFICATION = 5; + */ + NOTIFICATION = 5, } /**