diff --git a/docs/apidocs.swagger.yaml b/docs/apidocs.swagger.yaml index 9bed86aa..82c17fa7 100644 --- a/docs/apidocs.swagger.yaml +++ b/docs/apidocs.swagger.yaml @@ -2059,31 +2059,44 @@ definitions: storageType: $ref: '#/definitions/apiv1WorkspaceStorageSettingStorageType' description: storage_type is the storage type. - activedExternalStorageId: - type: integer - format: int32 - description: The id of actived external storage. - localStoragePathTemplate: + filepathTemplate: type: string title: |- - The template of local storage path. + The template of file path. e.g. assets/{timestamp}_{filename} uploadSizeLimitMb: type: string format: int64 description: The max upload size in megabytes. + s3Config: + $ref: '#/definitions/apiv1WorkspaceStorageSettingS3Config' + description: The S3 config. + apiv1WorkspaceStorageSettingS3Config: + type: object + properties: + accessKeyId: + type: string + accessKeySecret: + type: string + endpoint: + type: string + region: + type: string + bucket: + type: string + title: 'Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/' apiv1WorkspaceStorageSettingStorageType: type: string enum: - STORAGE_TYPE_UNSPECIFIED - STORAGE_TYPE_DATABASE - STORAGE_TYPE_LOCAL - - STORAGE_TYPE_EXTERNAL + - STORAGE_TYPE_S3 default: STORAGE_TYPE_UNSPECIFIED description: |2- - STORAGE_TYPE_DATABASE: STORAGE_TYPE_DATABASE is the database storage type. - STORAGE_TYPE_LOCAL: STORAGE_TYPE_LOCAL is the local storage type. - - STORAGE_TYPE_EXTERNAL: STORAGE_TYPE_EXTERNAL is the external storage type. + - STORAGE_TYPE_S3: STORAGE_TYPE_S3 is the S3 storage type. googlerpcStatus: type: object properties: diff --git a/plugin/storage/s3/s3.go b/plugin/storage/s3/s3.go index 0398bb6d..63769615 100644 --- a/plugin/storage/s3/s3.go +++ b/plugin/storage/s3/s3.go @@ -2,10 +2,7 @@ package s3 import ( "context" - "fmt" "io" - "net/url" - "strings" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -13,21 +10,17 @@ import ( "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/feature/s3/manager" awss3 "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/aws/aws-sdk-go-v2/service/s3/types" "github.com/pkg/errors" ) const LinkLifetime = 24 * time.Hour type Config struct { - AccessKey string - SecretKey string - Bucket string - EndPoint string - Region string - URLPrefix string - URLSuffix string - PreSign bool + AccessKeyID string + AcesssKeySecret string + Endpoint string + Region string + Bucket string } type Client struct { @@ -36,32 +29,21 @@ type Client struct { } func NewClient(ctx context.Context, config *Config) (*Client, error) { - // For some s3-compatible object stores, converting the hostname is not required, - // and not setting this option will result in not being able to access the corresponding object store address. - // But Aliyun OSS should disable this option - hostnameImmutable := true - if strings.HasSuffix(config.EndPoint, "aliyuncs.com") { - hostnameImmutable = false - } resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...any) (aws.Endpoint, error) { return aws.Endpoint{ - URL: config.EndPoint, - SigningRegion: config.Region, - HostnameImmutable: hostnameImmutable, + URL: config.Endpoint, }, nil }) - - awsConfig, err := s3config.LoadDefaultConfig(ctx, + s3Config, err := s3config.LoadDefaultConfig(ctx, s3config.WithEndpointResolverWithOptions(resolver), - s3config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(config.AccessKey, config.SecretKey, "")), + s3config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(config.AccessKeyID, config.AcesssKeySecret, "")), s3config.WithRegion(config.Region), ) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to load s3 config") } - client := awss3.NewFromConfig(awsConfig) - + client := awss3.NewFromConfig(s3Config) return &Client{ Client: client, Config: config, @@ -76,73 +58,14 @@ func (client *Client) UploadFile(ctx context.Context, filename string, fileType Body: src, ContentType: aws.String(fileType), } - // Set ACL according to if url prefix is set. - if client.Config.URLPrefix == "" && !client.Config.PreSign { - putInput.ACL = types.ObjectCannedACL(*aws.String("public-read")) - } uploadOutput, err := uploader.Upload(ctx, &putInput) if err != nil { return "", err } link := uploadOutput.Location - // If url prefix is set, use it as the file link. - if client.Config.URLPrefix != "" { - parts := strings.Split(filename, "/") - for i := range parts { - parts[i] = url.PathEscape(parts[i]) - } - link = fmt.Sprintf("%s/%s%s", client.Config.URLPrefix, strings.Join(parts, "/"), client.Config.URLSuffix) - } if link == "" { return "", errors.New("failed to get file link") } - if client.Config.PreSign { - return client.PreSignLink(ctx, link) - } return link, nil } - -// PreSignLink generates a pre-signed URL for the given sourceLink. -// If the link does not belong to the configured storage endpoint, it is returned as-is. -// If the link belongs to the storage, the function generates a pre-signed URL using the AWS S3 client. -func (client *Client) PreSignLink(ctx context.Context, sourceLink string) (string, error) { - u, err := url.Parse(sourceLink) - if err != nil { - return "", errors.Wrapf(err, "parse URL") - } - // if link doesn't belong to storage, then return as-is. - // the empty hostname is corner-case for AWS native endpoint. - endpointURL, err := url.Parse(client.Config.EndPoint) - if err != nil { - return "", errors.Wrapf(err, "parse Endpoint URL") - } - endpointHost := endpointURL.Hostname() - if client.Config.Bucket != "" && !strings.Contains(endpointHost, client.Config.Bucket) { - endpointHost = fmt.Sprintf("%s.%s", client.Config.Bucket, endpointHost) - } - if client.Config.EndPoint != "" && !strings.Contains(endpointHost, u.Hostname()) { - return sourceLink, nil - } - - filename := u.Path - if prefixLen := len(client.Config.URLPrefix); len(filename) >= prefixLen { - filename = filename[prefixLen:] - } - if suffixLen := len(client.Config.URLSuffix); len(filename) >= suffixLen { - filename = filename[:len(filename)-suffixLen] - } - filename = strings.Trim(filename, "/") - if strings.HasPrefix(filename, client.Config.Bucket) { - filename = strings.Trim(filename[len(client.Config.Bucket):], "/") - } - - req, err := awss3.NewPresignClient(client.Client).PresignGetObject(ctx, &awss3.GetObjectInput{ - Bucket: aws.String(client.Config.Bucket), - Key: aws.String(filename), - }, awss3.WithPresignExpires(LinkLifetime)) - if err != nil { - return "", errors.Wrapf(err, "pre-sign link") - } - return req.URL, nil -} diff --git a/proto/api/v1/workspace_setting_service.proto b/proto/api/v1/workspace_setting_service.proto index d57fd6df..9a669187 100644 --- a/proto/api/v1/workspace_setting_service.proto +++ b/proto/api/v1/workspace_setting_service.proto @@ -63,25 +63,32 @@ message WorkspaceCustomProfile { } message WorkspaceStorageSetting { - // storage_type is the storage type. - StorageType storage_type = 1; - // The id of actived external storage. - optional int32 actived_external_storage_id = 2; - // The template of local storage path. - // e.g. assets/{timestamp}_{filename} - string local_storage_path_template = 3; - // The max upload size in megabytes. - int64 upload_size_limit_mb = 4; - enum StorageType { STORAGE_TYPE_UNSPECIFIED = 0; // STORAGE_TYPE_DATABASE is the database storage type. STORAGE_TYPE_DATABASE = 1; // STORAGE_TYPE_LOCAL is the local storage type. STORAGE_TYPE_LOCAL = 2; - // STORAGE_TYPE_EXTERNAL is the external storage type. - STORAGE_TYPE_EXTERNAL = 3; + // STORAGE_TYPE_S3 is the S3 storage type. + STORAGE_TYPE_S3 = 3; } + // storage_type is the storage type. + StorageType storage_type = 1; + // The template of file path. + // e.g. assets/{timestamp}_{filename} + string filepath_template = 2; + // The max upload size in megabytes. + int64 upload_size_limit_mb = 3; + // Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/ + message S3Config { + string access_key_id = 1; + string access_key_secret = 2; + string endpoint = 3; + string region = 4; + string bucket = 5; + } + // The S3 config. + S3Config s3_config = 4; } message WorkspaceMemoRelatedSetting { diff --git a/proto/gen/api/v1/workspace_setting_service.pb.go b/proto/gen/api/v1/workspace_setting_service.pb.go index 83a0f176..0f180fb6 100644 --- a/proto/gen/api/v1/workspace_setting_service.pb.go +++ b/proto/gen/api/v1/workspace_setting_service.pb.go @@ -29,8 +29,8 @@ const ( WorkspaceStorageSetting_STORAGE_TYPE_DATABASE WorkspaceStorageSetting_StorageType = 1 // STORAGE_TYPE_LOCAL is the local storage type. WorkspaceStorageSetting_STORAGE_TYPE_LOCAL WorkspaceStorageSetting_StorageType = 2 - // STORAGE_TYPE_EXTERNAL is the external storage type. - WorkspaceStorageSetting_STORAGE_TYPE_EXTERNAL WorkspaceStorageSetting_StorageType = 3 + // STORAGE_TYPE_S3 is the S3 storage type. + WorkspaceStorageSetting_STORAGE_TYPE_S3 WorkspaceStorageSetting_StorageType = 3 ) // Enum value maps for WorkspaceStorageSetting_StorageType. @@ -39,13 +39,13 @@ var ( 0: "STORAGE_TYPE_UNSPECIFIED", 1: "STORAGE_TYPE_DATABASE", 2: "STORAGE_TYPE_LOCAL", - 3: "STORAGE_TYPE_EXTERNAL", + 3: "STORAGE_TYPE_S3", } WorkspaceStorageSetting_StorageType_value = map[string]int32{ "STORAGE_TYPE_UNSPECIFIED": 0, "STORAGE_TYPE_DATABASE": 1, "STORAGE_TYPE_LOCAL": 2, - "STORAGE_TYPE_EXTERNAL": 3, + "STORAGE_TYPE_S3": 3, } ) @@ -360,13 +360,13 @@ type WorkspaceStorageSetting struct { // storage_type is the storage type. StorageType WorkspaceStorageSetting_StorageType `protobuf:"varint,1,opt,name=storage_type,json=storageType,proto3,enum=memos.api.v1.WorkspaceStorageSetting_StorageType" json:"storage_type,omitempty"` - // The id of actived external storage. - ActivedExternalStorageId *int32 `protobuf:"varint,2,opt,name=actived_external_storage_id,json=activedExternalStorageId,proto3,oneof" json:"actived_external_storage_id,omitempty"` - // The template of local storage path. + // The template of file path. // e.g. assets/{timestamp}_{filename} - LocalStoragePathTemplate string `protobuf:"bytes,3,opt,name=local_storage_path_template,json=localStoragePathTemplate,proto3" json:"local_storage_path_template,omitempty"` + FilepathTemplate string `protobuf:"bytes,2,opt,name=filepath_template,json=filepathTemplate,proto3" json:"filepath_template,omitempty"` // The max upload size in megabytes. - UploadSizeLimitMb int64 `protobuf:"varint,4,opt,name=upload_size_limit_mb,json=uploadSizeLimitMb,proto3" json:"upload_size_limit_mb,omitempty"` + UploadSizeLimitMb int64 `protobuf:"varint,3,opt,name=upload_size_limit_mb,json=uploadSizeLimitMb,proto3" json:"upload_size_limit_mb,omitempty"` + // The S3 config. + S3Config *WorkspaceStorageSetting_S3Config `protobuf:"bytes,4,opt,name=s3_config,json=s3Config,proto3" json:"s3_config,omitempty"` } func (x *WorkspaceStorageSetting) Reset() { @@ -408,16 +408,9 @@ func (x *WorkspaceStorageSetting) GetStorageType() WorkspaceStorageSetting_Stora return WorkspaceStorageSetting_STORAGE_TYPE_UNSPECIFIED } -func (x *WorkspaceStorageSetting) GetActivedExternalStorageId() int32 { - if x != nil && x.ActivedExternalStorageId != nil { - return *x.ActivedExternalStorageId - } - return 0 -} - -func (x *WorkspaceStorageSetting) GetLocalStoragePathTemplate() string { +func (x *WorkspaceStorageSetting) GetFilepathTemplate() string { if x != nil { - return x.LocalStoragePathTemplate + return x.FilepathTemplate } return "" } @@ -429,6 +422,13 @@ func (x *WorkspaceStorageSetting) GetUploadSizeLimitMb() int64 { return 0 } +func (x *WorkspaceStorageSetting) GetS3Config() *WorkspaceStorageSetting_S3Config { + if x != nil { + return x.S3Config + } + return nil +} + type WorkspaceMemoRelatedSetting struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -668,6 +668,86 @@ func (x *SetWorkspaceSettingRequest) GetSetting() *WorkspaceSetting { return nil } +// Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/ +type WorkspaceStorageSetting_S3Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccessKeyId string `protobuf:"bytes,1,opt,name=access_key_id,json=accessKeyId,proto3" json:"access_key_id,omitempty"` + AccessKeySecret string `protobuf:"bytes,2,opt,name=access_key_secret,json=accessKeySecret,proto3" json:"access_key_secret,omitempty"` + Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + Region string `protobuf:"bytes,4,opt,name=region,proto3" json:"region,omitempty"` + Bucket string `protobuf:"bytes,5,opt,name=bucket,proto3" json:"bucket,omitempty"` +} + +func (x *WorkspaceStorageSetting_S3Config) Reset() { + *x = WorkspaceStorageSetting_S3Config{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_workspace_setting_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WorkspaceStorageSetting_S3Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkspaceStorageSetting_S3Config) ProtoMessage() {} + +func (x *WorkspaceStorageSetting_S3Config) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_workspace_setting_service_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkspaceStorageSetting_S3Config.ProtoReflect.Descriptor instead. +func (*WorkspaceStorageSetting_S3Config) Descriptor() ([]byte, []int) { + return file_api_v1_workspace_setting_service_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *WorkspaceStorageSetting_S3Config) GetAccessKeyId() string { + if x != nil { + return x.AccessKeyId + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetAccessKeySecret() string { + if x != nil { + return x.AccessKeySecret + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetEndpoint() string { + if x != nil { + return x.Endpoint + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetBucket() string { + if x != nil { + return x.Bucket + } + return "" +} + var File_api_v1_workspace_setting_service_proto protoreflect.FileDescriptor var file_api_v1_workspace_setting_service_proto_rawDesc = []byte{ @@ -729,104 +809,112 @@ var file_api_v1_workspace_setting_service_proto_rawDesc = []byte{ 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xbe, - 0x03, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, + 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xb8, + 0x04, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x54, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x42, 0x0a, 0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x18, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x64, - 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, - 0x64, 0x88, 0x01, 0x01, 0x12, 0x3d, 0x0a, 0x1b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x6c, 0x6f, 0x63, 0x61, 0x6c, - 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x61, 0x74, 0x68, 0x54, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, - 0x7a, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x11, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x4d, 0x62, 0x22, 0x79, 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, + 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x66, 0x69, 0x6c, + 0x65, 0x70, 0x61, 0x74, 0x68, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, + 0x14, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x5f, 0x6d, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x75, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x4d, 0x62, 0x12, 0x4b, + 0x0a, 0x09, 0x73, 0x33, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x33, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x08, 0x73, 0x33, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xa6, 0x01, 0x0a, 0x08, + 0x53, 0x33, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, + 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, + 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x75, + 0x63, 0x6b, 0x65, 0x74, 0x22, 0x73, 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x43, - 0x41, 0x4c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x03, 0x42, - 0x1e, 0x0a, 0x1c, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x22, - 0x8e, 0x01, 0x0a, 0x1b, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x6d, - 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, - 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x57, 0x69, 0x74, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, - 0x22, 0x1e, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x5b, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x35, 0x0a, - 0x1a, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x56, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x32, 0xf0, 0x03, 0x0a, - 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x94, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x41, 0x4c, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x33, 0x10, 0x03, 0x22, 0x8e, 0x01, 0x0a, 0x1b, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x76, 0x69, 0x73, + 0x69, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, + 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x77, 0x69, 0x74, + 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x57, 0x69, 0x74, 0x68, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x1e, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, - 0x93, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5b, 0x0a, 0x1d, 0x4c, 0x69, + 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x35, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x56, + 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x07, + 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x32, 0xf0, 0x03, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x94, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2a, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x93, 0x01, 0x0a, 0x13, 0x47, 0x65, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x32, 0xda, 0x41, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x7b, 0x6e, + 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x2a, 0x7d, 0x12, + 0xa7, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x22, 0x32, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, - 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0xa7, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x28, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, + 0x67, 0x22, 0x46, 0xda, 0x41, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x36, 0x3a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x32, 0x2b, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, + 0x7b, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x2a, 0x7d, 0x42, 0xb4, 0x01, 0x0a, 0x10, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x1c, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x46, 0xda, 0x41, 0x07, 0x73, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x3a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x32, 0x2b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x7b, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6e, - 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x2a, 0x7d, 0x42, - 0xb4, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x42, 0x1c, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, - 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, - 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x4d, 0x65, - 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, - 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, - 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, + 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, + 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, + 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, + 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, + 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -842,7 +930,7 @@ func file_api_v1_workspace_setting_service_proto_rawDescGZIP() []byte { } var file_api_v1_workspace_setting_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_api_v1_workspace_setting_service_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_api_v1_workspace_setting_service_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_api_v1_workspace_setting_service_proto_goTypes = []interface{}{ (WorkspaceStorageSetting_StorageType)(0), // 0: memos.api.v1.WorkspaceStorageSetting.StorageType (*WorkspaceSetting)(nil), // 1: memos.api.v1.WorkspaceSetting @@ -854,6 +942,7 @@ var file_api_v1_workspace_setting_service_proto_goTypes = []interface{}{ (*ListWorkspaceSettingsResponse)(nil), // 7: memos.api.v1.ListWorkspaceSettingsResponse (*GetWorkspaceSettingRequest)(nil), // 8: memos.api.v1.GetWorkspaceSettingRequest (*SetWorkspaceSettingRequest)(nil), // 9: memos.api.v1.SetWorkspaceSettingRequest + (*WorkspaceStorageSetting_S3Config)(nil), // 10: memos.api.v1.WorkspaceStorageSetting.S3Config } var file_api_v1_workspace_setting_service_proto_depIdxs = []int32{ 2, // 0: memos.api.v1.WorkspaceSetting.general_setting:type_name -> memos.api.v1.WorkspaceGeneralSetting @@ -861,19 +950,20 @@ var file_api_v1_workspace_setting_service_proto_depIdxs = []int32{ 5, // 2: memos.api.v1.WorkspaceSetting.memo_related_setting:type_name -> memos.api.v1.WorkspaceMemoRelatedSetting 3, // 3: memos.api.v1.WorkspaceGeneralSetting.custom_profile:type_name -> memos.api.v1.WorkspaceCustomProfile 0, // 4: memos.api.v1.WorkspaceStorageSetting.storage_type:type_name -> memos.api.v1.WorkspaceStorageSetting.StorageType - 1, // 5: memos.api.v1.ListWorkspaceSettingsResponse.settings:type_name -> memos.api.v1.WorkspaceSetting - 1, // 6: memos.api.v1.SetWorkspaceSettingRequest.setting:type_name -> memos.api.v1.WorkspaceSetting - 6, // 7: memos.api.v1.WorkspaceSettingService.ListWorkspaceSettings:input_type -> memos.api.v1.ListWorkspaceSettingsRequest - 8, // 8: memos.api.v1.WorkspaceSettingService.GetWorkspaceSetting:input_type -> memos.api.v1.GetWorkspaceSettingRequest - 9, // 9: memos.api.v1.WorkspaceSettingService.SetWorkspaceSetting:input_type -> memos.api.v1.SetWorkspaceSettingRequest - 7, // 10: memos.api.v1.WorkspaceSettingService.ListWorkspaceSettings:output_type -> memos.api.v1.ListWorkspaceSettingsResponse - 1, // 11: memos.api.v1.WorkspaceSettingService.GetWorkspaceSetting:output_type -> memos.api.v1.WorkspaceSetting - 1, // 12: memos.api.v1.WorkspaceSettingService.SetWorkspaceSetting:output_type -> memos.api.v1.WorkspaceSetting - 10, // [10:13] is the sub-list for method output_type - 7, // [7:10] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 10, // 5: memos.api.v1.WorkspaceStorageSetting.s3_config:type_name -> memos.api.v1.WorkspaceStorageSetting.S3Config + 1, // 6: memos.api.v1.ListWorkspaceSettingsResponse.settings:type_name -> memos.api.v1.WorkspaceSetting + 1, // 7: memos.api.v1.SetWorkspaceSettingRequest.setting:type_name -> memos.api.v1.WorkspaceSetting + 6, // 8: memos.api.v1.WorkspaceSettingService.ListWorkspaceSettings:input_type -> memos.api.v1.ListWorkspaceSettingsRequest + 8, // 9: memos.api.v1.WorkspaceSettingService.GetWorkspaceSetting:input_type -> memos.api.v1.GetWorkspaceSettingRequest + 9, // 10: memos.api.v1.WorkspaceSettingService.SetWorkspaceSetting:input_type -> memos.api.v1.SetWorkspaceSettingRequest + 7, // 11: memos.api.v1.WorkspaceSettingService.ListWorkspaceSettings:output_type -> memos.api.v1.ListWorkspaceSettingsResponse + 1, // 12: memos.api.v1.WorkspaceSettingService.GetWorkspaceSetting:output_type -> memos.api.v1.WorkspaceSetting + 1, // 13: memos.api.v1.WorkspaceSettingService.SetWorkspaceSetting:output_type -> memos.api.v1.WorkspaceSetting + 11, // [11:14] is the sub-list for method output_type + 8, // [8:11] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_api_v1_workspace_setting_service_proto_init() } @@ -990,20 +1080,31 @@ func file_api_v1_workspace_setting_service_proto_init() { return nil } } + file_api_v1_workspace_setting_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WorkspaceStorageSetting_S3Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_api_v1_workspace_setting_service_proto_msgTypes[0].OneofWrappers = []interface{}{ (*WorkspaceSetting_GeneralSetting)(nil), (*WorkspaceSetting_StorageSetting)(nil), (*WorkspaceSetting_MemoRelatedSetting)(nil), } - file_api_v1_workspace_setting_service_proto_msgTypes[3].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_v1_workspace_setting_service_proto_rawDesc, NumEnums: 1, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/store/workspace_setting.pb.go b/proto/gen/store/workspace_setting.pb.go index ad2340db..17e22d15 100644 --- a/proto/gen/store/workspace_setting.pb.go +++ b/proto/gen/store/workspace_setting.pb.go @@ -87,8 +87,8 @@ const ( WorkspaceStorageSetting_STORAGE_TYPE_DATABASE WorkspaceStorageSetting_StorageType = 1 // STORAGE_TYPE_LOCAL is the local storage type. WorkspaceStorageSetting_STORAGE_TYPE_LOCAL WorkspaceStorageSetting_StorageType = 2 - // STORAGE_TYPE_EXTERNAL is the external storage type. - WorkspaceStorageSetting_STORAGE_TYPE_EXTERNAL WorkspaceStorageSetting_StorageType = 3 + // STORAGE_TYPE_S3 is the S3 storage type. + WorkspaceStorageSetting_STORAGE_TYPE_S3 WorkspaceStorageSetting_StorageType = 3 ) // Enum value maps for WorkspaceStorageSetting_StorageType. @@ -97,13 +97,13 @@ var ( 0: "STORAGE_TYPE_UNSPECIFIED", 1: "STORAGE_TYPE_DATABASE", 2: "STORAGE_TYPE_LOCAL", - 3: "STORAGE_TYPE_EXTERNAL", + 3: "STORAGE_TYPE_S3", } WorkspaceStorageSetting_StorageType_value = map[string]int32{ "STORAGE_TYPE_UNSPECIFIED": 0, "STORAGE_TYPE_DATABASE": 1, "STORAGE_TYPE_LOCAL": 2, - "STORAGE_TYPE_EXTERNAL": 3, + "STORAGE_TYPE_S3": 3, } ) @@ -485,13 +485,13 @@ type WorkspaceStorageSetting struct { // storage_type is the storage type. StorageType WorkspaceStorageSetting_StorageType `protobuf:"varint,1,opt,name=storage_type,json=storageType,proto3,enum=memos.store.WorkspaceStorageSetting_StorageType" json:"storage_type,omitempty"` - // The id of actived external storage. - ActivedExternalStorageId *int32 `protobuf:"varint,2,opt,name=actived_external_storage_id,json=activedExternalStorageId,proto3,oneof" json:"actived_external_storage_id,omitempty"` - // The template of local storage path. + // The template of file path. // e.g. assets/{timestamp}_{filename} - LocalStoragePathTemplate string `protobuf:"bytes,3,opt,name=local_storage_path_template,json=localStoragePathTemplate,proto3" json:"local_storage_path_template,omitempty"` + FilepathTemplate string `protobuf:"bytes,2,opt,name=filepath_template,json=filepathTemplate,proto3" json:"filepath_template,omitempty"` // The max upload size in megabytes. - UploadSizeLimitMb int64 `protobuf:"varint,4,opt,name=upload_size_limit_mb,json=uploadSizeLimitMb,proto3" json:"upload_size_limit_mb,omitempty"` + UploadSizeLimitMb int64 `protobuf:"varint,3,opt,name=upload_size_limit_mb,json=uploadSizeLimitMb,proto3" json:"upload_size_limit_mb,omitempty"` + // The S3 config. + S3Config *WorkspaceStorageSetting_S3Config `protobuf:"bytes,4,opt,name=s3_config,json=s3Config,proto3" json:"s3_config,omitempty"` } func (x *WorkspaceStorageSetting) Reset() { @@ -533,16 +533,9 @@ func (x *WorkspaceStorageSetting) GetStorageType() WorkspaceStorageSetting_Stora return WorkspaceStorageSetting_STORAGE_TYPE_UNSPECIFIED } -func (x *WorkspaceStorageSetting) GetActivedExternalStorageId() int32 { - if x != nil && x.ActivedExternalStorageId != nil { - return *x.ActivedExternalStorageId - } - return 0 -} - -func (x *WorkspaceStorageSetting) GetLocalStoragePathTemplate() string { +func (x *WorkspaceStorageSetting) GetFilepathTemplate() string { if x != nil { - return x.LocalStoragePathTemplate + return x.FilepathTemplate } return "" } @@ -554,6 +547,13 @@ func (x *WorkspaceStorageSetting) GetUploadSizeLimitMb() int64 { return 0 } +func (x *WorkspaceStorageSetting) GetS3Config() *WorkspaceStorageSetting_S3Config { + if x != nil { + return x.S3Config + } + return nil +} + type WorkspaceMemoRelatedSetting struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -611,6 +611,86 @@ func (x *WorkspaceMemoRelatedSetting) GetDisplayWithUpdateTime() bool { return false } +// Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/ +type WorkspaceStorageSetting_S3Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccessKeyId string `protobuf:"bytes,1,opt,name=access_key_id,json=accessKeyId,proto3" json:"access_key_id,omitempty"` + AccessKeySecret string `protobuf:"bytes,2,opt,name=access_key_secret,json=accessKeySecret,proto3" json:"access_key_secret,omitempty"` + Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + Region string `protobuf:"bytes,4,opt,name=region,proto3" json:"region,omitempty"` + Bucket string `protobuf:"bytes,5,opt,name=bucket,proto3" json:"bucket,omitempty"` +} + +func (x *WorkspaceStorageSetting_S3Config) Reset() { + *x = WorkspaceStorageSetting_S3Config{} + if protoimpl.UnsafeEnabled { + mi := &file_store_workspace_setting_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WorkspaceStorageSetting_S3Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkspaceStorageSetting_S3Config) ProtoMessage() {} + +func (x *WorkspaceStorageSetting_S3Config) ProtoReflect() protoreflect.Message { + mi := &file_store_workspace_setting_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkspaceStorageSetting_S3Config.ProtoReflect.Descriptor instead. +func (*WorkspaceStorageSetting_S3Config) Descriptor() ([]byte, []int) { + return file_store_workspace_setting_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *WorkspaceStorageSetting_S3Config) GetAccessKeyId() string { + if x != nil { + return x.AccessKeyId + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetAccessKeySecret() string { + if x != nil { + return x.AccessKeySecret + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetEndpoint() string { + if x != nil { + return x.Endpoint + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *WorkspaceStorageSetting_S3Config) GetBucket() string { + if x != nil { + return x.Bucket + } + return "" +} + var File_store_workspace_setting_proto protoreflect.FileDescriptor var file_store_workspace_setting_proto_rawDesc = []byte{ @@ -678,67 +758,74 @@ var file_store_workspace_setting_proto_rawDesc = []byte{ 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, - 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xbd, 0x03, 0x0a, 0x17, 0x57, 0x6f, 0x72, + 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xb6, 0x04, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x53, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x73, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x42, 0x0a, 0x1b, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, - 0x52, 0x18, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x3d, 0x0a, - 0x1b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x70, - 0x61, 0x74, 0x68, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x18, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x14, - 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x5f, 0x6d, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x75, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x4d, 0x62, 0x22, 0x79, 0x0a, - 0x0b, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, - 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, - 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, - 0x41, 0x53, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x19, 0x0a, - 0x15, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, - 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x03, 0x42, 0x1e, 0x0a, 0x1c, 0x5f, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x22, 0x8e, 0x01, 0x0a, 0x1b, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, - 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x76, 0x69, 0x73, 0x69, - 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, - 0x12, 0x37, 0x0a, 0x18, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x57, 0x69, 0x74, 0x68, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x2a, 0xbb, 0x01, 0x0a, 0x13, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x4b, 0x65, - 0x79, 0x12, 0x25, 0x0a, 0x21, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x53, - 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x57, 0x4f, 0x52, 0x4b, - 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x41, - 0x53, 0x49, 0x43, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, - 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x45, 0x4e, 0x45, 0x52, - 0x41, 0x4c, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, - 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, - 0x45, 0x10, 0x03, 0x12, 0x22, 0x0a, 0x1e, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, - 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x52, 0x45, - 0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x04, 0x42, 0xa0, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x15, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xa2, - 0x02, 0x03, 0x4d, 0x53, 0x58, 0xaa, 0x02, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0xca, 0x02, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, - 0x65, 0xe2, 0x02, 0x17, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x4d, 0x65, - 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x69, 0x6c, + 0x65, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x54, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x62, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x4d, 0x62, 0x12, 0x4a, 0x0a, 0x09, 0x73, 0x33, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x2e, 0x53, 0x33, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x73, 0x33, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x1a, 0xa6, 0x01, 0x0a, 0x08, 0x53, 0x33, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, + 0x65, 0x79, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, + 0x65, 0x79, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x73, 0x0a, 0x0b, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x53, + 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x4f, + 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, + 0x53, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, + 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x33, 0x10, + 0x03, 0x22, 0x8e, 0x01, 0x0a, 0x1b, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, + 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x57, 0x69, 0x74, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x2a, 0xbb, 0x01, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x21, 0x57, 0x4f, + 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, + 0x4b, 0x45, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x53, + 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x01, 0x12, 0x1d, + 0x0a, 0x19, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, + 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x1d, 0x0a, + 0x19, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, + 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x10, 0x03, 0x12, 0x22, 0x0a, 0x1e, + 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, + 0x47, 0x5f, 0x4d, 0x45, 0x4d, 0x4f, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x04, + 0x42, 0xa0, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x42, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x29, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, + 0x65, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xa2, 0x02, 0x03, 0x4d, 0x53, 0x58, 0xaa, 0x02, + 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xca, 0x02, 0x0b, 0x4d, + 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xe2, 0x02, 0x17, 0x4d, 0x65, 0x6d, + 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x53, 0x74, + 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -754,7 +841,7 @@ func file_store_workspace_setting_proto_rawDescGZIP() []byte { } var file_store_workspace_setting_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_store_workspace_setting_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_store_workspace_setting_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_store_workspace_setting_proto_goTypes = []interface{}{ (WorkspaceSettingKey)(0), // 0: memos.store.WorkspaceSettingKey (WorkspaceStorageSetting_StorageType)(0), // 1: memos.store.WorkspaceStorageSetting.StorageType @@ -764,6 +851,7 @@ var file_store_workspace_setting_proto_goTypes = []interface{}{ (*WorkspaceCustomProfile)(nil), // 5: memos.store.WorkspaceCustomProfile (*WorkspaceStorageSetting)(nil), // 6: memos.store.WorkspaceStorageSetting (*WorkspaceMemoRelatedSetting)(nil), // 7: memos.store.WorkspaceMemoRelatedSetting + (*WorkspaceStorageSetting_S3Config)(nil), // 8: memos.store.WorkspaceStorageSetting.S3Config } var file_store_workspace_setting_proto_depIdxs = []int32{ 0, // 0: memos.store.WorkspaceSetting.key:type_name -> memos.store.WorkspaceSettingKey @@ -773,11 +861,12 @@ var file_store_workspace_setting_proto_depIdxs = []int32{ 7, // 4: memos.store.WorkspaceSetting.memo_related_setting:type_name -> memos.store.WorkspaceMemoRelatedSetting 5, // 5: memos.store.WorkspaceGeneralSetting.custom_profile:type_name -> memos.store.WorkspaceCustomProfile 1, // 6: memos.store.WorkspaceStorageSetting.storage_type:type_name -> memos.store.WorkspaceStorageSetting.StorageType - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 8, // 7: memos.store.WorkspaceStorageSetting.s3_config:type_name -> memos.store.WorkspaceStorageSetting.S3Config + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_store_workspace_setting_proto_init() } @@ -858,6 +947,18 @@ func file_store_workspace_setting_proto_init() { return nil } } + file_store_workspace_setting_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WorkspaceStorageSetting_S3Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_store_workspace_setting_proto_msgTypes[0].OneofWrappers = []interface{}{ (*WorkspaceSetting_BasicSetting)(nil), @@ -865,14 +966,13 @@ func file_store_workspace_setting_proto_init() { (*WorkspaceSetting_StorageSetting)(nil), (*WorkspaceSetting_MemoRelatedSetting)(nil), } - file_store_workspace_setting_proto_msgTypes[4].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_store_workspace_setting_proto_rawDesc, NumEnums: 2, - NumMessages: 6, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/store/workspace_setting.proto b/proto/store/workspace_setting.proto index 5ed2a09d..9061a0e3 100644 --- a/proto/store/workspace_setting.proto +++ b/proto/store/workspace_setting.proto @@ -55,25 +55,32 @@ message WorkspaceCustomProfile { } message WorkspaceStorageSetting { - // storage_type is the storage type. - StorageType storage_type = 1; - // The id of actived external storage. - optional int32 actived_external_storage_id = 2; - // The template of local storage path. - // e.g. assets/{timestamp}_{filename} - string local_storage_path_template = 3; - // The max upload size in megabytes. - int64 upload_size_limit_mb = 4; - enum StorageType { STORAGE_TYPE_UNSPECIFIED = 0; // STORAGE_TYPE_DATABASE is the database storage type. STORAGE_TYPE_DATABASE = 1; // STORAGE_TYPE_LOCAL is the local storage type. STORAGE_TYPE_LOCAL = 2; - // STORAGE_TYPE_EXTERNAL is the external storage type. - STORAGE_TYPE_EXTERNAL = 3; + // STORAGE_TYPE_S3 is the S3 storage type. + STORAGE_TYPE_S3 = 3; } + // storage_type is the storage type. + StorageType storage_type = 1; + // The template of file path. + // e.g. assets/{timestamp}_{filename} + string filepath_template = 2; + // The max upload size in megabytes. + int64 upload_size_limit_mb = 3; + // Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/ + message S3Config { + string access_key_id = 1; + string access_key_secret = 2; + string endpoint = 3; + string region = 4; + string bucket = 5; + } + // The S3 config. + S3Config s3_config = 4; } message WorkspaceMemoRelatedSetting { diff --git a/server/route/api/v1/resource_service.go b/server/route/api/v1/resource_service.go index 3a6a757b..7db79792 100644 --- a/server/route/api/v1/resource_service.go +++ b/server/route/api/v1/resource_service.go @@ -254,12 +254,12 @@ func SaveResourceBlob(ctx context.Context, s *store.Store, create *store.Resourc } if workspaceStorageSetting.StorageType == storepb.WorkspaceStorageSetting_STORAGE_TYPE_LOCAL { - localStoragePath := "assets/{timestamp}_{filename}" - if workspaceStorageSetting.LocalStoragePathTemplate != "" { - localStoragePath = workspaceStorageSetting.LocalStoragePathTemplate + filepathTemplate := "assets/{timestamp}_{filename}" + if workspaceStorageSetting.FilepathTemplate != "" { + filepathTemplate = workspaceStorageSetting.FilepathTemplate } - internalPath := localStoragePath + internalPath := filepathTemplate if !strings.Contains(internalPath, "{filename}") { internalPath = filepath.Join(internalPath, "{filename}") } @@ -287,46 +287,29 @@ func SaveResourceBlob(ctx context.Context, s *store.Store, create *store.Resourc } create.InternalPath = internalPath create.Blob = nil - } else if workspaceStorageSetting.StorageType == storepb.WorkspaceStorageSetting_STORAGE_TYPE_EXTERNAL { - if workspaceStorageSetting.ActivedExternalStorageId == nil { + } else if workspaceStorageSetting.StorageType == storepb.WorkspaceStorageSetting_STORAGE_TYPE_S3 { + s3Config := workspaceStorageSetting.S3Config + if s3Config == nil { return errors.Errorf("No actived external storage found") } - storage, err := s.GetStorage(ctx, &store.FindStorage{ID: workspaceStorageSetting.ActivedExternalStorageId}) - if err != nil { - return errors.Wrap(err, "Failed to find actived external storage") - } - if storage == nil { - return errors.Errorf("Storage %d not found", *workspaceStorageSetting.ActivedExternalStorageId) - } - if storage.Type != storepb.Storage_S3 { - return errors.Errorf("Unsupported storage type: %s", storage.Type.String()) - } - - s3Config := storage.Config.GetS3Config() - if s3Config == nil { - return errors.Errorf("S3 config not found") - } s3Client, err := s3.NewClient(ctx, &s3.Config{ - AccessKey: s3Config.AccessKey, - SecretKey: s3Config.SecretKey, - EndPoint: s3Config.EndPoint, - Region: s3Config.Region, - Bucket: s3Config.Bucket, - URLPrefix: s3Config.UrlPrefix, - URLSuffix: s3Config.UrlSuffix, - PreSign: s3Config.PreSign, + AccessKeyID: s3Config.AccessKeyId, + AcesssKeySecret: s3Config.AccessKeySecret, + Endpoint: s3Config.Endpoint, + Region: s3Config.Region, + Bucket: s3Config.Bucket, }) if err != nil { return errors.Wrap(err, "Failed to create s3 client") } - filePath := s3Config.Path - if !strings.Contains(filePath, "{filename}") { - filePath = filepath.Join(filePath, "{filename}") + filepathTemplate := workspaceStorageSetting.FilepathTemplate + if !strings.Contains(filepathTemplate, "{filename}") { + filepathTemplate = filepath.Join(filepathTemplate, "{filename}") } - filePath = replacePathTemplate(filePath, create.Filename) + filepathTemplate = replacePathTemplate(filepathTemplate, create.Filename) r := bytes.NewReader(create.Blob) - link, err := s3Client.UploadFile(ctx, filePath, create.Type, r) + link, err := s3Client.UploadFile(ctx, filepathTemplate, create.Type, r) if err != nil { return errors.Wrap(err, "Failed to upload via s3 client") } diff --git a/server/route/api/v1/workspace_setting_service.go b/server/route/api/v1/workspace_setting_service.go index 00d18dc8..517294bc 100644 --- a/server/route/api/v1/workspace_setting_service.go +++ b/server/route/api/v1/workspace_setting_service.go @@ -162,28 +162,46 @@ func convertWorkspaceGeneralSettingToStore(setting *v1pb.WorkspaceGeneralSetting return generalSetting } -func convertWorkspaceStorageSettingFromStore(setting *storepb.WorkspaceStorageSetting) *v1pb.WorkspaceStorageSetting { - if setting == nil { +func convertWorkspaceStorageSettingFromStore(settingpb *storepb.WorkspaceStorageSetting) *v1pb.WorkspaceStorageSetting { + if settingpb == nil { return nil } - return &v1pb.WorkspaceStorageSetting{ - StorageType: v1pb.WorkspaceStorageSetting_StorageType(setting.StorageType), - LocalStoragePathTemplate: setting.LocalStoragePathTemplate, - UploadSizeLimitMb: setting.UploadSizeLimitMb, - ActivedExternalStorageId: setting.ActivedExternalStorageId, + setting := &v1pb.WorkspaceStorageSetting{ + StorageType: v1pb.WorkspaceStorageSetting_StorageType(settingpb.StorageType), + FilepathTemplate: settingpb.FilepathTemplate, + UploadSizeLimitMb: settingpb.UploadSizeLimitMb, } + if settingpb.S3Config != nil { + setting.S3Config = &v1pb.WorkspaceStorageSetting_S3Config{ + AccessKeyId: settingpb.S3Config.AccessKeyId, + AccessKeySecret: settingpb.S3Config.AccessKeySecret, + Endpoint: settingpb.S3Config.Endpoint, + Region: settingpb.S3Config.Region, + Bucket: settingpb.S3Config.Bucket, + } + } + return setting } func convertWorkspaceStorageSettingToStore(setting *v1pb.WorkspaceStorageSetting) *storepb.WorkspaceStorageSetting { if setting == nil { return nil } - return &storepb.WorkspaceStorageSetting{ - StorageType: storepb.WorkspaceStorageSetting_StorageType(setting.StorageType), - LocalStoragePathTemplate: setting.LocalStoragePathTemplate, - UploadSizeLimitMb: setting.UploadSizeLimitMb, - ActivedExternalStorageId: setting.ActivedExternalStorageId, + settingpb := &storepb.WorkspaceStorageSetting{ + StorageType: storepb.WorkspaceStorageSetting_StorageType(setting.StorageType), + FilepathTemplate: setting.FilepathTemplate, + UploadSizeLimitMb: setting.UploadSizeLimitMb, } + if setting.S3Config != nil { + settingpb.S3Config = &storepb.WorkspaceStorageSetting_S3Config{ + AccessKeyId: setting.S3Config.AccessKeyId, + AccessKeySecret: setting.S3Config.AccessKeySecret, + Endpoint: setting.S3Config.Endpoint, + Region: setting.S3Config.Region, + Bucket: setting.S3Config.Bucket, + } + } + return settingpb } func convertWorkspaceMemoRelatedSettingFromStore(setting *storepb.WorkspaceMemoRelatedSetting) *v1pb.WorkspaceMemoRelatedSetting { diff --git a/server/server.go b/server/server.go index 026c897e..24faa890 100644 --- a/server/server.go +++ b/server/server.go @@ -22,7 +22,6 @@ import ( "github.com/usememos/memos/server/route/frontend" "github.com/usememos/memos/server/route/resource" "github.com/usememos/memos/server/route/rss" - resourcepresign "github.com/usememos/memos/server/service/resource_presign" versionchecker "github.com/usememos/memos/server/service/version_checker" "github.com/usememos/memos/store" ) @@ -148,7 +147,6 @@ func (s *Server) Shutdown(ctx context.Context) { } func (s *Server) StartBackgroundRunners(ctx context.Context) { - go resourcepresign.RunPreSignLinks(ctx, s.Store) go versionchecker.NewVersionChecker(s.Store, s.Profile).Start(ctx) } diff --git a/server/service/resource_presign/resource_presign.go b/server/service/resource_presign/resource_presign.go deleted file mode 100644 index 9186d2ef..00000000 --- a/server/service/resource_presign/resource_presign.go +++ /dev/null @@ -1,110 +0,0 @@ -package resourcepresign - -import ( - "context" - "log/slog" - "strings" - "time" - - "github.com/pkg/errors" - - "github.com/usememos/memos/plugin/storage/s3" - storepb "github.com/usememos/memos/proto/gen/store" - "github.com/usememos/memos/store" -) - -// RunPreSignLinks is a background runner that pre-signs external links stored in the database. -// It uses S3 client to generate presigned URLs and updates the corresponding resources in the store. -func RunPreSignLinks(ctx context.Context, dataStore *store.Store) { - for { - if err := signExternalLinks(ctx, dataStore); err != nil { - slog.Error("failed to pre-sign links", err) - } else { - slog.Debug("pre-signed links") - } - select { - case <-time.After(s3.LinkLifetime / 2): - case <-ctx.Done(): - return - } - } -} - -func signExternalLinks(ctx context.Context, dataStore *store.Store) error { - objectStore, err := findObjectStorage(ctx, dataStore) - if err != nil { - return errors.Wrapf(err, "find object storage") - } - if objectStore == nil || !objectStore.Config.PreSign { - // object storage not set or not supported - return nil - } - - resources, err := dataStore.ListResources(ctx, &store.FindResource{ - GetBlob: false, - }) - if err != nil { - return errors.Wrapf(err, "list resources") - } - - for _, resource := range resources { - if resource.ExternalLink == "" { - // not for object store - continue - } - if strings.Contains(resource.ExternalLink, "?") && time.Since(time.Unix(resource.UpdatedTs, 0)) < s3.LinkLifetime/2 { - // resource not signed (hack for migration) - // resource was recently updated - skipping - continue - } - - newLink, err := objectStore.PreSignLink(ctx, resource.ExternalLink) - if err != nil { - slog.Error("failed to pre-sign link", err) - continue - } - - now := time.Now().Unix() - if _, err := dataStore.UpdateResource(ctx, &store.UpdateResource{ - ID: resource.ID, - UpdatedTs: &now, - ExternalLink: &newLink, - }); err != nil { - return errors.Wrapf(err, "update resource %d link to %q", resource.ID, newLink) - } - } - - return nil -} - -// findObjectStorage returns current default storage if it's S3-compatible or nil otherwise. -// Returns error only in case of internal problems (ie: database or configuration issues). -// May return nil client and nil error. -func findObjectStorage(ctx context.Context, dataStore *store.Store) (*s3.Client, error) { - workspaceStorageSetting, err := dataStore.GetWorkspaceStorageSetting(ctx) - if err != nil { - return nil, errors.Wrap(err, "Failed to find workspaceStorageSetting") - } - if workspaceStorageSetting.StorageType != storepb.WorkspaceStorageSetting_STORAGE_TYPE_EXTERNAL || workspaceStorageSetting.ActivedExternalStorageId == nil { - return nil, nil - } - storage, err := dataStore.GetStorage(ctx, &store.FindStorage{ID: workspaceStorageSetting.ActivedExternalStorageId}) - if err != nil { - return nil, errors.Wrap(err, "Failed to find storage") - } - if storage == nil || storage.Type != storepb.Storage_S3 { - return nil, nil - } - - s3Config := storage.Config.GetS3Config() - return s3.NewClient(ctx, &s3.Config{ - AccessKey: s3Config.AccessKey, - SecretKey: s3Config.SecretKey, - EndPoint: s3Config.EndPoint, - Region: s3Config.Region, - Bucket: s3Config.Bucket, - URLPrefix: s3Config.UrlPrefix, - URLSuffix: s3Config.UrlSuffix, - PreSign: s3Config.PreSign, - }) -} diff --git a/store/workspace_setting.go b/store/workspace_setting.go index b3031100..f45f34d6 100644 --- a/store/workspace_setting.go +++ b/store/workspace_setting.go @@ -139,9 +139,9 @@ func (s *Store) GetWorkspaceMemoRelatedSetting(ctx context.Context) (*storepb.Wo } const ( - defaultWorkspaceStorageType = storepb.WorkspaceStorageSetting_STORAGE_TYPE_DATABASE - defaultWorkspaceUploadSizeLimitMb = 30 - defaultWorkspaceLocalStoragePathTemplate = "assets/{timestamp}_{filename}" + defaultWorkspaceStorageType = storepb.WorkspaceStorageSetting_STORAGE_TYPE_DATABASE + defaultWorkspaceUploadSizeLimitMb = 30 + defaultWorkspaceFilepathTemplate = "assets/{timestamp}_{filename}" ) func (s *Store) GetWorkspaceStorageSetting(ctx context.Context) (*storepb.WorkspaceStorageSetting, error) { @@ -162,8 +162,8 @@ func (s *Store) GetWorkspaceStorageSetting(ctx context.Context) (*storepb.Worksp if workspaceStorageSetting.UploadSizeLimitMb == 0 { workspaceStorageSetting.UploadSizeLimitMb = defaultWorkspaceUploadSizeLimitMb } - if workspaceStorageSetting.LocalStoragePathTemplate == "" { - workspaceStorageSetting.LocalStoragePathTemplate = defaultWorkspaceLocalStoragePathTemplate + if workspaceStorageSetting.FilepathTemplate == "" { + workspaceStorageSetting.FilepathTemplate = defaultWorkspaceFilepathTemplate } return workspaceStorageSetting, nil } diff --git a/web/src/components/CreateStorageServiceDialog.tsx b/web/src/components/CreateStorageServiceDialog.tsx deleted file mode 100644 index 8ba599b8..00000000 --- a/web/src/components/CreateStorageServiceDialog.tsx +++ /dev/null @@ -1,257 +0,0 @@ -import { Button, IconButton, Input, Checkbox, Typography } from "@mui/joy"; -import React, { useEffect, useState } from "react"; -import { toast } from "react-hot-toast"; -import { storageServiceClient } from "@/grpcweb"; -import { S3Config, Storage, Storage_Type } from "@/types/proto/api/v1/storage_service"; -import { useTranslate } from "@/utils/i18n"; -import { generateDialog } from "./Dialog"; -import Icon from "./Icon"; -import LearnMore from "./LearnMore"; -import RequiredBadge from "./RequiredBadge"; - -interface Props extends DialogProps { - storage?: Storage; - confirmCallback?: () => void; -} - -const CreateStorageServiceDialog: React.FC = (props: Props) => { - const t = useTranslate(); - const { destroy, storage, confirmCallback } = props; - const [basicInfo, setBasicInfo] = useState({ - title: "", - }); - const [type] = useState(Storage_Type.S3); - const [s3Config, setS3Config] = useState({ - endPoint: "", - region: "", - accessKey: "", - secretKey: "", - path: "", - bucket: "", - urlPrefix: "", - urlSuffix: "", - preSign: false, - }); - const isCreating = storage === undefined; - - useEffect(() => { - if (storage) { - setBasicInfo({ - title: storage.title, - }); - if (storage.type === "S3") { - setS3Config(S3Config.fromPartial(storage.config?.s3Config || {})); - } - } - }, []); - - const handleCloseBtnClick = () => { - destroy(); - }; - - const allowConfirmAction = () => { - if (basicInfo.title === "") { - return false; - } - if (type === "S3") { - if ( - s3Config.endPoint === "" || - s3Config.region === "" || - s3Config.accessKey === "" || - s3Config.secretKey === "" || - s3Config.bucket === "" - ) { - return false; - } - } - return true; - }; - - const handleConfirmBtnClick = async () => { - try { - if (isCreating) { - await storageServiceClient.createStorage({ - storage: Storage.fromPartial({ - title: basicInfo.title, - type: type, - config: { - s3Config: s3Config, - }, - }), - }); - } else { - await storageServiceClient.updateStorage({ - storage: Storage.fromPartial({ - id: storage?.id, - title: basicInfo.title, - type: type, - config: { - s3Config: s3Config, - }, - }), - updateMask: ["title", "config"], - }); - } - } catch (error: any) { - console.error(error); - toast.error(error.response.data.message); - } - if (confirmCallback) { - confirmCallback(); - } - destroy(); - }; - - const setPartialS3Config = (state: Partial) => { - setS3Config({ - ...s3Config, - ...state, - }); - }; - - return ( - <> -
- {t(isCreating ? "setting.storage-section.create-storage" : "setting.storage-section.update-storage")} - - - -
-
- - {t("common.name")} - - - - setBasicInfo({ - ...basicInfo, - title: e.target.value, - }) - } - fullWidth - /> - - {t("setting.storage-section.endpoint")} - - - setPartialS3Config({ endPoint: e.target.value })} - fullWidth - /> - - {t("setting.storage-section.region")} - - - setPartialS3Config({ region: e.target.value })} - fullWidth - /> - - {t("setting.storage-section.accesskey")} - - - setPartialS3Config({ accessKey: e.target.value })} - fullWidth - /> - - {t("setting.storage-section.secretkey")} - - - setPartialS3Config({ secretKey: e.target.value })} - fullWidth - /> - - {t("setting.storage-section.bucket")} - - - setPartialS3Config({ bucket: e.target.value })} - fullWidth - /> -
- {t("setting.storage-section.path")} - -
- setPartialS3Config({ path: e.target.value })} - fullWidth - /> - - {t("setting.storage-section.url-prefix")} - - setPartialS3Config({ urlPrefix: e.target.value })} - fullWidth - /> - - {t("setting.storage-section.url-suffix")} - - setPartialS3Config({ urlSuffix: e.target.value })} - fullWidth - /> - setPartialS3Config({ preSign: e.target.checked })} - /> -
- - -
-
- - ); -}; - -function showCreateStorageServiceDialog(storage?: Storage, confirmCallback?: () => void) { - generateDialog( - { - className: "create-storage-service-dialog", - dialogName: "create-storage-service-dialog", - }, - CreateStorageServiceDialog, - { storage, confirmCallback }, - ); -} - -export default showCreateStorageServiceDialog; diff --git a/web/src/components/Settings/StorageSection.tsx b/web/src/components/Settings/StorageSection.tsx index 9a09a17d..03bf3fb3 100644 --- a/web/src/components/Settings/StorageSection.tsx +++ b/web/src/components/Settings/StorageSection.tsx @@ -1,38 +1,21 @@ -import { - Button, - Divider, - Dropdown, - Input, - List, - ListItem, - Menu, - MenuButton, - MenuItem, - Radio, - RadioGroup, - Select, - Tooltip, - Option, -} from "@mui/joy"; +import { Button, Divider, Input, List, ListItem, Radio, RadioGroup, Tooltip } from "@mui/joy"; import { isEqual } from "lodash-es"; -import { useEffect, useMemo, useState } from "react"; +import { useMemo, useState } from "react"; import { toast } from "react-hot-toast"; import { Link } from "react-router-dom"; -import { storageServiceClient } from "@/grpcweb"; import { WorkspaceSettingPrefix, useWorkspaceSettingStore } from "@/store/v1"; -import { Storage } from "@/types/proto/api/v1/storage_service"; -import { WorkspaceStorageSetting, WorkspaceStorageSetting_StorageType } from "@/types/proto/api/v1/workspace_setting_service"; +import { + WorkspaceStorageSetting, + WorkspaceStorageSetting_S3Config, + WorkspaceStorageSetting_StorageType, +} from "@/types/proto/api/v1/workspace_setting_service"; import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting"; import { useTranslate } from "@/utils/i18n"; -import showCreateStorageServiceDialog from "../CreateStorageServiceDialog"; -import { showCommonDialog } from "../Dialog/CommonDialog"; import Icon from "../Icon"; -import LearnMore from "../LearnMore"; const StorageSection = () => { const t = useTranslate(); const workspaceSettingStore = useWorkspaceSettingStore(); - const [storageList, setStorageList] = useState([]); const [workspaceStorageSetting, setWorkspaceStorageSetting] = useState( WorkspaceStorageSetting.fromPartial( workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.WORKSPACE_SETTING_STORAGE)?.storageSetting || {}, @@ -48,26 +31,23 @@ const StorageSection = () => { workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.WORKSPACE_SETTING_STORAGE)?.storageSetting || {}, ); if (workspaceStorageSetting.storageType === WorkspaceStorageSetting_StorageType.STORAGE_TYPE_LOCAL) { - if (workspaceStorageSetting.localStoragePathTemplate.length === 0) { + if (workspaceStorageSetting.filepathTemplate.length === 0) { return false; } - } else if (workspaceStorageSetting.storageType === WorkspaceStorageSetting_StorageType.STORAGE_TYPE_EXTERNAL) { - if (!workspaceStorageSetting.activedExternalStorageId || workspaceStorageSetting.activedExternalStorageId === 0) { + } else if (workspaceStorageSetting.storageType === WorkspaceStorageSetting_StorageType.STORAGE_TYPE_S3) { + if ( + workspaceStorageSetting.s3Config?.accessKeyId.length === 0 || + workspaceStorageSetting.s3Config?.accessKeySecret.length === 0 || + workspaceStorageSetting.s3Config?.endpoint.length === 0 || + workspaceStorageSetting.s3Config?.region.length === 0 || + workspaceStorageSetting.s3Config?.bucket.length === 0 + ) { return false; } } return !isEqual(origin, workspaceStorageSetting); }, [workspaceStorageSetting, workspaceSettingStore.getState()]); - useEffect(() => { - fetchStorageList(); - }, []); - - const fetchStorageList = async () => { - const { storages } = await storageServiceClient.listStorages({}); - setStorageList(storages); - }; - const handleMaxUploadSizeChanged = async (event: React.FocusEvent) => { let num = parseInt(event.target.value); if (Number.isNaN(num)) { @@ -80,14 +60,45 @@ const StorageSection = () => { setWorkspaceStorageSetting(update); }; - const handleLocalStoragePathTemplateChanged = async (event: React.FocusEvent) => { + const handleFilepathTemplateChanged = async (event: React.FocusEvent) => { const update: WorkspaceStorageSetting = { ...workspaceStorageSetting, - localStoragePathTemplate: event.target.value, + filepathTemplate: event.target.value, }; setWorkspaceStorageSetting(update); }; + const handlePartialS3ConfigChanged = async (s3Config: Partial) => { + const update: WorkspaceStorageSetting = { + ...workspaceStorageSetting, + s3Config: WorkspaceStorageSetting_S3Config.fromPartial({ + ...workspaceStorageSetting.s3Config, + ...s3Config, + }), + }; + setWorkspaceStorageSetting(update); + }; + + const handleS3ConfigAccessKeyIdChanged = async (event: React.FocusEvent) => { + handlePartialS3ConfigChanged({ accessKeyId: event.target.value }); + }; + + const handleS3ConfigAccessKeySecretChanged = async (event: React.FocusEvent) => { + handlePartialS3ConfigChanged({ accessKeySecret: event.target.value }); + }; + + const handleS3ConfigEndpointChanged = async (event: React.FocusEvent) => { + handlePartialS3ConfigChanged({ endpoint: event.target.value }); + }; + + const handleS3ConfigRegionChanged = async (event: React.FocusEvent) => { + handlePartialS3ConfigChanged({ region: event.target.value }); + }; + + const handleS3ConfigBucketChanged = async (event: React.FocusEvent) => { + handlePartialS3ConfigChanged({ bucket: event.target.value }); + }; + const handleStorageTypeChanged = async (storageType: WorkspaceStorageSetting_StorageType) => { const update: WorkspaceStorageSetting = { ...workspaceStorageSetting, @@ -96,14 +107,6 @@ const StorageSection = () => { setWorkspaceStorageSetting(update); }; - const handleActivedExternalStorageIdChanged = async (activedExternalStorageId: number) => { - const update: WorkspaceStorageSetting = { - ...workspaceStorageSetting, - activedExternalStorageId: activedExternalStorageId, - }; - setWorkspaceStorageSetting(update); - }; - const saveWorkspaceStorageSetting = async () => { await workspaceSettingStore.setWorkspaceSetting({ name: `${WorkspaceSettingPrefix}${WorkspaceSettingKey.WORKSPACE_SETTING_STORAGE}`, @@ -112,24 +115,6 @@ const StorageSection = () => { toast.success("Updated"); }; - const handleDeleteStorage = (storage: Storage) => { - showCommonDialog({ - title: t("setting.storage-section.delete-storage"), - content: t("setting.storage-section.warning-text", { name: storage.title }), - style: "danger", - dialogName: "delete-storage-dialog", - onConfirm: async () => { - try { - await storageServiceClient.deleteStorage({ id: storage.id }); - } catch (error: any) { - console.error(error); - toast.error(error.response.data.message); - } - await fetchStorageList(); - }, - }); - }; - return (
{t("setting.storage-section.current-storage")}
@@ -143,7 +128,7 @@ const StorageSection = () => { > - +
@@ -161,30 +146,47 @@ const StorageSection = () => { onChange={handleMaxUploadSizeChanged} />
- {workspaceStorageSetting.storageType === WorkspaceStorageSetting_StorageType.STORAGE_TYPE_LOCAL && ( + {workspaceStorageSetting.storageType !== WorkspaceStorageSetting_StorageType.STORAGE_TYPE_DATABASE && (
- Local file path template + Filepath template
)} - {workspaceStorageSetting.storageType === WorkspaceStorageSetting_StorageType.STORAGE_TYPE_EXTERNAL && ( -
- Actived storage - -
+ {workspaceStorageSetting.storageType === WorkspaceStorageSetting_StorageType.STORAGE_TYPE_S3 && ( + <> +
+ Access key id + +
+
+ Access key secret + +
+
+ Endpoint + +
+
+ Region + +
+
+ Bucket + +
+ )}
-
-
- {t("setting.storage-section.storage-services")} - -
- -
-
- {storageList.map((storage) => ( -
-
-

{storage.title}

-
-
- - - - - - showCreateStorageServiceDialog(storage, fetchStorageList)}>{t("common.edit")} - handleDeleteStorage(storage)}>{t("common.delete")} - - -
-
- ))} - {storageList.length === 0 && ( -
-

No storage service found.

-
- )} -

{t("common.learn-more")}:

diff --git a/web/src/grpcweb.ts b/web/src/grpcweb.ts index 1d44b0e7..d6b521a6 100644 --- a/web/src/grpcweb.ts +++ b/web/src/grpcweb.ts @@ -6,7 +6,6 @@ import { InboxServiceDefinition } from "./types/proto/api/v1/inbox_service"; import { LinkServiceDefinition } from "./types/proto/api/v1/link_service"; import { MemoServiceDefinition } from "./types/proto/api/v1/memo_service"; import { ResourceServiceDefinition } from "./types/proto/api/v1/resource_service"; -import { StorageServiceDefinition } from "./types/proto/api/v1/storage_service"; import { TagServiceDefinition } from "./types/proto/api/v1/tag_service"; import { UserServiceDefinition } from "./types/proto/api/v1/user_service"; import { WebhookServiceDefinition } from "./types/proto/api/v1/webhook_service"; @@ -44,6 +43,4 @@ export const webhookServiceClient = clientFactory.create(WebhookServiceDefinitio export const linkServiceClient = clientFactory.create(LinkServiceDefinition, channel); -export const storageServiceClient = clientFactory.create(StorageServiceDefinition, channel); - export const identityProviderServiceClient = clientFactory.create(IdentityProviderServiceDefinition, channel);