From dc9dd04c3ab3983b8c9b6e44b1349c3515f12360 Mon Sep 17 00:00:00 2001 From: Viljami Date: Thu, 29 Aug 2024 19:08:55 +0200 Subject: [PATCH] Update file-api spec (strict mode support) --- .speakeasy/gen.lock | 18 ++- README.md | 8 +- docs/data-sources/file.md | 20 ++- docs/index.md | 2 +- docs/resources/file.md | 27 +++- .../epilot-file_file/data-source.tf | 3 +- examples/provider/provider.tf | 2 +- .../generated_resources.tf | 12 +- .../epilot-file_file-import/resource.tf | 45 ++----- .../resources/epilot-file_file/resource.tf | 3 +- gen.yaml | 2 +- internal/provider/file_data_source.go | 77 +++++++---- internal/provider/file_data_source_sdk.go | 25 +++- internal/provider/file_resource.go | 121 ++++++++++++++---- internal/provider/file_resource_sdk.go | 53 +++++++- .../types/{acl.go => base_entity_acl.go} | 2 +- internal/provider/types/base_entity_owner.go | 10 ++ internal/sdk/file.go | 16 ++- internal/sdk/internal/utils/requestbody.go | 22 ++-- internal/sdk/models/operations/deletefile.go | 21 +++ internal/sdk/models/operations/getfile.go | 21 +++ internal/sdk/models/operations/savefilev2.go | 32 +++++ internal/sdk/models/shared/baseentityacl.go | 31 +++++ internal/sdk/models/shared/baseentityowner.go | 25 ++++ internal/sdk/models/shared/fileentity.go | 69 +++++----- .../sdk/models/shared/savefilepayloadv2.go | 18 +++ internal/sdk/sdk.go | 4 +- openapi.yml | 83 ++++++++---- 28 files changed, 584 insertions(+), 188 deletions(-) rename internal/provider/types/{acl.go => base_entity_acl.go} (90%) create mode 100644 internal/provider/types/base_entity_owner.go create mode 100644 internal/sdk/models/shared/baseentityacl.go create mode 100644 internal/sdk/models/shared/baseentityowner.go diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 091ff27..3847e65 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: 11c8545a-deb6-44f9-ba56-e71722af6a51 management: - docChecksum: 50360e3007840627546142ce48be95c9 + docChecksum: 212bd2273c9b8279042fb22bd977068a docVersion: 0.2.0 - speakeasyVersion: 1.379.0 - generationVersion: 2.404.3 - releaseVersion: 0.3.3 - configChecksum: c252e910cbbbab187f755ef146f553aa + speakeasyVersion: 1.366.0 + generationVersion: 2.396.0 + releaseVersion: 0.4.0 + configChecksum: 600f6651c2bf8d84881581eb2d476d86 repoURL: https://github.com/epilot-dev/terraform-provider-epilot-file.git repoSubDirectory: . published: true @@ -15,12 +15,13 @@ features: additionalDependencies: 0.1.0 additionalProperties: 0.1.2 constsAndDefaults: 0.1.4 - core: 3.24.7 + core: 3.24.6 deprecations: 2.81.1 envVarSecurityUsage: 0.1.0 globalSecurity: 2.81.8 globalServerURLs: 2.82.1 inputOutputModels: 2.83.0 + nullables: 0.0.0 retries: 2.81.1 unions: 2.81.16 generatedFiles: @@ -72,6 +73,8 @@ generatedFiles: - internal/sdk/models/shared/fileitem.go - internal/sdk/models/shared/s3ref.go - internal/sdk/models/shared/filetype.go + - internal/sdk/models/shared/baseentityowner.go + - internal/sdk/models/shared/baseentityacl.go - internal/sdk/models/shared/savefilepayload.go - internal/sdk/models/shared/saves3filepayload.go - internal/sdk/models/shared/filerelationitem.go @@ -131,7 +134,8 @@ generatedFiles: - main.go - terraform-registry-manifest.json - tools/tools.go - - internal/provider/types/acl.go + - internal/provider/types/base_entity_acl.go + - internal/provider/types/base_entity_owner.go - internal/provider/types/s3_ref.go - internal/provider/types/file_item.go - USAGE.md diff --git a/README.md b/README.md index 04eb6a9..6ebacb6 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ terraform { required_providers { epilot-file = { source = "epilot-dev/epilot-file" - version = "0.3.3" + version = "0.4.0" } } } @@ -91,6 +91,12 @@ TF_REATTACH_PROVIDERS=... terraform apply ``` + +## Available Resources and Operations + + + + Terraform allows you to use local provider builds by setting a `dev_overrides` block in a configuration file called `.terraformrc`. This block overrides all other configured installation methods. diff --git a/docs/data-sources/file.md b/docs/data-sources/file.md index c2bd2a4..7281c1f 100644 --- a/docs/data-sources/file.md +++ b/docs/data-sources/file.md @@ -14,23 +14,30 @@ File DataSource ```terraform data "epilot-file_file" "my_file" { - id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" + id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" + strict = true } ``` ## Schema +### Optional + +- `strict` (Boolean) When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional` + ### Read-Only - `access_control` (String) must be one of ["private", "public-read"] -- `acl` (Attributes) Access control list for file entity (readonly) (see [below for nested schema](#nestedatt--acl)) +- `acl` (Attributes) Access control list (ACL) for an entity. Defines sharing access to external orgs or users. (see [below for nested schema](#nestedatt--acl)) +- `additional` (Map of String) Additional fields that are not part of the schema - `created_at` (String) - `custom_download_url` (String) Custom external download url used for the file - `filename` (String) - `id` (String) The ID of this resource. - `mime_type` (String) MIME type of the file - `org` (String) +- `owners` (Attributes List) (see [below for nested schema](#nestedatt--owners)) - `public_url` (String) Direct URL for file (public only if file access control is public-read) - `purpose` (List of String) - `readable_size` (String) Human readable file size @@ -54,6 +61,15 @@ Read-Only: - `view` (List of String) + +### Nested Schema for `owners` + +Read-Only: + +- `org_id` (String) +- `user_id` (String) + + ### Nested Schema for `s3ref` diff --git a/docs/index.md b/docs/index.md index ff704c0..b43b7df 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,7 +17,7 @@ terraform { required_providers { epilot-file = { source = "epilot-dev/epilot-file" - version = "0.3.3" + version = "0.4.0" } } } diff --git a/docs/resources/file.md b/docs/resources/file.md index 88c32d6..b7f9de0 100644 --- a/docs/resources/file.md +++ b/docs/resources/file.md @@ -21,7 +21,8 @@ resource "epilot-file_file" "my_file" { filename = "document.pdf" mime_type = "application/pdf" source_url = "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf" - type = "unknown" + strict = true + type = "application" } ``` @@ -31,22 +32,25 @@ resource "epilot-file_file" "my_file" { ### Optional - `access_control` (String) must be one of ["private", "public-read"]; Default: "private" +- `acl` (Attributes) Access control list (ACL) for an entity. Defines sharing access to external orgs or users. (see [below for nested schema](#nestedatt--acl)) +- `additional` (Map of String) Additional fields that are not part of the schema - `custom_download_url` (String) Custom external download url used for the file - `filename` (String) - `mime_type` (String) MIME type of the file - `purpose` (List of String) - `s3ref` (Attributes) (see [below for nested schema](#nestedatt--s3ref)) - `source_url` (String) Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true +- `strict` (Boolean) When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional`. Default: false - `tags` (List of String) - `title` (String) - `type` (String) must be one of ["document", "document_template", "text", "image", "video", "audio", "spreadsheet", "presentation", "font", "archive", "application", "unknown"] ### Read-Only -- `acl` (Attributes) Access control list for file entity (readonly) (see [below for nested schema](#nestedatt--acl)) - `created_at` (String) - `id` (String) The ID of this resource. - `org` (String) +- `owners` (Attributes List) (see [below for nested schema](#nestedatt--owners)) - `public_url` (String) Direct URL for file (public only if file access control is public-read) - `readable_size` (String) Human readable file size - `schema` (String) must be one of ["file"] @@ -54,6 +58,16 @@ resource "epilot-file_file" "my_file" { - `updated_at` (String) - `versions` (Attributes List) (see [below for nested schema](#nestedatt--versions)) + +### Nested Schema for `acl` + +Optional: + +- `delete` (List of String) +- `edit` (List of String) +- `view` (List of String) + + ### Nested Schema for `s3ref` @@ -63,14 +77,13 @@ Optional: - `key` (String) Not Null - -### Nested Schema for `acl` + +### Nested Schema for `owners` Read-Only: -- `delete` (List of String) -- `edit` (List of String) -- `view` (List of String) +- `org_id` (String) +- `user_id` (String) diff --git a/examples/data-sources/epilot-file_file/data-source.tf b/examples/data-sources/epilot-file_file/data-source.tf index 84fff68..5dacc31 100644 --- a/examples/data-sources/epilot-file_file/data-source.tf +++ b/examples/data-sources/epilot-file_file/data-source.tf @@ -1,3 +1,4 @@ data "epilot-file_file" "my_file" { - id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" + id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" + strict = true } \ No newline at end of file diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 1f836ee..130098b 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -2,7 +2,7 @@ terraform { required_providers { epilot-file = { source = "epilot-dev/epilot-file" - version = "0.3.3" + version = "0.4.0" } } } diff --git a/examples/resources/epilot-file_file-import/generated_resources.tf b/examples/resources/epilot-file_file-import/generated_resources.tf index 9ccae93..7ef8a5a 100644 --- a/examples/resources/epilot-file_file-import/generated_resources.tf +++ b/examples/resources/epilot-file_file-import/generated_resources.tf @@ -3,16 +3,24 @@ # __generated__ by Terraform from "91b9fd89-05ac-464d-8ac5-1379824471ac" resource "epilot-file_file" "my_file" { - access_control = "private" + access_control = "private" + acl = { + delete = ["org_739224"] + edit = ["org_739224"] + view = ["org_739224"] + } + additional = null custom_download_url = null filename = "8z87al.jpg" mime_type = "image/jpeg" + purpose = [] s3ref = { bucket = "epilot-dev-user-content" key = "739224/69f04890-fa8d-4d2e-9347-4ac384da107b/8z87al.jpg" } source_url = "https://file.dev.sls.epilot.io/v1/files/public/links/739224-taqDBUyNjSX7c_n2v6Zvv/8z87al.jpg" - tags = null + strict = null + tags = [] title = "8z87al.jpg" type = "image" } diff --git a/examples/resources/epilot-file_file-import/resource.tf b/examples/resources/epilot-file_file-import/resource.tf index ba972a5..7776754 100644 --- a/examples/resources/epilot-file_file-import/resource.tf +++ b/examples/resources/epilot-file_file-import/resource.tf @@ -1,38 +1,17 @@ -# import { -# to = epilot-file_file.my_file -# id = "91b9fd89-05ac-464d-8ac5-1379824471ac" -# } +import { + to = epilot-file_file.my_file + id = "91b9fd89-05ac-464d-8ac5-1379824471ac" +} # resource "epilot-file_file" "my_file" { # } # epilot-file_file.my_file: -resource "epilot-file_file" "my_file" { - access_control = "private" - filename = "8z87al.jpg" - mime_type = "image/jpeg" - source_url = "https://file.dev.sls.epilot.io/v1/files/public/links/739224-taqDBUyNjSX7c_n2v6Zvv/8z87al.jpg" - title = "8z87al.jpg" - type = "image" -} - -terraform { - required_providers { - epilot-file = { - source = "epilot-dev/epilot-file" - version = "2.1.1" - } - } -} - -variable "epilot_auth" { - type = string - description = "epilot_auth" -} - - -provider "epilot-file" { - # Configuration options - epilot_auth = var.epilot_auth - server_url = "https://file.dev.sls.epilot.io" -} +# resource "epilot-file_file" "my_file" { +# access_control = "private" +# filename = "8z87al.jpg" +# mime_type = "image/jpeg" +# source_url = "https://file.dev.sls.epilot.io/v1/files/public/links/739224-taqDBUyNjSX7c_n2v6Zvv/8z87al.jpg" +# title = "8z87al.jpg" +# type = "image" +# } diff --git a/examples/resources/epilot-file_file/resource.tf b/examples/resources/epilot-file_file/resource.tf index 671d93a..b99c3a5 100644 --- a/examples/resources/epilot-file_file/resource.tf +++ b/examples/resources/epilot-file_file/resource.tf @@ -6,5 +6,6 @@ resource "epilot-file_file" "my_file" { filename = "document.pdf" mime_type = "application/pdf" source_url = "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf" - type = "unknown" + strict = true + type = "application" } \ No newline at end of file diff --git a/gen.yaml b/gen.yaml index aef7383..44d28bf 100644 --- a/gen.yaml +++ b/gen.yaml @@ -27,7 +27,7 @@ go: outputModelSuffix: output packageName: openapi terraform: - version: 0.3.3 + version: 0.4.0 additionalDataSources: [] additionalDependencies: {} additionalResources: [] diff --git a/internal/provider/file_data_source.go b/internal/provider/file_data_source.go index cb538dc..4767ae3 100644 --- a/internal/provider/file_data_source.go +++ b/internal/provider/file_data_source.go @@ -29,26 +29,29 @@ type FileDataSource struct { // FileDataSourceModel describes the data model. type FileDataSourceModel struct { - AccessControl types.String `tfsdk:"access_control"` - ACL *tfTypes.ACL `tfsdk:"acl"` - CreatedAt types.String `tfsdk:"created_at"` - CustomDownloadURL types.String `tfsdk:"custom_download_url"` - Filename types.String `tfsdk:"filename"` - ID types.String `tfsdk:"id"` - MimeType types.String `tfsdk:"mime_type"` - Org types.String `tfsdk:"org"` - PublicURL types.String `tfsdk:"public_url"` - Purpose []types.String `tfsdk:"purpose"` - ReadableSize types.String `tfsdk:"readable_size"` - S3ref *tfTypes.S3Ref `tfsdk:"s3ref"` - Schema types.String `tfsdk:"schema"` - SizeBytes types.Int64 `tfsdk:"size_bytes"` - SourceURL types.String `tfsdk:"source_url"` - Tags []types.String `tfsdk:"tags"` - Title types.String `tfsdk:"title"` - Type types.String `tfsdk:"type"` - UpdatedAt types.String `tfsdk:"updated_at"` - Versions []tfTypes.FileItem `tfsdk:"versions"` + AccessControl types.String `tfsdk:"access_control"` + ACL *tfTypes.BaseEntityACL `tfsdk:"acl"` + Additional map[string]types.String `tfsdk:"additional"` + CreatedAt types.String `tfsdk:"created_at"` + CustomDownloadURL types.String `tfsdk:"custom_download_url"` + Filename types.String `tfsdk:"filename"` + ID types.String `tfsdk:"id"` + MimeType types.String `tfsdk:"mime_type"` + Org types.String `tfsdk:"org"` + Owners []tfTypes.BaseEntityOwner `tfsdk:"owners"` + PublicURL types.String `tfsdk:"public_url"` + Purpose []types.String `tfsdk:"purpose"` + ReadableSize types.String `tfsdk:"readable_size"` + S3ref *tfTypes.S3Ref `tfsdk:"s3ref"` + Schema types.String `tfsdk:"schema"` + SizeBytes types.Int64 `tfsdk:"size_bytes"` + SourceURL types.String `tfsdk:"source_url"` + Strict types.Bool `tfsdk:"strict"` + Tags []types.String `tfsdk:"tags"` + Title types.String `tfsdk:"title"` + Type types.String `tfsdk:"type"` + UpdatedAt types.String `tfsdk:"updated_at"` + Versions []tfTypes.FileItem `tfsdk:"versions"` } // Metadata returns the data source type name. @@ -82,7 +85,12 @@ func (r *FileDataSource) Schema(ctx context.Context, req datasource.SchemaReques ElementType: types.StringType, }, }, - Description: `Access control list for file entity (readonly)`, + Description: `Access control list (ACL) for an entity. Defines sharing access to external orgs or users.`, + }, + "additional": schema.MapAttribute{ + Computed: true, + ElementType: types.StringType, + Description: `Additional fields that are not part of the schema`, }, "created_at": schema.StringAttribute{ Computed: true, @@ -104,6 +112,19 @@ func (r *FileDataSource) Schema(ctx context.Context, req datasource.SchemaReques "org": schema.StringAttribute{ Computed: true, }, + "owners": schema.ListNestedAttribute{ + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "org_id": schema.StringAttribute{ + Computed: true, + }, + "user_id": schema.StringAttribute{ + Computed: true, + }, + }, + }, + }, "public_url": schema.StringAttribute{ Computed: true, Description: `Direct URL for file (public only if file access control is public-read)`, @@ -139,6 +160,11 @@ func (r *FileDataSource) Schema(ctx context.Context, req datasource.SchemaReques Computed: true, Description: `Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true`, }, + "strict": schema.BoolAttribute{ + Computed: true, + Optional: true, + Description: `When passed true, the response will contain only fields that match the schema, with non-matching fields included in ` + "`" + `__additional` + "`" + ``, + }, "tags": schema.ListAttribute{ Computed: true, ElementType: types.StringType, @@ -228,8 +254,15 @@ func (r *FileDataSource) Read(ctx context.Context, req datasource.ReadRequest, r var id string id = data.ID.ValueString() + strict := new(bool) + if !data.Strict.IsUnknown() && !data.Strict.IsNull() { + *strict = data.Strict.ValueBool() + } else { + strict = nil + } request := operations.GetFileRequest{ - ID: id, + ID: id, + Strict: strict, } res, err := r.client.File.GetFile(ctx, request) if err != nil { diff --git a/internal/provider/file_data_source_sdk.go b/internal/provider/file_data_source_sdk.go index f3a7ed6..e8a1b8e 100644 --- a/internal/provider/file_data_source_sdk.go +++ b/internal/provider/file_data_source_sdk.go @@ -3,6 +3,7 @@ package provider import ( + "encoding/json" tfTypes "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/types" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" "github.com/hashicorp/terraform-plugin-framework/types" @@ -11,10 +12,17 @@ import ( func (r *FileDataSourceModel) RefreshFromSharedFileEntity(resp *shared.FileEntity) { if resp != nil { + if len(resp.Additional) > 0 { + r.Additional = make(map[string]types.String) + for key, value := range resp.Additional { + result, _ := json.Marshal(value) + r.Additional[key] = types.StringValue(string(result)) + } + } if resp.ACL == nil { r.ACL = nil } else { - r.ACL = &tfTypes.ACL{} + r.ACL = &tfTypes.BaseEntityACL{} r.ACL.Delete = []types.String{} for _, v := range resp.ACL.Delete { r.ACL.Delete = append(r.ACL.Delete, types.StringValue(v)) @@ -34,6 +42,21 @@ func (r *FileDataSourceModel) RefreshFromSharedFileEntity(resp *shared.FileEntit r.CreatedAt = types.StringNull() } r.Org = types.StringPointerValue(resp.Org) + r.Owners = []tfTypes.BaseEntityOwner{} + if len(r.Owners) > len(resp.Owners) { + r.Owners = r.Owners[:len(resp.Owners)] + } + for ownersCount, ownersItem := range resp.Owners { + var owners1 tfTypes.BaseEntityOwner + owners1.OrgID = types.StringValue(ownersItem.OrgID) + owners1.UserID = types.StringPointerValue(ownersItem.UserID) + if ownersCount+1 > len(r.Owners) { + r.Owners = append(r.Owners, owners1) + } else { + r.Owners[ownersCount].OrgID = owners1.OrgID + r.Owners[ownersCount].UserID = owners1.UserID + } + } r.Purpose = []types.String{} for _, v := range resp.Purpose { r.Purpose = append(r.Purpose, types.StringValue(v)) diff --git a/internal/provider/file_resource.go b/internal/provider/file_resource.go index ab34236..4f88451 100644 --- a/internal/provider/file_resource.go +++ b/internal/provider/file_resource.go @@ -10,10 +10,12 @@ import ( "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" "github.com/epilot-dev/terraform-provider-epilot-file/internal/validators" speakeasy_stringvalidators "github.com/epilot-dev/terraform-provider-epilot-file/internal/validators/stringvalidators" + "github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" @@ -35,26 +37,29 @@ type FileResource struct { // FileResourceModel describes the resource data model. type FileResourceModel struct { - AccessControl types.String `tfsdk:"access_control"` - ACL *tfTypes.ACL `tfsdk:"acl"` - CreatedAt types.String `tfsdk:"created_at"` - CustomDownloadURL types.String `tfsdk:"custom_download_url"` - Filename types.String `tfsdk:"filename"` - ID types.String `tfsdk:"id"` - MimeType types.String `tfsdk:"mime_type"` - Org types.String `tfsdk:"org"` - PublicURL types.String `tfsdk:"public_url"` - Purpose []types.String `tfsdk:"purpose"` - ReadableSize types.String `tfsdk:"readable_size"` - S3ref *tfTypes.S3Ref `tfsdk:"s3ref"` - Schema types.String `tfsdk:"schema"` - SizeBytes types.Int64 `tfsdk:"size_bytes"` - SourceURL types.String `tfsdk:"source_url"` - Tags []types.String `tfsdk:"tags"` - Title types.String `tfsdk:"title"` - Type types.String `tfsdk:"type"` - UpdatedAt types.String `tfsdk:"updated_at"` - Versions []tfTypes.FileItem `tfsdk:"versions"` + AccessControl types.String `tfsdk:"access_control"` + ACL *tfTypes.BaseEntityACL `tfsdk:"acl"` + Additional map[string]types.String `tfsdk:"additional"` + CreatedAt types.String `tfsdk:"created_at"` + CustomDownloadURL types.String `tfsdk:"custom_download_url"` + Filename types.String `tfsdk:"filename"` + ID types.String `tfsdk:"id"` + MimeType types.String `tfsdk:"mime_type"` + Org types.String `tfsdk:"org"` + Owners []tfTypes.BaseEntityOwner `tfsdk:"owners"` + PublicURL types.String `tfsdk:"public_url"` + Purpose []types.String `tfsdk:"purpose"` + ReadableSize types.String `tfsdk:"readable_size"` + S3ref *tfTypes.S3Ref `tfsdk:"s3ref"` + Schema types.String `tfsdk:"schema"` + SizeBytes types.Int64 `tfsdk:"size_bytes"` + SourceURL types.String `tfsdk:"source_url"` + Strict types.Bool `tfsdk:"strict"` + Tags []types.String `tfsdk:"tags"` + Title types.String `tfsdk:"title"` + Type types.String `tfsdk:"type"` + UpdatedAt types.String `tfsdk:"updated_at"` + Versions []tfTypes.FileItem `tfsdk:"versions"` } func (r *FileResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { @@ -79,21 +84,34 @@ func (r *FileResource) Schema(ctx context.Context, req resource.SchemaRequest, r }, "acl": schema.SingleNestedAttribute{ Computed: true, + Optional: true, Attributes: map[string]schema.Attribute{ "delete": schema.ListAttribute{ Computed: true, + Optional: true, ElementType: types.StringType, }, "edit": schema.ListAttribute{ Computed: true, + Optional: true, ElementType: types.StringType, }, "view": schema.ListAttribute{ Computed: true, + Optional: true, ElementType: types.StringType, }, }, - Description: `Access control list for file entity (readonly)`, + Description: `Access control list (ACL) for an entity. Defines sharing access to external orgs or users.`, + }, + "additional": schema.MapAttribute{ + Computed: true, + Optional: true, + ElementType: types.StringType, + Description: `Additional fields that are not part of the schema`, + Validators: []validator.Map{ + mapvalidator.ValueStringsAre(validators.IsValidJSON()), + }, }, "created_at": schema.StringAttribute{ Computed: true, @@ -122,6 +140,19 @@ func (r *FileResource) Schema(ctx context.Context, req resource.SchemaRequest, r "org": schema.StringAttribute{ Computed: true, }, + "owners": schema.ListNestedAttribute{ + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "org_id": schema.StringAttribute{ + Computed: true, + }, + "user_id": schema.StringAttribute{ + Computed: true, + }, + }, + }, + }, "public_url": schema.StringAttribute{ Computed: true, Description: `Direct URL for file (public only if file access control is public-read)`, @@ -175,6 +206,12 @@ func (r *FileResource) Schema(ctx context.Context, req resource.SchemaRequest, r Optional: true, Description: `Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true`, }, + "strict": schema.BoolAttribute{ + Computed: true, + Optional: true, + Default: booldefault.StaticBool(false), + Description: `When passed true, the response will contain only fields that match the schema, with non-matching fields included in ` + "`" + `__additional` + "`" + `. Default: false`, + }, "tags": schema.ListAttribute{ Computed: true, Optional: true, @@ -283,7 +320,17 @@ func (r *FileResource) Create(ctx context.Context, req resource.CreateRequest, r return } - request := data.ToSharedSaveFilePayloadV2() + saveFilePayloadV2 := data.ToSharedSaveFilePayloadV2() + strict := new(bool) + if !data.Strict.IsUnknown() && !data.Strict.IsNull() { + *strict = data.Strict.ValueBool() + } else { + strict = nil + } + request := operations.SaveFileV2Request{ + SaveFilePayloadV2: saveFilePayloadV2, + Strict: strict, + } res, err := r.client.File.SaveFileV2(ctx, request) if err != nil { resp.Diagnostics.AddError("failure to invoke API", err.Error()) @@ -332,8 +379,15 @@ func (r *FileResource) Read(ctx context.Context, req resource.ReadRequest, resp var id string id = data.ID.ValueString() + strict := new(bool) + if !data.Strict.IsUnknown() && !data.Strict.IsNull() { + *strict = data.Strict.ValueBool() + } else { + strict = nil + } request := operations.GetFileRequest{ - ID: id, + ID: id, + Strict: strict, } res, err := r.client.File.GetFile(ctx, request) if err != nil { @@ -379,7 +433,17 @@ func (r *FileResource) Update(ctx context.Context, req resource.UpdateRequest, r return } - request := data.ToSharedSaveFilePayloadV2() + saveFilePayloadV2 := data.ToSharedSaveFilePayloadV2() + strict := new(bool) + if !data.Strict.IsUnknown() && !data.Strict.IsNull() { + *strict = data.Strict.ValueBool() + } else { + strict = nil + } + request := operations.SaveFileV2Request{ + SaveFilePayloadV2: saveFilePayloadV2, + Strict: strict, + } res, err := r.client.File.SaveFileV2(ctx, request) if err != nil { resp.Diagnostics.AddError("failure to invoke API", err.Error()) @@ -428,8 +492,15 @@ func (r *FileResource) Delete(ctx context.Context, req resource.DeleteRequest, r var id string id = data.ID.ValueString() + strict := new(bool) + if !data.Strict.IsUnknown() && !data.Strict.IsNull() { + *strict = data.Strict.ValueBool() + } else { + strict = nil + } request := operations.DeleteFileRequest{ - ID: id, + ID: id, + Strict: strict, } res, err := r.client.File.DeleteFile(ctx, request) if err != nil { diff --git a/internal/provider/file_resource_sdk.go b/internal/provider/file_resource_sdk.go index bc9e395..796b67e 100644 --- a/internal/provider/file_resource_sdk.go +++ b/internal/provider/file_resource_sdk.go @@ -3,6 +3,7 @@ package provider import ( + "encoding/json" tfTypes "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/types" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" "github.com/hashicorp/terraform-plugin-framework/types" @@ -10,6 +11,32 @@ import ( ) func (r *FileResourceModel) ToSharedSaveFilePayloadV2() *shared.SaveFilePayloadV2 { + additional := make(map[string]interface{}) + for additionalKey, additionalValue := range r.Additional { + var additionalInst interface{} + _ = json.Unmarshal([]byte(additionalValue.ValueString()), &additionalInst) + additional[additionalKey] = additionalInst + } + var acl *shared.BaseEntityACL + if r.ACL != nil { + var delete []string = []string{} + for _, deleteItem := range r.ACL.Delete { + delete = append(delete, deleteItem.ValueString()) + } + var edit []string = []string{} + for _, editItem := range r.ACL.Edit { + edit = append(edit, editItem.ValueString()) + } + var view []string = []string{} + for _, viewItem := range r.ACL.View { + view = append(view, viewItem.ValueString()) + } + acl = &shared.BaseEntityACL{ + Delete: delete, + Edit: edit, + View: view, + } + } id := new(string) if !r.ID.IsUnknown() && !r.ID.IsNull() { *id = r.ID.ValueString() @@ -80,6 +107,8 @@ func (r *FileResourceModel) ToSharedSaveFilePayloadV2() *shared.SaveFilePayloadV typeVar = nil } out := shared.SaveFilePayloadV2{ + Additional: additional, + ACL: acl, ID: id, Purpose: purpose, Tags: tags, @@ -97,10 +126,17 @@ func (r *FileResourceModel) ToSharedSaveFilePayloadV2() *shared.SaveFilePayloadV func (r *FileResourceModel) RefreshFromSharedFileEntity(resp *shared.FileEntity) { if resp != nil { + if len(resp.Additional) > 0 { + r.Additional = make(map[string]types.String) + for key, value := range resp.Additional { + result, _ := json.Marshal(value) + r.Additional[key] = types.StringValue(string(result)) + } + } if resp.ACL == nil { r.ACL = nil } else { - r.ACL = &tfTypes.ACL{} + r.ACL = &tfTypes.BaseEntityACL{} r.ACL.Delete = []types.String{} for _, v := range resp.ACL.Delete { r.ACL.Delete = append(r.ACL.Delete, types.StringValue(v)) @@ -121,6 +157,21 @@ func (r *FileResourceModel) RefreshFromSharedFileEntity(resp *shared.FileEntity) } r.ID = types.StringPointerValue(resp.ID) r.Org = types.StringPointerValue(resp.Org) + r.Owners = []tfTypes.BaseEntityOwner{} + if len(r.Owners) > len(resp.Owners) { + r.Owners = r.Owners[:len(resp.Owners)] + } + for ownersCount, ownersItem := range resp.Owners { + var owners1 tfTypes.BaseEntityOwner + owners1.OrgID = types.StringValue(ownersItem.OrgID) + owners1.UserID = types.StringPointerValue(ownersItem.UserID) + if ownersCount+1 > len(r.Owners) { + r.Owners = append(r.Owners, owners1) + } else { + r.Owners[ownersCount].OrgID = owners1.OrgID + r.Owners[ownersCount].UserID = owners1.UserID + } + } r.Purpose = []types.String{} for _, v := range resp.Purpose { r.Purpose = append(r.Purpose, types.StringValue(v)) diff --git a/internal/provider/types/acl.go b/internal/provider/types/base_entity_acl.go similarity index 90% rename from internal/provider/types/acl.go rename to internal/provider/types/base_entity_acl.go index bb00660..ea0f5f9 100644 --- a/internal/provider/types/acl.go +++ b/internal/provider/types/base_entity_acl.go @@ -4,7 +4,7 @@ package types import "github.com/hashicorp/terraform-plugin-framework/types" -type ACL struct { +type BaseEntityACL struct { Delete []types.String `tfsdk:"delete"` Edit []types.String `tfsdk:"edit"` View []types.String `tfsdk:"view"` diff --git a/internal/provider/types/base_entity_owner.go b/internal/provider/types/base_entity_owner.go new file mode 100644 index 0000000..10d217d --- /dev/null +++ b/internal/provider/types/base_entity_owner.go @@ -0,0 +1,10 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package types + +import "github.com/hashicorp/terraform-plugin-framework/types" + +type BaseEntityOwner struct { + OrgID types.String `tfsdk:"org_id"` + UserID types.String `tfsdk:"user_id"` +} diff --git a/internal/sdk/file.go b/internal/sdk/file.go index 920388a..a9eb4f8 100644 --- a/internal/sdk/file.go +++ b/internal/sdk/file.go @@ -75,6 +75,10 @@ func (s *File) DeleteFile(ctx context.Context, request operations.DeleteFileRequ req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) + if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { + return nil, fmt.Errorf("error populating query params: %w", err) + } + if err := utils.PopulateSecurity(ctx, req, s.sdkConfiguration.Security); err != nil { return nil, err } @@ -789,6 +793,10 @@ func (s *File) GetFile(ctx context.Context, request operations.GetFileRequest, o req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) + if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { + return nil, fmt.Errorf("error populating query params: %w", err) + } + if err := utils.PopulateSecurity(ctx, req, s.sdkConfiguration.Security); err != nil { return nil, err } @@ -922,7 +930,7 @@ func (s *File) GetFile(ctx context.Context, request operations.GetFileRequest, o // Saves a permanent file entity. Updates an existing file entity when `_id` is passed. // // Saves metadata to file entity and stores a version when `s3ref` or `source_url` is passed. -func (s *File) SaveFileV2(ctx context.Context, request *shared.SaveFilePayloadV2, opts ...operations.Option) (*operations.SaveFileV2Response, error) { +func (s *File) SaveFileV2(ctx context.Context, request operations.SaveFileV2Request, opts ...operations.Option) (*operations.SaveFileV2Response, error) { hookCtx := hooks.HookContext{ Context: ctx, OperationID: "saveFileV2", @@ -948,7 +956,7 @@ func (s *File) SaveFileV2(ctx context.Context, request *shared.SaveFilePayloadV2 return nil, fmt.Errorf("error generating URL: %w", err) } - bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "Request", "json", `request:"mediaType=application/json"`) + bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "SaveFilePayloadV2", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err } @@ -972,6 +980,10 @@ func (s *File) SaveFileV2(ctx context.Context, request *shared.SaveFilePayloadV2 req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) req.Header.Set("Content-Type", reqContentType) + if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { + return nil, fmt.Errorf("error populating query params: %w", err) + } + if err := utils.PopulateSecurity(ctx, req, s.sdkConfiguration.Security); err != nil { return nil, err } diff --git a/internal/sdk/internal/utils/requestbody.go b/internal/sdk/internal/utils/requestbody.go index cee9da2..0fd33cf 100644 --- a/internal/sdk/internal/utils/requestbody.go +++ b/internal/sdk/internal/utils/requestbody.go @@ -82,7 +82,7 @@ func serializeRequestBody(request interface{}, nullable, optional bool, requestF return serializeContentType(requestFieldName, SerializationMethodToContentType[serializationMethod], reflect.ValueOf(request), tag) } -func serializeContentType(fieldName string, mediaType string, val reflect.Value, tag string) (io.Reader, string, error) { +func serializeContentType(fieldName string, mediaType string, val reflect.Value, tag string) (*bytes.Buffer, string, error) { buf := &bytes.Buffer{} if isNil(val.Type(), val) { @@ -116,8 +116,6 @@ func serializeContentType(fieldName string, mediaType string, val reflect.Value, if err := encodeFormData(fieldName, buf, val.Interface()); err != nil { return nil, "", err } - case val.Type().Implements(reflect.TypeOf((*io.Reader)(nil)).Elem()): - return val.Interface().(io.Reader), mediaType, nil default: val = reflect.Indirect(val) @@ -126,8 +124,8 @@ func serializeContentType(fieldName string, mediaType string, val reflect.Value, if _, err := buf.WriteString(valToString(val.Interface())); err != nil { return nil, "", err } - case reflect.TypeOf(val.Interface()) == reflect.TypeOf([]byte(nil)): - if _, err := buf.Write(val.Interface().([]byte)); err != nil { + case val.Type() == reflect.TypeOf([]byte(nil)): + if _, err := buf.Write(val.Bytes()); err != nil { return nil, "", err } default: @@ -217,7 +215,7 @@ func encodeMultipartFormDataFile(w *multipart.Writer, fieldType reflect.Type, va var fieldName string var fileName string - var reader io.Reader + var content []byte for i := 0; i < fieldType.NumField(); i++ { field := fieldType.Field(i) @@ -228,19 +226,15 @@ func encodeMultipartFormDataFile(w *multipart.Writer, fieldType reflect.Type, va continue } - if tag.Content && val.CanInterface() { - if reflect.TypeOf(val.Interface()) == reflect.TypeOf([]byte(nil)) { - reader = bytes.NewReader(val.Interface().([]byte)) - } else if reflect.TypeOf(val.Interface()).Implements(reflect.TypeOf((*io.Reader)(nil)).Elem()) { - reader = val.Interface().(io.Reader) - } + if tag.Content { + content = val.Bytes() } else { fieldName = tag.Name fileName = val.String() } } - if fieldName == "" || fileName == "" || reader == nil { + if fieldName == "" || fileName == "" || content == nil { return fmt.Errorf("invalid multipart/form-data file") } @@ -248,7 +242,7 @@ func encodeMultipartFormDataFile(w *multipart.Writer, fieldType reflect.Type, va if err != nil { return err } - if _, err := io.Copy(fw, reader); err != nil { + if _, err := fw.Write(content); err != nil { return err } diff --git a/internal/sdk/models/operations/deletefile.go b/internal/sdk/models/operations/deletefile.go index b014ea9..86fb332 100644 --- a/internal/sdk/models/operations/deletefile.go +++ b/internal/sdk/models/operations/deletefile.go @@ -3,12 +3,26 @@ package operations import ( + "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" "net/http" ) type DeleteFileRequest struct { ID string `pathParam:"style=simple,explode=false,name=id"` + // When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional` + Strict *bool `default:"false" queryParam:"style=form,explode=true,name=strict"` +} + +func (d DeleteFileRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(d, "", false) +} + +func (d *DeleteFileRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &d, "", false, false); err != nil { + return err + } + return nil } func (o *DeleteFileRequest) GetID() string { @@ -18,6 +32,13 @@ func (o *DeleteFileRequest) GetID() string { return o.ID } +func (o *DeleteFileRequest) GetStrict() *bool { + if o == nil { + return nil + } + return o.Strict +} + type DeleteFileResponse struct { // HTTP response content type for this operation ContentType string diff --git a/internal/sdk/models/operations/getfile.go b/internal/sdk/models/operations/getfile.go index b6419d1..ff6c6ae 100644 --- a/internal/sdk/models/operations/getfile.go +++ b/internal/sdk/models/operations/getfile.go @@ -3,12 +3,26 @@ package operations import ( + "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" "net/http" ) type GetFileRequest struct { ID string `pathParam:"style=simple,explode=false,name=id"` + // When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional` + Strict *bool `default:"false" queryParam:"style=form,explode=true,name=strict"` +} + +func (g GetFileRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(g, "", false) +} + +func (g *GetFileRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &g, "", false, false); err != nil { + return err + } + return nil } func (o *GetFileRequest) GetID() string { @@ -18,6 +32,13 @@ func (o *GetFileRequest) GetID() string { return o.ID } +func (o *GetFileRequest) GetStrict() *bool { + if o == nil { + return nil + } + return o.Strict +} + type GetFileResponse struct { // HTTP response content type for this operation ContentType string diff --git a/internal/sdk/models/operations/savefilev2.go b/internal/sdk/models/operations/savefilev2.go index f5adb09..c0aea9d 100644 --- a/internal/sdk/models/operations/savefilev2.go +++ b/internal/sdk/models/operations/savefilev2.go @@ -3,10 +3,42 @@ package operations import ( + "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" "net/http" ) +type SaveFileV2Request struct { + SaveFilePayloadV2 *shared.SaveFilePayloadV2 `request:"mediaType=application/json"` + // When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional` + Strict *bool `default:"false" queryParam:"style=form,explode=true,name=strict"` +} + +func (s SaveFileV2Request) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(s, "", false) +} + +func (s *SaveFileV2Request) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &s, "", false, false); err != nil { + return err + } + return nil +} + +func (o *SaveFileV2Request) GetSaveFilePayloadV2() *shared.SaveFilePayloadV2 { + if o == nil { + return nil + } + return o.SaveFilePayloadV2 +} + +func (o *SaveFileV2Request) GetStrict() *bool { + if o == nil { + return nil + } + return o.Strict +} + type SaveFileV2Response struct { // HTTP response content type for this operation ContentType string diff --git a/internal/sdk/models/shared/baseentityacl.go b/internal/sdk/models/shared/baseentityacl.go new file mode 100644 index 0000000..9998b66 --- /dev/null +++ b/internal/sdk/models/shared/baseentityacl.go @@ -0,0 +1,31 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package shared + +// BaseEntityACL - Access control list (ACL) for an entity. Defines sharing access to external orgs or users. +type BaseEntityACL struct { + Delete []string `json:"delete,omitempty"` + Edit []string `json:"edit,omitempty"` + View []string `json:"view,omitempty"` +} + +func (o *BaseEntityACL) GetDelete() []string { + if o == nil { + return nil + } + return o.Delete +} + +func (o *BaseEntityACL) GetEdit() []string { + if o == nil { + return nil + } + return o.Edit +} + +func (o *BaseEntityACL) GetView() []string { + if o == nil { + return nil + } + return o.View +} diff --git a/internal/sdk/models/shared/baseentityowner.go b/internal/sdk/models/shared/baseentityowner.go new file mode 100644 index 0000000..8f359c1 --- /dev/null +++ b/internal/sdk/models/shared/baseentityowner.go @@ -0,0 +1,25 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package shared + +// BaseEntityOwner - The user / organization owning this entity. +// +// Note: Owner implicitly has access to the entity regardless of ACLs. +type BaseEntityOwner struct { + OrgID string `json:"org_id"` + UserID *string `json:"user_id,omitempty"` +} + +func (o *BaseEntityOwner) GetOrgID() string { + if o == nil { + return "" + } + return o.OrgID +} + +func (o *BaseEntityOwner) GetUserID() *string { + if o == nil { + return nil + } + return o.UserID +} diff --git a/internal/sdk/models/shared/fileentity.go b/internal/sdk/models/shared/fileentity.go index afb85af..c6559cc 100644 --- a/internal/sdk/models/shared/fileentity.go +++ b/internal/sdk/models/shared/fileentity.go @@ -9,34 +9,6 @@ import ( "time" ) -// ACL - Access control list for file entity (readonly) -type ACL struct { - Delete []string `json:"delete,omitempty"` - Edit []string `json:"edit,omitempty"` - View []string `json:"view,omitempty"` -} - -func (o *ACL) GetDelete() []string { - if o == nil { - return nil - } - return o.Delete -} - -func (o *ACL) GetEdit() []string { - if o == nil { - return nil - } - return o.Edit -} - -func (o *ACL) GetView() []string { - if o == nil { - return nil - } - return o.View -} - type Schema string const ( @@ -87,17 +59,20 @@ func (e *AccessControl) UnmarshalJSON(data []byte) error { } type FileEntity struct { - // Access control list for file entity (readonly) - ACL *ACL `json:"_acl,omitempty"` - CreatedAt *time.Time `json:"_created_at,omitempty"` - ID *string `json:"_id,omitempty"` - Org *string `json:"_org,omitempty"` - Purpose []string `json:"_purpose,omitempty"` - Schema *Schema `json:"_schema,omitempty"` - Tags []string `json:"_tags,omitempty"` - Title *string `json:"_title,omitempty"` - UpdatedAt *time.Time `json:"_updated_at,omitempty"` - AccessControl *AccessControl `default:"private" json:"access_control"` + // Additional fields that are not part of the schema + Additional map[string]any `json:"__additional,omitempty"` + // Access control list (ACL) for an entity. Defines sharing access to external orgs or users. + ACL *BaseEntityACL `json:"_acl,omitempty"` + CreatedAt *time.Time `json:"_created_at,omitempty"` + ID *string `json:"_id,omitempty"` + Org *string `json:"_org,omitempty"` + Owners []BaseEntityOwner `json:"_owners,omitempty"` + Purpose []string `json:"_purpose,omitempty"` + Schema *Schema `json:"_schema,omitempty"` + Tags []string `json:"_tags,omitempty"` + Title *string `json:"_title,omitempty"` + UpdatedAt *time.Time `json:"_updated_at,omitempty"` + AccessControl *AccessControl `default:"private" json:"access_control"` // Custom external download url used for the file CustomDownloadURL *string `json:"custom_download_url,omitempty"` Filename *string `json:"filename,omitempty"` @@ -127,7 +102,14 @@ func (f *FileEntity) UnmarshalJSON(data []byte) error { return nil } -func (o *FileEntity) GetACL() *ACL { +func (o *FileEntity) GetAdditional() map[string]any { + if o == nil { + return nil + } + return o.Additional +} + +func (o *FileEntity) GetACL() *BaseEntityACL { if o == nil { return nil } @@ -155,6 +137,13 @@ func (o *FileEntity) GetOrg() *string { return o.Org } +func (o *FileEntity) GetOwners() []BaseEntityOwner { + if o == nil { + return nil + } + return o.Owners +} + func (o *FileEntity) GetPurpose() []string { if o == nil { return nil diff --git a/internal/sdk/models/shared/savefilepayloadv2.go b/internal/sdk/models/shared/savefilepayloadv2.go index 8aed1c1..8c42134 100644 --- a/internal/sdk/models/shared/savefilepayloadv2.go +++ b/internal/sdk/models/shared/savefilepayloadv2.go @@ -35,6 +35,10 @@ func (e *SaveFilePayloadV2AccessControl) UnmarshalJSON(data []byte) error { } type SaveFilePayloadV2 struct { + // Additional fields that are not part of the schema + Additional map[string]any `json:"__additional,omitempty"` + // Access control list (ACL) for an entity. Defines sharing access to external orgs or users. + ACL *BaseEntityACL `json:"_acl,omitempty"` ID *string `json:"_id,omitempty"` Purpose []string `json:"_purpose,omitempty"` Tags []string `json:"_tags,omitempty"` @@ -62,6 +66,20 @@ func (s *SaveFilePayloadV2) UnmarshalJSON(data []byte) error { return nil } +func (o *SaveFilePayloadV2) GetAdditional() map[string]any { + if o == nil { + return nil + } + return o.Additional +} + +func (o *SaveFilePayloadV2) GetACL() *BaseEntityACL { + if o == nil { + return nil + } + return o.ACL +} + func (o *SaveFilePayloadV2) GetID() *string { if o == nil { return nil diff --git a/internal/sdk/sdk.go b/internal/sdk/sdk.go index a0d87bd..db1037d 100644 --- a/internal/sdk/sdk.go +++ b/internal/sdk/sdk.go @@ -154,8 +154,8 @@ func New(opts ...SDKOption) *SDK { Language: "go", OpenAPIDocVersion: "0.2.0", SDKVersion: "0.0.1", - GenVersion: "2.404.3", - UserAgent: "speakeasy-sdk/go 0.0.1 2.404.3 0.2.0 github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk", + GenVersion: "2.396.0", + UserAgent: "speakeasy-sdk/go 0.0.1 2.396.0 0.2.0 github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk", Hooks: hooks.New(), }, } diff --git a/openapi.yml b/openapi.yml index 942825c..d05cdcf 100644 --- a/openapi.yml +++ b/openapi.yml @@ -17,6 +17,8 @@ tags: security: - EpilotAuth: [] - CookieAuth: [] +servers: + - url: https://file.sls.epilot.io paths: /v2/files/upload: post: @@ -67,6 +69,8 @@ paths: Saves metadata to file entity and stores a version when `s3ref` or `source_url` is passed. tags: - File + parameters: + - $ref: "#/components/parameters/StrictQueryParam" requestBody: content: application/json: @@ -222,6 +226,7 @@ paths: type: boolean default: false description: Generate a source_url for the file entity, if it doesn't have one + - $ref: "#/components/parameters/StrictQueryParam" responses: 200: description: File Entity @@ -241,6 +246,7 @@ paths: required: true schema: $ref: "#/components/schemas/FileEntityId" + - $ref: "#/components/parameters/StrictQueryParam" responses: 200: description: The deleted file @@ -784,9 +790,7 @@ components: example: "123" readOnly: true _id: - allOf: - - $ref: "#/components/schemas/FileEntityId" - - readOnly: true + $ref: "#/components/schemas/FileEntityId" - $ref: "#/components/schemas/FileAttributes" - type: object properties: @@ -811,25 +815,17 @@ components: format: date-time readOnly: true _acl: - type: object - description: Access control list for file entity (readonly) + $ref: "#/components/schemas/BaseEntityAcl" + _owners: + type: array readOnly: true - properties: - view: - type: array - items: - type: string - example: org_123 - edit: - type: array - items: - type: string - example: org_123 - delete: - type: array - items: - type: string - example: org_123 + items: + $ref: "#/components/schemas/BaseEntityOwner" + __additional: + type: object + description: Additional fields that are not part of the schema + additionalProperties: true + nullable: true required: - _title - _schema @@ -1014,5 +1010,46 @@ components: last_accessed_at: type: string description: "The most recent timestamp when the file was accessed" -servers: - - url: https://file.sls.epilot.io + BaseEntityOwner: + description: | + The user / organization owning this entity. + + Note: Owner implicitly has access to the entity regardless of ACLs. + type: object + properties: + org_id: + type: string + example: "123" + user_id: + type: string + example: "123" + required: + - org_id + BaseEntityAcl: + type: object + description: Access control list (ACL) for an entity. Defines sharing access to external orgs or users. + properties: + view: + type: array + items: + type: string + example: org:456 + edit: + type: array + items: + type: string + example: org:456 + delete: + type: array + items: + type: string + example: org:456 + parameters: + StrictQueryParam: + name: strict + in: query + required: false + description: When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional` + schema: + type: boolean + default: false