diff --git a/bin/redoc-container b/bin/redoc-container new file mode 100755 index 000000000..526680ca8 --- /dev/null +++ b/bin/redoc-container @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# +# instructions: +# run this script +# open http://127.0.0.1:8081 +# +# Prefer to use ./redoc - this version does not auto-reload changes + +set -e + +DIR=$(cd `dirname $0` && pwd) +ROOT_DIR="${DIR}/.." + +echo "Docs will be available at http://localhost:8081/" + +docker run -it --rm -p 8081:80 \ + -v "${ROOT_DIR}:/usr/share/nginx/html/swagger/" \ + -e SPEC_URL=swagger/openapi.yaml \ + -e REDOC_OPTIONS="required-props-first=1 path-in-middle-panel=1" \ + redocly/redoc diff --git a/examples/SignatureRequestCreateEmbeddedExample.cs b/examples/SignatureRequestCreateEmbeddedExample.cs index 7f9786caf..cd3badd87 100644 --- a/examples/SignatureRequestCreateEmbeddedExample.cs +++ b/examples/SignatureRequestCreateEmbeddedExample.cs @@ -22,7 +22,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false ); var signers1 = new SubSignatureRequestSigner( diff --git a/examples/SignatureRequestCreateEmbeddedExample.java b/examples/SignatureRequestCreateEmbeddedExample.java index 5193cee20..a432c2f35 100644 --- a/examples/SignatureRequestCreateEmbeddedExample.java +++ b/examples/SignatureRequestCreateEmbeddedExample.java @@ -29,6 +29,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); diff --git a/examples/SignatureRequestCreateEmbeddedExample.php b/examples/SignatureRequestCreateEmbeddedExample.php index 61d74044e..185e3b749 100644 --- a/examples/SignatureRequestCreateEmbeddedExample.php +++ b/examples/SignatureRequestCreateEmbeddedExample.php @@ -16,7 +16,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestSigner()) ->setName("Jack") diff --git a/examples/SignatureRequestCreateEmbeddedExample.py b/examples/SignatureRequestCreateEmbeddedExample.py index 2e1b93c1d..adf6b8f02 100644 --- a/examples/SignatureRequestCreateEmbeddedExample.py +++ b/examples/SignatureRequestCreateEmbeddedExample.py @@ -16,6 +16,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestSigner( diff --git a/examples/SignatureRequestCreateEmbeddedExample.rb b/examples/SignatureRequestCreateEmbeddedExample.rb index 55db08ca7..3b33e2f80 100644 --- a/examples/SignatureRequestCreateEmbeddedExample.rb +++ b/examples/SignatureRequestCreateEmbeddedExample.rb @@ -12,6 +12,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestSigner.new signers_1.name = "Jack" diff --git a/examples/SignatureRequestCreateEmbeddedExample.sh b/examples/SignatureRequestCreateEmbeddedExample.sh index 1ef8303f3..58b8708aa 100644 --- a/examples/SignatureRequestCreateEmbeddedExample.sh +++ b/examples/SignatureRequestCreateEmbeddedExample.sh @@ -18,4 +18,5 @@ curl -X POST 'https://api.hellosign.com/v3/signature_request/create_embedded' \ -F 'signing_options[upload]=1' \ -F 'signing_options[phone]=1' \ -F 'signing_options[default_type]=draw' \ + -F 'signing_options[force_advanced_signature_details]=0' \ -F 'test_mode=1' diff --git a/examples/SignatureRequestCreateEmbeddedExample.ts b/examples/SignatureRequestCreateEmbeddedExample.ts index a2c620a2e..811c0c7aa 100644 --- a/examples/SignatureRequestCreateEmbeddedExample.ts +++ b/examples/SignatureRequestCreateEmbeddedExample.ts @@ -12,6 +12,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestSigner = { diff --git a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.cs b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.cs index d40f34240..5138e9e69 100644 --- a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.cs +++ b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.cs @@ -22,7 +22,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false ); var signers1 = new SubSignatureRequestTemplateSigner( diff --git a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.java b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.java index 309d422ee..f94b403d2 100644 --- a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.java +++ b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.java @@ -29,6 +29,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); diff --git a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.php b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.php index 3ff0454e8..ab2b4f850 100644 --- a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.php +++ b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.php @@ -16,7 +16,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestTemplateSigner()) ->setRole("Client") diff --git a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.py b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.py index 6a5835760..885a24811 100644 --- a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.py +++ b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.py @@ -16,6 +16,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestTemplateSigner( diff --git a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.rb b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.rb index 2de72cf8a..18d1d8be4 100644 --- a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.rb +++ b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.rb @@ -12,6 +12,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestTemplateSigner.new signers_1.role = "Client" diff --git a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.sh b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.sh index 91e0a48ec..0a247f007 100644 --- a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.sh +++ b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.sh @@ -12,4 +12,5 @@ curl -X POST 'https://api.hellosign.com/v3/signature_request/create_embedded_wit -F 'signing_options[upload]=1' \ -F 'signing_options[phone]=1' \ -F 'signing_options[default_type]=draw' \ + -F 'signing_options[force_advanced_signature_details]=0' \ -F 'test_mode=1' diff --git a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.ts b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.ts index a2ee15e46..3914dfe02 100644 --- a/examples/SignatureRequestCreateEmbeddedWithTemplateExample.ts +++ b/examples/SignatureRequestCreateEmbeddedWithTemplateExample.ts @@ -12,6 +12,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestTemplateSigner = { diff --git a/examples/SignatureRequestSendExample.cs b/examples/SignatureRequestSendExample.cs index 2958c264c..d5e8ad896 100644 --- a/examples/SignatureRequestSendExample.cs +++ b/examples/SignatureRequestSendExample.cs @@ -26,7 +26,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false, ); var signers1 = new SubSignatureRequestSigner( diff --git a/examples/SignatureRequestSendExample.java b/examples/SignatureRequestSendExample.java index 313b895b7..7db66e606 100644 --- a/examples/SignatureRequestSendExample.java +++ b/examples/SignatureRequestSendExample.java @@ -32,6 +32,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); diff --git a/examples/SignatureRequestSendExample.php b/examples/SignatureRequestSendExample.php index f922a579e..f8ab05ef0 100644 --- a/examples/SignatureRequestSendExample.php +++ b/examples/SignatureRequestSendExample.php @@ -19,7 +19,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestSigner()) ->setName("Jack") diff --git a/examples/SignatureRequestSendExample.py b/examples/SignatureRequestSendExample.py index 21b1bfc26..033e973fe 100644 --- a/examples/SignatureRequestSendExample.py +++ b/examples/SignatureRequestSendExample.py @@ -20,6 +20,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestSigner( diff --git a/examples/SignatureRequestSendExample.rb b/examples/SignatureRequestSendExample.rb index 28905902d..45958b7a3 100644 --- a/examples/SignatureRequestSendExample.rb +++ b/examples/SignatureRequestSendExample.rb @@ -15,6 +15,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestSigner.new signers_1.name = "Jack" diff --git a/examples/SignatureRequestSendExample.sh b/examples/SignatureRequestSendExample.sh index 089a2c6be..6f1e15a7f 100644 --- a/examples/SignatureRequestSendExample.sh +++ b/examples/SignatureRequestSendExample.sh @@ -19,5 +19,6 @@ curl -X POST 'https://api.hellosign.com/v3/signature_request/send' \ -F 'signing_options[upload]=1' \ -F 'signing_options[phone]=1' \ -F 'signing_options[default_type]=draw' \ + -F 'signing_options[force_advanced_signature_details]=0' \ -F 'field_options[date_format]=DD - MM - YYYY' \ -F 'test_mode=1' diff --git a/examples/SignatureRequestSendExample.ts b/examples/SignatureRequestSendExample.ts index 910a66743..064e68ad3 100644 --- a/examples/SignatureRequestSendExample.ts +++ b/examples/SignatureRequestSendExample.ts @@ -16,6 +16,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestSigner = { diff --git a/examples/SignatureRequestSendWithTemplateExample.cs b/examples/SignatureRequestSendWithTemplateExample.cs index 024b92ce8..72d43c3d3 100644 --- a/examples/SignatureRequestSendWithTemplateExample.cs +++ b/examples/SignatureRequestSendWithTemplateExample.cs @@ -22,7 +22,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false, ); var signers1 = new SubSignatureRequestTemplateSigner( diff --git a/examples/SignatureRequestSendWithTemplateExample.java b/examples/SignatureRequestSendWithTemplateExample.java index f44a67ed9..5c6bd8d6b 100644 --- a/examples/SignatureRequestSendWithTemplateExample.java +++ b/examples/SignatureRequestSendWithTemplateExample.java @@ -29,6 +29,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); diff --git a/examples/SignatureRequestSendWithTemplateExample.php b/examples/SignatureRequestSendWithTemplateExample.php index d68205392..747882e76 100644 --- a/examples/SignatureRequestSendWithTemplateExample.php +++ b/examples/SignatureRequestSendWithTemplateExample.php @@ -16,7 +16,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestTemplateSigner()) ->setRole("Client") diff --git a/examples/SignatureRequestSendWithTemplateExample.py b/examples/SignatureRequestSendWithTemplateExample.py index 468a6b101..7c94fedc6 100644 --- a/examples/SignatureRequestSendWithTemplateExample.py +++ b/examples/SignatureRequestSendWithTemplateExample.py @@ -16,6 +16,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestTemplateSigner( diff --git a/examples/SignatureRequestSendWithTemplateExample.rb b/examples/SignatureRequestSendWithTemplateExample.rb index 4ee78fded..237c12fe5 100644 --- a/examples/SignatureRequestSendWithTemplateExample.rb +++ b/examples/SignatureRequestSendWithTemplateExample.rb @@ -12,6 +12,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestTemplateSigner.new signers_1.role = "Client" diff --git a/examples/SignatureRequestSendWithTemplateExample.sh b/examples/SignatureRequestSendWithTemplateExample.sh index 520089167..e59ee1b24 100644 --- a/examples/SignatureRequestSendWithTemplateExample.sh +++ b/examples/SignatureRequestSendWithTemplateExample.sh @@ -18,4 +18,5 @@ curl -X POST 'https://api.hellosign.com/v3/signature_request/send_with_template' -F 'signing_options[upload]=1' \ -F 'signing_options[phone]=1' \ -F 'signing_options[default_type]=draw' \ + -F 'signing_options[force_advanced_signature_details]=0' \ -F 'test_mode=1' diff --git a/examples/SignatureRequestSendWithTemplateExample.ts b/examples/SignatureRequestSendWithTemplateExample.ts index 88219107a..d327aec9b 100644 --- a/examples/SignatureRequestSendWithTemplateExample.ts +++ b/examples/SignatureRequestSendWithTemplateExample.ts @@ -12,6 +12,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestTemplateSigner = { diff --git a/examples/TemplateUpdateExample.cs b/examples/TemplateUpdateExample.cs new file mode 100644 index 000000000..0fc66e5ed --- /dev/null +++ b/examples/TemplateUpdateExample.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +using Dropbox.Sign.Api; +using Dropbox.Sign.Client; +using Dropbox.Sign.Model; + +namespace Dropbox.SignSandbox; + +public class TemplateUpdateExample +{ + public static void Run() + { + var config = new Configuration(); + config.Username = "YOUR_API_KEY"; + // config.AccessToken = "YOUR_ACCESS_TOKEN"; + + var formFields1 = new SubUpdateFormField( + apiId: "uniqueIdHere_1", + name: "New name 1" + ); + + var formFields2 = new SubUpdateFormField( + apiId: "uniqueIdHere_2", + name: "New name 2" + ); + + var formFields = new List + { + formFields1, + formFields2, + }; + + var templateUpdateRequest = new TemplateUpdateRequest( + title: "Test Title", + subject: "Test Subject", + message: "Test Message", + ccRoles: [ + "CC Role 1", + "CC Role 2", + ], + formFields: formFields + ); + + try + { + var response = new TemplateApi(config).TemplateUpdate( + templateId: "f57db65d3f933b5316d398057a36176831451a35", + templateUpdateRequest: templateUpdateRequest + ); + + Console.WriteLine(response); + } + catch (ApiException e) + { + Console.WriteLine("Exception when calling TemplateApi#TemplateUpdate: " + e.Message); + Console.WriteLine("Status Code: " + e.ErrorCode); + Console.WriteLine(e.StackTrace); + } + } +} diff --git a/examples/TemplateUpdateExample.java b/examples/TemplateUpdateExample.java new file mode 100644 index 000000000..25c622553 --- /dev/null +++ b/examples/TemplateUpdateExample.java @@ -0,0 +1,65 @@ +package com.dropbox.sign_sandbox; + +import com.dropbox.sign.ApiException; +import com.dropbox.sign.Configuration; +import com.dropbox.sign.api.*; +import com.dropbox.sign.auth.*; +import com.dropbox.sign.JSON; +import com.dropbox.sign.model.*; + +import java.io.File; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class TemplateUpdateExample +{ + public static void main(String[] args) + { + var config = Configuration.getDefaultApiClient(); + ((HttpBasicAuth) config.getAuthentication("api_key")).setUsername("YOUR_API_KEY"); + // ((HttpBearerAuth) config.getAuthentication("oauth2")).setBearerToken("YOUR_ACCESS_TOKEN"); + + var formFields1 = new SubUpdateFormField(); + formFields1.apiId("uniqueIdHere_1"); + formFields1.name("New name 1"); + + var formFields2 = new SubUpdateFormField(); + formFields2.apiId("uniqueIdHere_2"); + formFields2.name("New name 2"); + + var formFields = new ArrayList(List.of ( + formFields1, + formFields2 + )); + + var templateUpdateRequest = new TemplateUpdateRequest(); + templateUpdateRequest.title("Test Title"); + templateUpdateRequest.subject("Test Subject"); + templateUpdateRequest.message("Test Message"); + templateUpdateRequest.ccRoles(List.of ( + "CC Role 1", + "CC Role 2" + )); + templateUpdateRequest.formFields(formFields); + + try + { + var response = new TemplateApi(config).templateUpdate( + "f57db65d3f933b5316d398057a36176831451a35", // templateId + templateUpdateRequest + ); + + System.out.println(response); + } catch (ApiException e) { + System.err.println("Exception when calling TemplateApi#templateUpdate"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} diff --git a/examples/TemplateUpdateExample.php b/examples/TemplateUpdateExample.php new file mode 100644 index 000000000..c827bc301 --- /dev/null +++ b/examples/TemplateUpdateExample.php @@ -0,0 +1,46 @@ +setUsername("YOUR_API_KEY"); +// $config->setAccessToken("YOUR_ACCESS_TOKEN"); + +$form_fields_1 = (new Dropbox\Sign\Model\SubUpdateFormField()) + ->setApiId("uniqueIdHere_1") + ->setName("New name 1"); + +$form_fields_2 = (new Dropbox\Sign\Model\SubUpdateFormField()) + ->setApiId("uniqueIdHere_2") + ->setName("New name 2"); + +$form_fields = [ + $form_fields_1, + $form_fields_2, +]; + +$template_update_request = (new Dropbox\Sign\Model\TemplateUpdateRequest()) + ->setTitle("Test Title") + ->setSubject("Test Subject") + ->setMessage("Test Message") + ->setCcRoles([ + "CC Role 1", + "CC Role 2", + ]) + ->setFormFields($form_fields); + +try { + $response = (new Dropbox\Sign\Api\TemplateApi(config: $config))->templateUpdate( + template_id: "f57db65d3f933b5316d398057a36176831451a35", + template_update_request: $template_update_request, + ); + + print_r($response); +} catch (Dropbox\Sign\ApiException $e) { + echo "Exception when calling TemplateApi#templateUpdate: {$e->getMessage()}"; +} diff --git a/examples/TemplateUpdateExample.py b/examples/TemplateUpdateExample.py new file mode 100644 index 000000000..39e767acb --- /dev/null +++ b/examples/TemplateUpdateExample.py @@ -0,0 +1,47 @@ +import json +from datetime import date, datetime +from pprint import pprint + +from dropbox_sign import ApiClient, ApiException, Configuration, api, models + +configuration = Configuration( + username="YOUR_API_KEY", + # access_token="YOUR_ACCESS_TOKEN", +) + +with ApiClient(configuration) as api_client: + form_fields_1 = models.SubUpdateFormField( + api_id="uniqueIdHere_1", + name="New name 1", + ) + + form_fields_2 = models.SubUpdateFormField( + api_id="uniqueIdHere_2", + name="New name 2", + ) + + form_fields = [ + form_fields_1, + form_fields_2, + ] + + template_update_request = models.TemplateUpdateRequest( + title="Test Title", + subject="Test Subject", + message="Test Message", + cc_roles=[ + "CC Role 1", + "CC Role 2", + ], + form_fields=form_fields, + ) + + try: + response = api.TemplateApi(api_client).template_update( + template_id="f57db65d3f933b5316d398057a36176831451a35", + template_update_request=template_update_request, + ) + + pprint(response) + except ApiException as e: + print("Exception when calling TemplateApi#template_update: %s\n" % e) diff --git a/examples/TemplateUpdateExample.rb b/examples/TemplateUpdateExample.rb new file mode 100644 index 000000000..e0332ea8f --- /dev/null +++ b/examples/TemplateUpdateExample.rb @@ -0,0 +1,41 @@ +require "json" +require "dropbox-sign" + +Dropbox::Sign.configure do |config| + config.username = "YOUR_API_KEY" + # config.access_token = "YOUR_ACCESS_TOKEN" +end + +form_fields_1 = Dropbox::Sign::SubUpdateFormField.new +form_fields_1.api_id = "uniqueIdHere_1" +form_fields_1.name = "New name 1" + +form_fields_2 = Dropbox::Sign::SubUpdateFormField.new +form_fields_2.api_id = "uniqueIdHere_2" +form_fields_2.name = "New name 2" + +form_fields = [ + form_fields_1, + form_fields_2, +] + +template_update_request = Dropbox::Sign::TemplateUpdateRequest.new +template_update_request.title = "Test Title" +template_update_request.subject = "Test Subject" +template_update_request.message = "Test Message" +template_update_request.cc_roles = [ + "CC Role 1", + "CC Role 2", +] +template_update_request.form_fields = form_fields + +begin + response = Dropbox::Sign::TemplateApi.new.template_update( + "f57db65d3f933b5316d398057a36176831451a35", # template_id + template_update_request, + ) + + p response +rescue Dropbox::Sign::ApiError => e + puts "Exception when calling TemplateApi#template_update: #{e}" +end diff --git a/examples/TemplateUpdateExample.ts b/examples/TemplateUpdateExample.ts new file mode 100644 index 000000000..92c8d4566 --- /dev/null +++ b/examples/TemplateUpdateExample.ts @@ -0,0 +1,43 @@ +import * as fs from 'fs'; +import api from "@dropbox/sign" +import models from "@dropbox/sign" + +const apiCaller = new api.TemplateApi(); +apiCaller.username = "YOUR_API_KEY"; +// apiCaller.accessToken = "YOUR_ACCESS_TOKEN"; + +const formFields1: models.SubUpdateFormField = { + apiId: "uniqueIdHere_1", + name: "New name 1", +}; + +const formFields2: models.SubUpdateFormField = { + apiId: "uniqueIdHere_2", + name: "New name 2", +}; + +const formFields = [ + formFields1, + formFields2, +]; + +const templateUpdateRequest: models.TemplateUpdateRequest = { + title: "Test Title", + subject: "Test Subject", + message: "Test Message", + ccRoles: [ + "CC Role 1", + "CC Role 2", + ], + formFields: formFields, +}; + +apiCaller.templateUpdate( + "f57db65d3f933b5316d398057a36176831451a35", // templateId + templateUpdateRequest, +).then(response => { + console.log(response.body); +}).catch(error => { + console.log("Exception when calling TemplateApi#templateUpdate:"); + console.log(error.body); +}); diff --git a/examples/json/SignatureRequestCreateEmbeddedRequest.json b/examples/json/SignatureRequestCreateEmbeddedRequest.json index 724db5940..1fd4aa543 100644 --- a/examples/json/SignatureRequestCreateEmbeddedRequest.json +++ b/examples/json/SignatureRequestCreateEmbeddedRequest.json @@ -27,7 +27,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "test_mode": true } diff --git a/examples/json/SignatureRequestCreateEmbeddedWithTemplateRequest.json b/examples/json/SignatureRequestCreateEmbeddedWithTemplateRequest.json index 742998123..079d37786 100644 --- a/examples/json/SignatureRequestCreateEmbeddedWithTemplateRequest.json +++ b/examples/json/SignatureRequestCreateEmbeddedWithTemplateRequest.json @@ -17,7 +17,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "test_mode": true } diff --git a/examples/json/SignatureRequestSendRequest.json b/examples/json/SignatureRequestSendRequest.json index adfda81ec..96d61af2f 100644 --- a/examples/json/SignatureRequestSendRequest.json +++ b/examples/json/SignatureRequestSendRequest.json @@ -30,7 +30,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "field_options": { "date_format": "DD - MM - YYYY" diff --git a/examples/json/SignatureRequestSendWithTemplateRequest.json b/examples/json/SignatureRequestSendWithTemplateRequest.json index a79d1c35b..5ee34fe05 100644 --- a/examples/json/SignatureRequestSendWithTemplateRequest.json +++ b/examples/json/SignatureRequestSendWithTemplateRequest.json @@ -30,7 +30,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "test_mode": true } diff --git a/examples/json/TemplateUpdateRequest.json b/examples/json/TemplateUpdateRequest.json new file mode 100644 index 000000000..4dab19474 --- /dev/null +++ b/examples/json/TemplateUpdateRequest.json @@ -0,0 +1,16 @@ +{ + "title": "Test Title", + "subject": "Test Subject", + "message": "Test Message", + "cc_roles": ["CC Role 1", "CC Role 2"], + "form_fields": [ + { + "api_id": "uniqueIdHere_1", + "name": "New name 1" + }, + { + "api_id": "uniqueIdHere_2", + "name": "New name 2" + } + ] +} diff --git a/openapi-raw.yaml b/openapi-raw.yaml index 629c7a0ac..14ccac22a 100644 --- a/openapi-raw.yaml +++ b/openapi-raw.yaml @@ -65,6 +65,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -167,6 +169,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -263,6 +267,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 409_example: $ref: '#/components/examples/Error409Response' 4XX_example: @@ -363,6 +369,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -462,6 +470,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -560,10 +570,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -671,10 +681,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -763,6 +773,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -867,6 +879,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -977,6 +991,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1080,6 +1096,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1186,6 +1204,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -1284,12 +1304,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1386,10 +1406,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1475,10 +1495,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1570,12 +1590,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1669,6 +1689,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -1852,6 +1874,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1945,6 +1969,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2040,6 +2066,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2129,6 +2157,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2245,6 +2275,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2338,6 +2370,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2444,6 +2478,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2540,10 +2576,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2637,6 +2673,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: [] @@ -2732,6 +2770,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: [] @@ -2827,6 +2867,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2923,12 +2965,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3025,6 +3067,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -3119,6 +3163,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -3227,10 +3273,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3330,10 +3376,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3444,12 +3490,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3561,12 +3607,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3675,12 +3721,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3789,12 +3835,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3904,14 +3950,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4009,14 +4055,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4121,14 +4167,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4226,6 +4272,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 410_example: @@ -4346,6 +4394,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 409_example: $ref: '#/components/examples/Error409Response' 4XX_example: @@ -4445,6 +4495,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -4552,14 +4604,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4652,6 +4704,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -4756,10 +4810,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4968,6 +5022,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5077,6 +5133,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5175,6 +5233,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5255,6 +5315,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5342,6 +5404,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5439,6 +5503,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5535,10 +5601,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5634,6 +5700,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5747,10 +5815,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5849,6 +5917,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5963,10 +6033,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6072,6 +6142,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -6179,6 +6251,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6288,6 +6362,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6383,6 +6459,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6494,14 +6572,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6598,14 +6676,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6709,14 +6787,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6813,10 +6891,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6933,10 +7011,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7042,6 +7120,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -7092,6 +7172,123 @@ paths: seo: title: '_t__TemplateRemoveUser::SEO::TITLE' description: '_t__TemplateRemoveUser::SEO::DESCRIPTION' + '/template/update/{template_id}': + post: + tags: + - Template + summary: '_t__TemplateUpdate::SUMMARY' + description: '_t__TemplateUpdate::DESCRIPTION' + operationId: templateUpdate + parameters: + - + name: template_id + in: path + description: '_t__TemplateUpdate::TEMPLATE_ID' + required: true + schema: + type: string + example: f57db65d3f933b5316d398057a36176831451a35 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TemplateUpdateRequest' + examples: + example: + $ref: '#/components/examples/TemplateUpdateRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/TemplateUpdateRequest' + responses: + '200': + description: 'successful operation' + headers: + X-RateLimit-Limit: + $ref: '#/components/headers/X-RateLimit-Limit' + X-RateLimit-Remaining: + $ref: '#/components/headers/X-RateLimit-Remaining' + X-Ratelimit-Reset: + $ref: '#/components/headers/X-Ratelimit-Reset' + content: + application/json: + schema: + $ref: '#/components/schemas/TemplateGetResponse' + examples: + example: + $ref: '#/components/examples/TemplateGetResponse' + 4XX: + description: failed_operation + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + 400_example: + $ref: '#/components/examples/Error400Response' + 401_example: + $ref: '#/components/examples/Error401Response' + 402_example: + $ref: '#/components/examples/Error402Response' + 403_example: + $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' + 409_example: + $ref: '#/components/examples/Error409Response' + 4XX_example: + $ref: '#/components/examples/Error4XXResponse' + security: + - + api_key: [] + - + oauth2: + - template_access + x-codeSamples: + - + lang: PHP + label: PHP + source: + $ref: examples/TemplateUpdateExample.php + - + lang: 'C#' + label: 'C#' + source: + $ref: examples/TemplateUpdateExample.cs + - + lang: TypeScript + label: TypeScript + source: + $ref: examples/TemplateUpdateExample.ts + - + lang: Java + label: Java + source: + $ref: examples/TemplateUpdateExample.java + - + lang: Ruby + label: Ruby + source: + $ref: examples/TemplateUpdateExample.rb + - + lang: Python + label: Python + source: + $ref: examples/TemplateUpdateExample.py + - + lang: cURL + label: cURL + source: + $ref: examples/TemplateUpdateExample.sh + x-meta: + seo: + title: '_t__TemplateUpdate::SEO::TITLE' + description: '_t__TemplateUpdate::SEO::DESCRIPTION' + x-hideOn: + - doc + - sdk '/template/update_files/{template_id}': post: tags: @@ -7152,12 +7349,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7263,6 +7460,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7368,6 +7567,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -7472,12 +7673,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7583,6 +7784,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -7776,6 +7979,14 @@ components: description: '_t__EmbeddedEditUrl::TEST_MODE' type: boolean default: false + signer_experience: + description: '_t__EmbeddedEditUrl::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object FaxLineAddUserRequest: required: @@ -8022,6 +8233,7 @@ components: - user_activity - document_status - sms_activity + - fax_usage maxItems: 2 minItems: 1 start_date: @@ -8253,6 +8465,14 @@ components: description: '_t__SignatureRequestCreateEmbedded::POPULATE_AUTO_FILL_FIELDS' type: boolean default: false + signer_experience: + description: '_t__SignatureRequestCreateEmbedded::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc expires_at: description: '_t__SignatureRequestCreateEmbedded::EXPIRES_AT' type: integer @@ -8329,6 +8549,14 @@ components: description: '_t__SignatureRequestCreateEmbeddedWithTemplate::POPULATE_AUTO_FILL_FIELDS' type: boolean default: false + signer_experience: + description: '_t__SignatureRequestCreateEmbeddedWithTemplate::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object SignatureRequestEditRequest: properties: @@ -8439,6 +8667,14 @@ components: description: '_t__SignatureRequestSend::EXPIRES_AT' type: integer nullable: true + signer_experience: + description: '_t__SignatureRequestSend::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object SignatureRequestEditEmbeddedRequest: required: @@ -8548,6 +8784,14 @@ components: description: '_t__SignatureRequestCreateEmbedded::EXPIRES_AT' type: integer nullable: true + signer_experience: + description: '_t__SignatureRequestCreateEmbedded::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object SignatureRequestEditEmbeddedWithTemplateRequest: required: @@ -8620,6 +8864,14 @@ components: description: '_t__SignatureRequestCreateEmbeddedWithTemplate::POPULATE_AUTO_FILL_FIELDS' type: boolean default: false + signer_experience: + description: '_t__SignatureRequestCreateEmbeddedWithTemplate::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object SignatureRequestEditWithTemplateRequest: description: '' @@ -8695,6 +8947,14 @@ components: description: '_t__SignatureRequestSendWithTemplate::TITLE' type: string maxLength: 255 + signer_experience: + description: '_t__SignatureRequestSendWithTemplate::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object SignatureRequestRemindRequest: required: @@ -8823,6 +9083,14 @@ components: description: '_t__SignatureRequestSend::EXPIRES_AT' type: integer nullable: true + signer_experience: + description: '_t__SignatureRequestSend::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object SignatureRequestSendWithTemplateRequest: description: '' @@ -8904,6 +9172,14 @@ components: description: '_t__SignatureRequestSendWithTemplate::TITLE' type: string maxLength: 255 + signer_experience: + description: '_t__SignatureRequestSendWithTemplate::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object SignatureRequestUpdateRequest: required: @@ -9246,6 +9522,17 @@ components: type: integer default: 12 type: object + SubUpdateFormField: + required: + - api_id + properties: + api_id: + description: '_t__Sub::UpdateFormField::API_ID' + type: string + name: + description: '_t__Sub::UpdateFormField::NAME' + type: string + type: object SubFormFieldsPerDocumentHyperlink: description: '_t__Sub::FormFieldsPerDocument::DESCRIPTION_EXTENDS' allOf: @@ -9708,6 +9995,24 @@ components: type: string format: email type: object + SubSignerExperience: + description: '_t__Sub::SignerExperience::DESCRIPTION' + properties: + form_view: + description: '_t__Sub::SignerExperience::DEFAULT' + type: string + enum: + - disabled + - enabled + - enabled_by_default + - forced + x-hideOn: + - sdk + - doc + type: object + x-hideOn: + - sdk + - doc SubTemplateRole: properties: name: @@ -9747,6 +10052,10 @@ components: description: '_t__Sub::SigningOptions::UPLOAD' type: boolean default: false + force_advanced_signature_details: + description: '_t__Sub::SigningOptions::FORCE_ADVANCED_SIGNATURE_DETAILS' + type: boolean + default: false type: object SubWhiteLabelingOptions: description: '_t__Sub::WhiteLabelingOptions::DESCRIPTION' @@ -9954,6 +10263,14 @@ components: description: '_t__TemplateCreate::USE_PREEXISTING_FIELDS' type: boolean default: false + signer_experience: + description: '_t__TemplateCreate::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object TemplateCreateEmbeddedDraftRequest: required: @@ -10064,6 +10381,14 @@ components: description: '_t__TemplateCreateEmbeddedDraft::USE_PREEXISTING_FIELDS' type: boolean default: false + signer_experience: + description: '_t__TemplateCreateEmbeddedDraft::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object TemplateRemoveUserRequest: properties: @@ -10075,6 +10400,41 @@ components: type: string format: email type: object + TemplateUpdateRequest: + properties: + cc_roles: + description: '_t__TemplateUpdate::CC_ROLES' + type: array + items: + type: string + title: + description: '_t__TemplateUpdate::TITLE' + type: string + subject: + description: '_t__TemplateUpdate::SUBJECT' + type: string + maxLength: 200 + message: + description: '_t__TemplateUpdate::MESSAGE' + type: string + maxLength: 5000 + form_fields: + description: '_t__TemplateUpdate::FORM_FIELDS' + type: array + items: + $ref: '#/components/schemas/SubUpdateFormField' + signer_experience: + description: '_t__TemplateCreateEmbeddedDraft::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc + type: object + x-hideOn: + - sdk + - doc TemplateUpdateFilesRequest: properties: client_id: @@ -10213,6 +10573,14 @@ components: description: '_t__UnclaimedDraftCreate::EXPIRES_AT' type: integer nullable: true + signer_experience: + description: '_t__UnclaimedDraftCreate::SIGNER_EXPERIENCE' + allOf: + - + $ref: '#/components/schemas/SubSignerExperience' + x-hideOn: + - sdk + - doc type: object UnclaimedDraftCreateEmbeddedRequest: description: '' @@ -10850,6 +11218,8 @@ components: nullable: true usage: $ref: '#/components/schemas/AccountResponseUsage' + settings: + $ref: '#/components/schemas/AccountResponseSettings' type: object x-internal-class: true OAuthTokenResponse: @@ -10897,6 +11267,20 @@ components: nullable: true type: object x-internal-class: true + AccountResponseSettings: + description: '_t__Account::SETTINGS' + properties: + signer_access_codes: + description: '_t__AccountSettings::SIGNER_ACCESS_CODES' + type: boolean + sms_delivery: + description: '_t__AccountSettings::SMS_DELIVERY' + type: boolean + sms_authentication: + description: '_t__AccountSettings::SMS_AUTHENTICATION' + type: boolean + type: object + x-internal-class: true AccountResponseUsage: description: '_t__Account::USAGE' properties: @@ -11226,6 +11610,7 @@ components: - user_activity - document_status - sms_activity + - fax_usage type: object x-internal-class: true SignatureRequestResponse: @@ -11332,6 +11717,14 @@ components: description: '_t__SignatureRequestResponse::BULK_SEND_JOB_ID' type: string nullable: true + signer_experience: + description: '_t__SignatureRequestSignerExperience::DESCRIPTION' + allOf: + - + $ref: '#/components/schemas/SignatureRequestSignerExperience' + x-hideOn: + - sdk + - doc type: object x-internal-class: true SignatureRequestResponseAttachment: @@ -11689,6 +12082,25 @@ components: nullable: true type: object x-internal-class: true + SignatureRequestSignerExperience: + description: '_t__SignatureRequestSignerExperience::DESCRIPTION' + required: + - form_view + properties: + form_view: + description: '_t__Sub::SignerExperience::DEFAULT' + type: string + enum: + - disabled + - enabled + - enabled_by_default + - forced + x-hideOn: + - sdk + - doc + type: object + x-internal-class: true + x-hideOn: sdk TeamResponse: description: '_t__TeamResponse::DESCRIPTION' properties: @@ -11857,6 +12269,14 @@ components: type: array items: $ref: '#/components/schemas/SignatureRequestResponseAttachment' + signer_experience: + description: '_t__SignatureRequestSignerExperience::DESCRIPTION' + allOf: + - + $ref: '#/components/schemas/SignatureRequestSignerExperience' + x-hideOn: + - sdk + - doc type: object x-internal-class: true TemplateResponseAccount: @@ -12641,14 +13061,6 @@ components: $ref: '#/components/schemas/WarningResponse' type: object x-internal-class: true - TemplateEditResponse: - required: - - template_id - properties: - template_id: - description: '_t__TemplateResponse::TEMPLATE_ID' - type: string - type: object TemplateGetResponse: required: - template @@ -12976,6 +13388,13 @@ components: summary: 'Default Example' value: $ref: examples/json/TemplateRemoveUserRequest.json + TemplateUpdateRequest: + summary: 'Default Example' + value: + $ref: examples/json/TemplateUpdateRequest.json + x-hideOn: + - sdk + - doc TemplateUpdateFilesRequest: summary: 'Default Example' value: diff --git a/openapi-sdk.yaml b/openapi-sdk.yaml index c123c2eec..f2497b6e8 100644 --- a/openapi-sdk.yaml +++ b/openapi-sdk.yaml @@ -65,6 +65,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -173,6 +175,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -269,6 +273,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 409_example: $ref: '#/components/examples/Error409Response' 4XX_example: @@ -369,6 +375,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -468,6 +476,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -566,10 +576,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -677,10 +687,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -769,6 +779,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -873,6 +885,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -983,6 +997,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1086,6 +1102,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1192,6 +1210,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -1290,12 +1310,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1392,10 +1412,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1481,10 +1501,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1576,12 +1596,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1675,6 +1695,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -1858,6 +1880,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1951,6 +1975,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2046,6 +2072,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2135,6 +2163,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2251,6 +2281,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2344,6 +2376,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2450,6 +2484,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2546,10 +2582,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2643,6 +2679,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: [] @@ -2738,6 +2776,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: [] @@ -2836,6 +2876,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2935,12 +2977,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3040,6 +3082,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -3143,6 +3187,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -3251,10 +3297,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3354,10 +3400,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3471,12 +3517,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3591,12 +3637,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3708,12 +3754,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3825,12 +3871,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3943,14 +3989,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4051,14 +4097,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4166,14 +4212,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4271,6 +4317,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 410_example: @@ -4394,6 +4442,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 409_example: $ref: '#/components/examples/Error409Response' 4XX_example: @@ -4493,6 +4543,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -4603,14 +4655,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4708,6 +4760,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -4812,10 +4866,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5029,6 +5083,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5138,6 +5194,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5236,6 +5294,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5316,6 +5376,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5403,6 +5465,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5500,6 +5564,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5596,10 +5662,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5695,6 +5761,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5808,10 +5876,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5910,6 +5978,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -6024,10 +6094,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6133,6 +6203,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -6188,7 +6260,12 @@ paths: tags: - Template summary: 'Create Template' - description: 'Creates a template that can then be used.' + description: |- + Creates a template that can be used in future signature requests. + + If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). + + Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. operationId: templateCreate requestBody: required: true @@ -6240,6 +6317,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6349,6 +6428,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6444,6 +6525,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6558,14 +6641,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6665,14 +6748,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6779,14 +6862,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6883,10 +6966,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7006,10 +7089,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7115,6 +7198,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -7237,12 +7322,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7348,6 +7433,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7456,6 +7543,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -7563,12 +7652,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7677,6 +7766,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -8136,6 +8227,7 @@ components: - user_activity - document_status - sms_activity + - fax_usage maxItems: 2 minItems: 1 start_date: @@ -8670,7 +8762,7 @@ components: Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -8997,7 +9089,7 @@ components: Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -9165,13 +9257,12 @@ components: type: boolean default: false deprecated: true - x-hideOn: doc is_eid: description: |- Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -9267,13 +9358,12 @@ components: type: boolean default: false deprecated: true - x-hideOn: doc is_eid: description: |- Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -9734,6 +9824,17 @@ components: type: integer default: 12 type: object + SubUpdateFormField: + required: + - api_id + properties: + api_id: + description: 'The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found' + type: string + name: + description: 'The new name of the field. If not passed the name will remain unchanged.' + type: string + type: object SubFormFieldsPerDocumentHyperlink: description: 'This class extends `SubFormFieldsPerDocumentBase`.' allOf: @@ -10266,9 +10367,11 @@ components: type: object SubSigningOptions: description: |- - This allows the requester to specify the types allowed for creating a signature. + This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + + **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. required: - default_type properties: @@ -10296,6 +10399,10 @@ components: description: 'Allows uploading the signature' type: boolean default: false + force_advanced_signature_details: + description: 'Turning on advanced signature details for the signature request' + type: boolean + default: false type: object SubWhiteLabelingOptions: description: |- @@ -11590,6 +11697,8 @@ components: nullable: true usage: $ref: '#/components/schemas/AccountResponseUsage' + settings: + $ref: '#/components/schemas/AccountResponseSettings' type: object x-internal-class: true OAuthTokenResponse: @@ -11637,6 +11746,20 @@ components: nullable: true type: object x-internal-class: true + AccountResponseSettings: + description: 'Subset of configured settings' + properties: + signer_access_codes: + description: 'Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).' + type: boolean + sms_delivery: + description: 'Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).' + type: boolean + sms_authentication: + description: 'Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).' + type: boolean + type: object + x-internal-class: true AccountResponseUsage: description: 'Details concerning monthly usage' properties: @@ -11966,6 +12089,7 @@ components: - user_activity - document_status - sms_activity + - fax_usage type: object x-internal-class: true SignatureRequestResponse: @@ -13565,14 +13689,6 @@ components: $ref: '#/components/schemas/WarningResponse' type: object x-internal-class: true - TemplateEditResponse: - required: - - template_id - properties: - template_id: - description: 'The id of the Template.' - type: string - type: object TemplateGetResponse: required: - template diff --git a/openapi.yaml b/openapi.yaml index 4d4ae426d..f75975178 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -65,6 +65,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -173,6 +175,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -269,6 +273,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 409_example: $ref: '#/components/examples/Error409Response' 4XX_example: @@ -369,6 +375,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -468,6 +476,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -566,10 +576,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -677,10 +687,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -769,6 +779,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -873,6 +885,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -983,6 +997,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1086,6 +1102,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1192,6 +1210,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -1290,12 +1310,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1392,10 +1412,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1481,10 +1501,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1576,12 +1596,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1675,6 +1695,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -1858,6 +1880,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -1951,6 +1975,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2046,6 +2072,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2135,6 +2163,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2251,6 +2281,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2344,6 +2376,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -2450,6 +2484,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2546,10 +2582,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2643,6 +2679,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: [] @@ -2738,6 +2776,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: [] @@ -2836,6 +2876,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -2935,12 +2977,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3040,6 +3082,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -3143,6 +3187,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -3251,10 +3297,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3354,10 +3400,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3471,12 +3517,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3591,12 +3637,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3708,12 +3754,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3825,12 +3871,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -3943,14 +3989,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4051,14 +4097,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4166,14 +4212,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4271,6 +4317,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 410_example: @@ -4394,6 +4442,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 409_example: $ref: '#/components/examples/Error409Response' 4XX_example: @@ -4493,6 +4543,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -4603,14 +4655,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 410_example: $ref: '#/components/examples/Error410Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -4708,6 +4760,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -4812,10 +4866,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5029,6 +5083,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5138,6 +5194,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5236,6 +5294,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5316,6 +5376,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5403,6 +5465,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -5500,6 +5564,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5596,10 +5662,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5695,6 +5761,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5808,10 +5876,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -5910,6 +5978,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -6024,10 +6094,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6133,6 +6203,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -6188,7 +6260,12 @@ paths: tags: - Template summary: 'Create Template' - description: 'Creates a template that can then be used.' + description: |- + Creates a template that can be used in future signature requests. + + If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). + + Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. operationId: templateCreate requestBody: required: true @@ -6240,6 +6317,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6349,6 +6428,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6444,6 +6525,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -6558,14 +6641,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6665,14 +6748,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6779,14 +6862,14 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' 422_example: $ref: '#/components/examples/Error422Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -6883,10 +6966,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 404_example: - $ref: '#/components/examples/Error404Response' 429_example: $ref: '#/components/examples/Error429Response' + 404_example: + $ref: '#/components/examples/Error404Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7006,10 +7089,10 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' - 409_example: - $ref: '#/components/examples/Error409Response' 429_example: $ref: '#/components/examples/Error429Response' + 409_example: + $ref: '#/components/examples/Error409Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7115,6 +7198,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 4XX_example: @@ -7237,12 +7322,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7348,6 +7433,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7456,6 +7543,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -7563,12 +7652,12 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: $ref: '#/components/examples/Error409Response' - 429_example: - $ref: '#/components/examples/Error429Response' 4XX_example: $ref: '#/components/examples/Error4XXResponse' security: @@ -7677,6 +7766,8 @@ paths: $ref: '#/components/examples/Error402Response' 403_example: $ref: '#/components/examples/Error403Response' + 429_example: + $ref: '#/components/examples/Error429Response' 404_example: $ref: '#/components/examples/Error404Response' 409_example: @@ -8136,6 +8227,7 @@ components: - user_activity - document_status - sms_activity + - fax_usage maxItems: 2 minItems: 1 start_date: @@ -8670,7 +8762,7 @@ components: Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -8997,7 +9089,7 @@ components: Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -9160,7 +9252,7 @@ components: Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -9251,7 +9343,7 @@ components: Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. type: boolean default: false message: @@ -9712,6 +9804,17 @@ components: type: integer default: 12 type: object + SubUpdateFormField: + required: + - api_id + properties: + api_id: + description: 'The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found' + type: string + name: + description: 'The new name of the field. If not passed the name will remain unchanged.' + type: string + type: object SubFormFieldsPerDocumentHyperlink: description: 'This class extends `SubFormFieldsPerDocumentBase`.' allOf: @@ -10244,9 +10347,11 @@ components: type: object SubSigningOptions: description: |- - This allows the requester to specify the types allowed for creating a signature. + This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + + **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. required: - default_type properties: @@ -10274,6 +10379,10 @@ components: description: 'Allows uploading the signature' type: boolean default: false + force_advanced_signature_details: + description: 'Turning on advanced signature details for the signature request' + type: boolean + default: false type: object SubWhiteLabelingOptions: description: |- @@ -11568,6 +11677,8 @@ components: nullable: true usage: $ref: '#/components/schemas/AccountResponseUsage' + settings: + $ref: '#/components/schemas/AccountResponseSettings' type: object x-internal-class: true OAuthTokenResponse: @@ -11615,6 +11726,20 @@ components: nullable: true type: object x-internal-class: true + AccountResponseSettings: + description: 'Subset of configured settings' + properties: + signer_access_codes: + description: 'Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).' + type: boolean + sms_delivery: + description: 'Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).' + type: boolean + sms_authentication: + description: 'Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).' + type: boolean + type: object + x-internal-class: true AccountResponseUsage: description: 'Details concerning monthly usage' properties: @@ -11944,6 +12069,7 @@ components: - user_activity - document_status - sms_activity + - fax_usage type: object x-internal-class: true SignatureRequestResponse: @@ -12415,6 +12541,12 @@ components: nullable: true type: object x-internal-class: true + SignatureRequestSignerExperience: + description: 'Configuration options for modifying the settings of the signer application. Supports changing the form view behavior.' + required: + - form_view + type: object + x-internal-class: true TeamResponse: description: 'Contains information about your team and its members' properties: @@ -13543,14 +13675,6 @@ components: $ref: '#/components/schemas/WarningResponse' type: object x-internal-class: true - TemplateEditResponse: - required: - - template_id - properties: - template_id: - description: 'The id of the Template.' - type: string - type: object TemplateGetResponse: required: - template diff --git a/oseg/.editorconfig b/oseg/.editorconfig new file mode 100644 index 000000000..9b037faf2 --- /dev/null +++ b/oseg/.editorconfig @@ -0,0 +1,5 @@ +[{*.yml,*.yaml,*.md}] +indent_style = space +indent_size = 2 +[*.py] +indent_size = 4 diff --git a/oseg/.gitignore b/oseg/.gitignore new file mode 100644 index 000000000..a47ac5fac --- /dev/null +++ b/oseg/.gitignore @@ -0,0 +1,65 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.venv/ +.python-version +.pytest_cache + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/oseg/Dockerfile b/oseg/Dockerfile new file mode 100644 index 000000000..8349e9701 --- /dev/null +++ b/oseg/Dockerfile @@ -0,0 +1,36 @@ +FROM ghcr.io/astral-sh/uv:python3.13-alpine +LABEL maintainer="Dropbox Sign " + +# Install the project into `/app` +WORKDIR /app + +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 + +# Copy from the cache instead of linking since it's a mounted volume +ENV UV_LINK_MODE=copy + +# Install the project's dependencies using the lockfile and settings +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --no-dev + +# Then, add the rest of the project source code and install it +# Installing separately from its dependencies allows optimal layer caching +ADD ./pyproject.toml /app/pyproject.toml +ADD ./uv.lock /app/uv.lock +ADD ./oseg /app/oseg +ADD ./static /app/static +ADD ./LICENSE /app/LICENSE +ADD ./README.md /app/README.md +ADD ./run.py /app/run.py + +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + +# Place executables in the environment at the front of the path +ENV PATH="/app/.venv/bin:$PATH" + +# Reset the entrypoint, don't invoke `uv` +ENTRYPOINT ["python", "/app/run.py"] diff --git a/oseg/README.md b/oseg/README.md new file mode 100644 index 000000000..707bbdfd3 --- /dev/null +++ b/oseg/README.md @@ -0,0 +1,69 @@ +# OSEG - OpenAPI SDK Example Generator + +Create (almost) ready to use SDK snippets for SDKs generated using [openapi-generator](https://openapi-generator.tech/) using example data from your OpenAPI spec. + +## Where does the example data come from? + +Example data used to generate the code snippets can come from a number of places: + +* example or examples values in schema +* default values in schema +* Externally referenced JSON files defined in schema +* You can also create a JSON file with examples for all the endpoints you want + +OSEG currently generates one code snippet file per `requestBody` definition, but only a single example per `parameters` definition. + +In other words, you can generate multiple examples of the same operation/endpoint by having multiple `requestBody` definitions. Each generate example will have different data embedded within it. However, since `parameters` is tied to a single operation, the same data will apply to any and all `requestBody` definitions. + +If you use a custom JSON file with examples you can define as many examples per endpoint as you want, since you can define each data source separately (`query`, `path`, `header`, `cookie`, and `body`) per endpoint. + +## How to run + +The entrypoint to this project is `run.py`. It currently supports two commands: + +### config-help + +Prints all config options available to a given generator. + +Run `python3 run.py config-help --help` for more details. + +Show config options for the `python` generator: + +```bash +python3 run.py config-help -g python +``` + +## Tests + +See [tests directory](tests). + +## Feature support + +The aim of this project is to cover the most common use-cases in an OpenAPI spec. + +### Supported + +* Requests with and without formdata: `openapi-generator` will create a different interface if an endpoint's `content-type` has formdata (`multipart/form-data` or `application/x-www-form-urlencoded`) and everything else +* Discriminators with `allOf` + +### Issues + +The following are issues with the SDK code generated by `openapi-generator`. + +* `allOf` without a discriminator: Depending on the `openapi-generator` generator used, the generated SDK may be completely broken + * `typescript-node` SDK code is generated broken by `openapi-generator` + * Other SDKs currently supported by OSEG will usually just use a generic `object` type +* `anyOf` + * `typescript-node` generated SDK does not set data + * `php` generated SDK does not set data + * Other SDKs currently supported by OSEG generate a class +* `oneOf` + * `typescript-node` generated SDK does not set data + * `php` generated SDK does not set data + * Other SDKs currently supported by OSEG generate a class +* Multiple values in `type` definition. New in OpenAPI 3.1 `type` can now be an array of supported types + * `c#`, `java`, `ruby` Generate a class + * `python` generates a class but does not use it, types property as the first value in `type` + * `php` generates a class, data not set + * `typescript-node` generates a class, data not set +* `openapi-generator` generates a class for inline schema with `type=object`. If two or more Operations share identical inline schema definitions, `openapi-generator` will only generate a class for one of the Operations, and all Operations will reference this class. The name of the class depends on which Operation is read first by `openapi-generator`, but it may not reflect the first definition within the OAS file and thus is impossible for OSEG to know the name of the class ahead of time. diff --git a/oseg/bin/build b/oseg/bin/build new file mode 100755 index 000000000..265922fcc --- /dev/null +++ b/oseg/bin/build @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +DIR=$(cd `dirname $0` && pwd) +BASE_DIR="${DIR}/.." + +pushd "${BASE_DIR}" +uv build +popd diff --git a/oseg/bin/code-cov b/oseg/bin/code-cov new file mode 100755 index 000000000..410c51a08 --- /dev/null +++ b/oseg/bin/code-cov @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -e + +DIR=$(cd `dirname $0` && pwd) +BASE_DIR="${DIR}/.." + +pushd "${BASE_DIR}" +uv run coverage run -m unittest discover -s tests +uv run coverage html --omit=tests/* +popd diff --git a/oseg/bin/docker-build b/oseg/bin/docker-build new file mode 100755 index 000000000..e9a8dd669 --- /dev/null +++ b/oseg/bin/docker-build @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -e + +DIR=$(cd `dirname $0` && pwd) +VERSION=$1 + +if [[ -z "${VERSION-}" ]]; then + echo "Must provide version" + exit 1 +fi + +pushd "${DIR}/.." + +docker image build \ + -f Dockerfile \ + -t dropbox/oseg:${VERSION} . + +popd diff --git a/oseg/oseg/__init__.py b/oseg/oseg/__init__.py new file mode 100644 index 000000000..8b2e088d3 --- /dev/null +++ b/oseg/oseg/__init__.py @@ -0,0 +1,16 @@ +import os + +# coding: utf-8 + +""" + oseg +""" + +__version__ = "0.3-dev" +__ROOT_DIR__ = os.path.dirname(os.path.abspath(__file__)) + "/.." + +from .jinja_extension import * +from .generator import * +from .model import * +from .parser import * +from .oseg import * diff --git a/oseg/oseg/generator/__init__.py b/oseg/oseg/generator/__init__.py new file mode 100644 index 000000000..03b7b453d --- /dev/null +++ b/oseg/oseg/generator/__init__.py @@ -0,0 +1,18 @@ +from .base_generator import ( + BaseConfig, + BaseConfigDef, + BaseConfigOseg, + BaseGenerator, + GeneratorFactory, + Project, + ProjectTemplateFilesDef, + PropsOptionalT, +) +from .csharp_generator import CSharpGenerator +from .java_generator import JavaGenerator +from .kotlin_generator import KotlinGenerator +from .php_generator import PhpGenerator +from .python_generator import PythonGenerator +from .ruby_generator import RubyGenerator +from .typescript_axios_generator import TypescriptAxiosGenerator +from .typescript_node_generator import TypescriptNodeGenerator diff --git a/oseg/oseg/generator/base_generator.py b/oseg/oseg/generator/base_generator.py new file mode 100644 index 000000000..789fe45f6 --- /dev/null +++ b/oseg/oseg/generator/base_generator.py @@ -0,0 +1,305 @@ +from __future__ import annotations +import json +import os +import re +import openapi_pydantic as oa +from abc import abstractmethod +from dataclasses import dataclass +from typing import Protocol, TypedDict, Any, Type +from oseg import model, parser + + +class PropsOptionalT(TypedDict): + description: str + default: Any + + +class BaseConfigDef(TypedDict): + generatorName: str + additionalProperties: dict[str, any] + + +@dataclass +class BaseConfigOseg: + # Skip printing optional properties that do not have a value + ignoreOptionalUnset: bool + security: dict[str, str] + + +class BaseConfig(Protocol): + GENERATOR_NAME: str + PROPS_REQUIRED: dict[str, str] + PROPS_OPTIONAL: dict[str, PropsOptionalT] + + _config: dict[str, any] + oseg: BaseConfigOseg + + def __init__(self, config: dict[str, any]): + self._config = config + + @classmethod + def config_help(cls): + return { + "required": cls.PROPS_REQUIRED, + "optional": cls.PROPS_OPTIONAL, + } + + def _parse_security(self) -> dict[str, any]: + security = {} + + for name, values in self._config.items(): + if name.startswith("oseg.security."): + security[name.replace("oseg.security.", "")] = values + + return ( + security + if security + else self.PROPS_OPTIONAL["oseg.security"].get("default") + ) + + def _get_value(self, name: str) -> any: + return self._config.get(name, self.PROPS_OPTIONAL[name].get("default")) + + +@dataclass +class ProjectTemplateFilesDef: + source: str + target: str + values: dict[str, str] + + +class Project: + config: BaseConfig + + def __init__(self, config: BaseConfig, base_dir: str, output_dir: str): + self.config = config + self.base_dir: str = base_dir + self.output_dir: str = output_dir + + if not os.path.isdir(f"{base_dir}/{output_dir}"): + os.makedirs(f"{base_dir}/{output_dir}") + +class BaseGenerator(Protocol): + CONFIG_CLASS = BaseConfig + PROJECT_CLASS = Project + FILE_EXTENSION: str + NAME: str + TEMPLATE: str + X_ENUM_VARNAMES = "x-enum-varnames" + X_ENUM_VARNAMES_OVERRIDE = "x-enum-varnames-override" + + def __init__( + self, + config: BaseConfig, + operation: model.Operation, + property_container: model.PropertyContainer, + ): + self.config: BaseConfig = config + self.operation: model.Operation = operation + self.property_container: model.PropertyContainer = property_container + self.template_parser: parser.TemplateParser = parser.TemplateParser(self) + + @abstractmethod + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + raise NotImplementedError + + @abstractmethod + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + """Changes a variable name to not be in conflict with + generator's reserved keywords. + + Some generators like csharp have an additional set of reserved + keywords that are only enforced in Model classes. This set is + triggered with secondary=True. + """ + + raise NotImplementedError + + @abstractmethod + def print_apiname(self, name: str) -> str: + raise NotImplementedError + + @abstractmethod + def print_classname(self, name: str) -> str: + raise NotImplementedError + + @abstractmethod + def print_methodname(self, name: str) -> str: + raise NotImplementedError + + @abstractmethod + def print_propname(self, name: str) -> str: + raise NotImplementedError + + @abstractmethod + def print_variablename(self, name: str) -> str: + raise NotImplementedError + + @abstractmethod + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + raise NotImplementedError + + def print_file(self, item: model.PropertyFile) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(i) + + return printable + + if item.value is None: + return printable + + printable.value = item.value + + return printable + + def print_free_form(self, item: model.PropertyFreeForm) -> model.PrintableFreeForm: + printable = model.PrintableFreeForm() + printable.value = item.value + printable.is_array = item.is_array + printable.has_properties = item.has_properties + + return printable + + @abstractmethod + def print_null(self) -> str: + raise NotImplementedError + + def force_print_parameters(self) -> bool: + return False + + def has_named_parameters(self) -> bool: + """Checks if this generator language support named parameters""" + return False + + def _to_json(self, value: any) -> str: + return json.dumps(value, ensure_ascii=False) + + def _get_enum_varname( + self, + schema: oa.Schema, + value: any, + ) -> tuple[str | None, bool]: + if value is None: + return None, False + + target = ( + schema.items.enum + if parser.TypeChecker.is_array(schema) and schema.items + else schema.enum + ) + + if not target or value not in target: + return None, False + + index = target.index(value) + + overrides = schema.model_extra.get(self.X_ENUM_VARNAMES_OVERRIDE) + + if overrides: + enum_varnames: list[str] = overrides.get(self.NAME) + + if enum_varnames and len(enum_varnames) - 1 >= index: + return enum_varnames[index], True + + enum_varnames = schema.model_extra.get(self.X_ENUM_VARNAMES) + + if enum_varnames and len(enum_varnames) - 1 >= index: + return enum_varnames[index], False + + return None, False + + def _escape_dollar(self, value: str) -> str: + """If the value contains $ try to escape it""" + + value = self._to_json(value) + + if "$" not in value: + return value + + return re.sub(r"(? None: + cls.generators[gen.NAME] = gen + + @classmethod + def config_class(cls, name: str) -> Type[BaseConfig]: + return cls.generator_class(name).CONFIG_CLASS + + @classmethod + def config_factory(cls, config: dict | str) -> BaseConfig: + if isinstance(config, str): + data = parser.FileLoader.get_file_contents(config) + + if not len(data): + raise NotImplementedError(f"{config} contains invalid data") + + config = data + + additional_properties = config.get("additionalProperties", {}) + + return cls.config_class(config.get("generatorName"))(additional_properties) + + @classmethod + def project_factory( + cls, + config: BaseConfig, + base_dir: str, + output_dir: str, + ) -> Project: + return cls.generator_class(config.GENERATOR_NAME).PROJECT_CLASS( + config, + base_dir, + output_dir, + ) + + @classmethod + def generator_class(cls, name: str) -> Type[BaseGenerator]: + if name not in cls.generators: + raise NotImplementedError(f"Generator '{name}' not found") + + return cls.generators[name] + + @classmethod + def generator_factory( + cls, + config: BaseConfig, + operation: model.Operation, + property_container: model.PropertyContainer, + ) -> BaseGenerator: + return cls.generator_class(config.GENERATOR_NAME)( + config, + operation, + property_container, + ) + + @classmethod + def default_generator_names(cls) -> list[str]: + result = list(cls.generators.keys()) + result.sort() + + return result diff --git a/oseg/oseg/generator/csharp_generator.py b/oseg/oseg/generator/csharp_generator.py new file mode 100644 index 000000000..a8ece24ba --- /dev/null +++ b/oseg/oseg/generator/csharp_generator.py @@ -0,0 +1,361 @@ +import inspect +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict +from oseg import generator, model +from oseg.parser import NormalizeStr + +ConfigDef = TypedDict( + "ConfigDef", + { + "packageName": str, + "packageGuid": str | None, + "oseg.namespace": str | None, + "oseg.packageGuid": str | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + namespace: str | None + packageGuid: str + + +class CSharpConfig(generator.BaseConfig): + GENERATOR_NAME = "csharp" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "packageName": inspect.cleandoc( + """ + The C# package name of the source package. This is the SDK package + you are generating example snippets for. Ex: Org.OpenAPITools + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "packageGuid": { + "description": inspect.cleandoc( + """ + The GUID of the source package. + (Default: {C69F4F3D-BE68-4A19-A3F0-5EEE1810150B}) + """ + ), + "default": "{C69F4F3D-BE68-4A19-A3F0-5EEE1810150B}", + }, + "oseg.namespace": { + "description": inspect.cleandoc( + """ + Namespace for your example snippets. + Ex: OSEG.Examples + """ + ), + "default": None, + }, + "oseg.packageGuid": { + "description": inspect.cleandoc( + """ + The GUID that will be associated with the C# project. + (Default: {4D6EE6C1-B6BF-402C-9D5D-C67B3A3D66B0}) + """ + ), + "default": "{4D6EE6C1-B6BF-402C-9D5D-C67B3A3D66B0}", + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.packageName = config.get("packageName") + assert isinstance(self.packageName, str) + + self.packageGuid = self._get_value("packageGuid") + + self.oseg = ConfigOseg( + namespace=self._get_value("oseg.namespace"), + packageGuid=self._get_value("oseg.packageGuid"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class Project(generator.Project): + config: CSharpConfig + + def setup(self) -> None: + pass + + +class CSharpGenerator(generator.BaseGenerator): + CONFIG_CLASS = CSharpConfig + PROJECT_CLASS = Project + FILE_EXTENSION = "cs" + NAME = "csharp" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "var" + RESERVED_KEYWORDS = [ + "abstract", + "as", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "do", + "double", + "else", + "enum", + "event", + "explicit", + "extern", + "false", + "finally", + "fixed", + "float", + "for", + "foreach", + "goto", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "lock", + "long", + "namespace", + "new", + "null", + "object", + "operator", + "out", + "override", + "params", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "virtual", + "void", + "volatile", + "while", + ] + RESERVED_KEYWORDS_SECONDARY = [ + "configuration", + "version", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + if secondary: + return name.lower() in self.RESERVED_KEYWORDS_SECONDARY + + return name.lower() in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + return NormalizeStr.camel_case(f"{self.RESERVED_KEYWORD_PREPEND}_{name}") + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_propname(self, name: str) -> str: + return self.print_variablename(name) + + def print_variablename(self, name: str) -> str: + return self.unreserve_keyword(NormalizeStr.camel_case(name)) + + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + printable.target_type = self._get_target_type(item=item, parent=parent) + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + + return printable + + printable.value = self._handle_value(item, item.value, parent) + + return printable + + def print_null(self) -> str: + return "null" + + def has_named_parameters(self) -> bool: + return True + + def _get_target_type( + self, + item: model.PropertyScalar, + parent: model.PropertyObject | None, + ) -> str: + if item.type == oa.DataType.BOOLEAN: + return "bool" + + if item.type == oa.DataType.STRING: + if item.is_enum: + if parent is None: + return "string" + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + + return f"{parent_type}.{enum_type}" + + if item.format == model.DataFormat.DATETIME.value: + return "DateTime" + + if item.format == model.DataFormat.DATE.value: + return "DateOnly" + + return "string" + + if item.type == oa.DataType.INTEGER: + return "int" + + if item.type == oa.DataType.NUMBER: + if item.format in [ + model.DataFormat.FLOAT.value, + model.DataFormat.DOUBLE.value, + ]: + return item.format + + if item.format == model.DataFormat.INT64.value: + return "long" + + return "int" + + return "" + + def _handle_value( + self, + item: model.PropertyScalar, + value: any, + parent: model.PropertyObject | None, + ) -> any: + if item.is_enum: + enum_name = self._get_enum_name(item, value) + + if enum_name is None: + return self.print_null() + + if parent is None: + return self._to_json(value) + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + + return f"{parent_type}.{enum_type}.{enum_name}" + + if item.type == oa.DataType.STRING: + if item.format == model.DataFormat.DATETIME.value: + return f'DateTime.Parse("{value}")' + + if item.format == model.DataFormat.DATE.value: + return f'DateOnly.Parse("{value}")' + + return self._to_json(value) + + def _get_enum_name( + self, + item: model.PropertyScalar, + value: any, + ) -> str | None: + if value is None: + return None + + enum_varname, is_override = self._get_enum_varname(item.schema, value) + + if enum_varname is not None: + return enum_varname + + if value == "" and "" in item.schema.enum: + return "Empty" + + return NormalizeStr.pascal_case(value) + + +generator.GeneratorFactory.register(CSharpGenerator) diff --git a/oseg/oseg/generator/java_generator.py b/oseg/oseg/generator/java_generator.py new file mode 100644 index 000000000..98f494dc7 --- /dev/null +++ b/oseg/oseg/generator/java_generator.py @@ -0,0 +1,371 @@ +import inspect +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict +from oseg import generator, model +from oseg.parser import NormalizeStr, PascalCaseOption, CamelCaseOption + +ConfigDef = TypedDict( + "ConfigDef", + { + "invokerPackage": str, + "apiPackage": str, + "modelPackage": str, + "artifactId": str | None, + "oseg.package": str | None, + "oseg.printApiCallProperty": bool | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + package: str | None + printApiCallProperty: bool + + +class JavaConfig(generator.BaseConfig): + GENERATOR_NAME = "java" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "invokerPackage": inspect.cleandoc( + """ + The root namespace of the source package. This is the SDK package + you are generating example snippets for. Ex: org.openapitools.client + """ + ), + "apiPackage": inspect.cleandoc( + """ + The API namespace of the source package. + Ex: org.openapitools.client.api + """ + ), + "modelPackage": inspect.cleandoc( + """ + The Model namespace of the source package. + Ex: org.openapitools.client.model + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "artifactId": { + "description": inspect.cleandoc( + """ + artifactId of the source package. (Default: openapi-java-client) + """ + ), + "default": "openapi-java-client", + }, + "oseg.package": { + "description": inspect.cleandoc( + """ + Package for your example snippets. + Ex: oseg.petstore.examples + """ + ), + "default": None, + }, + "oseg.printApiCallProperty": { + "description": inspect.cleandoc( + """ + Add property name as comment for non-variable values passed to + the API call method. (Default: true) + """ + ), + "default": True, + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.invokerPackage = config.get("invokerPackage") + self.apiPackage = config.get("apiPackage") + self.modelPackage = config.get("modelPackage") + + assert isinstance(self.invokerPackage, str) + assert isinstance(self.apiPackage, str) + assert isinstance(self.modelPackage, str) + + self.artifactId = self._get_value("artifactId") + + self.oseg = ConfigOseg( + package=self._get_value("oseg.package"), + printApiCallProperty=self._get_value("oseg.printApiCallProperty"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class JavaGenerator(generator.BaseGenerator): + CONFIG_CLASS = JavaConfig + FILE_EXTENSION = "java" + NAME = "java" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "_" + RESERVED_KEYWORDS = [ + "_", + "abstract", + "apiclient", + "apiexception", + "apiresponse", + "assert", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "configuration", + "const", + "continue", + "default", + "do", + "double", + "else", + "enum", + "extends", + "file", + "final", + "finally", + "float", + "for", + "goto", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "list", + "localdate", + "localreturntype", + "localtime", + "localvaraccept", + "localvaraccepts", + "localvarauthnames", + "localvarcollectionqueryparams", + "localvarcontenttype", + "localvarcontenttypes", + "localvarcookieparams", + "localvarformparams", + "localvarheaderparams", + "localvarpath", + "localvarpostbody", + "localvarqueryparams", + "long", + "native", + "new", + "null", + "object", + "offsetdatetime", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "stringutil", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "try", + "void", + "volatile", + "while", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + return name.lower() in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + if name == "_": + return "u" + + return f"{self.RESERVED_KEYWORD_PREPEND}{name}" + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case( + f"{name}Api", + option=PascalCaseOption.LOWERCASE_CONTIGUOUS, + ) + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + result = NormalizeStr.camel_case(name) + + # if the original method name starts with _, keep it + if name.startswith("_"): + return f"_{result}" + + return result + + def print_propname(self, name: str) -> str: + return self.unreserve_keyword( + NormalizeStr.camel_case( + name, + CamelCaseOption.LOWERCASE_FIRST_SECTION, + ) + ) + + def print_variablename(self, name: str) -> str: + return self.unreserve_keyword( + NormalizeStr.camel_case( + name, + CamelCaseOption.LOWERCASE_FIRST_SECTION, + ) + ) + + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + if item.type == oa.DataType.STRING and item.is_enum: + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + + if not parent: + printable.target_type = enum_type + else: + parent_type = NormalizeStr.pascal_case(parent.type) + printable.target_type = f"{parent_type}.{enum_type}" + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + + return printable + + printable.value = self._handle_value(item, item.value, parent) + + return printable + + def print_null(self) -> str: + return "null" + + def force_print_parameters(self) -> bool: + return True + + def _handle_value( + self, + item: model.PropertyScalar, + value: any, + parent: model.PropertyObject | None, + ) -> any: + if value is None: + return self._to_json(value) + + if item.type == oa.DataType.STRING: + if item.is_enum: + enum_name = self._get_enum_name(item, value) + + if enum_name is None: + return self.print_null() + + if parent is None: + return self._to_json(value) + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + + return f"{parent_type}.{enum_type}.{enum_name}" + + if item.format == model.DataFormat.DATETIME.value: + return f'OffsetDateTime.parse("{value}")' + + if item.format == model.DataFormat.DATE.value: + return f'LocalDate.parse("{value}")' + + int_fixed = self._fix_ints(item, value) + + return int_fixed if int_fixed is not None else self._to_json(value) + + def _get_enum_name( + self, + item: model.PropertyScalar, + value: any, + ) -> str | None: + if value is None: + return None + + enum_varname, is_override = self._get_enum_varname(item.schema, value) + + if enum_varname is not None: + return enum_varname + + if value == "" and "" in item.schema.enum: + return "Empty" + + return NormalizeStr.underscore(value).upper() + + def _fix_ints(self, item: model.PropertyScalar, value: any) -> any: + if item.type not in [oa.DataType.INTEGER, oa.DataType.NUMBER] or value is None: + return None + + if item.format == model.DataFormat.FLOAT.value: + return f"{value}F" + elif item.format == model.DataFormat.DOUBLE.value: + return f"{value}D" + elif item.format == model.DataFormat.INT64.value: + return f"{value}L" + + if item.type == oa.DataType.NUMBER: + return f"BigDecimal.valueOf({value})" + + return value + + +generator.GeneratorFactory.register(JavaGenerator) diff --git a/oseg/oseg/generator/kotlin_generator.py b/oseg/oseg/generator/kotlin_generator.py new file mode 100644 index 000000000..4e4e7789c --- /dev/null +++ b/oseg/oseg/generator/kotlin_generator.py @@ -0,0 +1,354 @@ +import inspect + +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict + +from oseg import generator, model +from oseg.parser import NormalizeStr, CamelCaseOption + +ConfigDef = TypedDict( + "ConfigDef", + { + "groupId": str, + "packageName": str, + "artifactId": str | None, + "oseg.package": str | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + package: str | None + + +class KotlinConfig(generator.BaseConfig): + GENERATOR_NAME = "kotlin" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "groupId": inspect.cleandoc( + """ + Generated artifact package's organization. This is the SDK package + you are generating example snippets for. Ex: org.openapitools + """ + ), + "packageName": inspect.cleandoc( + """ + Generated artifact package name. + Ex: org.openapitools.client + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "artifactId": { + "description": inspect.cleandoc( + """ + artifactId of the source package. (Default: openapi-kotlin-client) + """ + ), + "default": "openapi-kotlin-client", + }, + "oseg.package": { + "description": inspect.cleandoc( + """ + Package for your example snippets. + Ex: oseg.petstore.examples + """ + ), + "default": None, + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.groupId = config.get("groupId") + self.packageName = config.get("packageName") + + assert isinstance(self.groupId, str) + assert isinstance(self.packageName, str) + + self.artifactId = self._get_value("artifactId") + + self.oseg = ConfigOseg( + package=self._get_value("oseg.package"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class KotlinGenerator(generator.BaseGenerator): + CONFIG_CLASS = KotlinConfig + FILE_EXTENSION = "kt" + NAME = "kotlin" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "_" + RESERVED_KEYWORDS = [ + "_", + "ApiResponse", + "abstract", + "actual", + "annotation", + "as", + "break", + "class", + "companion", + "const", + "constructor", + "continue", + "contract", + "crossinline", + "data", + "delegate", + "do", + "dynamic", + "else", + "enum", + "expect", + "external", + "false", + "field", + "final", + "finally", + "for", + "fun", + "if", + "import", + "in", + "infix", + "init", + "inline", + "inner", + "interface", + "internal", + "is", + "it", + "lateinit", + "noinline", + "null", + "object", + "open", + "operator", + "out", + "override", + "package", + "param", + "private", + "property", + "protected", + "public", + "receiver", + "reified", + "return", + "sealed", + "setparam", + "super", + "suspend", + "tailrec", + "this", + "throw", + "true", + "try", + "typealias", + "typeof", + "val", + "var", + "vararg", + "when", + "where", + "while", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + return name.lower() in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + if name == "_": + return "u" + + return f"{self.RESERVED_KEYWORD_PREPEND}{name}" + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + result = NormalizeStr.camel_case(name) + + # if the original method name starts with _, keep it + if name.startswith("_"): + return f"_{result}" + + return result + + def print_propname(self, name: str) -> str: + return self.unreserve_keyword( + NormalizeStr.camel_case( + name, + CamelCaseOption.LOWERCASE_FIRST_SECTION, + ) + ) + + def print_variablename(self, name: str) -> str: + return self.unreserve_keyword( + NormalizeStr.camel_case( + name, + CamelCaseOption.LOWERCASE_FIRST_SECTION, + ) + ) + + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + if item.type == oa.DataType.STRING and item.is_enum: + enum_type = NormalizeStr.pascal_case(f"{item.name}") + + if not parent: + parent_type = NormalizeStr.pascal_case(self.operation.api_name) + operation_id = NormalizeStr.pascal_case(self.operation.operation_id) + printable.target_type = ( + f"{parent_type}Api.{enum_type}{operation_id}" + ) + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + else: + parent_type = NormalizeStr.pascal_case(parent.type) + printable.target_type = f"{parent_type}.{enum_type}" + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + + return printable + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + + return printable + + printable.value = self._handle_value(item, item.value, parent) + + return printable + + def print_null(self) -> str: + return "null" + + def has_named_parameters(self) -> bool: + return True + + def _handle_value( + self, + item: model.PropertyScalar, + value: any, + parent: model.PropertyObject | None, + ) -> any: + if value is None: + return self._to_json(value) + + if item.type == oa.DataType.STRING: + if item.is_enum: + enum_name = self._get_enum_name(item, value) + + if enum_name is None: + return self.print_null() + + if parent is None or item not in parent.properties.values(): + parent_type = NormalizeStr.pascal_case(self.operation.api_name) + operation_id = NormalizeStr.pascal_case(self.operation.operation_id) + enum_type = NormalizeStr.uc_first( + NormalizeStr.camel_case( + value=item.name, + option=CamelCaseOption.LOWERCASE_FIRST_SECTION, + ) + ) + + return f"{parent_type}Api.{enum_type}{operation_id}.{value}" + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}") + + return f"{parent_type}.{enum_type}.{enum_name}" + + if item.format == model.DataFormat.DATETIME.value: + return f'OffsetDateTime.parse("{value}")' + + if item.format == model.DataFormat.DATE.value: + return f'LocalDate.parse("{value}")' + + if isinstance(value, str): + return self._escape_dollar(value) + + return self._to_json(value) + + def _get_enum_name( + self, + item: model.PropertyScalar, + value: any, + ) -> str | None: + if value is None: + return None + + value: str + + enum_varname, is_override = self._get_enum_varname(item.schema, value) + + if enum_varname is not None: + return enum_varname + + if value == "" and "" in item.schema.enum: + return "Empty" + + return NormalizeStr.camel_case(value.replace("-", "_minus_")) + + +generator.GeneratorFactory.register(KotlinGenerator) diff --git a/oseg/oseg/generator/php_generator.py b/oseg/oseg/generator/php_generator.py new file mode 100644 index 000000000..728aadddb --- /dev/null +++ b/oseg/oseg/generator/php_generator.py @@ -0,0 +1,319 @@ +import inspect +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict +from oseg import generator, model +from oseg.parser import NormalizeStr + +ConfigDef = TypedDict( + "ConfigDef", + { + "invokerPackage": str, + "composerPackageName": str | None, + "oseg.namespace": str | None, + "oseg.composerPackageName": str | None, + "oseg.autoloadLocation": str | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + namespace: str | None + composerPackageName: str | None + autoloadLocation: str | None + + +class PhpConfig(generator.BaseConfig): + GENERATOR_NAME = "php" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "invokerPackage": inspect.cleandoc( + """ + The namespace of the source package. This is the SDK package + you are generating example snippets for. Ex: Yay\\Pets + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "composerPackageName": { + "description": inspect.cleandoc( + """ + Composer package name of the source package. + (Default: openapi/client) + """ + ), + "default": "openapi/client", + }, + "oseg.namespace": { + "description": inspect.cleandoc( + """ + Namespace for your example snippets. + Ex: OSEG\\PetStoreExamples + """ + ), + "default": None, + }, + "oseg.composerPackageName": { + "description": inspect.cleandoc( + """ + The name to use in the composer package name, for your example snippets. + Ex: oseg/petstore_examples + """ + ), + "default": None, + }, + "oseg.autoloadLocation": { + "description": inspect.cleandoc( + """ + Path to Composer autoloader. + Ex: __DIR__ . '/../vendor/autoload.php' + """ + ), + "default": None, + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.invokerPackage = config.get("invokerPackage") + assert isinstance(self.invokerPackage, str) + + self.composerPackageName = self._get_value("composerPackageName") + + self.oseg = ConfigOseg( + namespace=self._get_value("oseg.namespace"), + composerPackageName=self._get_value("oseg.composerPackageName"), + autoloadLocation=self._get_value("oseg.autoloadLocation"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class PhpGenerator(generator.BaseGenerator): + CONFIG_CLASS = PhpConfig + FILE_EXTENSION = "php" + NAME = "php" + TEMPLATE = f"{NAME}.jinja2" + + # reserved keyword functionality only applicable to enums + RESERVED_KEYWORD_PREPEND = "_" + RESERVED_KEYWORDS = [ + "__halt_compiler", + "_header_accept", + "_tempbody", + "abstract", + "and", + "array", + "as", + "break", + "callable", + "case", + "catch", + "class", + "clone", + "const", + "continue", + "declare", + "default", + "die", + "do", + "echo", + "else", + "elseif", + "empty", + "enddeclare", + "endfor", + "endforeach", + "endif", + "endswitch", + "endwhile", + "eval", + "exit", + "extends", + "final", + "for", + "foreach", + "formparams", + "function", + "global", + "goto", + "headerparams", + "httpbody", + "if", + "implements", + "include", + "include_once", + "instanceof", + "insteadof", + "interface", + "isset", + "list", + "namespace", + "new", + "or", + "print", + "private", + "protected", + "public", + "queryparams", + "require", + "require_once", + "resourcepath", + "return", + "static", + "switch", + "throw", + "trait", + "try", + "unset", + "use", + "var", + "while", + "xor", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + return False + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + return name + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + return NormalizeStr.camel_case(name) + + def print_propname(self, name: str) -> str: + return NormalizeStr.snake_case(name) + + def print_variablename(self, name: str) -> str: + name = NormalizeStr.snake_case(name) + + if not name.startswith("$"): + return "$" + name + + return name + + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + + return printable + + printable.value = self._handle_value(item, item.value, parent) + + return printable + + def has_named_parameters(self) -> bool: + return True + + def print_null(self) -> str: + return "null" + + def _handle_value( + self, + item: model.PropertyScalar, + value: any, + parent: model.PropertyObject | None, + ) -> any: + if item.value is None: + return self._to_json(value) + + if item.type == oa.DataType.STRING: + # if enum but no parent, use the literal value + if item.is_enum and parent is not None: + namespace = self.config.invokerPackage + enum_name = self._get_enum_name(item, item.name, value) + parent_type = NormalizeStr.pascal_case(parent.type) + + return f"{namespace}\\Model\\{parent_type}::{enum_name}" + + if item.format in [ + model.DataFormat.DATETIME.value, + model.DataFormat.DATE.value, + ]: + return f'new \\DateTime("{value}")' + + if isinstance(value, str): + return self._escape_dollar(value) + + return self._to_json(value) + + def _get_enum_name( + self, + item: model.PropertyScalar, + name: str, + value: any, + ) -> str: + enum_varname, is_override = self._get_enum_varname(item.schema, value) + + if enum_varname is not None: + if is_override: + return enum_varname + + return NormalizeStr.underscore(f"{name}_{enum_varname}").upper() + + if value == "" or value is None: + return NormalizeStr.underscore(f"{name}_EMPTY").upper() + + name = NormalizeStr.underscore(name) + value = NormalizeStr.underscore(value) + + if value.lower() in self.RESERVED_KEYWORDS: + value = f"{self.RESERVED_KEYWORD_PREPEND}{value}" + + return f"{name}_{value}".upper() + + +generator.GeneratorFactory.register(PhpGenerator) diff --git a/oseg/oseg/generator/python_generator.py b/oseg/oseg/generator/python_generator.py new file mode 100644 index 000000000..cfee1c966 --- /dev/null +++ b/oseg/oseg/generator/python_generator.py @@ -0,0 +1,242 @@ +import inspect +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict +from oseg import generator, model +from oseg.parser import NormalizeStr + +ConfigDef = TypedDict( + "ConfigDef", + { + "packageName": str, + "oseg.propertyNamingConvention": str | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + propertyNamingConvention: str | None + + +class PythonConfig(generator.BaseConfig): + GENERATOR_NAME = "python" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "packageName": inspect.cleandoc( + """ + The package name of the source package. This is the SDK package + you are generating example snippets for. Ex: openapi_client + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "oseg.propertyNamingConvention": { + "description": inspect.cleandoc( + """ + Naming convention of Model method property names, + one of "camelCase" or "snake_case". (Default: snake_case) + """ + ), + "default": "snake_case", + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.packageName = config.get("packageName") + assert isinstance(self.packageName, str) + + self.oseg = ConfigOseg( + propertyNamingConvention=self._get_value("oseg.propertyNamingConvention"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class Project(generator.Project): + config: PythonConfig + + def setup(self) -> None: + pass + + +class PythonGenerator(generator.BaseGenerator): + CONFIG_CLASS = PythonConfig + PROJECT_CLASS = Project + FILE_EXTENSION = "py" + NAME = "python" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "var_" + RESERVED_KEYWORDS = [ + "all_params", + "and", + "as", + "assert", + "async", + "auth_settings", + "await", + "base64", + "body_params", + "break", + "class", + "continue", + "date", + "def", + "del", + "elif", + "else", + "except", + "exec", + "false", + "field", + "finally", + "float", + "for", + "form_params", + "from", + "global", + "header_params", + "if", + "import", + "in", + "is", + "json", + "lambda", + "local_var_files", + "none", + "nonlocal", + "not", + "or", + "pass", + "path_params", + "print", + "property", + "query_params", + "raise", + "resource_path", + "return", + "schema", + "self", + "true", + "try", + "while", + "with", + "yield", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + return NormalizeStr.snake_case(name) in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + return f"{self.RESERVED_KEYWORD_PREPEND}{name}" + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + return NormalizeStr.snake_case(name) + + def print_propname(self, name: str) -> str: + """openapi-generator/Python uses pydantic + property name aliases, + but only for Model properties. + + API call method properties will always be snake_case, + so use print_variablename for that call. + """ + + # todo unit test + prop_case = self.config.oseg.propertyNamingConvention + + if prop_case == "camel_case": + return NormalizeStr.camel_case(self.unreserve_keyword(name)) + + return NormalizeStr.snake_case(self.unreserve_keyword(name)) + + def print_variablename(self, name: str) -> str: + return self.unreserve_keyword(NormalizeStr.snake_case(name)) + + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(self._handle_value(item, i)) + + return printable + + printable.value = self._handle_value(item, item.value) + + return printable + + def print_null(self) -> str: + return "None" + + def has_named_parameters(self) -> bool: + return True + + def _handle_value(self, item: model.PropertyScalar, value: any) -> any: + if item.type == oa.DataType.BOOLEAN or value is None: + return value + + if item.type == oa.DataType.STRING: + if item.format == model.DataFormat.DATETIME.value: + return f"datetime.fromisoformat({self._to_json(value)})" + + if item.format == model.DataFormat.DATE.value: + return f"date.fromisoformat({self._to_json(value)})" + + return self._to_json(value) + + +generator.GeneratorFactory.register(PythonGenerator) diff --git a/oseg/oseg/generator/ruby_generator.py b/oseg/oseg/generator/ruby_generator.py new file mode 100644 index 000000000..5236fc911 --- /dev/null +++ b/oseg/oseg/generator/ruby_generator.py @@ -0,0 +1,233 @@ +import inspect +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict +from oseg import generator, model +from oseg.parser import NormalizeStr + +ConfigDef = TypedDict( + "ConfigDef", + { + "gemName": str, + "moduleName": str, + "oseg.printApiCallProperty": bool | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + printApiCallProperty: bool | None + + +class RubyConfig(generator.BaseConfig): + GENERATOR_NAME = "ruby" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "gemName": inspect.cleandoc( + """ + The gem name of the source package. This is the SDK package + you are generating example snippets for. Ex: openapi_client + """ + ), + "moduleName": inspect.cleandoc( + """ + The module name of the source package. This is the SDK package + you are generating example snippets for. Ex: OpenAPIClient + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "oseg.printApiCallProperty": { + "description": inspect.cleandoc( + """ + Add property name as comment for non-variable values passed to + the API call method. (Default: true) + """ + ), + "default": {}, + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.gemName = config.get("gemName") + self.moduleName = config.get("moduleName") + + assert isinstance(self.gemName, str) + assert isinstance(self.moduleName, str) + + self.oseg = ConfigOseg( + printApiCallProperty=self._get_value("oseg.printApiCallProperty"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class RubyGenerator(generator.BaseGenerator): + CONFIG_CLASS = RubyConfig + FILE_EXTENSION = "rb" + NAME = "ruby" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "_" + RESERVED_KEYWORDS = [ + "__file__", + "__line__", + "_header_accept", + "_header_accept_result", + "_header_content_type", + "alias", + "and", + "auth_names", + "begin", + "break", + "case", + "class", + "def", + "defined?", + "do", + "else", + "elsif", + "end", + "ensure", + "false", + "for", + "form_params", + "header_params", + "if", + "in", + "local_var_path", + "module", + "next", + "nil", + "not", + "or", + "post_body", + "query_params", + "redo", + "rescue", + "retry", + "return", + "self", + "send", + "super", + "then", + "true", + "undef", + "unless", + "until", + "when", + "while", + "yield", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + return name.lower() in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + return f"{self.RESERVED_KEYWORD_PREPEND}{name}" + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + return NormalizeStr.snake_case(name) + + def print_propname(self, name: str) -> str: + return self.unreserve_keyword(NormalizeStr.snake_case(name)) + + def print_variablename(self, name: str) -> str: + return self.unreserve_keyword(NormalizeStr.snake_case(name)) + + def print_scalar( + self, + parent: model.PropertyObject, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(self._handle_value(item, i)) + + return printable + + printable.value = self._handle_value(item, item.value) + + return printable + + def print_null(self) -> str: + return "nil" + + def _handle_value(self, item: model.PropertyScalar, value: any) -> any: + if value is None: + return self.print_null() + + if item.type == oa.DataType.STRING: + if item.format == model.DataFormat.DATETIME.value: + return f'Date.parse("{value}").to_time' + + if item.format == model.DataFormat.DATE.value: + return f'Date.parse("{value}").to_date' + + int_fixed = self._fix_ints(item, value) + + return int_fixed if int_fixed is not None else self._to_json(value) + + def _fix_ints(self, item: model.PropertyScalar, value: any) -> any: + if item.type not in [oa.DataType.INTEGER, oa.DataType.NUMBER] or value is None: + return None + + if item.type == oa.DataType.NUMBER: + return f"({value}).to_f" + + return value + + +generator.GeneratorFactory.register(RubyGenerator) diff --git a/oseg/oseg/generator/typescript_axios_generator.py b/oseg/oseg/generator/typescript_axios_generator.py new file mode 100644 index 000000000..91818b22f --- /dev/null +++ b/oseg/oseg/generator/typescript_axios_generator.py @@ -0,0 +1,303 @@ +import inspect +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict +from oseg import generator, model +from oseg.parser import NormalizeStr, PascalCaseOption + +ConfigDef = TypedDict( + "ConfigDef", + { + "npmName": str, + "oseg.npmName": str | None, + "oseg.printApiCallProperty": bool | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + npmName: str | None + printApiCallProperty: bool | None + + +class TypescriptAxiosConfig(generator.BaseConfig): + GENERATOR_NAME = "typescript-axios" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "npmName": inspect.cleandoc( + """ + The package name of the source package. This is the SDK package + you are generating example snippets for. Ex: openapi_client + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "oseg.npmName": { + "description": inspect.cleandoc( + """ + The package name to use in the package.json, for your example snippets. + Ex: @oseg/petstore_examples + """ + ), + "default": None, + }, + "oseg.printApiCallProperty": { + "description": inspect.cleandoc( + """ + Add property name as comment for non-variable values passed to + the API call method. (Default: true) + """ + ), + "default": {}, + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.npmName = config.get("npmName") + assert isinstance(self.npmName, str) + + self.oseg = ConfigOseg( + npmName=self._get_value("oseg.npmName"), + printApiCallProperty=self._get_value("oseg.printApiCallProperty"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class TypescriptAxiosGenerator(generator.BaseGenerator): + CONFIG_CLASS = TypescriptAxiosConfig + FILE_EXTENSION = "ts" + NAME = "typescript-axios" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "_" + RESERVED_KEYWORDS = [ + "abstract", + "await", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "double", + "else", + "enum", + "export", + "extends", + "false", + "final", + "finally", + "float", + "for", + "formParams", + "function", + "goto", + "headerParams", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "let", + "long", + "native", + "new", + "null", + "options", + "package", + "private", + "protected", + "public", + "queryParameters", + "requestOptions", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "transient", + "true", + "try", + "typeof", + "useFormData", + "var", + "varLocalDeferred", + "varLocalPath", + "void", + "volatile", + "while", + "with", + "yield", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + return name.lower() in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + return f"{self.RESERVED_KEYWORD_PREPEND}{name}" + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + return NormalizeStr.camel_case(name) + + def print_propname(self, name: str) -> str: + return self.unreserve_keyword(name) + + def print_variablename(self, name: str) -> str: + return self.unreserve_keyword(NormalizeStr.camel_case(name)) + + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + printable.target_type = self._get_target_type(item=item, parent=parent) + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + + return printable + + printable.value = self._handle_value(item, item.value, parent) + + return printable + + def print_null(self) -> str: + return "undefined" + + def _get_target_type( + self, + item: model.PropertyScalar, + parent: model.PropertyObject | None, + ) -> str | None: + if item.type == oa.DataType.STRING and item.is_enum: + if parent is None: + return None + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + + return f"{parent_type}.{enum_type}" + + return None + + def _handle_value( + self, + item: model.PropertyScalar, + value: any, + parent: model.PropertyObject | None, + ) -> any: + if item.type != oa.DataType.STRING: + return self._to_json(value) + + if item.is_enum: + enum_name = self._get_enum_name(item, value) + + if enum_name is None: + return self.print_null() + + if parent is None: + return self._to_json(value) + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + enum_name = NormalizeStr.pascal_case( + enum_name, + option=PascalCaseOption.LOWERCASE_CONTIGUOUS, + ) + + final = f"api.{parent_type}{enum_type}.{enum_name}" + + # if currently in api call method, append ".toString()" to enums + if parent and self.property_container.body == parent: + if self.property_container.request.has_formdata: + final += ".toString()" + + return final + + return self._to_json(value) + + def _get_enum_name( + self, + item: model.PropertyScalar, + value: any, + ) -> str | None: + enum_varname, is_override = self._get_enum_varname(item.schema, value) + + if enum_varname is not None: + return enum_varname + + if value == "" and "" in item.schema.enum: + return "Empty" + + if value is None: + return None + + return NormalizeStr.pascal_case(value) + + +generator.GeneratorFactory.register(TypescriptAxiosGenerator) diff --git a/oseg/oseg/generator/typescript_node_generator.py b/oseg/oseg/generator/typescript_node_generator.py new file mode 100644 index 000000000..8a09dd8a5 --- /dev/null +++ b/oseg/oseg/generator/typescript_node_generator.py @@ -0,0 +1,308 @@ +import inspect +import openapi_pydantic as oa +from dataclasses import dataclass +from typing import TypedDict +from oseg import generator, model +from oseg.parser import NormalizeStr, PascalCaseOption + +ConfigDef = TypedDict( + "ConfigDef", + { + "npmName": str, + "oseg.npmName": str | None, + "oseg.printApiCallProperty": bool | None, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + npmName: str | None + printApiCallProperty: bool | None + + +class TypescriptNodeConfig(generator.BaseConfig): + GENERATOR_NAME = "typescript-node" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "npmName": inspect.cleandoc( + """ + The package name of the source package. This is the SDK package + you are generating example snippets for. Ex: openapi_client + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "oseg.npmName": { + "description": inspect.cleandoc( + """ + The package name to use in the package.json, for your example snippets. + Ex: @oseg/petstore_examples + """ + ), + "default": None, + }, + "oseg.printApiCallProperty": { + "description": inspect.cleandoc( + """ + Add property name as comment for non-variable values passed to + the API call method. (Default: true) + """ + ), + "default": {}, + }, + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.npmName = config.get("npmName") + assert isinstance(self.npmName, str) + + self.oseg = ConfigOseg( + npmName=self._get_value("oseg.npmName"), + printApiCallProperty=self._get_value("oseg.printApiCallProperty"), + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class TypescriptNodeGenerator(generator.BaseGenerator): + CONFIG_CLASS = TypescriptNodeConfig + FILE_EXTENSION = "ts" + NAME = "typescript-node" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "_" + RESERVED_KEYWORDS = [ + "abstract", + "await", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "double", + "else", + "enum", + "export", + "extends", + "false", + "final", + "finally", + "float", + "for", + "formParams", + "function", + "goto", + "headerParams", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "let", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "queryParameters", + "requestOptions", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "transient", + "true", + "try", + "typeof", + "useFormData", + "var", + "varLocalDeferred", + "varLocalPath", + "void", + "volatile", + "while", + "with", + "yield", + ] + + config: CONFIG_CLASS + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + return name.lower() in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + return f"{self.RESERVED_KEYWORD_PREPEND}{name}" + + def print_apiname(self, name: str) -> str: + return NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + return NormalizeStr.camel_case(name) + + def print_propname(self, name: str) -> str: + return self.unreserve_keyword(NormalizeStr.camel_case(name)) + + def print_variablename(self, name: str) -> str: + return self.unreserve_keyword(NormalizeStr.camel_case(name)) + + def print_scalar( + self, + parent: model.PropertyObject | None, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + printable.is_enum = item.is_enum + printable.target_type = self._get_target_type(item=item, parent=parent) + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(self._handle_value(item, i, parent)) + + return printable + + printable.value = self._handle_value(item, item.value, parent) + + return printable + + def print_null(self) -> str: + return "undefined" + + def _get_target_type( + self, + item: model.PropertyScalar, + parent: model.PropertyObject | None, + ) -> str | None: + if item.type == oa.DataType.STRING and item.is_enum: + if parent is None: + return None + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + + return f"{parent_type}.{enum_type}" + + return None + + def _handle_value( + self, + item: model.PropertyScalar, + value: any, + parent: model.PropertyObject | None, + ) -> any: + if item.type != oa.DataType.STRING: + return self._to_json(value) + + if item.is_enum: + enum_name = self._get_enum_name(item, value) + + if enum_name is None: + return self.print_null() + + if parent is None: + return self._to_json(value) + + parent_type = NormalizeStr.pascal_case(parent.type) + enum_type = NormalizeStr.pascal_case(f"{item.name}Enum") + enum_name = NormalizeStr.pascal_case( + enum_name, + option=PascalCaseOption.LOWERCASE_CONTIGUOUS, + ) + + final = f"models.{parent_type}.{enum_type}.{enum_name}" + + # if currently in api call method, append ".toString()" to enums + if parent and self.property_container.body == parent: + if self.property_container.request.has_formdata: + final += ".toString()" + + return final + + if item.format == model.DataFormat.DATETIME.value: + return f'new Date("{value}")' + + if item.format == model.DataFormat.DATE.value: + return self._to_json(value) + + return self._to_json(value) + + def _get_enum_name( + self, + item: model.PropertyScalar, + value: any, + ) -> str | None: + enum_varname, is_override = self._get_enum_varname(item.schema, value) + + if enum_varname is not None: + return enum_varname + + if value == "" and "" in item.schema.enum: + return "Empty" + + if value is None: + return None + + return NormalizeStr.pascal_case(value) + + +generator.GeneratorFactory.register(TypescriptNodeGenerator) diff --git a/oseg/oseg/jinja_extension/__init__.py b/oseg/oseg/jinja_extension/__init__.py new file mode 100644 index 000000000..806254df8 --- /dev/null +++ b/oseg/oseg/jinja_extension/__init__.py @@ -0,0 +1 @@ +from .jinja_ext import JinjaExt diff --git a/oseg/oseg/jinja_extension/jinja_ext.py b/oseg/oseg/jinja_extension/jinja_ext.py new file mode 100644 index 000000000..752b97eb7 --- /dev/null +++ b/oseg/oseg/jinja_extension/jinja_ext.py @@ -0,0 +1,121 @@ +from __future__ import annotations +import jinja2 +from jinja2 import ext, pass_context +from jinja2.runtime import Context, Undefined +from typing import Callable +from oseg import generator, model + + +class JinjaExt(jinja2.ext.Extension): + _sdk_generator: generator.BaseGenerator + + @staticmethod + def factory() -> JinjaExt: + env = jinja2.Environment( + loader=jinja2.PackageLoader("oseg"), + trim_blocks=True, + lstrip_blocks=True, + extensions=[JinjaExt], + ) + + extension: JinjaExt = env.extensions.get( + "oseg.jinja_extension.jinja_ext.JinjaExt" + ) + + return extension + + def __init__(self, environment: jinja2.Environment): + super().__init__(environment) + + environment.filters["split"]: Callable[[str, str], str] = ( + lambda value, separator: value.split(separator) + ) + environment.filters["print_apiname"]: Callable[[str], str] = ( + lambda name: self._sdk_generator.print_apiname(name) + ) + environment.filters["print_classname"]: Callable[[str], str] = ( + lambda name: self._sdk_generator.print_classname(name) + ) + environment.filters["print_methodname"]: Callable[[str], str] = ( + lambda name: self._sdk_generator.print_methodname(name) + ) + environment.filters["print_propname"]: Callable[[str], str] = ( + lambda name: self._sdk_generator.print_propname(name) + ) + environment.filters["print_variablename"]: Callable[[str], str] = ( + lambda name: self._sdk_generator.print_variablename(name) + ) + + environment.globals.update(parse_security=self._parse_security) + environment.globals.update(parse_objects=self._parse_objects) + environment.globals.update( + parse_object_properties=self._parse_object_properties + ) + environment.globals.update( + parse_object_list_properties=self._parse_object_list_properties + ) + environment.globals.update( + parse_api_call_properties=self._parse_api_call_properties + ) + environment.globals.update(print_null=lambda: self._sdk_generator.print_null()) + + def template(self, sdk_generator: generator.BaseGenerator) -> jinja2.Template: + self._sdk_generator = sdk_generator + + return self.environment.get_template(self._sdk_generator.TEMPLATE) + + @pass_context + def _parse_security( + self, + context: Context, + indent_count: int, + ) -> dict[str, str]: + return self._sdk_generator.template_parser.parse_security( + macros=model.JinjaMacros(context.parent), + indent_count=indent_count, + ) + + def _parse_objects(self) -> dict[str, model.PropertyObject]: + return self._sdk_generator.template_parser.parse_objects() + + @pass_context + def _parse_object_properties( + self, + context: Context, + parent: model.PropertyObject, + indent_count: int, + ) -> dict[str, str]: + return self._sdk_generator.template_parser.parse_object_properties( + macros=model.JinjaMacros(context.parent), + parent=parent, + indent_count=indent_count, + ) + + @pass_context + def _parse_object_list_properties( + self, + context: Context, + parent: model.PropertyObjectArray, + indent_count: int, + ) -> str: + return self._sdk_generator.template_parser.parse_object_list_properties( + macros=model.JinjaMacros(context.parent), + parent=parent, + indent_count=indent_count, + ) + + @pass_context + def _parse_api_call_properties( + self, + context: Context, + indent_count: int, + required_flag: bool | None = None, + ) -> dict[str, str]: + if isinstance(required_flag, Undefined): + required_flag = None + + return self._sdk_generator.template_parser.parse_api_call_properties( + macros=model.JinjaMacros(context.parent), + indent_count=indent_count, + required_flag=required_flag, + ) diff --git a/oseg/oseg/model/__init__.py b/oseg/oseg/model/__init__.py new file mode 100644 index 000000000..d0fb54de9 --- /dev/null +++ b/oseg/oseg/model/__init__.py @@ -0,0 +1,37 @@ +from .properties import ( + DataFormat, + PropertyFile, + PropertyFreeForm, + PropertyScalar, + PropertyObject, + PropertyObjectArray, + PROPERTY_NON_OBJECT_TYPE, + PROPERTY_OBJECT_TYPE, + PROPERTY_TYPES, + SCALAR_TYPES, +) +from .property_container import PropertyContainer + +from .example_data import ( + EXAMPLE_DATA_BODY, + EXAMPLE_DATA_BY_OPERATION, + EXAMPLE_DATA_BY_NAME, + ExampleDataDef, + ExampleDataParamDef, + ExampleData, + ExampleDataParams, +) + +from .security import Security, SecurityMethod +from .response import Response +from .request import Request +from .operation import Operation + +from .jinja_macros import JinjaMacros + +from .printable import ( + PrintableFreeForm, + PrintableObject, + PrintableScalar, + PrintableSecurity, +) diff --git a/oseg/oseg/model/example_data.py b/oseg/oseg/model/example_data.py new file mode 100644 index 000000000..566de2dd8 --- /dev/null +++ b/oseg/oseg/model/example_data.py @@ -0,0 +1,120 @@ +from typing import TypedDict, Union, NotRequired + +""" +When passing example data to OaParser we expect the data to be grouped +by Operation ID and then the name of the example. +See EXAMPLE_DATA_BY_OPERATION: + +{ + "[OPERATION_ID]": { + "[EXAMPLE_NAME]": { + "body": { + "name": "My pet name" + } + "path": { + "id": 12345 + }, + "query": {}, + "header": {}, + "cookie": {} + } + } +} + +When passing example data to an Operation or Request the data should be +grouped only by name of the example. See EXAMPLE_DATA_BY_NAME: + +{ + "[EXAMPLE_NAME]": { + "body": { + "name": "My pet name" + } + "path": { + "id": 12345 + }, + "query": {}, + "header": {}, + "cookie": {} + } +} + +Body data can be a key:value object or an array of key:value objects: + +{ + "[EXAMPLE_NAME]": { + "body": [ + { + "name": "My pet name" + } + ] + } +} + +""" + +EXAMPLE_DATA_BODY = Union[dict[str, any], list[dict[str, any]]] + + +class ExampleDataParamDef(TypedDict): + path: NotRequired[dict[str, any]] + query: NotRequired[dict[str, any]] + header: NotRequired[dict[str, any]] + cookie: NotRequired[dict[str, any]] + + +class ExampleDataDef(ExampleDataParamDef): + body: NotRequired[EXAMPLE_DATA_BODY] + + +class ExampleDataParams: + def __init__(self, data: ExampleDataParamDef): + path = data.get("path") + query = data.get("query") + header = data.get("header") + cookie = data.get("cookie") + + self.path: dict[str, any] = path if isinstance(path, dict) else {} + self.query: dict[str, any] = query if isinstance(query, dict) else {} + self.header: dict[str, any] = header if isinstance(header, dict) else {} + self.cookie: dict[str, any] = cookie if isinstance(cookie, dict) else {} + self.has_data: bool = self._has_data() + + def _has_data(self) -> bool: + return bool( + len(self.path.keys()) + or len(self.query.keys()) + or len(self.header.keys()) + or len(self.cookie.keys()) + ) + + +class ExampleData: + def __init__(self, body: EXAMPLE_DATA_BODY, parameters: ExampleDataParams): + self.body: EXAMPLE_DATA_BODY = body + self.path: dict[str, any] = parameters.path + self.query: dict[str, any] = parameters.query + self.header: dict[str, any] = parameters.header + self.cookie: dict[str, any] = parameters.cookie + self.has_body_data: bool = self._has_body_data() + self.has_parameter_data: bool = self._has_parameter_data() + + def _has_body_data(self) -> bool: + if isinstance(self.body, list): + return bool(len(self.body)) + + if isinstance(self.body, dict): + return bool(len(self.body.keys())) + + return self.body is not None + + def _has_parameter_data(self) -> bool: + return bool( + len(self.path.keys()) + or len(self.query.keys()) + or len(self.header.keys()) + or len(self.cookie.keys()) + ) + + +EXAMPLE_DATA_BY_NAME = dict[str, ExampleDataDef] +EXAMPLE_DATA_BY_OPERATION = dict[str, EXAMPLE_DATA_BY_NAME] diff --git a/oseg/oseg/model/jinja_macros.py b/oseg/oseg/model/jinja_macros.py new file mode 100644 index 000000000..3ba7c6e2c --- /dev/null +++ b/oseg/oseg/model/jinja_macros.py @@ -0,0 +1,14 @@ +from jinja2.runtime import Macro + + +class JinjaMacros: + def __init__(self, macros: dict[str, Macro]): + self.print_object: Macro = macros["print_object"] + self.print_object_array: Macro = macros["print_object_array"] + self.print_scalar: Macro = macros["print_scalar"] + self.print_scalar_array: Macro = macros["print_scalar_array"] + self.print_file: Macro = macros["print_file"] + self.print_file_array: Macro = macros["print_file_array"] + self.print_free_form: Macro = macros["print_free_form"] + self.print_free_form_array: Macro = macros["print_free_form_array"] + self.print_security: Macro = macros["print_security"] diff --git a/oseg/oseg/model/operation.py b/oseg/oseg/model/operation.py new file mode 100644 index 000000000..98dc731b9 --- /dev/null +++ b/oseg/oseg/model/operation.py @@ -0,0 +1,37 @@ +import openapi_pydantic as oa +from oseg import model + + +class Operation: + CODEGEN_REQUEST_BODY_NAME = "x-codegen-request-body-name" + + def __init__( + self, + operation: oa.Operation, + request: model.Request, + response: model.Response | None, + security: model.Security | None, + api_name: str, + http_method: str, + ): + self._operation: oa.Operation = operation + self.request: model.Request = request + self.response: model.Response | None = response + self.security: model.Security | None = security + self.api_name: str = api_name + self.http_method: str = http_method + self.operation_id: str = operation.operationId + self.extensions: dict[str, any] = {} + + for k, v in operation.model_extra.items(): + if k.startswith("x-"): + self.extensions[k] = v + + self.request.operation = self + + def request_body_name(self) -> str | None: + return ( + self.extensions[self.CODEGEN_REQUEST_BODY_NAME] + if self.CODEGEN_REQUEST_BODY_NAME in self.extensions + else None + ) diff --git a/oseg/oseg/model/printable.py b/oseg/oseg/model/printable.py new file mode 100644 index 000000000..91954c2cb --- /dev/null +++ b/oseg/oseg/model/printable.py @@ -0,0 +1,35 @@ +from dataclasses import dataclass +from typing import Literal + + +@dataclass +class PrintableFreeForm: + value: dict[str, any] | list[dict[str, any]] | None = None + is_array: bool = False + has_properties: bool = False + + +@dataclass +class PrintableObject: + value: str | list[str] | None = None + is_array: bool = False + target_type: str | None = None + + +@dataclass +class PrintableScalar: + value: str | list[str] | None = None + is_array: bool = False + is_enum: bool = False + target_type: str | None = None + + +@dataclass +class PrintableSecurity: + name: str + key: str + method: Literal["access_token", "api_key", "basic"] + value: str = "" + value_2: str = "" + # is the first security scheme(s) for Operation + is_primary: bool = False diff --git a/oseg/oseg/model/properties.py b/oseg/oseg/model/properties.py new file mode 100644 index 000000000..9280b071e --- /dev/null +++ b/oseg/oseg/model/properties.py @@ -0,0 +1,344 @@ +from __future__ import annotations + +from enum import Enum + +import openapi_pydantic as oa +from typing import Union, TypeVar, Generic, Protocol +from oseg import parser + + +SCALAR_TYPES = [ + oa.DataType.BOOLEAN, + oa.DataType.INTEGER, + oa.DataType.NUMBER, + oa.DataType.STRING, +] + + +class DataFormat(str, Enum): + DATETIME = "date-time" + DATE = "date" + FLOAT = "float" + DOUBLE = "double" + INT64 = "int64" + + +class PropertyInterface(Protocol): + value: any + + def __init__( + self, + schema: oa.Schema, + name: str, + value: any, + is_required: bool, + is_set: bool, + ): + self.schema: oa.Schema = schema + self.name: str = name + # maps to property name ignoring conflicts with other identical names + self.original_name: str = name + self.value = value + self.is_array: bool = parser.TypeChecker.is_array(self.schema) + self.is_required: bool = is_required + self.is_nullable: bool = parser.TypeChecker.is_nullable(self.schema) + self.is_set: bool = is_set + self.type: oa.DataType = self._get_type() + + # todo currently only support single type, not list of types + def _get_type(self) -> oa.DataType: + if self.is_array: + # todo figure out why this happens + if self.schema.items is None: + raise NotImplementedError("Array items == None") + + if isinstance(self.schema.items.type, list): + return self.schema.items.type[0] + + return self.schema.items.type + + if isinstance(self.schema.type, list): + return self.schema.type[0] + + return self.schema.type + + def _needs_default_value(self) -> bool: + if self.value is not None: + return False + + if not self.is_required or self.is_nullable: + return False + + return True + + +class PropertyFile(PropertyInterface): + _T = str | list[str] | None + _FORMAT_BYTES = "byte" + value: _T + + def __init__( + self, + schema: oa.Schema, + name: str, + value: _T, + is_required: bool, + is_set: bool, + ): + super().__init__(schema, name, value, is_required, is_set) + + self.is_bytes: bool = self.schema.schema_format == self._FORMAT_BYTES + + if self._needs_default_value(): + self.value = "some_file.pdf" if not self.is_array else [] + + +class PropertyFreeForm(PropertyInterface): + _T = dict[str, any] | list[dict[str, any]] | None + value: _T + has_properties: bool + + def __init__( + self, + schema: oa.Schema, + name: str, + value: _T, + is_required: bool, + is_set: bool, + ): + super().__init__(schema, name, value, is_required, is_set) + + if self._needs_default_value(): + self.value = {} if not self.is_array else [] + + self.has_properties = False + + if not self.is_array: + self.has_properties = bool(schema.properties == {}) + else: + self.has_properties = bool(schema.items.properties == {}) + + +class PropertyScalar(PropertyInterface): + _T_SINGLE = Union[str, int, bool] + _T_LIST = Union[list[str], list[int], list[bool]] + _T = Union[_T_SINGLE, _T_LIST, None] + value: _T + + def __init__( + self, + schema: oa.Schema, + name: str, + value: _T, + is_required: bool, + is_set: bool, + ): + super().__init__(schema, name, value, is_required, is_set) + + self.format: str | None = self._set_string_format() + self.is_enum: bool = self._set_is_enum() + self._normalize_value() + + def _normalize_value(self) -> None: + needs_default_value = self._needs_default_value() + + if self.is_array: + self.value: PropertyScalar._T_LIST + result = [] + + if not needs_default_value and self.value is None: + return + + for i in self.value if self.value is not None else []: + if self.type == oa.DataType.STRING: + result.append(str(i)) + elif self.type == oa.DataType.BOOLEAN: + result.append(bool(i)) + else: + i: int + result.append(i) + + self.value = result + + return + + if not needs_default_value and self.value is None: + return + + if self.type == oa.DataType.STRING: + value = self.value + + if needs_default_value: + value = self.schema.enum[0] if self.is_enum else f"{self.name}_string" + + self.value = str(value) + elif self.type == oa.DataType.BOOLEAN: + value = self.value if not needs_default_value else False + self.value = bool(value) + else: + value = self.value if not needs_default_value else 0 + self.value = value + + def _set_string_format(self) -> str | None: + if self.is_array: + return ( + self.schema.items.schema_format + if hasattr(self.schema.items, "schema_format") + else None + ) + + return ( + self.schema.schema_format if hasattr(self.schema, "schema_format") else None + ) + + def _set_is_enum(self) -> bool: + if self.is_array: + return ( + hasattr(self.schema.items, "enum") + and self.schema.items.enum is not None + ) + + return hasattr(self.schema, "enum") and self.schema.enum is not None + + +class PropertyObjectInterface(Protocol): + schema: oa.Schema + type: str + base_type: str | None + is_nullable: bool + is_required: bool + is_set: bool + name: str + # maps to property name ignoring conflicts with other identical names + original_name: str + properties: dict | list + is_array: bool + + +class PropertyObject(PropertyObjectInterface): + _TYPE = TypeVar("_TYPE", bound=type) + + def __init__( + self, + schema: oa.Schema, + _type: str, + base_type: str | None, + is_required: bool, + ): + self.schema = schema + self.type = _type + # discriminator base type, if any + self.base_type = base_type + self.is_required = is_required + self.is_nullable = parser.TypeChecker.is_nullable(self.schema) + self.properties: dict[str, PROPERTY_TYPES] = {} + self.name = _type + self.original_name = _type + self.is_set = True + self.is_array = False + + @property + def objects(self) -> dict[str, PropertyObject]: + return self._get_properties_of_type(PropertyObject, False) + + @property + def array_objects(self) -> dict[str, PropertyObjectArray]: + return self._get_properties_of_type(PropertyObjectArray, True) + + @property + def scalars(self) -> dict[str, PropertyScalar]: + return self._get_properties_of_type(PropertyScalar, False) + + @property + def array_scalars(self) -> dict[str, PropertyScalar]: + return self._get_properties_of_type(PropertyScalar, True) + + @property + def files(self) -> dict[str, PropertyFile]: + return self._get_properties_of_type(PropertyFile, False) + + @property + def array_files(self) -> dict[str, PropertyFile]: + return self._get_properties_of_type(PropertyFile, True) + + @property + def free_forms(self) -> dict[str, PropertyFreeForm]: + return self._get_properties_of_type(PropertyFreeForm, False) + + @property + def array_free_forms(self) -> dict[str, PropertyFreeForm]: + return self._get_properties_of_type(PropertyFreeForm, True) + + def non_objects( + self, + required: bool | None = None, + ) -> dict[str, PROPERTY_NON_OBJECT_TYPE]: + all_props = ( + self.scalars + | self.array_scalars + | self.files + | self.array_files + | self.free_forms + | self.array_free_forms + ) + ordered = {} + + for prop_name, prop in all_props.items(): + if (required is None or required is True) and prop.is_required: + ordered[prop_name] = prop + + for prop_name, prop in all_props.items(): + if (required is None or required is False) and not prop.is_required: + ordered[prop_name] = prop + + return ordered + + def _get_properties_of_type( + self, + type_of: Generic[_TYPE], + is_array: bool, + ) -> dict[str, Generic[_TYPE]]: + result = {} + + for name, prop in self.properties.items(): + if type_of == PropertyObject and isinstance(prop, type_of): + result[name] = prop + + continue + + if type_of == PropertyObjectArray and isinstance(prop, type_of): + result[name] = prop + + continue + + if not isinstance(prop, type_of) or prop.is_array != is_array: + continue + + result[name] = prop + + return result + + +class PropertyObjectArray(PropertyObjectInterface): + def __init__( + self, + schema: oa.Schema, + _type: str, + is_required: bool, + is_set: bool, + ): + self.schema: oa.Schema = schema + self.type: str = _type + self.base_type: str = _type + self.is_required: bool = is_required + self.is_nullable: bool = parser.TypeChecker.is_nullable(self.schema) + self.properties: list[PROPERTY_OBJECT_TYPE] = [] + self.name = _type + self.original_name = _type + self.is_set = is_set + self.is_array = True + + +PROPERTY_NON_OBJECT_TYPE = Union[PropertyFile, PropertyFreeForm, PropertyScalar] +PROPERTY_OBJECT_TYPE = Union[PropertyObject, PropertyObjectArray] +PROPERTY_TYPES = Union[PROPERTY_NON_OBJECT_TYPE, PROPERTY_OBJECT_TYPE] diff --git a/oseg/oseg/model/property_container.py b/oseg/oseg/model/property_container.py new file mode 100644 index 000000000..c3ffd2586 --- /dev/null +++ b/oseg/oseg/model/property_container.py @@ -0,0 +1,116 @@ +from __future__ import annotations +import openapi_pydantic as oa +from oseg import model, parser + + +class PropertyContainer: + _sorted: parser.SortedProperties + + def __init__(self, request: model.Request): + self._body: model.PROPERTY_TYPES | None = None + self.path: model.PropertyObject | None = None + self.query: model.PropertyObject | None = None + self.header: model.PropertyObject | None = None + self.cookie: model.PropertyObject | None = None + self.request: model.Request = request + self.is_body_required: bool = request.is_required + + self._is_sorted: bool = False + self._flattened_objects: dict[str, model.PropertyObject] = {} + self._sorter: parser.PropertySorter = parser.PropertySorter(self) + self._flattener: parser.PropertyFlattener = parser.PropertyFlattener(self) + + @property + def has_data(self) -> bool: + if parser.TypeChecker.is_property_objectish(self._body): + has_body_data = len(list(self._body.properties)) + else: + has_body_data = self._body is not None + + return bool( + has_body_data + or (self.path is not None and len(list(self.path.properties))) + or (self.query is not None and len(list(self.query.properties))) + or (self.header is not None and len(list(self.header.properties))) + or (self.cookie is not None and len(list(self.cookie.properties))) + ) + + @property + def body(self): + return self._body + + @body.setter + def body(self, data: model.PROPERTY_TYPES | None): + self._clear_sorted_properties() + self._body = data + + @property + def body_type(self) -> str | None: + body = self.body + + if body is None: + return None + + if isinstance(body, model.PropertyObjectArray): + return body.properties[0].type + + return body.type + + def is_parameter(self, prop: model.PROPERTY_TYPES) -> bool: + return ( + (self.path and prop in self.path.properties.values()) + or (self.query and prop in self.query.properties.values()) + or (self.header and prop in self.header.properties.values()) + or (self.cookie and prop in self.cookie.properties.values()) + ) + + def set_parameters( + self, + data: model.PropertyObject, + param_in: oa.ParameterLocation, + ) -> None: + self._clear_sorted_properties() + + if param_in.value == oa.ParameterLocation.PATH.value: + self.path = data + + if param_in.value == oa.ParameterLocation.QUERY.value: + self.query = data + + if param_in.value == oa.ParameterLocation.HEADER.value: + self.header = data + + if param_in.value == oa.ParameterLocation.COOKIE.value: + self.cookie = data + + def properties( + self, + required_flag: bool | None = None, + ) -> dict[str, model.PROPERTY_TYPES]: + self._sort() + + if required_flag is True: + return self._sorted.required + + if required_flag is False: + return self._sorted.optional + + return {**self._sorted.required, **self._sorted.optional} + + def flattened_objects(self) -> dict[str, model.PropertyObject]: + self._sort() + + return self._flattened_objects + + def _sort(self) -> None: + # properties not yet sorted/named + if not self._is_sorted: + self._is_sorted = True + self._sorted = self._sorter.sort() + self._flattened_objects = self._flattener.flatten() + + def _clear_sorted_properties(self): + self._required_properties = {} + self._optional_properties = {} + self._flattened_objects = {} + self._is_sorted = False diff --git a/oseg/oseg/model/request.py b/oseg/oseg/model/request.py new file mode 100644 index 000000000..b6b67b2bf --- /dev/null +++ b/oseg/oseg/model/request.py @@ -0,0 +1,74 @@ +import openapi_pydantic as oa +from dataclasses import dataclass +from oseg import model, parser + + +@dataclass +class Request: + def __init__( + self, + oa_parser: parser.OaParser, + operation: oa.Operation, + example_data_parser: parser.ExampleDataParser, + ): + self._oa_parser: parser.OaParser = oa_parser + self._example_data_parser: parser.ExampleDataParser = example_data_parser + self.body: oa.Schema | None = None + self.body_type: str | None = None + self.parameters: list[oa.Parameter] = ( + operation.parameters if operation.parameters else [] + ) + self.content: oa.MediaType | None = None + self.content_type: str = "" + self.has_formdata: bool = False + self.is_required: bool = False + + # only parameter data + if not operation.requestBody: + self.content_type = "application/json" + else: + self.is_required = operation.requestBody.required + self._set_content(operation.requestBody.content) + + self._example_data: dict[str, model.PropertyContainer] = ( + self._example_data_parser.from_oas_data(self, operation) + ) + self._custom_example_data: dict[str, model.PropertyContainer] = {} + + @property + def example_data(self) -> dict[str, model.PropertyContainer]: + # default to returning only custom examples + if len(self._custom_example_data): + return self._custom_example_data + + # fallback to example data read from the OAS file + return self._example_data + + @example_data.setter + def example_data(self, data: model.EXAMPLE_DATA_BY_NAME | None): + """Add custom data. + + If passing empty data then we delete previous custom data. + """ + + self._custom_example_data = self._example_data_parser.from_custom_data( + request=self, + example_data=data, + ) + + def _set_content(self, contents: dict[str, oa.MediaType]) -> None: + for content_type, content in contents.items(): + self.content = content + self.content_type = content_type + self.has_formdata = ( + content_type in parser.OperationParser.FORM_DATA_CONTENT_TYPES + ) + + if content.media_type_schema: + self.body = content.media_type_schema + self.body_type = self._oa_parser.get_component_name(self.body) + + if parser.TypeChecker.is_array(self.body): + self.body_type = self._oa_parser.get_component_name(self.body.items) + + return diff --git a/oseg/oseg/model/response.py b/oseg/oseg/model/response.py new file mode 100644 index 000000000..64343d396 --- /dev/null +++ b/oseg/oseg/model/response.py @@ -0,0 +1,39 @@ +import openapi_pydantic as oa +from oseg import parser + + +class Response: + def __init__( + self, + oa_parser: parser.OaParser, + response: oa.Response, + http_code: str, + ): + self._oa_parser: parser.OaParser = oa_parser + self._response: oa.Response = response + self.body: oa.Schema | None = None + self.body_type: str | None = None + self.http_code: str = http_code + self.content_type: str = "" + self._content: oa.MediaType | None = None + self.is_binary: bool = False + + self._set_content() + + def _set_content(self) -> None: + if not self._response.content: + return + + for content_type, content in self._response.content.items(): + self._content = content + self.content_type = content_type + + if content.media_type_schema: + self.body = content.media_type_schema + self.body_type = self._oa_parser.get_component_name(self.body) + self.is_binary = parser.TypeChecker.is_file(self.body) + + if parser.TypeChecker.is_array(self.body): + self.body_type = self._oa_parser.get_component_name(self.body.items) + + return diff --git a/oseg/oseg/model/security.py b/oseg/oseg/model/security.py new file mode 100644 index 000000000..0eed83204 --- /dev/null +++ b/oseg/oseg/model/security.py @@ -0,0 +1,115 @@ +import openapi_pydantic as oa +from dataclasses import dataclass +from enum import Enum +from oseg import parser + + +class SecurityTypeEnum(str, Enum): + API_KEY = "apiKey" + HTTP = "http" + OAUTH2 = "oauth2" + + # not currently supported + MUTUAL_TLS = "mutualTLS" + OPEN_ID_CONNECT = "openIdConnect" + + +class SecuritySchemeEnum(str, Enum): + BASIC = "basic" + BEARER = "bearer" + # not currently supported + DIGEST = "digest" + + +class SecurityMethod(str, Enum): + """What TemplateParser will actually use""" + + ACCESS_TOKEN = "access_token" + API_KEY = "api_key" + BASIC = "basic" + + +@dataclass +class SecurityScheme: + name: str + # key is the key value in the securitySchemes definition, not the "name" property + key: str + method: SecurityMethod + + +class Security: + def __init__( + self, + oa_parser: parser.OaParser, + operation: oa.Operation, + ): + self.is_optional: bool = False + self.schemes: list[dict[str, SecurityScheme]] = [] + + if ( + # security not defined anywhere + not operation.security + and not oa_parser.components.securitySchemes + # security disabled for this operation + ) or operation.security == {}: + self.is_optional = True + + return + + # operation-level security overrides global security schemes + for security in operation.security: + # empty dict means security is optional for this operation + if security == {}: + self.is_optional = True + + continue + + if isinstance(security, str): + scheme = oa_parser.components.securitySchemes[security] + + self.schemes.append( + { + security: SecurityScheme( + name=scheme.name if scheme.name else "", + key=security, + method=self._resolve_scheme_method(scheme), + ) + } + ) + + continue + + joined = {} + for key in security: + scheme = oa_parser.components.securitySchemes[key] + joined[key] = SecurityScheme( + name=scheme.name if scheme.name else "", + key=key, + method=self._resolve_scheme_method(scheme), + ) + + self.schemes.append(joined) + + def _resolve_scheme_method( + self, + security_scheme: oa.SecurityScheme, + ) -> SecurityMethod: + if security_scheme.type == SecurityTypeEnum.API_KEY: + return SecurityMethod.API_KEY + + if ( + security_scheme.type == SecurityTypeEnum.HTTP + and security_scheme.scheme == SecuritySchemeEnum.BASIC + ): + return SecurityMethod.BASIC + + if ( + security_scheme.type == SecurityTypeEnum.HTTP + and security_scheme.scheme == SecuritySchemeEnum.BEARER + ): + return SecurityMethod.ACCESS_TOKEN + + if security_scheme.type == SecurityTypeEnum.OAUTH2: + return SecurityMethod.ACCESS_TOKEN + + raise NotImplementedError("Cannot resolve security scheme type") diff --git a/oseg/oseg/oseg.py b/oseg/oseg/oseg.py new file mode 100644 index 000000000..236ab1de4 --- /dev/null +++ b/oseg/oseg/oseg.py @@ -0,0 +1,79 @@ +import os +from . import jinja_extension, generator, model, parser + + +class Generator: + def __init__( + self, + oas_file: str, + operation_id: str | None = None, + example_data: model.EXAMPLE_DATA_BY_OPERATION | str | None = None, + ): + if isinstance(example_data, str): + example_data = ( + parser.FileLoader.get_file_contents(example_data) + if os.path.isfile(example_data) + else None + ) + + self._oa_parser = parser.OaParser( + oas_file, + operation_id, + example_data, + ) + + def generate( + self, + config: generator.BaseConfig, + output_dir: str, + ) -> int: + jinja = jinja_extension.JinjaExt.factory() + + if not os.path.isdir(output_dir): + os.makedirs(output_dir) + + for _, operation in self._oa_parser.operations.items(): + for name, property_container in operation.request.example_data.items(): + sdk_generator = generator.GeneratorFactory.generator_factory( + config, + operation, + property_container, + ) + + operation_id = operation.operation_id + filename = parser.NormalizeStr.pascal_case(f"{operation_id}_{name}") + file_extension = sdk_generator.FILE_EXTENSION + target_file = f"{output_dir}/{filename}.{file_extension}" + + print(f"Begin parsing for {sdk_generator.NAME} {filename}") + + rendered = jinja.template(sdk_generator).render( + operation=operation, + example_name=name, + config=config, + ) + + with open(target_file, "w", encoding="utf-8") as f: + f.write(rendered) + + return 0 + + def setup_project( + self, + config: generator.BaseConfig, + base_dir: str, + output_dir: str, + ) -> int: + generator.GeneratorFactory.project_factory( + config, + base_dir, + output_dir, + ) + + return 0 + + def read_config_file( + self, + config: generator.BaseConfigDef | str, + ) -> generator.BaseConfig: + return generator.GeneratorFactory.config_factory(config) diff --git a/oseg/oseg/parser/__init__.py b/oseg/oseg/parser/__init__.py new file mode 100644 index 000000000..26178983f --- /dev/null +++ b/oseg/oseg/parser/__init__.py @@ -0,0 +1,18 @@ +from .file_loader import FileLoader +from .oa_parser import OaParser + +from .example_data_parser import ExampleDataParser +from .component_resolver import ComponentResolver, OA_RESOLVABLE +from .normalize_str import ( + NormalizeStr, + CamelCaseOption, + PascalCaseOption, + UnderscoreOption, +) +from .operation_parser import OperationParser +from .property_flattener import PropertyFlattener +from .property_parser import PropertyParser +from .property_sorter import PropertySorter, SortedProperties +from .schema_joiner import SchemaJoiner +from .template_parser import TemplateParser +from .type_checker import TypeChecker diff --git a/oseg/oseg/parser/component_resolver.py b/oseg/oseg/parser/component_resolver.py new file mode 100644 index 000000000..e8298a948 --- /dev/null +++ b/oseg/oseg/parser/component_resolver.py @@ -0,0 +1,495 @@ +import hashlib +import openapi_pydantic as oa +from typing import Union +from oseg import parser + +OA_RESOLVABLE = Union[ + oa.Example, + oa.Parameter, + oa.RequestBody, + oa.Response, + oa.Schema, + oa.SecurityScheme, +] + + +class ComponentResolver: + """Keeps track of all named Components. Also generates + dynamic-named Schemas. + + "Named" Component Schemas are considered those explicitly defined in + your OAS '#/components/schemas/' section. These schema are referenced by other + Schema using '$ref'. The '$ref' value looks like + '#/components/schemas/Pet'. openapi-generator will use this value to + generate a matching class name. + + For example, the csharp generator will create a file at + src/Org.OpenAPITools/Model/Pet.cs for '#/components/schemas/Pet'. + + Working with '$ref' throughout the codebase is annoying. It is much + simpler to resolve all these '$ref' to the actual Schema object. We + do not want to check if a given oa.Schema object is actually an + oa.Reference and then resolve it to get the oa.Schema object. + We can resolve everything here in one go. + + However, a resolved oa.Schema object itself does not actually know + what its '$ref' value is, so we cannot get the name for it without + first knowing looking at the parent oa.Reference! To solve this, we + can keep track of all named Schemas here. + + Pass in the resolved oa.Schema object and get back the original name + used in the '#/components/schemas/' section. + + Additionally, you can define type=object schemas outside of + the '#/components/schemas/' section, without using a '$ref' value. + When generating SDKs, openapi-generator will still create concrete + classes, but the name of these classes is dynamically generated + by combining information from the parent Schema. We will still want + to keep track of this name. + """ + + def __init__(self, oa_parser: parser.OaParser): + self._oa_parser: parser.OaParser = oa_parser + self._names: dict[int, str] = {} + self._dynamic_names: dict[str, str] = {} + + self._component_examples() + self._component_schemas() + self._component_parameters() + self._component_request_bodies() + self._component_responses() + self._component_security_schemes() + self._operations() + self._component_schema_properties() + + def name(self, schema: OA_RESOLVABLE) -> str | None: + schema_id = id(schema) + + return self._names[schema_id] if schema_id in self._names else None + + def _add(self, schema: OA_RESOLVABLE, name: str) -> None: + self._names[id(schema)] = name + + def _component_examples(self) -> None: + """Find named in '#/components/examples/'.""" + + for name, example in self._oa_parser.components.examples.items(): + example = self._oa_parser.resolve_example(example) + self._oa_parser.components.examples[name] = example + + self._add(example, name) + + def _component_schemas(self) -> None: + """Find named in '#/components/schemas/' first. + + Doing this process prevents incorrectly generating + dynamically-named Schemas later on. + + Do not process schema properties. If the schema is defined within + '#/components/schemas/' it will get the correct name generated, but + if there is an inline-defined, nested object property that may also + be identical to one defined in an operation of RequestBody then we want + to use that dynamically-generated name. + """ + + for name, schema in self._oa_parser.components.schemas.items(): + schema = self._oa_parser.resolve_component(schema) + self._oa_parser.components.schemas[name] = schema + + if not self._is_nameable(schema): + continue + + self._add(schema, name) + self._examples(schema) + + def _component_schema_properties(self) -> None: + """If an Operation has an inline-defined object that is identical to + an inline-defined object within '#/components/schemas/', then both + schemas will use the same name. + + We process properties of objects within '#/components/schemas/' after + processing all Operations and RequestBodies, so any identical schemas + will use the names generated by those. + + Otherwise, the generated name will include the parent component's name + as part of its final name. + """ + + for name, schema in self._oa_parser.components.schemas.copy().items(): + self._schema_properties(schema, name) + + def _component_parameters(self) -> None: + """Find named in '#/components/parameters/'. + + These components will NOT generate a distinct class! + """ + + for name, parameter in self._oa_parser.components.parameters.items(): + parameter = self._oa_parser.resolve_parameter(parameter) + schema = self._oa_parser.resolve_component(parameter.param_schema) + parameter.param_schema = schema + self._oa_parser.components.parameters[name] = parameter + + # empty name to prevent class being used + self._add(parameter, "") + self._schema_properties(schema, name) + self._examples(parameter) + + def _component_request_bodies(self) -> None: + """Find named in '#/components/requestBodies/'.""" + + for name, request_body in self._oa_parser.components.requestBodies.items(): + request_body = self._oa_parser.resolve_request_body(request_body) + self._oa_parser.components.requestBodies[name] = request_body + + self._add(request_body, name) + self._request_body(request_body) + + def _component_responses(self) -> None: + """Find named in '#/components/responses/'. + + Inline objects inside a '#/components/responses/' response will + NOT generate a distinct class! + """ + + for name, response in self._oa_parser.components.responses.items(): + response = self._oa_parser.resolve_response(response) + self._oa_parser.components.responses[name] = response + + self._add(response, name) + self._response(response) + + def _component_security_schemes(self) -> None: + """Find named in '#/components/securitySchemes/'.""" + + for name, security in self._oa_parser.components.securitySchemes.items(): + security = self._oa_parser.resolve_security(security) + self._oa_parser.components.securitySchemes[name] = security + + self._add(security, name) + + def _operations(self) -> None: + """Operation Requests will contain schemas in 'parameters' + and 'requestBody'. + """ + + for _, path_item in self._oa_parser.paths.items(): + self._parameters(path_item) + + for method in parser.OperationParser.HTTP_METHODS: + operation: oa.Operation | None = getattr(path_item, method) + + if not operation: + continue + + self._parameters(operation) + self._merge_parameters(path_item, operation) + self._operation_examples(operation) + + if operation.requestBody: + operation.requestBody = self._oa_parser.resolve_request_body( + operation.requestBody + ) + self._request_body(operation.requestBody, operation) + + if operation.responses: + for http_code, response in operation.responses.items(): + response = self._oa_parser.resolve_response(response) + operation.responses[http_code] = response + self._response(response) + + if operation.security is None: + operation.security = self._oa_parser.components.securitySchemes + + def _examples(self, schema: oa.Schema | oa.MediaType | oa.Parameter) -> None: + if schema.example: + schema.example = self._oa_parser.resolve_example(schema.example) + + if hasattr(schema, "examples") and schema.examples: + # list only for Schema + if isinstance(schema.examples, list): + for index, example in enumerate(schema.examples): + schema.examples[index] = self._oa_parser.resolve_example(example) + else: + for example_name, example in schema.examples.items(): + schema.examples[example_name] = self._oa_parser.resolve_example( + example + ) + + def _schema_properties( + self, + parent_schema: oa.Schema, + parent_name: str, + from_request_body: bool = False, + ) -> None: + self._all_of(parent_schema) + + if parser.TypeChecker.is_array(parent_schema): + parent_schema.items = self._oa_parser.resolve_component(parent_schema.items) + + if not parent_schema.properties: + return None + + for property_name, property_schema in parent_schema.properties.items(): + property_schema = self._oa_parser.resolve_component(property_schema) + parent_schema.properties[property_name] = property_schema + + self._dynamic_property( + schema=property_schema, + parent_name=parent_name, + name=property_name, + from_request_body=from_request_body, + ) + + if parser.TypeChecker.is_array(property_schema): + property_schema.items = self._oa_parser.resolve_component( + property_schema.items + ) + + self._all_of(property_schema) + self._examples(property_schema) + + def _dynamic_property( + self, + schema: oa.Schema, + parent_name: str, + name: str, + from_request_body: bool, + ) -> None: + """Generate a name for dynamic inline schemas. + + If from_request_body == True, it will try to find a pre-existing name + from the _dynamic_names dict. This dict is solely for names generated + for inline schemes defined within a request body. + + Otherwise, it generates a name using the parent schema name and property + name + """ + + if not self._is_nameable(schema): + return + + if self.name(schema): + return + + if not parser.TypeChecker.is_array(schema): + if schema.title is not None: + final_name = schema.title + else: + schema_hash = self._generate_schema_hash(schema) + + # check if an identical inline schema definition has already + # named, and use that name + if schema_hash in self._dynamic_names: + final_name = self._dynamic_names[schema_hash] + else: + final_name = f"{parent_name}_{name}" + + if from_request_body: + self._dynamic_names[schema_hash] = final_name + + self._add(schema, final_name) + self._oa_parser.components.schemas[final_name] = schema + + if parser.TypeChecker.is_object(schema): + self._schema_properties(schema, final_name, from_request_body) + + return + + schema.items = self._oa_parser.resolve_component(schema.items) + items_name = self.name(schema.items) + + if not items_name and parser.TypeChecker.is_object_array(schema): + schema_hash = self._generate_schema_hash(schema.items) + + if schema_hash in self._dynamic_names: + items_name = self._dynamic_names[schema_hash] + else: + items_name = f"{parent_name}_{name}_inner" + self._dynamic_names[schema_hash] = items_name + + self._add(schema.items, items_name) + self._schema_properties(schema.items, items_name, from_request_body) + + def _request_body( + self, + request_body: oa.RequestBody | oa.Reference, + operation: oa.Operation | None = None, + ) -> None: + for content_type, media_type in request_body.content.items(): + if not media_type.media_type_schema: + continue + + schema = self._oa_parser.resolve_component(media_type.media_type_schema) + media_type.media_type_schema = schema + name = self.name(schema) + + # if body data is an array, use the name of the items schema + if parser.TypeChecker.is_array(schema): + schema.items = self._oa_parser.resolve_component(schema.items) + array_name = self.name(schema.items) + + if array_name is None and name: + self._add(schema.items, name) + self._oa_parser.components.requestBodies[name] = schema.items + + if name is None and operation: + if schema.title is not None: + name = schema.title + else: + schema_hash = self._generate_schema_hash(schema) + + # check if an identical inline schema definition has already + # named, and use that name + if schema_hash in self._dynamic_names: + name = self._dynamic_names[schema_hash] + else: + name = f"{operation.operationId}_request" + self._dynamic_names[schema_hash] = name + + self._add(schema, name) + self._oa_parser.components.schemas[name] = schema + + self._schema_properties(schema, name, from_request_body=True) + self._examples(media_type) + + # openapi-generator will only ever look at the first request + return + + def _response( + self, + response: oa.Response | oa.Reference, + ) -> None: + """Unlike RequestBody, we don't care about properties in response schemas""" + + if not response.content: + return + + for content_type, media_type in response.content.items(): + if not media_type.media_type_schema: + continue + + schema = self._oa_parser.resolve_component(media_type.media_type_schema) + media_type.media_type_schema = schema + self._examples(media_type) + + def _parameters(self, parent: oa.Operation | oa.PathItem) -> None: + """named parameters do not create a class""" + + if not parent.parameters: + return + + result: list[oa.Parameter] = [] + + for parameter in parent.parameters: + parameter = self._oa_parser.resolve_parameter(parameter) + + if self.name(parameter) is None and self._is_nameable(parameter): + parameter.param_schema = self._oa_parser.resolve_component( + parameter.param_schema + ) + + add_to_components = True + if parameter.param_schema.title is not None: + name = parameter.param_schema.title + elif hasattr(parent, "operationId"): + name = f"{parent.operationId}_{parameter.name}_parameter" + else: + name = f"{parameter.name}_parameter" + add_to_components = False + + self._add(parameter, name) + + if add_to_components: + self._oa_parser.components.parameters[name] = parameter + + schema = self._oa_parser.resolve_component(parameter.param_schema) + parameter.param_schema = schema + result.append(parameter) + + parent.parameters = result + + def _merge_parameters( + self, + path_item: oa.PathItem, + operation: oa.Operation, + ) -> None: + """Merge Common Parameters (CParams) and Operation Parameters (OParams). + + CParams order will take precedence over OParams. + An OParams overrides a CParams's data but not its defined order. + CParams will always be listed before OParams, while also respecting + "required" flags. + """ + + if not path_item.parameters: + return + + # No OParams, copy all CParams to OParams + if not operation.parameters: + operation.parameters = path_item.parameters + + return + + merged: dict[str, oa.Parameter] = {} + + for parameter in path_item.parameters: + merged[f"{parameter.param_in}_{parameter.name}"] = parameter + + # override CParams with OParams where applicable + for parameter in operation.parameters: + merged[f"{parameter.param_in}_{parameter.name}"] = parameter + + operation.parameters = list(merged.values()) + + def _operation_examples(self, operation: oa.Operation) -> None: + if not operation.model_extra or "examples" not in operation.model_extra: + return + + operation_examples = operation.model_extra.get("examples") + + for example_name, example in operation_examples.items(): + if not isinstance(example, dict): + continue + + if "$ref" not in example: + continue + + example: oa.Example + + operation_examples[example_name] = self._oa_parser.resolve_example(example) + + def _all_of(self, schema: oa.Schema) -> None: + if not schema.allOf: + return + + schemas = [] + + for i in schema.allOf: + resolved = self._oa_parser.resolve_component(i) + resolved_name = self.name(resolved) + + self._schema_properties(resolved, resolved_name) + schemas.append(resolved) + + schema.allOf = schemas + + def _is_nameable(self, schema: OA_RESOLVABLE) -> bool: + return ( + parser.TypeChecker.is_ref(schema) + or parser.TypeChecker.is_ref_array(schema) + or parser.TypeChecker.is_object(schema) + or parser.TypeChecker.is_object_array(schema) + # Schema + or (hasattr(schema, "allOf") and schema.allOf) + # RequestBody / Response + or (hasattr(schema, "content") and schema.content) + # Parameter + or ( + hasattr(schema, "param_schema") + and self._is_nameable(schema.param_schema) + ) + ) + + def _generate_schema_hash(self, schema: OA_RESOLVABLE) -> str: + return hashlib.sha256(str(schema).encode()).hexdigest() diff --git a/oseg/oseg/parser/example_data_parser.py b/oseg/oseg/parser/example_data_parser.py new file mode 100644 index 000000000..b5784c22a --- /dev/null +++ b/oseg/oseg/parser/example_data_parser.py @@ -0,0 +1,396 @@ +from __future__ import annotations +import openapi_pydantic as oa +from oseg import parser, model + + +class ExampleDataParser: + DEFAULT_EXAMPLE_NAME = "example" + + def __init__(self, oa_parser: parser.OaParser): + self._oa_parser: parser.OaParser = oa_parser + self._property_parser: parser.PropertyParser = parser.PropertyParser(oa_parser) + self._schema_joiner: parser.SchemaJoiner = parser.SchemaJoiner(oa_parser) + + def from_oas_data( + self, + request: model.Request, + operation: oa.Operation, + ) -> dict[str, model.PropertyContainer]: + """Parse example data embedded in OAS file. + + Only needs done once per Request. + """ + + """Operation has "examples" defined in OAS file""" + operation_examples = self._get_operation_example_data(operation) + + if len(operation_examples.keys()): + results = {} + + for example_name, example in operation_examples.items(): + results[example_name] = self._parse_example( + request=request, + example_data=model.ExampleData( + body=example.get("body", {}), + parameters=model.ExampleDataParams(example), + ), + ) + + return results + + """Read parameter example data from OAS file. + + We will only ever want a single set of example data for parameters. + + We will copy the same set of parameter example data for all body data + in this request. + + To have different example data for any given request + use custom example data. + """ + example_data_params = model.ExampleDataParams( + self._get_parameter_example_data(request), + ) + example_data_body = self._get_body_example_data(request) + + # only parameter data found + if not len(example_data_body.keys()): + return { + self.DEFAULT_EXAMPLE_NAME: self._parse_example( + request=request, + example_data=model.ExampleData( + body={}, + parameters=example_data_params, + ), + ) + } + + # copy the same set of parameter example data to all + results = {} + + for name, body_example in example_data_body.items(): + results[name] = self._parse_example( + request=request, + example_data=model.ExampleData( + body=body_example, + parameters=example_data_params, + ), + ) + + return results + + def from_custom_data( + self, + request: model.Request, + example_data: model.EXAMPLE_DATA_BY_NAME | None, + ) -> dict[str, model.PropertyContainer]: + """Custom example data provided outside of OAS file""" + + if example_data is None: + return {} + + results = {} + + for name, example in example_data.items(): + if not isinstance(example, dict): + continue + + example_data = model.ExampleData( + body=example.get("body", {}), + parameters=model.ExampleDataParams(example), + ) + + if not example_data.has_body_data and not example_data.has_parameter_data: + continue + + results[name] = self._parse_example( + request=request, + example_data=example_data, + ) + + return results + + def _get_operation_example_data( + self, + operation: oa.Operation, + ) -> model.EXAMPLE_DATA_BY_NAME: + """Read operation example data from OAS file. + + Each operation can have multiple examples containing body and parameters. + """ + + if not operation.model_extra or "examples" not in operation.model_extra: + return {} + + operation_examples = operation.model_extra.get("examples") + + if not isinstance(operation_examples, dict): + return {} + + # multiple examples from operation schema + data = {} + + for example_name, example in operation_examples.items(): + file_data = self._oa_parser.file_loader.get_example_data(example) + + if file_data: + data[example_name] = file_data + + return data + + def _get_parameter_example_data( + self, + request: model.Request, + ) -> model.ExampleDataParamDef: + result = { + oa.ParameterLocation.PATH.value: {}, + oa.ParameterLocation.QUERY.value: {}, + oa.ParameterLocation.HEADER.value: {}, + oa.ParameterLocation.COOKIE.value: {}, + } + + if not request.parameters: + return result + + for parameter in request.parameters: + value = None + + if parameter.example: + value = parameter.example + elif parameter.examples: + for k, v in parameter.examples.items(): + value = v.value + break + elif parameter.param_schema.example: + value = parameter.param_schema.example + elif ( + hasattr(parameter.param_schema, "examples") + and parameter.param_schema.examples + ): + value = parameter.param_schema.examples[0] + elif parameter.param_schema.default is not None: + value = parameter.param_schema.default + + result[parameter.param_in][parameter.name] = value + + return result + + def _get_body_example_data( + self, + request: model.Request, + ) -> dict[str, model.EXAMPLE_DATA_BODY]: + """Read body example data from OAS file. + + Each request can have multiple body examples. + """ + + # Data from content schema wins out over property-specific data + content_examples = self._example_data_from_content(request.content) + + if len(content_examples.keys()): + return content_examples + + # no body, nothing further to check + if not request.body: + return {} + + return { + self.DEFAULT_EXAMPLE_NAME: self._example_data_from_properties( + schema=request.body, + parents=[], + ), + } + + def _example_data_from_content( + self, + content: oa.MediaType | None, + ) -> dict[str, any]: + if not content: + return {} + + # only a single example from content schema + if content.example and ( + (isinstance(content.example, dict) and len(content.example.keys())) + or (isinstance(content.example, list) and len(content.example)) + ): + return {self.DEFAULT_EXAMPLE_NAME: content.example} + + if not content.examples or not len(content.examples.keys()): + return {} + + # multiple examples from content schema + data = {} + + for example_name, example in content.examples.items(): + file_data = self._oa_parser.file_loader.get_example_data(example) + + if file_data: + data[example_name] = file_data + + continue + + if isinstance(example.value, dict): + data[example_name] = example.value + + return data + + def _example_data_from_properties( + self, + schema: oa.Schema, + parents: list[int], + ) -> model.EXAMPLE_DATA_BODY | None: + schema_id = id(schema) + + if schema_id in parents: + return None + + parents.append(schema_id) + + # example data wins out over everything + if schema.example is not None: + return schema.example + + # examples data wins out over everything else, + # but only want the first set of values + if hasattr(schema, "examples") and schema.examples is not None: + return schema.examples[0] + + # if property is nullable and default value is null, use it + if schema.default is None and parser.TypeChecker.is_nullable(schema): + return None + + if schema.default is not None: + return schema.default + + if parser.TypeChecker.is_array(schema): + items_data = self._example_data_from_properties( + schema=schema.items, + parents=parents[:], + ) + + if items_data is not None: + return [items_data] + + return [] + + data = {} + + if parser.TypeChecker.is_object(schema): + for prop_name, prop_schema in schema.properties.items(): + result = self._example_data_from_properties( + schema=prop_schema, + parents=parents[:], + ) + + if self._can_skip_null(schema, prop_schema, prop_name, result): + continue + + data[prop_name] = result + + """Once we have base object default data built see if we are dealing + with a discriminator or allOf + """ + if parser.TypeChecker.is_object(schema) or schema.allOf: + merged = self._schema_joiner.merge_schemas_and_properties(schema, data) + + for prop_name, prop_schema in merged.properties.items(): + result = self._example_data_from_properties( + schema=prop_schema, + parents=parents[:], + ) + + if self._can_skip_null(schema, prop_schema, prop_name, result): + continue + + data[prop_name] = result + + return data if len(data.keys()) else None + + def _parse_example( + self, + request: model.Request, + example_data: model.ExampleData, + ) -> model.PropertyContainer: + container = model.PropertyContainer(request) + + loop_data = { + oa.ParameterLocation.PATH: example_data.path, + oa.ParameterLocation.QUERY: example_data.query, + oa.ParameterLocation.HEADER: example_data.header, + oa.ParameterLocation.COOKIE: example_data.cookie, + } + + for param_in, param_data in loop_data.items(): + schema = self._schema_for_params_in( + parameters=request.parameters, + param_in=param_in, + ) + + if schema: + container.set_parameters( + data=self._property_parser.parse( + schema=schema, + data=param_data, + ), + param_in=param_in, + ) + + if request.body: + parsed = self._property_parser.parse( + schema=request.body, + data=example_data.body, + ) + + if parsed: + container.body = parsed + + return container + + def _schema_for_params_in( + self, + parameters: list[oa.Parameter], + param_in: oa.ParameterLocation, + ) -> oa.Schema | None: + """Generates a temporary Schema for parsing by PropertyParser""" + + properties = {} + required = [] + + for parameter in parameters: + if parameter.param_in.value != param_in.value: + continue + + properties[parameter.name] = parameter.param_schema + + if parameter.required: + required.append(parameter.name) + + if not len(properties.keys()): + return None + + schema = oa.Schema() + schema.properties = properties + schema.required = required + + return schema + + def _can_skip_null( + self, + parent: oa.Schema, + prop: oa.Schema, + prop_name: str, + value: any, + ) -> bool: + """If a property's value is None, and it is not required, and it is non-nullable, + do not add it to example data. + """ + + if value is not None: + return False + + if parent.required and prop_name in parent.required: + return False + elif parser.TypeChecker.is_nullable(prop): + return False + + return True diff --git a/oseg/oseg/parser/file_loader.py b/oseg/oseg/parser/file_loader.py new file mode 100644 index 000000000..f873c69ef --- /dev/null +++ b/oseg/oseg/parser/file_loader.py @@ -0,0 +1,56 @@ +import json +import os +import openapi_pydantic as oa +import yaml +from pathlib import Path + + +class FileLoader: + def __init__(self, oas_file: str): + self._oas_file: str = oas_file + self.base_dir: str = os.path.dirname(oas_file) + self.oas: dict[str, any] = self.get_file_contents(self._oas_file) + self._cached_example_data: dict[str, dict[str, any]] = {} + + @staticmethod + def get_file_contents(filename: str) -> dict[str, any]: + if not os.path.isfile(filename): + return {} + + with open(filename, "r", encoding="utf-8") as f: + if Path(filename).suffix == ".json": + results = json.load(f) + else: + results = yaml.safe_load(f) + + return results if isinstance(results, dict) else {} + + def get_example_data(self, example_schema: oa.Example) -> dict[str, any] | None: + """Read example data from external file. + + The filename comes from embedded $ref value in an Example schema. + Filenames are prepended with the directory where the OAS file is + located. + """ + + if not isinstance(example_schema.value, dict): + return None + + ref = example_schema.value.get("$ref") + + if not ref: + return None + + if ref in self._cached_example_data: + return self._cached_example_data[ref] + + filename = f"{self.base_dir}/{ref}" + + try: + data = self.get_file_contents(filename) + self._cached_example_data[ref] = data + + return data + except Exception as e: + print(f"Error reading example file {filename}") + print(e) diff --git a/oseg/oseg/parser/normalize_str.py b/oseg/oseg/parser/normalize_str.py new file mode 100644 index 000000000..3c41ae729 --- /dev/null +++ b/oseg/oseg/parser/normalize_str.py @@ -0,0 +1,239 @@ +import re +from enum import Enum +from typing import Callable + + +class CamelCaseOption(Enum): + UPPERCASE_KEEP = 1 + LOWERCASE_CONTIGUOUS = 2 + LOWERCASE_FIRST_SECTION = 3 + + +class PascalCaseOption(Enum): + UPPERCASE_KEEP = 1 + LOWERCASE_CONTIGUOUS = 2 + + +class UnderscoreOption(Enum): + FIRST_CHAR_JOIN = 1 + FIRST_CHAR_SEPARATE = 2 + + +class NormalizeStr: + _REGEX_CACHE: dict[str, re.Pattern[str]] = {} + _camelize_cache: dict[str, str] = {} + _underscore_cache: dict[str, str] = {} + + @classmethod + def camel_case( + cls, + value: str, + option: CamelCaseOption = CamelCaseOption.UPPERCASE_KEEP, + ) -> str: + """camelCase a string + + option: CamelCaseOption + Keep uppercase characters as-is. Otherwise you won't see + contiguous uppercase characters. + + For "LD-API-Version": + UPPERCASE_KEEP: lDAPIVersion + LOWERCASE_CONTIGUOUS: ldApiVersion + LOWERCASE_FIRST_SECTION: ldAPIVersion + """ + + if option == CamelCaseOption.LOWERCASE_CONTIGUOUS: + value = cls.snake_case(value) + + if option == CamelCaseOption.LOWERCASE_FIRST_SECTION: + values = cls.underscore(value).split("_") + values[0] = values[0].lower() + value = "_".join(values) + + return cls.lc_first(cls._camelize(value)) + + @classmethod + def pascal_case( + cls, + value: str, + option: PascalCaseOption = PascalCaseOption.UPPERCASE_KEEP, + ) -> str: + """PascalCase a string + + option: PascalCaseOption + Keep uppercase characters as-is. Otherwise you won't see + contiguous uppercase characters. + + For "UserID_789": + UPPERCASE_KEEP: UserID789 + LOWERCASE_CONTIGUOUS: UserId789 + """ + + if option == PascalCaseOption.LOWERCASE_CONTIGUOUS: + value = cls.snake_case(value) + + return cls.uc_first(cls._camelize(value)) + + @classmethod + def snake_case(cls, value: str) -> str: + """snake_case a string, all lowercase""" + + return cls.underscore(value).lower() + + @classmethod + def underscore( + cls, + value: str, + option: UnderscoreOption = UnderscoreOption.FIRST_CHAR_JOIN, + ) -> str: + """Underscore the given word. + + Character case is left as-is. + + separate_first_char: UnderscoreOption + When a string is two characters long and both characters + are uppercase, separate them with an underscore: + + For "AB": + FIRST_CHAR_JOIN: AB + FIRST_CHAR_SEPARATE: A_B + + When a string is three characters or longer and the first two + characters are uppercase, always separate them with an underscore: + + For "ABC": + FIRST_CHAR_JOIN: ABC + FIRST_CHAR_SEPARATE: A_BC + + Copied from openapi-generator + https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/StringUtils.java + """ + + if value is None: + return "" + + cache_key = f"{value}_{option.value}" + + if cache_key in cls._underscore_cache: + return cls._underscore_cache[cache_key] + + if len(value) < 2: + return value + + replacement_pattern = r"\1_\2" + + # Replace package separator with slash. + result = cls._get_regex_pattern("underscore_pkg_separator_pattern").sub( + "/", value + ) + # Replace $ with two underscores for inner classes. + result = cls._get_regex_pattern("dollar_pattern").sub("__", result) + # Replace capital letter with _ plus lowercase letter. + result = cls._get_regex_pattern("underscore_capital_letter_pattern").sub( + replacement_pattern, result + ) + result = cls._get_regex_pattern("underscore_lowercase_pattern").sub( + replacement_pattern, result + ) + result = result.replace("-", "_") + # Replace space with underscore + result = result.replace(" ", "_") + # Replace non-alphanumeric with _ + result = cls._get_regex_pattern( + "underscore_non_alphanumeric_underscore_pattern" + ).sub("_", result) + # Replace any double __ with single _ (yes it undoes a step from above) + result = result.replace("__", "_") + # Remove trailing whitespace or _ + result = result.strip(" _") + + # the first char is special, it will always be separate from rest + # when caps and next character is caps + if ( + option == UnderscoreOption.FIRST_CHAR_SEPARATE + and len(result) >= 2 + and result[0].isupper() + and result[1].isupper() + ): + result = f"{result[:1].upper()}_{result[1:]}" + + cls._underscore_cache[cache_key] = result + + return result + + @classmethod + def _camelize(cls, value: str) -> str: + if value in cls._camelize_cache: + return cls._camelize_cache[value] + + original = value + + value = cls.underscore(value) + + # Replace all slashes with dots + value = cls._get_regex_pattern("camelize_slash_pattern").sub( + lambda m: "." + m.group(1).replace("\\", "\\\\"), value + ) + + # Uppercase first letter of each part split by dots + value = "".join(cls.uc_first(part) for part in value.split(".")) + + # Apply uppercase pattern replacement + match = cls._get_regex_pattern("camelize_uppercase_pattern").match(value) + if match: + value = match.group(1) + match.group(2).upper() + match.group(3) + value = cls._get_regex_pattern("dollar_pattern").sub("\\$", value) + + # Remove all underscores + value = cls._get_regex_pattern("camelize_underscore_pattern").sub( + lambda m: m.group(2).upper() if m.group(2).islower() else m.group(2), value + ) + value = cls._get_regex_pattern("camelize_simple_underscore_pattern").sub( + "", value + ) + + # Remove all hyphens + value = cls._get_regex_pattern("camelize_hyphen_pattern").sub( + lambda m: m.group(2).upper(), value + ) + + cls._camelize_cache[original] = value + + return value + + @classmethod + def uc_first(cls, value: str) -> str: + return f"{value[:1].upper()}{value[1:]}" + + @classmethod + def lc_first(cls, value: str) -> str: + return f"{value[:1].lower()}{value[1:]}" + + @classmethod + def _get_regex_pattern(cls, name: str) -> re.Pattern[str]: + if name in cls._REGEX_CACHE: + return cls._REGEX_CACHE[name] + + patterns: dict[str, Callable[[], re.Pattern[str]]] = { + "dollar_pattern": lambda: re.compile(r"\$"), + "camelize_slash_pattern": lambda: re.compile(r"\/(.?)"), + "camelize_uppercase_pattern": lambda: re.compile(r"(\.?)(\w)([^\.]*)$"), + "camelize_underscore_pattern": lambda: re.compile(r"(_)(.)"), + "camelize_hyphen_pattern": lambda: re.compile(r"(-)(.)"), + "camelize_simple_underscore_pattern": lambda: re.compile(r"_"), + "underscore_capital_letter_pattern": lambda: re.compile( + r"([A-Z]+)([A-Z][a-z][a-z]+)" + ), + "underscore_lowercase_pattern": lambda: re.compile(r"([a-z\d])([A-Z])"), + "underscore_pkg_separator_pattern": lambda: re.compile(r"\."), + "underscore_non_alphanumeric_underscore_pattern": lambda: re.compile( + r"[^a-zA-Z0-9]" + ), + } + + if name not in patterns: + raise NotImplementedError + + cls._REGEX_CACHE[name] = patterns[name]() + + return cls._REGEX_CACHE[name] diff --git a/oseg/oseg/parser/oa_parser.py b/oseg/oseg/parser/oa_parser.py new file mode 100644 index 000000000..f3eea3e1a --- /dev/null +++ b/oseg/oseg/parser/oa_parser.py @@ -0,0 +1,146 @@ +from __future__ import annotations +import openapi_pydantic as oa +from oseg import model, parser + + +class OaParser: + def __init__( + self, + oas_file: str, + operation_id: str | None = None, + example_data: model.EXAMPLE_DATA_BY_OPERATION | None = None, + ): + self.file_loader: parser.FileLoader = parser.FileLoader(oas_file) + self._openapi: oa.OpenAPI = oa.parse_obj(self.file_loader.oas) + self._setup_oas() + + self.paths: dict[str, oa.PathItem] = self._openapi.paths + self.security: list[dict[str, list[str]]] | None = self._openapi.security + self.components: oa.Components = self._openapi.components + + self._component_resolver: parser.ComponentResolver = parser.ComponentResolver( + self, + ) + example_data_parser: parser.ExampleDataParser = parser.ExampleDataParser(self) + operation_parser: parser.OperationParser = parser.OperationParser( + self, + example_data_parser, + ) + + self.operations: dict[str, model.Operation] = operation_parser.setup_operations( + operation_id=operation_id, + example_data=example_data, + ) + + def resolve_component(self, schema: oa.Schema | oa.Reference) -> oa.Schema: + return self._get_resolved_component(schema, self.components.schemas) + + def resolve_parameter(self, schema: oa.Parameter | oa.Reference) -> oa.Parameter: + return self._get_resolved_component(schema, self.components.parameters) + + def resolve_request_body( + self, + schema: oa.RequestBody | oa.Reference, + ) -> oa.RequestBody: + return self._get_resolved_component(schema, self.components.requestBodies) + + def resolve_response(self, schema: oa.Response | oa.Reference) -> oa.Response: + return self._get_resolved_component(schema, self.components.responses) + + def resolve_security( + self, + schema: oa.SecurityScheme | oa.Reference, + ) -> oa.SecurityScheme: + return self._get_resolved_component(schema, self.components.securitySchemes) + + def resolve_example(self, schema: oa.Example | oa.Reference) -> oa.Example | None: + return self._get_resolved_component(schema, self.components.examples) + + def resolve_property( + self, + schema: oa.Schema | oa.Reference, + property_name: str, + ) -> oa.Schema | None: + """Only returns a Schema for properties that have a 'type' value""" + + schema = self.resolve_component(schema) + + if schema.properties is None: + return None + + property_schema = schema.properties.get(property_name) + + if property_schema is None: + return None + + property_schema = self.resolve_component(property_schema) + + if not hasattr(property_schema, "type") or not property_schema.type: + return None + + return property_schema + + def get_component_name(self, schema: parser.OA_RESOLVABLE) -> str | None: + return self._component_resolver.name(schema) + + def _setup_oas(self) -> None: + if not self._openapi.components: + self._openapi.components = oa.Components() + + if not self._openapi.components.examples: + self._openapi.components.examples = {} + + if not self._openapi.components.headers: + self._openapi.components.headers = {} + + if not self._openapi.components.parameters: + self._openapi.components.parameters = {} + + if ( + hasattr(self._openapi.components, "pathItems") + and not self._openapi.components.pathItems + ): + self._openapi.components.pathItems = {} + + if not self._openapi.components.requestBodies: + self._openapi.components.requestBodies = {} + + if not self._openapi.components.responses: + self._openapi.components.responses = {} + + if not self._openapi.components.schemas: + self._openapi.components.schemas = {} + + if not self._openapi.components.securitySchemes: + self._openapi.components.securitySchemes = {} + + if not self._openapi.paths: + self._openapi.paths = {} + + def _get_resolved_component( + self, + schema: parser.OA_RESOLVABLE, + components: dict[str, parser.OA_RESOLVABLE], + ): + name = None + + # Example schema may use "$ref" for external file + if isinstance(schema, dict) and "ref" in schema: + name = schema.get("ref").split("/").pop() + elif isinstance(schema, dict) and "$ref" in schema: + name = schema.get("$ref").split("/").pop() + + if name is not None: + return self._get_resolved_component(components.get(name), components) + + if name is None and not parser.TypeChecker.is_ref(schema): + return schema + + if isinstance(schema, str): + name = schema.split("/").pop() + elif hasattr(schema, "model_extra") and "$ref" in schema.model_extra: + name = schema.model_extra.get("$ref").split("/").pop() + else: + name = schema.ref.split("/").pop() + + return self._get_resolved_component(components.get(name), components) diff --git a/oseg/oseg/parser/operation_parser.py b/oseg/oseg/parser/operation_parser.py new file mode 100644 index 000000000..eef6345bc --- /dev/null +++ b/oseg/oseg/parser/operation_parser.py @@ -0,0 +1,110 @@ +from __future__ import annotations +import openapi_pydantic as oa +from oseg import parser, model + + +class OperationParser: + HTTP_METHODS = [ + "get", + "post", + "put", + "patch", + "delete", + "head", + "options", + "trace", + ] + + FORM_DATA_CONTENT_TYPES = [ + "application/x-www-form-urlencoded", + "multipart/form-data", + ] + + DEFAULT_API_NAME = "default" + + def __init__( + self, + oa_parser: parser.OaParser, + example_data_parser: parser.ExampleDataParser, + ): + self._oa_parser: parser.OaParser = oa_parser + self._example_data_parser: parser.ExampleDataParser = example_data_parser + + def setup_operations( + self, + operation_id: str | None, + example_data: model.EXAMPLE_DATA_BY_OPERATION | None, + ) -> dict[str, model.Operation]: + example_data = example_data if example_data else {} + + if operation_id: + operation_id = operation_id.lower() + + operations: dict[str, model.Operation] = {} + + for path, path_item in self._oa_parser.paths.items(): + for http_method in self.HTTP_METHODS: + oa_operation: oa.Operation | None = getattr(path_item, http_method) + + if not oa_operation or ( + operation_id and oa_operation.operationId.lower() != operation_id + ): + continue + + custom_example_data = example_data.get(oa_operation.operationId, {}) + + if not isinstance(custom_example_data, dict): + custom_example_data = {} + + request = self._get_request(oa_operation, custom_example_data) + + operation = model.Operation( + operation=oa_operation, + request=request, + response=self._get_response(oa_operation), + security=model.Security(self._oa_parser, oa_operation), + api_name=self._get_api_name(oa_operation), + http_method=http_method, + ) + + operations[oa_operation.operationId] = operation + + return operations + + def _get_request( + self, + operation: oa.Operation, + custom_example_data: model.EXAMPLE_DATA_BY_NAME, + ) -> model.Request | None: + """Only want the first request, if any""" + + request = model.Request( + oa_parser=self._oa_parser, + operation=operation, + example_data_parser=self._example_data_parser, + ) + + request.example_data = custom_example_data + + return request + + def _get_response(self, operation: oa.Operation) -> model.Response | None: + """Only want the first response, if any""" + + if not operation.responses: + return None + + for http_code, response in operation.responses.items(): + return model.Response( + oa_parser=self._oa_parser, + response=response, + http_code=http_code, + ) + + return None + + def _get_api_name(self, operation: oa.Operation) -> str: + if operation.tags and len(operation.tags): + return operation.tags[0] + + return self.DEFAULT_API_NAME diff --git a/oseg/oseg/parser/property_flattener.py b/oseg/oseg/parser/property_flattener.py new file mode 100644 index 000000000..8e316b4c0 --- /dev/null +++ b/oseg/oseg/parser/property_flattener.py @@ -0,0 +1,110 @@ +from __future__ import annotations +from oseg import model, parser + + +class PropertyFlattener: + def __init__(self, container: model.PropertyContainer): + self._container: model.PropertyContainer = container + + def flatten(self) -> dict[str, model.PROPERTY_OBJECT_TYPE]: + """Reads through request parameters and body data to recursively find all + PropertyObject and PropertyObjectArray objects, returned in a flat + dict. + + Any object dependencies (sub-objects) of a given object will + be found and appended to the list before the object itself. + In this way sub-objects can be parsed in a Jinja template as + variables before the object variable that references them is parsed. + + Non-objects are not included as they can be defined inline as an + object's property. + """ + + result = {} + + for name, prop in self._container.properties().items(): + if not isinstance(prop, model.PropertyObject) and not isinstance( + prop, model.PropertyObjectArray + ): + continue + + sub_results = self._flatten_object( + parent=prop, + parent_name="", + ) + + result = {**result, **sub_results} + + """If formdata then we are dealing with each body property + individually so we must add the object to the result list + """ + if self._container.body and self._container.request.has_formdata: + current = {prop.name: prop} + result = {**result, **current} + + """Requests without formdata will have their body content defined + as a single object in the request, containing all its sub data. + + See OperationParser::FORM_DATA_CONTENT_TYPES + """ + if ( + self._container.body + and not self._container.request.has_formdata + and parser.TypeChecker.is_property_objectish(self._container.body) + ): + result[self._container.body_type] = self._container.body + + return result + + def _flatten_object( + self, + parent: model.PROPERTY_OBJECT_TYPE, + parent_name: str, + ) -> dict[str, model.PROPERTY_OBJECT_TYPE]: + """Children are added to the top of results""" + + result = {} + parent_name = f"{parent_name}_" if parent_name else "" + + if isinstance(parent, model.PropertyObjectArray): + name = f"{parent_name}{parent.name}" + + i = 1 + for prop in parent.properties: + sub_name = f"{name}_{i}" + prop.name = sub_name + result = { + **self._flatten_object(prop, sub_name), + **result, + sub_name: prop, + } + i += 1 + + return result + + for name, prop in parent.objects.items(): + sub_name = f"{parent_name}{name}" + prop.name = sub_name + result = { + **self._flatten_object(prop, sub_name), + **result, + sub_name: prop, + } + + for name, array_obj in parent.array_objects.items(): + i = 1 + sub_name_base = f"{parent_name}{name}" + + for prop in array_obj.properties: + sub_name = f"{sub_name_base}_{i}" + prop.name = sub_name + result = { + **self._flatten_object(prop, sub_name), + **result, + sub_name: prop, + } + i += 1 + + result[sub_name_base] = array_obj + + return result diff --git a/oseg/oseg/parser/property_parser.py b/oseg/oseg/parser/property_parser.py new file mode 100644 index 000000000..b950b0eac --- /dev/null +++ b/oseg/oseg/parser/property_parser.py @@ -0,0 +1,412 @@ +from __future__ import annotations +import openapi_pydantic as oa +from typing import Callable +from oseg import model, parser + + +class PropertyParser: + def __init__(self, oa_parser: parser.OaParser): + self._oa_parser: parser.OaParser = oa_parser + self._schema_joiner: parser.SchemaJoiner = parser.SchemaJoiner(oa_parser) + + def parse( + self, + schema: oa.Schema, + data: dict[str, any] | list[dict[str, any] | any], + ) -> model.PROPERTY_TYPES: + if parser.TypeChecker.is_array(schema): + assert isinstance( + data, list + ), "Body schema is list, example data should also be a list" + + if self._is_root_level_non_object(schema.items): + return self._create_non_object_container(schema, data) + + container: model.PropertyObjectArray | None = None + + for i_data in data: + sub_container = self._create_property_object_container( + schema=schema.items, + data=i_data, + parents=[], + ) + + if container is None: + type_of = sub_container.base_type + + if type_of is None: + type_of = sub_container.type + + container = model.PropertyObjectArray( + schema=schema, + _type=type_of, + is_required=sub_container.is_required, + is_set=True, + ) + + container.properties.append(sub_container) + + return container + + if self._is_root_level_non_object(schema): + return self._create_non_object_container(schema, data) + + return self._create_property_object_container( + schema=schema, + data=data, + parents=[], + ) + + def _create_property_object_container( + self, + schema: oa.Schema, + data: dict[str, any], + parents: list[int], + ) -> model.PropertyObject | model.PROPERTY_NON_OBJECT_TYPE: + data_is_none = False + + if data is None: + data_is_none = True + data = {} + + merged_values = self._schema_joiner.merge_schemas_and_properties(schema, data) + properties = merged_values.properties + base_type = None + type_of = self._oa_parser.get_component_name(schema) + + if merged_values.discriminator_target_type is not None: + base_type = type_of + type_of = merged_values.discriminator_target_type + + container = model.PropertyObject( + schema=schema, + _type=type_of, + base_type=base_type, + is_required=False, + ) + + schema_id = id(schema) + + if schema_id in parents and data_is_none: + return container + + parents.append(schema_id) + + for name, property_schema in properties.items(): + for current_schema in merged_values.schemas: + non_object_property_schema = self._oa_parser.resolve_property( + schema=current_schema, + property_name=name, + ) + + if self._handle_object( + container=container, + schema=property_schema, + name=name, + data=data, + parents=parents, + ): + break + + if self._handle_array_object( + container=container, + schema=property_schema, + name=name, + data=data, + parents=parents, + ): + break + + if non_object_property_schema and self._handle_file( + container=container, + schema=non_object_property_schema, + name=name, + data=data, + ): + continue + + if non_object_property_schema and self._handle_free_form( + container=container, + schema=non_object_property_schema, + name=name, + data=data, + ): + continue + + if non_object_property_schema and self._handle_scalar( + container=container, + schema=non_object_property_schema, + name=name, + data=data, + ): + continue + + return container + + def _create_non_object_container( + self, + schema: oa.Schema, + data: any, + ) -> model.PROPERTY_NON_OBJECT_TYPE: + """Handles root-level non-object properties""" + + is_array = parser.TypeChecker.is_array(schema) + + name = "body" if not is_array else "request_body" + result = self._handle_file( + container=None, + schema=schema, + name=name, + data={name: data}, + ) + + if result: + return result + + result = self._handle_free_form( + container=None, + schema=schema, + name="request_body", + data={"request_body": data}, + ) + + if result: + return result + + name = "body" if not is_array else "request_body" + result = self._handle_scalar( + container=None, + schema=schema, + name=name, + data={name: data}, + ) + + if result: + return result + + raise NotImplementedError("_handle_no_object() unable to handle data") + + def _handle_object( + self, + container: model.PropertyObject, + schema: oa.Reference | oa.Schema, + name: str, + data: dict[str, any], + parents: list[int], + ) -> bool: + """handle named object""" + + # todo when ref object is free-form object, return early here + + if parser.TypeChecker.is_array(schema): + return False + + # allOf to be handled recursively + if not parser.TypeChecker.is_object( + schema + ) and not parser.TypeChecker.is_all_of(schema): + return False + + type_of = self._oa_parser.get_component_name(schema) + is_required = self._is_required(container.schema, name) + value = data.get(name) + + if not is_required and value is None: + value = schema.default + + # this is a non-named object, use free-form. + # Happens with parameter objects + if type_of is None: + container.properties[name] = model.PropertyFreeForm( + schema=schema, + name=name, + value=value, + is_required=self._is_required(container.schema, name), + is_set=name in data, + ) + + return True + + parsed = self._create_property_object_container( + schema=schema, + data=value, + parents=parents[:], + ) + parsed.is_required = is_required + parsed.is_set = name in data + + container.properties[name] = parsed + + return True + + def _handle_array_object( + self, + container: model.PropertyObject, + schema: oa.Reference | oa.Schema, + name: str, + data: dict[str, any], + parents: list[int], + ) -> bool: + """handle arrays of named objects""" + + if not parser.TypeChecker.is_array(schema): + return False + + # allOf to be handled recursively + if not parser.TypeChecker.is_object( + schema.items + ) and not parser.TypeChecker.is_all_of(schema.items): + return False + + type_of = self._oa_parser.get_component_name(schema.items) + is_required = self._is_required(container.schema, name) + value = data.get(name) + + if not is_required and value is None: + value = schema.items.default + + # required but value still null, default to sane value + if value is None or not isinstance(value, list): + value = [] + + if container.schema.properties: + parent = container.schema.properties.get(name) + else: + parent = container.schema + + # this is a non-named object, use free-form. + # Happens with parameter objects + if type_of is None: + container.properties[name] = model.PropertyFreeForm( + schema=schema, + name=name, + value=value, + is_required=self._is_required(parent, name), + is_set=name in data, + ) + + return True + + prop_obj_array = model.PropertyObjectArray( + schema=parent, + _type=type_of, + is_required=is_required, + is_set=name in data, + ) + + for example in value: + parsed = self._create_property_object_container( + schema=schema.items, + data=example, + parents=parents[:], + ) + parsed.is_required = is_required + + prop_obj_array.properties.append(parsed) + + container.properties[name] = prop_obj_array + + return True + + def _handle_file( + self, + container: model.PropertyObject | None, + schema: oa.Schema, + name: str, + data: dict[str, any], + ) -> model.PropertyFile | None: + """handle binary (file upload) types""" + + if not self._is_resolvable_of(schema, parser.TypeChecker.is_file): + return None + + result = model.PropertyFile( + schema=schema, + name=name, + value=data.get(name), + is_required=( + self._is_required(container.schema, name) if container else False + ), + is_set=name in data, + ) + + if container: + container.properties[name] = result + + return result + + def _handle_free_form( + self, + container: model.PropertyObject | None, + schema: oa.Schema, + name: str, + data: dict[str, any], + ) -> model.PropertyFreeForm | None: + """handle free-form type, ignore inline schemas that should use $ref""" + + if not self._is_resolvable_of(schema, parser.TypeChecker.is_free_form): + return None + + value = data.get(name) + if value == "{}": + value = {} + + result = model.PropertyFreeForm( + schema=schema, + name=name, + value=value, + is_required=( + self._is_required(container.schema, name) if container else False + ), + is_set=name in data, + ) + + if container: + container.properties[name] = result + + return result + + def _handle_scalar( + self, + container: model.PropertyObject | None, + schema: oa.Schema, + name: str, + data: dict[str, any], + ) -> model.PropertyScalar | None: + """handle scalar types""" + + if not self._is_resolvable_of(schema, parser.TypeChecker.is_scalar): + return None + + result = model.PropertyScalar( + schema=schema, + name=name, + value=data.get(name), + is_required=( + self._is_required(container.schema, name) if container else False + ), + is_set=name in data, + ) + + if not result.is_required and result.value is None and not result.is_nullable: + result.is_set = False + + if container: + container.properties[name] = result + + return result + + def _is_required(self, schema: oa.Schema, prop_name: str) -> bool: + return bool(schema.required and prop_name in schema.required) + + def _is_resolvable_of(self, schema: oa.Schema, callback: Callable) -> bool: + return callback(schema) or ( + parser.TypeChecker.is_array(schema) and callback(schema.items) + ) + + def _is_root_level_non_object(self, schema: oa.Schema) -> bool: + return bool( + self._is_resolvable_of(schema, parser.TypeChecker.is_file) + or self._is_resolvable_of(schema, parser.TypeChecker.is_free_form) + or self._is_resolvable_of(schema, parser.TypeChecker.is_scalar) + ) diff --git a/oseg/oseg/parser/property_sorter.py b/oseg/oseg/parser/property_sorter.py new file mode 100644 index 000000000..0e2c53ee4 --- /dev/null +++ b/oseg/oseg/parser/property_sorter.py @@ -0,0 +1,144 @@ +from __future__ import annotations +import openapi_pydantic as oa +from dataclasses import dataclass +from oseg import model, parser + + +@dataclass +class SortedProperties: + required: dict[str, model.PROPERTY_TYPES] + optional: dict[str, model.PROPERTY_TYPES] + + +class PropertySorter: + def __init__(self, container: model.PropertyContainer): + self._container: model.PropertyContainer = container + + def sort(self) -> SortedProperties: + used_property_names = {} + + required_parameters = self._parameters_by_required(True) + optional_parameters = self._parameters_by_required(False) + required_body = self._body_params_by_required(True) + optional_body = self._body_params_by_required(False) + + result = SortedProperties( + required={}, + optional={}, + ) + + # todo check new name isn't already explicitly set for a property + for parameter in required_parameters: + name = self._generate_name(parameter.name, used_property_names) + obj = self._parameter_object(parameter) + + # todo this happens with anyOf schema + if obj is None: + print(f"Skipping {name}@{parameter.param_in.value}, unsupported") + continue + + obj.name = name + result.required[name] = obj + + for name, prop in required_body.items(): + name = self._generate_name(name, used_property_names) + prop.name = name + result.required[name] = prop + + for parameter in optional_parameters: + name = self._generate_name(parameter.name, used_property_names) + obj = self._parameter_object(parameter) + + # todo this happens with anyOf schema + if obj is None: + print(f"Skipping {name}@{parameter.param_in.value}, unsupported") + continue + + obj.name = name + result.optional[name] = obj + + for name, prop in optional_body.items(): + name = self._generate_name(name, used_property_names) + prop.name = name + result.optional[name] = prop + + return result + + def _parameters_by_required(self, required_flag: bool) -> list[oa.Parameter]: + required_parameters = [] + optional_parameters = [] + + for param in self._container.request.parameters: + if param.required: + required_parameters.append(param) + else: + optional_parameters.append(param) + + if required_flag: + return required_parameters + + return optional_parameters + + def _parameter_object(self, param: oa.Parameter) -> model.PROPERTY_TYPES | None: + """Returns the PropertyObject for a given oa.Parameter regardless + of what its param_in value is: path, query, header, cookie""" + + if param.param_in.value == oa.ParameterLocation.PATH.value: + return self._container.path.properties.get(param.name) + + if param.param_in == oa.ParameterLocation.QUERY.value: + return self._container.query.properties.get(param.name) + + if param.param_in == oa.ParameterLocation.HEADER.value: + return self._container.header.properties.get(param.name) + + if param.param_in == oa.ParameterLocation.COOKIE.value: + return self._container.cookie.properties.get(param.name) + + def _body_params_by_required( + self, + required: bool, + ) -> dict[str, model.PROPERTY_TYPES]: + if not self._container.body: + return {} + + # single body property + if not self._container.request.has_formdata or isinstance( + self._container.body, list + ): + if (required and self._container.request.is_required) or ( + not required and not self._container.request.is_required + ): + if parser.TypeChecker.is_property_objectish(self._container.body): + return {self._container.body_type: self._container.body} + + return {self._container.body.name: self._container.body} + + return {} + + results = {} + + # list each body property individually + for name, prop in self._container.body.properties.items(): + if (required and prop.is_required) or ( + not required and not prop.is_required + ): + results[name] = prop + + return results + + def _generate_name(self, name: str, used_property_names: dict[str, int]) -> str: + """Keeps track of what property names have already been used""" + + name_lower = name.lower() + + if name_lower in used_property_names: + count = used_property_names[name_lower] + 1 + name = f"{name}{count}" + used_property_names[name_lower] = count + + return name + + used_property_names[name_lower] = 1 + + return name diff --git a/oseg/oseg/parser/schema_joiner.py b/oseg/oseg/parser/schema_joiner.py new file mode 100644 index 000000000..8c9932a9c --- /dev/null +++ b/oseg/oseg/parser/schema_joiner.py @@ -0,0 +1,134 @@ +import openapi_pydantic as oa +from dataclasses import dataclass +from oseg import parser + + +@dataclass +class JoinedValues: + schemas: list[oa.Schema] + properties: dict[str, oa.Reference | oa.Schema] + discriminator_target_type: str | None = None + + +class SchemaJoiner: + def __init__(self, oa_parser: parser.OaParser): + self._oa_parser: parser.OaParser = oa_parser + + def merge_schemas_and_properties( + self, + schema: oa.Schema, + data: dict[str, any] | None, + ) -> JoinedValues: + """When a Schema uses allOf will merge all Schemas and the properties + of those Schemas. + + Currently only useful for Schema that use a discriminator and allOf. + + data is only used by discriminator + """ + + discriminated = self._resolve_discriminator(schema, data) + + if discriminated: + return discriminated + + all_of = self._resolve_all_of(schema) + + if all_of: + return all_of + + return JoinedValues( + schemas=[schema], + properties=self._get_properties([schema]), + ) + + def _resolve_discriminator( + self, + schema: oa.Schema, + data: dict[str, any] | None, + ) -> JoinedValues | None: + """Returns all schemas that build a discriminator. + + The last Schema will always take precedence with regards to properties + and other metadata + """ + + if not parser.TypeChecker.is_discriminator(schema) or data is None: + return None + + # the property that is used as the discriminator key + key = schema.discriminator.propertyName + # all possible discriminator targets, [key value: target_schema] + mapping = schema.discriminator.mapping + # value decides the final schema + value: str = data.get(key) + + if not value: + return None + + ref = mapping.get(value) + + if not ref: + return None + + resolved_name = ref.split("/").pop() + resolved = self._oa_parser.components.schemas.get(resolved_name) + + joined = self._resolve_all_of(resolved) + joined.discriminator_target_type = resolved_name + + return joined + + def _resolve_all_of(self, schema: oa.Schema) -> JoinedValues | None: + """Returns all schemas that build a ref via allOf. + + The last Schema will always take precedence with regards to properties + and other metadata + """ + + if not schema.allOf: + return None + + return JoinedValues( + schemas=schema.allOf, + properties=self._get_properties(schema.allOf), + ) + + def _get_properties( + self, + schemas: list[oa.Schema], + ) -> dict[str, oa.Reference | oa.Schema]: + result = {} + required = [] + + for schema in schemas: + if schema.required: + required = required + schema.required + + if parser.TypeChecker.is_array(schema): + body_name = self._oa_parser.get_component_name(schema.items).lower() + + if body_name in result: + del result[body_name] + + result[body_name] = schema + + if not hasattr(schema, "properties") or schema.properties is None: + continue + + for property_name, property_schema in schema.properties.items(): + if property_name in result: + del result[property_name] + + result[property_name] = property_schema + + sorted_results = {} + for name in required: + # todo unit test + if name not in result: + continue + + sorted_results[name] = result[name] + del result[name] + + return {**sorted_results, **result} diff --git a/oseg/oseg/parser/template_parser.py b/oseg/oseg/parser/template_parser.py new file mode 100644 index 000000000..a3fbe9ae5 --- /dev/null +++ b/oseg/oseg/parser/template_parser.py @@ -0,0 +1,383 @@ +from __future__ import annotations +from oseg import generator as g, model, parser + + +class TemplateParser: + def __init__(self, generator: g.BaseGenerator): + self._generator: g.BaseGenerator = generator + + def parse_security( + self, + macros: model.JinjaMacros, + indent_count: int, + ) -> dict[str, str]: + """Prints security/authentication""" + + security_config = self._generator.config.oseg.security + result = {} + is_primary = True + + for schemes in self._generator.operation.security.schemes: + for key, scheme in schemes.items(): + if scheme.method == model.SecurityMethod.BASIC: + result[key] = macros.print_security( + printable=model.PrintableSecurity( + name=scheme.name, + key=key, + method=scheme.method.value, + value=security_config.get(f"{key}.username", ""), + value_2=security_config.get(f"{key}.password", None), + is_primary=is_primary, + ) + ) + + continue + + result[key] = macros.print_security( + printable=model.PrintableSecurity( + name=scheme.name, + key=key, + method=scheme.method.value, + value=security_config.get(f"{key}.{scheme.method.value}", ""), + is_primary=is_primary, + ) + ) + + is_primary = False + + return self._indent(result, indent_count) + + def parse_objects(self) -> dict[str, model.PROPERTY_OBJECT_TYPE]: + """Parse all top-level object variables""" + + property_container = self._generator.property_container + + result = {} + + for name, obj in property_container.flattened_objects().items(): + # if object is not required, is not nullable, and has no example data, + # we can skip printing it + if not obj.is_required and not obj.is_nullable and not obj.is_set: + continue + + result[name] = obj + + return result + + def parse_object_properties( + self, + macros: model.JinjaMacros, + parent: model.PropertyObject, + indent_count: int, + ) -> dict[str, str]: + """Parse properties of a given Model object""" + + property_container = self._generator.property_container + + result = {} + + for _, prop in parent.non_objects().items(): + # if config flag oseg.ignoreOptionalUnset is enabled, + # and property is not required, and does not have example data, + # we can skip printing it + if ( + self._generator.config.oseg.ignoreOptionalUnset + and not prop.is_required + and prop.value is None + and not prop.is_set + ): + continue + + prop_name = self._resolve_keyword(prop.name, prop.original_name) + prop_name = self._resolve_keyword(prop_name, prop.original_name, True) + + result[prop_name] = self._parse_non_objects( + macros=macros, + parent=parent, + prop=prop, + ) + + parent_name = f"{parent.name}_" if property_container.body != parent else "" + + for name, parsed in self._parse_object(parent, parent_name).items(): + if not parsed.is_array: + result[name] = macros.print_object(parsed) + else: + result[name] = macros.print_object_array(parsed) + + return self._indent(result, indent_count) + + def parse_object_list_properties( + self, + macros: model.JinjaMacros, + parent: model.PropertyObjectArray, + indent_count: int, + ) -> str: + """Parse root-level data for a list data for a single Model object""" + + printable = model.PrintableObject() + printable.is_array = True + printable.value = [] + + if parent.properties: + first_item = parent.properties[0] + printable.target_type = first_item.type + + if first_item.base_type: + printable.target_type = first_item.base_type + else: + printable.target_type = parent.type + + i = 1 + for prop in parent.properties: + printable.value.append(prop.name) + i += 1 + + parent_name = self._resolve_keyword(parent.name, parent.original_name) + + result = {parent_name: macros.print_object_array(printable)} + + return self._indent(result, indent_count)[parent_name] + + def parse_api_call_properties( + self, + macros: model.JinjaMacros, + indent_count: int, + required_flag: bool | None = None, + ) -> dict[str, str]: + """Parse data passed directly to an API object. + + Can include Parameters as well as body data. + If current request is of type "multipart/form-data" or + "application/x-www-form-urlencoded" we will usually want to print each + body parameter individually. + + Otherwise we will pass a single Model object containing all body data. + + Data is always sorted as: + + 1) Required Parameters + 2) Required body data + 3) Optional Parameters + 4) Optional body data + """ + + property_container = self._generator.property_container + + result = {} + # When all api call values are null, and none are required + # don't print anything + has_data = False + force_print_parameters = self._generator.force_print_parameters() + + for _, prop in property_container.properties(required_flag).items(): + if property_container.body and prop == property_container.body: + operation = self._generator.operation + override_request_body_name = operation.request_body_name() + + request_body_name = ( + override_request_body_name + if override_request_body_name + else prop.name + ) + + prop_name = self._resolve_keyword(request_body_name, prop.original_name) + has_data = True + + if parser.TypeChecker.is_property_objectish(prop): + result[prop_name] = self._generator.print_variablename( + property_container.body.type + ) + + continue + + # non-object single value + result[prop_name] = self._parse_non_objects( + macros=macros, + parent=None, + prop=prop, + ) + + continue + + prop_name = self._resolve_keyword(prop.name, prop.original_name) + + if isinstance(prop, model.PropertyObject) or isinstance( + prop, model.PropertyObjectArray + ): + # If a property listed in the api call signature is not required, + # and has no example data, we want to print a null value + # instead of simply skipping printing it completely. + # We always want to use all properties during the api call + # because some generators do not have named parameters, + # meaning they must list all properties in the order defined + # in the OAS + if not prop.is_required and not prop.is_set: + # if generator language supports named parameters then + # we can skip null values + if self._generator.has_named_parameters(): + continue + + result[prop_name] = self._generator.print_null() + else: + has_data = True + result[prop_name] = self._generator.print_variablename(prop_name) + + continue + + # if generator language supports named parameters then + # we can skip null values + if ( + not prop.is_required + and not prop.is_set + and self._generator.has_named_parameters() + ): + continue + + result[prop_name] = self._parse_non_objects( + macros=macros, + parent=None, + prop=prop, + ) + + if ( + prop.value is not None + or prop.is_required + or (force_print_parameters and property_container.is_parameter(prop)) + ): + has_data = True + + if not has_data: + return self._indent({}, indent_count) + + return self._indent(result, indent_count) + + def _parse_non_objects( + self, + macros: model.JinjaMacros, + parent: model.PropertyObject | None, + prop: model.PROPERTY_NON_OBJECT_TYPE, + ) -> any: + if isinstance(prop, model.PropertyScalar): + printable = self._generator.print_scalar(parent, prop) + + if printable.is_array: + return macros.print_scalar_array(printable) + + return macros.print_scalar(printable) + elif isinstance(prop, model.PropertyFile): + printable = self._generator.print_file(prop) + + if printable.is_array: + return macros.print_file_array(printable) + + return macros.print_file(printable) + elif isinstance(prop, model.PropertyFreeForm): + printable = self._generator.print_free_form(prop) + + if printable.is_array: + return macros.print_free_form_array(printable) + + return macros.print_free_form(printable) + + return None + + def _parse_object( + self, + obj: model.PropertyObject, + parent_name: str, + ) -> dict[str, model.PrintableObject]: + result = {} + for property_name, sub_obj in obj.objects.items(): + # todo test + if not sub_obj.is_required and not sub_obj.is_set: + continue + + prop_name = self._resolve_keyword(property_name, sub_obj.original_name) + prop_name = self._resolve_keyword(prop_name, sub_obj.original_name, True) + + printable = model.PrintableObject() + result[prop_name] = printable + + # todo test multiple objects in array belonging to objects in array + # do not overwrite each other's names + printable.value = sub_obj.name + printable.target_type = sub_obj.type + + for property_name, array_obj in obj.array_objects.items(): + # todo test + if not array_obj.is_required and not array_obj.is_set: + continue + + prop_name = self._resolve_keyword(property_name, array_obj.original_name) + prop_name = self._resolve_keyword(prop_name, array_obj.original_name, True) + + printable = model.PrintableObject() + result[prop_name] = printable + + # todo test multiple objects in array belonging to objects in array + # do not overwrite each other's names + printable.value = f"{parent_name}{prop_name}" + printable.target_type = array_obj.name + + return result + + def _indent( + self, + property_values: dict[str, str | None], + indent_count: int, + ) -> dict[str, str | None]: + indent = " " * indent_count + + for name, value in property_values.items(): + if value is None: + continue + + property_values[name] = value.replace("\n", f"\n{indent}") + + return property_values + + def _resolve_keyword(self, name: str, original_name: str, secondary: bool = False): + """When two properties have identical names and will be listed + at the same level (parameters + root-level body properties) we + automatically append an increasing integer to the name to avoid + conflicts. + + For example: + - "property_name" + - "property_name2" + - "property_name3" + + This runs into the problem where the original name might have been + one of the target language's reserved keywords, but the updated + name will not match due to the appended integer. + + For example Python has "for" as a reserved keyword. Property names + will have "var_" prepended by openapi-generator to avoid using the + reserved keyword. + + "for" -> "val_for" + + However, if an integer has been appended to the property name then + it would no longer match, but openapi-generator will still have + prepended "var_" to the name. + + We must check against the original unchanged property name to decide + if the name is a reserved keyword. + """ + + if self._generator.is_reserved_keyword(original_name, secondary): + return self._generator.unreserve_keyword( + name=name, + force=True, + secondary=secondary, + ) + + if self._generator.is_reserved_keyword(name, secondary): + return self._generator.unreserve_keyword( + name=name, + force=True, + secondary=secondary, + ) + + return name diff --git a/oseg/oseg/parser/type_checker.py b/oseg/oseg/parser/type_checker.py new file mode 100644 index 000000000..862439366 --- /dev/null +++ b/oseg/oseg/parser/type_checker.py @@ -0,0 +1,153 @@ +from __future__ import annotations +import openapi_pydantic as oa +from typing import Union +from pydantic import BaseModel +from oseg import model + + +class TypeChecker: + SCHEMA_UNION = Union[BaseModel, oa.Schema] + REF_UNION = Union[BaseModel, oa.Reference] + + # Exclude "base64" because that will be considered a string in SDKs + _FILE_FORMATS = [ + "byte", + "binary", + ] + + @classmethod + def is_array(cls, schema: SCHEMA_UNION) -> bool: + return cls._is_of_type(schema, oa.DataType.ARRAY) + + @classmethod + def is_all_of(cls, schema: SCHEMA_UNION) -> bool: + return bool( + hasattr(schema, "allOf") and schema.allOf is not None and len(schema.allOf) + ) + + @classmethod + def is_discriminator(cls, schema: SCHEMA_UNION) -> bool: + return bool( + cls.is_object(schema) + and schema.discriminator + and schema.discriminator.propertyName + and schema.discriminator.mapping + ) + + @classmethod + def is_file(cls, schema: SCHEMA_UNION) -> bool: + """OpenAPI 3.1 has several possible ways to define a file upload property + but openapi-generator does not care and ignored anything that is not + "type=string" and "format=binary" or "format=byte". + + The following are considered "files" by OpenAPI 3.1 but not by + openapi-generator: + + * contentMediaType: application/octet-stream + * contentEncoding: base64 + """ + + return ( + cls._is_of_type(schema, oa.DataType.STRING) + and hasattr(schema, "schema_format") + and schema.schema_format in cls._FILE_FORMATS + ) + + @classmethod + def is_file_array(cls, schema: SCHEMA_UNION) -> bool: + return cls.is_array(schema) and cls.is_file(schema.items) + + @classmethod + def is_free_form(cls, schema: SCHEMA_UNION) -> bool: + return bool( + not cls.is_object(schema) + and cls._is_of_type(schema, oa.DataType.OBJECT) + and (schema.properties is None or schema.properties == {}) + ) + + @classmethod + def is_free_form_array(cls, schema: SCHEMA_UNION) -> bool: + return cls.is_array(schema) and cls.is_free_form(schema.items) + + @classmethod + def is_property_objectish(cls, prop: model.PROPERTY_TYPES) -> bool: + return isinstance(prop, model.PropertyObject) or isinstance( + prop, model.PropertyObjectArray + ) + + @classmethod + def is_object(cls, schema: SCHEMA_UNION) -> bool: + return ( + not cls.is_ref(schema) + and cls._is_of_type(schema, oa.DataType.OBJECT) + and schema.properties + ) + + @classmethod + def is_object_array(cls, schema: SCHEMA_UNION) -> bool: + return cls.is_array(schema) and cls.is_object(schema.items) + + @classmethod + def is_ref(cls, schema: REF_UNION) -> bool: + return hasattr(schema, "ref") or ( + hasattr(schema, "model_extra") and "$ref" in schema.model_extra + ) + + @classmethod + def is_ref_array(cls, schema: REF_UNION) -> bool: + return cls.is_array(schema) and cls.is_ref(schema.items) + + @classmethod + def is_scalar(cls, schema: SCHEMA_UNION) -> bool: + return bool( + hasattr(schema, "type") + and cls._is_of_scalar_type(schema.type) + and not cls.is_file(schema) + ) + + @classmethod + def is_scalar_array(cls, schema: SCHEMA_UNION) -> bool: + return cls.is_array(schema) and cls.is_scalar(schema.items) + + @classmethod + def is_nullable(cls, schema: SCHEMA_UNION) -> bool: + # 3.0 + if hasattr(schema, "nullable"): + return bool(schema.nullable) + + # 3.1 + return bool( + hasattr(schema, "type") + and isinstance(schema.type, list) + and "null" in schema.type + ) + + @classmethod + def is_nullable_array(cls, schema: SCHEMA_UNION) -> bool: + return cls.is_array(schema) and cls.is_nullable(schema) + + @classmethod + def _is_of_type(cls, schema: SCHEMA_UNION, data_type: oa.DataType) -> bool: + if not hasattr(schema, "type") or not schema.type: + return False + + # 3.1 + if isinstance(schema.type, list): + for t in schema.type: + if data_type.value == t.value: + return True + + return False + + return schema.type.value == data_type.value + + @classmethod + def _is_of_scalar_type(cls, propery_type: oa.DataType | list[oa.DataType]) -> bool: + if isinstance(propery_type, list): + for t in propery_type: + if t in model.SCALAR_TYPES: + return True + + return False + + return propery_type in model.SCALAR_TYPES diff --git a/oseg/oseg/templates/_macros.jinja2 b/oseg/oseg/templates/_macros.jinja2 new file mode 100644 index 000000000..59353fb3c --- /dev/null +++ b/oseg/oseg/templates/_macros.jinja2 @@ -0,0 +1,19 @@ +{%- macro parse_security_macro(indent_count) -%} + {{- caller(parse_security(indent_count)) }} +{%- endmacro -%} + +{%- macro parse_objects_macro() -%} + {{- caller(parse_objects()) }} +{%- endmacro -%} + +{%- macro parse_object_properties_macro(obj, indent_count) -%} + {{- caller(parse_object_properties(obj, indent_count)) }} +{%- endmacro -%} + +{%- macro parse_object_list_properties_macro(obj, indent_count) -%} + {{- caller(parse_object_list_properties(obj, indent_count)) }} +{%- endmacro -%} + +{%- macro parse_api_call_properties_macro(indent_count, required_flag) -%} + {{- caller(parse_api_call_properties(indent_count, required_flag)) }} +{%- endmacro -%} diff --git a/oseg/oseg/templates/csharp.jinja2 b/oseg/oseg/templates/csharp.jinja2 new file mode 100644 index 000000000..4bbb9d96d --- /dev/null +++ b/oseg/oseg/templates/csharp.jinja2 @@ -0,0 +1,165 @@ +{%- macro print_scalar(printable) -%} +{{ printable.value }} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +new FileStream( + path: "{{ printable.value }}", + mode: FileMode.Open +) + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +new List{% if not printable.value %}(){% else %} + +{ + {% for i in printable.value %} + new FileStream( + path: "{{ i }}", + mode: FileMode.Open + ), + {% endfor %} +} + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}new Dictionary(){%- else %} +JsonSerializer.Deserialize>(""" + {{ printable.value|tojson(4)|indent(4) }} +""") + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}new List<{% if printable.has_properties %}object{% else %}Dictionary{% endif %}>(){%- else %} +JsonSerializer.Deserialize{% endif %}>>(""" + {{ printable.value|tojson(4)|indent(4) }} +""") + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} +{{ printable.value|print_variablename }} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +new List<{{ printable.target_type|print_classname }}>{% if not printable.value %}(){% else %} + +{ + {% for i in printable.value %} + {{ i|print_variablename }}, + {% endfor %} +} + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "// " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}config.ApiKey.Add("{{ printable.name }}", {{ printable.value|tojson }}); +{%- elif printable.method == "access_token" %}{{ comment }}config.AccessToken = {{ printable.value|tojson }}; +{%- else %}{{ comment }}config.Username = {{ printable.value|tojson }};{% if printable.value_2 != None %}{{ "" }} +{{ comment }}config.Password = {{ printable.value_2|tojson }};{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +using {{ config.packageName }}.Api; +using {{ config.packageName }}.Client; +using {{ config.packageName }}.Model; + +{% if config.oseg.namespace %} +namespace {{ config.oseg.namespace }}; + +{% endif %} +public class {{ (operation.operation_id ~ "_" ~ example_name)|print_classname }} +{ + public static void Run() + { + var config = new Configuration(); + {% if operation.security.is_optional %} + // Authentication is optional for this API endpoint + {% endif %} +{% call(security_schemes) m.parse_security_macro(8) %} + {% for _, security in security_schemes.items() %} + {{ security }} + {% endfor %} +{% endcall %} + +{% call(objects) m.parse_objects_macro() %} + {% for obj_name, obj in objects.items() %} + {% if not obj.is_array %} + var {{ obj_name|print_variablename }} = new {{ obj.type|print_classname }}( + {% call(properties) m.parse_object_properties_macro(obj, 12) %} + {% for name, value in properties.items() %} + {{ name|print_propname }}: {{ value }}{% if not loop.last %},{% endif %} + + {% endfor %} + {% endcall %} + ); + {% else %} + var {{ obj_name|print_variablename }} = {{ "" }} + {%- call(value) m.parse_object_list_properties_macro(obj, 8) %} + {{- value }}; + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} + try + { + {{ "" -}} +{% call(properties) m.parse_api_call_properties_macro(16) %} + {% if operation.response and operation.response.body %}var response = {% endif -%} + new {{ operation.api_name|print_apiname }}(config).{{ operation.operation_id|print_methodname }}({%- if not properties %}); +{% else %} + + {% for name, value in properties.items() %} + {{ name|print_propname }}: {{ value }}{% if not loop.last %},{% endif %} + + {% endfor %} + ); +{% endif %} +{% endcall %} + {% if operation.response and operation.response.body and not operation.response.is_binary %} + + Console.WriteLine(response); + {% elif operation.response and operation.response.is_binary %} + var fileStream = File.Create("./file_response"); + response.Seek(0, SeekOrigin.Begin); + response.CopyTo(fileStream); + fileStream.Close(); + {% endif %} + } + catch (ApiException e) + { + Console.WriteLine("Exception when calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}: " + e.Message); + Console.WriteLine("Status Code: " + e.ErrorCode); + Console.WriteLine(e.StackTrace); + } + } +} +{{ "" }} diff --git a/oseg/oseg/templates/java.jinja2 b/oseg/oseg/templates/java.jinja2 new file mode 100644 index 000000000..1977970ee --- /dev/null +++ b/oseg/oseg/templates/java.jinja2 @@ -0,0 +1,165 @@ +{%- macro print_scalar(printable) -%} +{{ printable.value }} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +List.of {% if not printable.value %}(){% else %} +( + {% for i in printable.value %} + {{ i }}{% if not loop.last %},{% endif %} + + {% endfor %} +) + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +new File("{{ printable.value }}") + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +List.of {% if not printable.value %}(){% else %} +( + {% for i in printable.value %} + new File("{{ i }}"){% if not loop.last %},{% endif %} + + {% endfor %} +) + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}Map.of (){%- else %} +JSON.deserialize(""" + {{ printable.value|tojson(4)|indent(4) }} +""", Map.class) + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}List.of (){%- else %} +JSON.deserialize(""" + {{ printable.value|tojson(4)|indent(4) }} +""", List.class) + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} +{{ printable.value|print_variablename }} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +new ArrayList<{{ printable.target_type|print_classname }}>(List.of {% if not printable.value %}()){% else %} +( + {% for i in printable.value %} + {{ i|print_variablename }}{% if not loop.last %},{% endif %} + + {% endfor %} +)) + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "// " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}((ApiKeyAuth) config.getAuthentication("{{ printable.key }}")).setApiKey({{ printable.value|tojson }}); +{%- elif printable.method == "access_token" %}{{ comment }}((HttpBearerAuth) config.getAuthentication("{{ printable.key }}")).setBearerToken({{ printable.value|tojson }}); +{%- else %}{{ comment }}((HttpBasicAuth) config.getAuthentication("{{ printable.key }}")).setUsername({{ printable.value|tojson }});{% if printable.value_2 != None %}{{ "" }} +{{ comment }}((HttpBasicAuth) config.getAuthentication("{{ printable.key }}")).setPassword({{ printable.value_2|tojson }});{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- macro print_variable_name_as_comment(name, value) -%} + {% if config.oseg.printApiCallProperty %} + {% if name|print_propname != value %} // {{ name|print_propname }}{% endif %} + {% endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +package {{ config.oseg.package }}; + +import {{ config.invokerPackage }}.ApiException; +import {{ config.invokerPackage }}.Configuration; +import {{ config.apiPackage }}.*; +import {{ config.invokerPackage }}.auth.*; +import {{ config.invokerPackage }}.JSON; +import {{ config.modelPackage }}.*; + +import java.io.File; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class {{ (operation.operation_id ~ "_" ~ example_name)|print_classname }} +{ + public static void main(String[] args) + { + var config = Configuration.getDefaultApiClient(); + {% if operation.security.is_optional %} + // Authentication is optional for this API endpoint + {% endif %} +{% call(security_schemes) m.parse_security_macro(8) %} + {% for _, security in security_schemes.items() %} + {{ security }} + {% endfor %} +{% endcall %} + +{% call(objects) m.parse_objects_macro() %} + {% for obj_name, obj in objects.items() %} + {% if not obj.is_array %} + {% call(properties) m.parse_object_properties_macro(obj, 8) %} + var {{ obj_name|print_variablename }} = new {{ obj.type|print_classname }}(); + {% for name, value in properties.items() %} + {{ obj_name|print_variablename }}.{{ name|print_methodname }}({{ value }}); + {% endfor %} + {% endcall %} + {% else %} + var {{ obj_name|print_variablename }} = {{ "" }} + {%- call(value) m.parse_object_list_properties_macro(obj, 8) %} + {{- value }}; + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} + try + { + {{ "" -}} +{% call(properties) m.parse_api_call_properties_macro(16) %} + {% if operation.response and operation.response.body %}var response = {% endif -%} + new {{ operation.api_name|print_apiname }}(config).{{ operation.operation_id|print_methodname }}({%- if not properties %}); +{% else %} + + {% for name, value in properties.items() %} + {{ value }}{% if not loop.last %},{% endif %}{{ print_variable_name_as_comment(name, value) }} + {% endfor %} + ); +{% endif %} +{% endcall %} + {% if operation.response and operation.response.body and not operation.response.is_binary %} + + System.out.println(response); + {% elif operation.response and operation.response.is_binary %} + response.renameTo(new File("./file_response")); + {% endif %} + } catch (ApiException e) { + System.err.println("Exception when calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +{{ "" }} diff --git a/oseg/oseg/templates/kotlin.jinja2 b/oseg/oseg/templates/kotlin.jinja2 new file mode 100644 index 000000000..ece575422 --- /dev/null +++ b/oseg/oseg/templates/kotlin.jinja2 @@ -0,0 +1,157 @@ +{%- macro print_scalar(printable) -%} +{{ printable.value }} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +listOf {% if not printable.value %}(){% else %} +( + {% for i in printable.value %} + {{ i }}, + {% endfor %} +) + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +File("{{ printable.value }}") + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +listOf {% if not printable.value %}(){% else %} +( + {% for i in printable.value %} + File("{{ i }}"), + {% endfor %} +) + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}mapOf (){%- else %} +Serializer.moshi.adapter>().fromJson(""" + {{ printable.value|tojson(4)|indent(4) }} +""")!! + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}listOf (){%- else %} +Serializer.moshi.adapter>>().fromJson(""" + {{ printable.value|tojson(4)|indent(4) }} +""")!! + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} +{{ printable.value|print_variablename }} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +arrayListOf<{{ printable.target_type|print_classname }}>({% if not printable.value %}){% else %} + + {% for i in printable.value %} + {{ i|print_variablename }}, + {% endfor %} +) + {%- endif %}{%- endif %} +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "// " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}ApiClient.apiKey["{{ printable.name }}"] = {{ printable.value|tojson }} +{%- elif printable.method == "access_token" %}{{ comment }}ApiClient.accessToken = {{ printable.value|tojson }} +{%- else %}{{ comment }}ApiClient.username = {{ printable.value|tojson }}{% if printable.value_2 != None %}{{ "" }} +{{ comment }}ApiClient.password = {{ printable.value_2|tojson }}{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +package {{ config.oseg.package }} + +import {{ config.packageName }}.infrastructure.* +import {{ config.packageName }}.apis.* +import {{ config.packageName }}.models.* + +import java.io.File +import java.time.LocalDate +import java.time.OffsetDateTime +import kotlin.collections.ArrayList +import kotlin.collections.List +import kotlin.collections.Map +import com.squareup.moshi.adapter + +@ExperimentalStdlibApi +class {{ (operation.operation_id ~ "_" ~ example_name)|print_classname }} +{ + fun {{ operation.operation_id|print_methodname }}() + { + {% if operation.security.is_optional %} + // Authentication is optional for this API endpoint + {% endif %} +{% call(security_schemes) m.parse_security_macro(8) %} + {% for _, security in security_schemes.items() %} + {{ security }} + {% endfor %} +{% endcall %} + +{% call(objects) m.parse_objects_macro() %} + {% for obj_name, obj in objects.items() %} + {% if not obj.is_array %} + {% call(properties) m.parse_object_properties_macro(obj, 12) %} + val {{ obj_name|print_variablename }} = {{ obj.type|print_classname }}({%- if not properties %}) + {% else %} + + {% for name, value in properties.items() %} + {{ name|print_propname }} = {{ value }}, + {% endfor %} + ) + {% endif %} + {% endcall %} + {% else %} + val {{ obj_name|print_variablename }} = {{ "" }} + {%- call(value) m.parse_object_list_properties_macro(obj, 8) %} + {{- value }} + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} + try + { + {{ "" -}} +{% call(properties) m.parse_api_call_properties_macro(16) %} + {% if operation.response and operation.response.body %}val response = {% endif -%} + {{ operation.api_name|print_apiname }}().{{ operation.operation_id|print_methodname }}({%- if not properties %}); +{% else %} + + {% for name, value in properties.items() %} + {{ name|print_propname }} = {{ value }}, + {% endfor %} + ) +{% endif %} +{% endcall %} + {% if operation.response and operation.response.body and not operation.response.is_binary %} + + println(response) + {% elif operation.response and operation.response.is_binary %} + response.renameTo(new File("./file_response")) + {% endif %} + } catch (e: ClientException) { + println("4xx response calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}") + e.printStackTrace() + } catch (e: ServerException) { + println("5xx response calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}") + e.printStackTrace() + } + } +} +{{ "" }} diff --git a/oseg/oseg/templates/php.jinja2 b/oseg/oseg/templates/php.jinja2 new file mode 100644 index 000000000..349625748 --- /dev/null +++ b/oseg/oseg/templates/php.jinja2 @@ -0,0 +1,141 @@ +{%- macro print_scalar(printable) -%} +{{ printable.value }} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +new SplFileObject("{{ printable.value }}") + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.values %} + new SplFileObject("{{ i }}"), + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}[]{%- else %} +json_decode(<<<'EOD' + {{ printable.value|tojson(4)|indent(4) }} +EOD, true) + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}[]{%- else %} +json_decode(<<<'EOD' + {{ printable.value|tojson(4)|indent(4) }} +EOD, true) + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +{{ printable.value|print_variablename }} + {%- endif %} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i|print_variablename }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "// " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}$config->setApiKey("{{ printable.name }}", {{ printable.value|tojson }}); +{%- elif printable.method == "access_token" %}{{ comment }}$config->setAccessToken({{ printable.value|tojson }}); +{%- else %}{{ comment }}$config->setUsername({{ printable.value|tojson }});{% if printable.value_2 != None %}{{ "" }} +{{ comment }}$config->setPassword({{ printable.value_2|tojson }});{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +{{ ("set" ~ "_" ~ name)|print_methodname }}({{ value }}){% if loop.last %};{% endif %} + + {% endfor %} + {% endcall %} + {% else %} +{{ obj_name|print_variablename }} = {{ "" }} + {%- call(value) m.parse_object_list_properties_macro(obj, 0) %} +{{- value }}; + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} +try { + {{ "" -}} +{% call(properties) m.parse_api_call_properties_macro(8) %} + {% if operation.response and operation.response.body %}$response = {% endif -%} + (new {{ config.invokerPackage }}\Api\{{ operation.api_name|print_apiname }}(config: $config))->{{ operation.operation_id|print_methodname }}({%- if not properties %}); +{% else %} + + {% for name, value in properties.items() %} + {{ name|print_propname }}: {{ value }}, + {% endfor %} + ); +{% endif %} +{% endcall %} +{% if operation.response and operation.response.body and not operation.response.is_binary %} + + print_r($response); +{% elif operation.response and operation.response.is_binary %} + + copy($response->getRealPath(), __DIR__ . '/file_response'); +{% endif %} +} catch ({{ config.invokerPackage }}\ApiException $e) { + echo "Exception when calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}: {$e->getMessage()}"; +} +{{ "" }} diff --git a/oseg/oseg/templates/python.jinja2 b/oseg/oseg/templates/python.jinja2 new file mode 100644 index 000000000..e1676eaec --- /dev/null +++ b/oseg/oseg/templates/python.jinja2 @@ -0,0 +1,138 @@ +{%- macro print_scalar(printable) -%} +{{ printable.value }} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +open("{{ printable.value }}", "rb").read() + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + open("{{ i }}", "rb").read(), + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}{}{%- else %} +json.loads(""" + {{ printable.value|tojson(4)|indent(4) }} +""") + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}[]{%- else %} +json.loads(""" + {{ printable.value|tojson(4)|indent(4) }} +""") + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} +{{ printable.value|print_variablename }} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} +[ + {% for i in printable.value %} + {{ i|print_variablename }}, + {% endfor %} +] +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "# " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}api_key={"{{ printable.key }}": {{ printable.value|tojson }}}, +{%- elif printable.method == "access_token" %}{{ comment }}access_token={{ printable.value|tojson }}, +{%- else %}{{ comment }}username={{ printable.value|tojson }},{% if printable.value_2 != None %}{{ "" }} +{{ comment }}password={{ printable.value_2|tojson }},{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +import json +from datetime import date, datetime +from pprint import pprint + +from {{ config.packageName }} import ApiClient, ApiException, Configuration, api, models + +configuration = Configuration({% if not operation.security %}){% else %} + + {% if operation.security.is_optional %} + # Authentication is optional for this API endpoint + {% endif %} + {% call(security_schemes) m.parse_security_macro(4) %} + {% for _, security in security_schemes.items() %} + {{ security }} + {% endfor %} + {% endcall %} +) +{% endif %} + +with ApiClient(configuration) as api_client: +{% call(objects) m.parse_objects_macro() %} + {% for obj_name, obj in objects.items() %} + {% if not obj.is_array %} + {{ obj_name|print_variablename }} = models.{{ obj.type|print_classname }}( + {% call(properties) m.parse_object_properties_macro(obj, 8) %} + {% for name, value in properties.items() %} + {{ name|print_propname }}={{ value }}, + {% endfor %} + {% endcall %} + ) + {% else %} + {{ obj_name|print_variablename }} = {{ "" }} + {%- call(value) m.parse_object_list_properties_macro(obj, 4) %} + {{- value }} + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} + try: + {{ "" -}} +{% call(properties) m.parse_api_call_properties_macro(12) %} + {% if operation.response and operation.response.body %}response = {% endif -%} + api.{{ operation.api_name|print_apiname }}(api_client).{{ operation.operation_id|print_methodname }}({%- if not properties %}) +{% else %} + + {% for name, value in properties.items() %} + {# + Use print_variablename here because Python generator uses property name aliases + but only for Model objects, not the API call method. + #} + {{ name|print_variablename }}={{ value }}, + {% endfor %} + ) +{% endif %} +{% endcall %} + {% if operation.response and operation.response.body and not operation.response.is_binary %} + + pprint(response) + {% elif operation.response and operation.response.is_binary %} + + open("./file_response", "wb").write(response.read()) + {% endif %} + except ApiException as e: + print("Exception when calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}: %s\n" % e) +{{ "" }} diff --git a/oseg/oseg/templates/ruby.jinja2 b/oseg/oseg/templates/ruby.jinja2 new file mode 100644 index 000000000..87a28c5b5 --- /dev/null +++ b/oseg/oseg/templates/ruby.jinja2 @@ -0,0 +1,145 @@ +{%- macro print_scalar(printable) -%} +{{ printable.value }} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +File.new("{{ printable.value }}", "r") + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + File.new("{{ i }}", "r"), + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}{}{%- else %} +JSON.parse(<<-EOD + {{ printable.value|tojson(4)|indent(4) }} + EOD +) + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}[]{%- else %} +JSON.parse(<<-EOD + {{ printable.value|tojson(4)|indent(4) }} + EOD +) + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} +{{ printable.value|print_variablename }} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} +[ + {% for i in printable.value %} + {{ i|print_variablename }}, + {% endfor %} +] +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "# " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}config.api_key["{{ printable.name }}"] = {{ printable.value|tojson }} +{%- elif printable.method == "access_token" %}{{ comment }}config.access_token = {{ printable.value|tojson }} +{%- else %}{{ comment }}config.username = {{ printable.value|tojson }}{% if printable.value_2 != None %}{{ "" }} +{{ comment }}config.password = {{ printable.value_2|tojson }}{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- macro print_variable_name_as_comment(name, value) -%} + {% if config.oseg.printApiCallProperty %} + {% if name|print_variablename != value %} # {{ name|print_variablename }}{% endif %} + {% endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +require "json" +require "{{ config.gemName }}" + +{{ config.moduleName }}.configure do |config| +{% if operation.security.is_optional %} + # Authentication is optional for this API endpoint +{% endif %} +{% call(security_schemes) m.parse_security_macro(4) %} + {% for _, security in security_schemes.items() %} + {{ security }} + {% endfor %} +{% endcall %} +end + +{% call(objects) m.parse_objects_macro() %} + {% for obj_name, obj in objects.items() %} + {% if not obj.is_array %} +{{ obj_name|print_variablename }} = {{ config.moduleName }}::{{ obj.type|print_classname }}.new + {% call(properties) m.parse_object_properties_macro(obj, 0) %} + {% for name, value in properties.items() %} +{{ obj_name|print_variablename }}.{{ name|print_methodname }} = {{ value }} + {% endfor %} + {% endcall %} + {% else %} +{{ obj_name|print_variablename }} = {{ "" }} + {%- call(value) m.parse_object_list_properties_macro(obj, 0) %} + {{- value }} + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} +begin + {{ "" -}} +{% call(properties) m.parse_api_call_properties_macro(8, True) %} + {% call(opt_properties) m.parse_api_call_properties_macro(8, False) %} + {% if operation.response and operation.response.body %}response = {% endif -%} + {{ config.moduleName }}::{{ operation.api_name|print_apiname }}.new.{{ operation.operation_id|print_methodname }}{%- if not properties and not opt_properties %} + + {% else %}( + {% for name, value in properties.items() %} + {{ value }},{{ print_variable_name_as_comment(name, value) }} + {% endfor %} + {% if opt_properties %} + { + {% for name, value in opt_properties.items() %} + {{ name|print_propname }}: {{ value }}, + {% endfor %} + }, + {% endif %} + ) + {% endif %} + {% endcall %} +{% endcall %} +{% if operation.response and operation.response.body and not operation.response.is_binary %} + + p response +{% elif operation.response and operation.response.is_binary %} + + FileUtils.cp(response.path, "./file_response") +{% endif %} +rescue {{ config.moduleName }}::ApiError => e + puts "Exception when calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}: #{e}" +end +{{ "" }} diff --git a/oseg/oseg/templates/typescript-axios.jinja2 b/oseg/oseg/templates/typescript-axios.jinja2 new file mode 100644 index 000000000..64895510e --- /dev/null +++ b/oseg/oseg/templates/typescript-axios.jinja2 @@ -0,0 +1,130 @@ +{%- macro print_scalar(printable) -%} +{% if printable.value == "null" %}{{ print_null() }}{% else %} +{{ printable.value }} +{%- endif %} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +new File(["contents of file"], "{{ printable.value }}") + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + new File(["contents of file"], "{{ i }}"), + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}{}{%- else %} +{{ printable.value|tojson(2) }} + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}[]{%- else %} +{{ printable.value|tojson(2) }} + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +{{ printable.value|print_variablename }} + {%- endif %} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i|print_variablename }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "// " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}apiKey: {{ printable.value|tojson }}, +{%- elif printable.method == "access_token" %}{{ comment }}accessToken: {{ printable.value|tojson }}, +{%- else %}{{ comment }}username: {{ printable.value|tojson }},{% if printable.value_2 != None %}{{ "" }} +{{ comment }}password: {{ printable.value_2|tojson }},{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- macro print_variable_name_as_comment(name, value) -%} + {% if config.oseg.printApiCallProperty %} + {% if name|print_variablename != value %} // {{ name|print_variablename }}{% endif %} + {% endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +import axios, { AxiosError } from "axios"; +import * as api from "{{ config.npmName }}" + +const configuration = new api.Configuration({ +{% if operation.security.is_optional %} +// Authentication is optional for this API endpoint +{% endif %} +{% call(security_schemes) m.parse_security_macro(0) %} + {% for _, security in security_schemes.items() %} + {{ security }} + {% endfor %} +{% endcall %} +}); + +{% call(objects) m.parse_objects_macro() %} + {% for obj_name, obj in objects.items() %} + {% if not obj.is_array %} + {% call(properties) m.parse_object_properties_macro(obj, 2) %} +const {{ obj_name|print_variablename }}: api.{{ obj.type|print_classname }} = { + {% for name, value in properties.items() %} + {{ name|print_propname }}: {{ value }}, + {% endfor %} + {% endcall %} +}; + {% else %} + {%- call(value) m.parse_object_list_properties_macro(obj, 0) %} +const {{ obj_name|print_variablename }} = {{ value }}; + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} +{% call(properties) m.parse_api_call_properties_macro(2) %} +new api.{{ operation.api_name|print_apiname }}(configuration).{{ operation.operation_id|print_methodname }}({% if not properties %}) +{%- else %} + + {% for name, value in properties.items() %} + {{ value }},{{ print_variable_name_as_comment(name, value) }} + {% endfor %} +){% endif %}{% endcall %}{%- if operation.response and operation.response.body %}.then(response => { +{% if not operation.response.is_binary %} + console.log(response.data); +{% elif operation.response.is_binary %} + // handle file response via response.data +{% endif -%} +}){% endif %}.catch((error: Error | AxiosError) => { + console.log("Exception when calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}:"); + axios.isAxiosError(error) ? console.log(error.message) : console.log(error); +}); +{{ "" }} diff --git a/oseg/oseg/templates/typescript-node.jinja2 b/oseg/oseg/templates/typescript-node.jinja2 new file mode 100644 index 000000000..62a490d8d --- /dev/null +++ b/oseg/oseg/templates/typescript-node.jinja2 @@ -0,0 +1,131 @@ +{%- macro print_scalar(printable) -%} +{% if printable.value == "null" %}{{ print_null() }}{% else %} +{{ printable.value }} +{%- endif %} +{%- endmacro -%} + +{%- macro print_scalar_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_file(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +fs.createReadStream("{{ printable.value }}") + {%- endif %} +{%- endmacro -%} + +{%- macro print_file_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + fs.createReadStream("{{ i }}"), + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}{}{%- else %} +{{ printable.value|tojson(2) }} + {%- endif %} +{%- endmacro -%} + +{%- macro print_free_form_array(printable) -%} + {% if printable.value == None %}{{ print_null() }} + {%- elif not printable.value %}[]{%- else %} +{{ printable.value|tojson(2) }} + {%- endif %} +{%- endmacro -%} + +{%- macro print_object(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +{{ printable.value|print_variablename }} + {%- endif %} +{%- endmacro -%} + +{%- macro print_object_array(printable) -%} + {% if printable.value == None %}{{ print_null() }}{% else %} +[ + {% for i in printable.value %} + {{ i|print_variablename }}, + {% endfor %} +] + {%- endif %} +{%- endmacro -%} + +{%- macro print_security(printable) -%} + {% set comment = "" %} + {% if not printable.is_primary %}{% set comment = "// " %}{% endif %} +{%- if printable.method == "api_key" %}{{ comment }}apiCaller.setApiKey( + {{- "" }}api.{{ (operation.api_name ~ "ApiApiKeys")|print_classname }}.{{ printable.key }}, {{ printable.value|tojson }}); +{%- elif printable.method == "access_token" %}{{ comment }}apiCaller.accessToken = {{ printable.value|tojson }}; +{%- else %}{{ comment }}apiCaller.username = {{ printable.value|tojson }};{% if printable.value_2 != None %}{{ "" }} +{{ comment }}apiCaller.password = {{ printable.value_2|tojson }};{% endif %} +{%- endif %} +{%-endmacro -%} + +{%- macro print_variable_name_as_comment(name, value) -%} + {% if config.oseg.printApiCallProperty %} + {% if name|print_variablename != value %} // {{ name|print_variablename }}{% endif %} + {% endif %} +{%-endmacro -%} + +{%- import "_macros.jinja2" as m with context -%} + +import * as fs from 'fs'; +import api from "{{ config.npmName }}" +import models from "{{ config.npmName }}" + +const apiCaller = new api.{{ operation.api_name|print_apiname }}(); +{% if operation.security.is_optional %} +// Authentication is optional for this API endpoint +{% endif %} +{% call(security_schemes) m.parse_security_macro(0) %} + {% for _, security in security_schemes.items() %} +{{ security }} + {% endfor %} +{% endcall %} + +{% call(objects) m.parse_objects_macro() %} + {% for obj_name, obj in objects.items() %} + {% if not obj.is_array %} + {% call(properties) m.parse_object_properties_macro(obj, 2) %} +const {{ obj_name|print_variablename }}: models.{{ obj.type|print_classname }} = { + {% for name, value in properties.items() %} + {{ name|print_propname }}: {{ value }}, + {% endfor %} + {% endcall %} +}; + {% else %} + {%- call(value) m.parse_object_list_properties_macro(obj, 0) %} +const {{ obj_name|print_variablename }} = {{ value }}; + {% endcall %} + {% endif %} + + {% endfor %} +{% endcall %} +{% call(properties) m.parse_api_call_properties_macro(2) %} +apiCaller.{{ operation.operation_id|print_methodname }}({% if not properties %}) +{%- else %} + + {% for name, value in properties.items() %} + {{ value }},{{ print_variable_name_as_comment(name, value) }} + {% endfor %} +){% endif %}{% endcall %}{%- if operation.response and operation.response.body %}.then(response => { +{% if not operation.response.is_binary %} + console.log(response.body); +{% elif operation.response.is_binary %} + fs.createWriteStream('./file_response').write(response.body); +{% endif -%} +}){% endif %}.catch(error => { + console.log("Exception when calling {{ operation.api_name|print_apiname }}#{{ operation.operation_id|print_methodname }}:"); + console.log(error.body); +}); +{{ "" }} diff --git a/oseg/pyproject.toml b/oseg/pyproject.toml new file mode 100644 index 000000000..192340494 --- /dev/null +++ b/oseg/pyproject.toml @@ -0,0 +1,43 @@ +[project] +name = "oseg" +version = "0.1-dev" +description = "OpenAPI SDK Example Generator" +readme = "README.md" +requires-python = ">=3.13" +keywords = ["OpenAPI", "openapi-generator", "sdk"] +authors = [ + { name = "Dropbox Sign", email = "apisupport@hellosign.com" }, +] +classifiers = [ + "Development Status :: 4 - Beta", +] +dependencies = [ + "Jinja2~=3.1", + "openapi-pydantic~=0.5", + "pydantic~=2.10", + "PyYAML~=6.0", + "click~=8.1", + "tabulate~=0.9", +] + +[project.urls] +Documentation = "https://github.com/hellosign/hellosign-openapi" +Issues = "https://github.com/hellosign/hellosign-openapi" +Source = "https://github.com/hellosign/hellosign-openapi" + +[dependency-groups] +dev = [ + "black", + "coverage", + "mock", +] + +[tool.setuptools.packages] +find = { include = ["oseg"] } + +[tool.black] +force-exclude = "templates" + +[build-system] +requires = ["setuptools>=43.0.0", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/oseg/run-sign.py b/oseg/run-sign.py new file mode 100644 index 000000000..ed1647719 --- /dev/null +++ b/oseg/run-sign.py @@ -0,0 +1,71 @@ +from oseg import Generator, __ROOT_DIR__ + + +def main(): + operation_id = None + target_sdk = None + + project_dir = f"{__ROOT_DIR__}/../" + + sdks = { + "csharp": { + "base_dir": project_dir, + "output_dir": "examples", + "config": f"{project_dir}/sdks/dotnet/openapi-config.yaml" + }, + "java": { + "base_dir": project_dir, + "output_dir": "examples", + "config": f"{project_dir}/sdks/java-v2/openapi-config.yaml" + }, + "php": { + "base_dir": project_dir, + "output_dir": "examples", + "config": f"{project_dir}/sdks/php/openapi-config.yaml" + }, + "python": { + "base_dir": project_dir, + "output_dir": "examples", + "config": f"{project_dir}/sdks/python/openapi-config.yaml" + }, + "ruby": { + "base_dir": project_dir, + "output_dir": "examples", + "config": f"{project_dir}/sdks/ruby/openapi-config.yaml" + }, + "typescript-axios": { + "base_dir": project_dir, + "output_dir": "examples", + "config": f"{project_dir}/sdks/node/openapi-config.yaml" + }, + } + + oas_file = f"{project_dir}/openapi-sdk.yaml" + example_data_file = None + + oseg_generator = Generator( + oas_file=oas_file, + operation_id=operation_id, + example_data=example_data_file, + ) + + for sdk_name, sdk in sdks.items(): + if target_sdk and sdk_name != target_sdk: + continue + + config = oseg_generator.read_config_file(sdk["config"]) + + oseg_generator.generate( + config=config, + output_dir=f"{sdk["base_dir"]}/{sdk["output_dir"]}", + ) + + oseg_generator.setup_project( + config=config, + base_dir=sdk["base_dir"], + output_dir=sdk["output_dir"], + ) + + +if __name__ == "__main__": + main() diff --git a/oseg/run.py b/oseg/run.py new file mode 100644 index 000000000..69ee221b2 --- /dev/null +++ b/oseg/run.py @@ -0,0 +1,216 @@ +import inspect +import json +import os +import click +from tabulate import tabulate +from oseg import Generator, generator as g + +""" +Example: +python3 run.py generate \ + -i openapi.yaml \ + -o generated/python/src \ + --config-file config-python.yaml \ + --example-data-file example_data.json + +or: + +python3 run.py generate \ + -i openapi.yaml \ + -o generated/python/src \ + --generator-name python \ + --config '{ + "packageName": "openapi_client", + "oseg.propertyNamingConvention": "camel_case", + "oseg.ignoreOptionalUnset": false + }' \ + --example-data-file example_data.json + +or: + +python3 run.py config-help -g python +""" + + +generator_names = g.GeneratorFactory.default_generator_names() + + +@click.group() +def cli(): + pass + + +@click.command() +@click.option( + "-i", + "--input-spec", + "spec_file", + required=True, + help="Path to OpenAPI file", +) +@click.option( + "-o", + "--output", + "output_dir", + required=True, + help="Where to write the generated files", +) +@click.option( + "--config-file", + "config_file", + help=inspect.cleandoc( + f""" + Config file for the target SDK to generate examples for. + + One of {", ".join(generator_names)}. + + When defined you should not use --generator-name or --config, + otherwise required. + """ + ), +) +@click.option( + "--generator-name", + "generator_name", + help=inspect.cleandoc( + f""" + Generator to use. + + One of {", ".join(generator_names)}. + + When defined you should not use --config-file, otherwise required alongside + --config. + """ + ), +) +@click.option( + "--config", + "config", + help=inspect.cleandoc( + """ + Config properties available to the chosen generator, as a JSON blob. + + When defined you should not use --config-file, otherwise required alongside + --generator-name. + """ + ), +) +@click.option( + "--example-data-file", + "example_data_file", + help="Path to optional external file containing example data", +) +@click.option( + "--operation-id", + "operation_id", + help="Optionally process only a single operation", +) +def generate( + spec_file: str, + output_dir: str, + config_file: str | None, + generator_name: str | None, + config: str | None, + example_data_file: str | None, + operation_id: str | None, +): + resolved_config = get_config(config_file, generator_name, config) + + example_data = None + + if example_data_file and os.path.isfile(example_data_file): + with open(example_data_file, "r", encoding="utf-8") as f: + example_data = json.load(f) + + generator = Generator( + oas_file=spec_file, + operation_id=operation_id, + example_data=example_data, + ) + + generator.generate( + config=resolved_config, + output_dir=output_dir, + ) + + +@click.command() +@click.option( + "-g", + "--generator-name", + "generator_name", + required=True, + help=inspect.cleandoc( + f""" + Config help for chosen lang. + + One of {", ".join(generator_names)}. + """ + ), +) +def config_help(generator_name: str): + result = g.GeneratorFactory.config_class(generator_name).config_help() + + data = [ + ["Name", "", "Required", "Default"], + ] + + for name, description in result["required"].items(): + data.append([name, description, "Yes", ""]) + + for name, sub in result["optional"].items(): + data.append([name, sub["description"], "No", sub["default"]]) + + print( + "\n" + + inspect.cleandoc( + """ + Note: Any config name not prepended with "oseg" refers to the source + SDK. These names come directly from openapi-generator. See + https://openapi-generator.tech/docs/generators/ for more information. + """ + ) + + "\n" + ) + + print( + tabulate(data, headers="firstrow", tablefmt="simple", maxcolwidths=[None, 40]) + ) + + pass + + +def get_config( + config_file: str | None, + generator_name: str | None, + config: str | None, +) -> str | g.BaseConfig: + if config_file: + assert ( + generator_name is None + ), "--generator-name cannot be used with --config-file" + + assert config is None, "--config cannot be used with --config-file" + + return g.GeneratorFactory.config_factory(config_file) + + assert isinstance(generator_name, str) and ( + generator_name in generator_names + ), f"--generator-name must be one of {", ".join(generator_names)}" + + assert isinstance(config, str), f"--config required when --config-file is not used" + + return g.GeneratorFactory.config_factory( + { + "generatorName": generator_name, + "additionalProperties": json.loads(config), + } + ) + + +cli.add_command(generate) +cli.add_command(config_help) + + +if __name__ == "__main__": + cli() diff --git a/oseg/tests/fixtures/common_parameters.yaml b/oseg/tests/fixtures/common_parameters.yaml new file mode 100644 index 000000000..2766355fc --- /dev/null +++ b/oseg/tests/fixtures/common_parameters.yaml @@ -0,0 +1,241 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Common Parameters Examples +paths: + /additional_parameter_at_start: + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + post: + tags: + - pet + operationId: additional_parameter_at_start + parameters: + - name: additional_parameter + in: query + schema: + type: string + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: {} + /additional_parameter_in_middle: + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + post: + tags: + - pet + operationId: additional_parameter_in_middle + parameters: + - name: param_1 + in: query + schema: + type: string + - name: additional_parameter + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: {} + /additional_parameter_at_end: + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + post: + tags: + - pet + operationId: additional_parameter_at_end + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - name: additional_parameter + in: query + schema: + type: string + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: {} + /parameters_in_different_order: + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + post: + tags: + - pet + operationId: parameters_in_different_order + parameters: + - name: additional_parameter + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - name: param_1 + in: query + schema: + type: string + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: {} + /override_parameter_data: + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + post: + tags: + - pet + operationId: override_parameter_data + parameters: + - name: param_1 + in: query + schema: + type: integer + - name: param_2 + in: query + schema: + type: string + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: {} + /no_parameter_data: + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: integer + - $ref: '#/components/parameters/Param3' + - name: param_4 + in: query + schema: + $ref: '#/components/schemas/Param4' + post: + tags: + - pet + operationId: no_parameter_data + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: {} +components: + parameters: + Param3: + name: param_3 + in: query + schema: + type: string + schemas: + Param4: + type: string diff --git a/oseg/tests/fixtures/component_resolver.yaml b/oseg/tests/fixtures/component_resolver.yaml new file mode 100644 index 000000000..4b9ac70e8 --- /dev/null +++ b/oseg/tests/fixtures/component_resolver.yaml @@ -0,0 +1,213 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Component Resolver Examples +paths: + /inline_nested_schema_root: + post: + tags: + - pet + operationId: inline_nested_schema_root + requestBody: + content: + application/json: + schema: + type: object + properties: + labels: + type: array + description: Array of labels (comma-separated strings) + items: + type: string + required: true + responses: + '200': + description: Successful operation + /another_inline_nested_schema_root_2: + post: + tags: + - pet + operationId: another_inline_nested_schema_root_2 + requestBody: + content: + application/json: + schema: + type: object + properties: + labels: + type: array + description: Array of labels (comma-separated strings) + items: + type: string + required: true + responses: + '200': + description: Successful operation + /inline_nested_schema_nested: + post: + tags: + - pet + operationId: inline_nested_schema_nested + requestBody: + content: + application/json: + schema: + type: object + properties: + nested_inline: + type: object + properties: + labels: + type: array + description: Array of labels (comma-separated strings) + items: + type: string + required: true + responses: + '200': + description: Successful operation + inline_nested_schema_identical_name_1: + post: + tags: + - pet + operationId: inline_nested_schema_identical_name_1 + requestBody: + content: + application/json: + schema: + type: object + properties: + id: + type: string + some_property_name: + type: object + properties: + name: + type: string + description: Shared description for name property + description: Shared description for this object + responses: + '200': + description: Success +components: + responses: + SomeResponseRef: + $ref: '#/components/responses/SomeResponse' + SomeResponse: + description: 'successful operation' + content: + text/plain: + schema: + type: string + default: 'Response value' + schemas: + SomeSchemaRef: + $ref: '#/components/schemas/SomeSchema' + SomeSchema: + type: object + properties: + prop_1: + type: string + # to match inline_nested_schema_identical_name_1.some_property_name + SomeSchemaWithDupe1: + type: object + properties: + prop_1: + type: object + properties: + name: + type: string + description: Shared description for name property + description: Shared description for this object + SomeSchemaWithDupe2: + type: object + properties: + prop_1: + type: object + properties: + # to match inline_nested_schema_identical_name_1.some_property_name + prop_2: + type: object + properties: + name: + type: string + description: Shared description for name property + description: Shared description for this object + SchemaWithInner: + type: object + properties: + prop_1: + type: object + description: Some random description SchemaWithInner 1 + properties: + prop_2: + type: array + description: Some random description SchemaWithInner 2 + items: + type: object + properties: + prop_3: + type: object + description: Some random description SchemaWithInner 3 + properties: + name: + type: string + description: Some random description SchemaWithInner 4 + SchemaWithInnerInner: + type: object + properties: + prop_1: + type: object + description: Some random description SchemaWithInnerInner 1 + properties: + prop_2: + type: array + description: Some random description SchemaWithInnerInner 2 + items: + type: object + properties: + prop_3: + type: array + description: Some random description SchemaWithInnerInner 3 + items: + type: object + properties: + prop_4: + type: object + description: Some random description SchemaWithInner 4 + properties: + name: + type: string + description: Some random description SchemaWithInner 5 + parameters: + SomeParameterRef: + $ref: '#/components/parameters/SomeParameter' + SomeParameter: + name: some_parameter + in: query + schema: + type: string + requestBodies: + SomeRequestBodyRef: + $ref: '#/components/requestBodies/SomeRequestBody' + SomeRequestBody: + content: + multipart/form-data: {} + examples: + SomeExampleRef: + $ref: '#/components/examples/SomeExample' + SomeExample: + summary: 'Some Example' + value: + key_1: value_1 + securitySchemes: + petstore_auth_ref: + $ref: '#/components/securitySchemes/petstore_auth' + api_key_ref: + $ref: '#/components/securitySchemes/api_key' + petstore_auth: + type: oauth2 + api_key: + type: apiKey + name: api_key + in: header diff --git a/oseg/tests/fixtures/config-mock.yaml b/oseg/tests/fixtures/config-mock.yaml new file mode 100644 index 000000000..4c463e696 --- /dev/null +++ b/oseg/tests/fixtures/config-mock.yaml @@ -0,0 +1,15 @@ +generatorName: mock +additionalProperties: + packageName: openapi_client + projectName: openapi-client + oseg.ignoreOptionalUnset: true + oseg.security.api_key_scheme.api_key: YOUR_API_KEY + oseg.security.http_basic_scheme.username: YOUR_USERNAME + oseg.security.http_basic_scheme.password: YOUR_PASSWORD + oseg.security.http_bearer_scheme.access_token: YOUR_ACCESS_TOKEN_1 + oseg.security.oauth2_scheme.access_token: YOUR_ACCESS_TOKEN_2 +globalProperties: + apiTests: false + modelTests: false + apiDocs: false + modelDocs: false diff --git a/oseg/tests/fixtures/discriminator.yaml b/oseg/tests/fixtures/discriminator.yaml new file mode 100644 index 000000000..ec7bf04bc --- /dev/null +++ b/oseg/tests/fixtures/discriminator.yaml @@ -0,0 +1,78 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Discriminator Examples +tags: + - name: pet +paths: + /default: + post: + tags: + - pet + operationId: default + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + type: + type: string + # array of discriminators + Dogs: + type: object + properties: + dogs: + type: array + items: + $ref: '#/components/schemas/Dog' + # single discriminator + Dog: + type: object + properties: + id: + type: integer + breed: + type: string + mans_best_friend: + $ref: '#/components/schemas/MansBestFriend' + discriminator: + propertyName: breed + mapping: + beagle: '#/components/schemas/Beagle' + terrier: '#/components/schemas/Terrier' + Beagle: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hound + Terrier: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hunting + # array of allOf without discriminator + Terriers: + type: object + properties: + terriers: + type: array + items: + $ref: '#/components/schemas/Terrier' + MansBestFriend: + type: boolean diff --git a/oseg/tests/fixtures/enums.yaml b/oseg/tests/fixtures/enums.yaml new file mode 100644 index 000000000..a20a7ba3f --- /dev/null +++ b/oseg/tests/fixtures/enums.yaml @@ -0,0 +1,56 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Enums Examples +tags: + - name: pet +paths: + /default: + post: + tags: + - pet + operationId: default + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '200': + description: Successful operation +components: + schemas: + Pet: + type: object + properties: + enum_prop_1: + type: string + enum: + - value_1 + - value_2 + - value_3 + enum_prop_2: + type: string + enum: + - value_1 + - value_2 + - value_3 + x-enum-varnames: + - ENUM_VARNAME_1 + - ENUM_VARNAME_2 + - ENUM_VARNAME_3 + enum_prop_3: + type: string + enum: + - value_1 + - value_2 + - value_3 + x-enum-varnames-override: + csharp: + - ENUM_VARNAME_OVERRIDE_CSHARP_1 + - ENUM_VARNAME_OVERRIDE_CSHARP_2 + - ENUM_VARNAME_OVERRIDE_CSHARP_3 + mock: + - ENUM_VARNAME_OVERRIDE_MOCK_1 + - ENUM_VARNAME_OVERRIDE_MOCK_2 + - ENUM_VARNAME_OVERRIDE_MOCK_3 diff --git a/oseg/tests/fixtures/example_data_parser-body.yaml b/oseg/tests/fixtures/example_data_parser-body.yaml new file mode 100644 index 000000000..eed2a9259 --- /dev/null +++ b/oseg/tests/fixtures/example_data_parser-body.yaml @@ -0,0 +1,159 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - ExampleDataParser - Array Body +tags: + - name: pet +paths: + /single_body: + post: + tags: + - pet + operationId: single_body + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + /array_body: + post: + tags: + - pet + operationId: array_body + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + /discriminator: + post: + tags: + - pet + operationId: discriminator + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Dog' + /all_of: + post: + tags: + - pet + operationId: all_of + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Terrier' + /content_example: + post: + tags: + - pet + operationId: content_example + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + example: + id: 50 + name: fish + schema: + $ref: '#/components/schemas/Pet' + /content_examples: + post: + tags: + - pet + operationId: content_examples + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + examples: + example_name: + value: + id: 500 + name: birds + schema: + $ref: '#/components/schemas/Pet' + /body_with_examples: + post: + tags: + - pet + operationId: body_with_examples + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SchemaWithExamples" + responses: + '200': + description: Successful operation +components: + schemas: + Pet: + properties: + id: + type: integer + example: 10 + name: + type: string + example: doggie + type: object + Dog: + type: object + properties: + id: + type: integer + example: 10 + breed: + type: string + example: terrier + discriminator: + propertyName: breed + mapping: + beagle: '#/components/schemas/Beagle' + terrier: '#/components/schemas/Terrier' + Beagle: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hound + Terrier: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hunting + SchemaWithExamples: + type: object + properties: + key_1: + type: string + examples: + - key_1: value_1 + - key_1: value_2 diff --git a/oseg/tests/fixtures/example_data_parser-external_example.yaml b/oseg/tests/fixtures/example_data_parser-external_example.yaml new file mode 100644 index 000000000..3d68ef147 --- /dev/null +++ b/oseg/tests/fixtures/example_data_parser-external_example.yaml @@ -0,0 +1,94 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - ExampleDataParser - External Example +tags: + - name: pet +paths: + /operation_example: + post: + tags: + - pet + operationId: operation_example + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Dog' + examples: + example_1: + $ref: '#/components/examples/OperationExample1' + example_2: + $ref: '#/components/examples/OperationExample2' + /content_example: + post: + tags: + - pet + operationId: content_example + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Dog' + examples: + example_1: + $ref: '#/components/examples/ContentExample1' + example_2: + $ref: '#/components/examples/ContentExample2' +components: + schemas: + Dog: + type: object + properties: + id: + type: integer + example: 10 + breed: + type: string + example: terrier + discriminator: + propertyName: breed + mapping: + beagle: '#/components/schemas/Beagle' + terrier: '#/components/schemas/Terrier' + Beagle: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hound + Terrier: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hunting + examples: + OperationExample1: + summary: 'External Operation Example #1' + value: + $ref: external_data/example_data-operation_example_1.json + OperationExample2: + summary: 'External Operation Example #2' + value: + $ref: external_data/example_data-operation_example_2.json + ContentExample1: + summary: 'External Content Example #1' + value: + $ref: external_data/example_data-content_example_1.json + ContentExample2: + summary: 'External Content Example #2' + value: + $ref: external_data/example_data-content_example_2.json diff --git a/oseg/tests/fixtures/example_data_parser-path-query-parameters.yaml b/oseg/tests/fixtures/example_data_parser-path-query-parameters.yaml new file mode 100644 index 000000000..3badd93b9 --- /dev/null +++ b/oseg/tests/fixtures/example_data_parser-path-query-parameters.yaml @@ -0,0 +1,266 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - ExampleDataParser - Path & Query Parameters +tags: + - name: tag_1 +paths: + /param_with_example: + get: + tags: + - tag_1 + operationId: param_with_example + parameters: + - + name: param_name_1 + in: query + required: false + schema: + type: string + example: value_1 + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /param_with_example_with_default: + get: + tags: + - tag_1 + operationId: param_with_example_with_default + parameters: + - + name: param_name_1 + in: query + required: false + schema: + type: string + default: value_2 + example: value_1 + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /param_without_example_with_default_is_required: + get: + tags: + - tag_1 + operationId: param_without_example_with_default_is_required + parameters: + - + name: param_name_1 + in: query + required: true + schema: + type: string + default: value_2 + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /param_without_example_with_default_not_required: + get: + tags: + - tag_1 + operationId: param_without_example_with_default_not_required + parameters: + - + name: param_name_1 + in: query + required: false + schema: + type: string + default: value_2 + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /param_without_example_without_default_is_required: + get: + tags: + - tag_1 + operationId: param_without_example_without_default_is_required + parameters: + - + name: param_name_1 + in: query + required: true + schema: + type: string + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /param_without_example_without_default_not_required: + get: + tags: + - tag_1 + operationId: param_without_example_without_default_not_required + parameters: + - + name: param_name_1 + in: query + required: false + schema: + type: string + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /param_as_array: + get: + tags: + - tag_1 + operationId: param_as_array + parameters: + - + name: param_name_1 + in: query + required: false + schema: + type: array + items: + type: string + example: + - value_1 + - value_2 + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /mixed_params: + get: + tags: + - tag_1 + operationId: mixed_params + parameters: + - + name: param_with_example + in: query + required: false + schema: + type: string + example: value_1 + - + name: param_with_example_with_default + in: query + required: false + schema: + type: string + default: value_2 + example: value_1 + - + name: param_without_example_with_default_is_required + in: query + required: true + schema: + type: string + default: value_2 + - + name: param_without_example_with_default_not_required + in: query + required: false + schema: + type: string + default: value_2 + - + name: param_without_example_without_default_is_required + in: query + required: true + schema: + type: string + - + name: param_without_example_without_default_not_required + in: query + required: false + schema: + type: string + - + name: param_as_array + in: query + required: false + schema: + type: array + items: + type: string + example: + - value_1 + - value_2 + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /param_not_in_query_or_path: + get: + tags: + - tag_1 + operationId: param_not_in_query_or_path + parameters: + - + name: param_name_1 + in: header + required: false + schema: + type: string + example: value_1 + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation + /different_param_in: + get: + tags: + - tag_1 + operationId: different_param_in + parameters: + - + name: param_name_1 + in: path + required: true + schema: + type: string + example: path_value + - + name: param_name_1 + in: query + required: false + schema: + type: string + example: query_value + - + name: param_name_1 + in: header + required: false + schema: + type: string + example: header_value + - + name: param_name_1 + in: cookie + required: false + schema: + type: string + example: cookie_value + requestBody: + content: + application/json: {} + responses: + '200': + description: successful operation diff --git a/oseg/tests/fixtures/example_data_parser-single-requestBody.yaml b/oseg/tests/fixtures/example_data_parser-single-requestBody.yaml new file mode 100644 index 000000000..4fb06521a --- /dev/null +++ b/oseg/tests/fixtures/example_data_parser-single-requestBody.yaml @@ -0,0 +1,50 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - ExampleDataParser - Single requestBody +tags: + - name: pet +paths: + /single_request_body: + post: + tags: + - pet + operationId: single_request_body + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + /multiple_request_body: + post: + tags: + - pet + operationId: multiple_request_body + responses: + '200': + description: Successful operation + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Customer' + application/json: + schema: + $ref: '#/components/schemas/Pet' +components: + schemas: + Customer: + properties: + id: + type: integer + example: 100000 + type: object + Pet: + properties: + id: + type: integer + example: 10 + type: object diff --git a/oseg/tests/fixtures/external_data/example_data-content_example_1.json b/oseg/tests/fixtures/external_data/example_data-content_example_1.json new file mode 100644 index 000000000..a42d045f6 --- /dev/null +++ b/oseg/tests/fixtures/external_data/example_data-content_example_1.json @@ -0,0 +1,5 @@ +{ + "id": 100, + "breed": "terrier", + "group": "hunting" +} diff --git a/oseg/tests/fixtures/external_data/example_data-content_example_2.json b/oseg/tests/fixtures/external_data/example_data-content_example_2.json new file mode 100644 index 000000000..25bff5b19 --- /dev/null +++ b/oseg/tests/fixtures/external_data/example_data-content_example_2.json @@ -0,0 +1,5 @@ +{ + "id": 200, + "breed": "beagle", + "group": "hound" +} diff --git a/oseg/tests/fixtures/external_data/example_data-operation_example_1.json b/oseg/tests/fixtures/external_data/example_data-operation_example_1.json new file mode 100644 index 000000000..a98dcd91c --- /dev/null +++ b/oseg/tests/fixtures/external_data/example_data-operation_example_1.json @@ -0,0 +1,7 @@ +{ + "body": { + "id": 100, + "breed": "terrier", + "group": "hunting" + } +} diff --git a/oseg/tests/fixtures/external_data/example_data-operation_example_2.json b/oseg/tests/fixtures/external_data/example_data-operation_example_2.json new file mode 100644 index 000000000..cf2b0bbfd --- /dev/null +++ b/oseg/tests/fixtures/external_data/example_data-operation_example_2.json @@ -0,0 +1,7 @@ +{ + "body": { + "id": 200, + "breed": "beagle", + "group": "hound" + } +} diff --git a/oseg/tests/fixtures/mock_generator.py b/oseg/tests/fixtures/mock_generator.py new file mode 100644 index 000000000..0ac6280ad --- /dev/null +++ b/oseg/tests/fixtures/mock_generator.py @@ -0,0 +1,241 @@ +import inspect +from dataclasses import dataclass + +from jinja2.runtime import Macro +from mock import mock +from typing import TypedDict +from oseg import generator, model, parser + +ConfigDef = TypedDict( + "ConfigDef", + { + "packageName": str, + "oseg.ignoreOptionalUnset": bool | None, + "oseg.security": dict[str, any] | None, + }, +) + + +@dataclass +class ConfigOseg(generator.BaseConfigOseg): + pass + + +class MockConfig(generator.BaseConfig): + GENERATOR_NAME = "mock" + oseg: ConfigOseg + _config: ConfigDef + + PROPS_REQUIRED = { + "packageName": inspect.cleandoc( + """ + The package name of the source package. This is the SDK package + you are generating example snippets for. Ex: openapi_client + """ + ), + } + + PROPS_OPTIONAL: dict[str, generator.PropsOptionalT] = { + "oseg.ignoreOptionalUnset": { + "description": inspect.cleandoc( + """ + Skip printing optional properties that do not have + a value. (Default: true) + """ + ), + "default": True, + }, + "oseg.security": { + "description": inspect.cleandoc( + """ + Security scheme definitions + """ + ), + "default": {}, + }, + } + + def __init__(self, config: ConfigDef): + super().__init__(config) + + self.packageName = config.get("packageName") + assert isinstance(self.packageName, str) + + self.oseg = ConfigOseg( + ignoreOptionalUnset=self._get_value("oseg.ignoreOptionalUnset"), + security=self._parse_security(), + ) + + +class MockGenerator(generator.BaseGenerator): + FILE_EXTENSION = "mock" + NAME = "mock" + TEMPLATE = f"{NAME}.jinja2" + + RESERVED_KEYWORD_PREPEND = "var_" + RESERVED_KEYWORDS = [ + "try", + "while", + "with", + ] + RESERVED_KEYWORDS_SECONDARY = [ + "configuration", + "version", + ] + + _config: MockConfig + + def is_reserved_keyword(self, name: str, secondary: bool = False) -> bool: + parsed = parser.NormalizeStr.snake_case(name) + + if secondary: + return parsed in self.RESERVED_KEYWORDS_SECONDARY + + return parsed in self.RESERVED_KEYWORDS + + def unreserve_keyword( + self, + name: str, + force: bool = False, + secondary: bool = False, + ) -> str: + if not force and not self.is_reserved_keyword(name, secondary): + return name + + if not name.startswith(self.RESERVED_KEYWORD_PREPEND): + return f"{self.RESERVED_KEYWORD_PREPEND}{name}" + + return name + + def print_apiname(self, name: str) -> str: + return parser.NormalizeStr.pascal_case(f"{name}Api") + + def print_classname(self, name: str) -> str: + return parser.NormalizeStr.pascal_case(name) + + def print_methodname(self, name: str) -> str: + return parser.NormalizeStr.camel_case(name) + + def print_propname(self, name: str) -> str: + name = parser.NormalizeStr.snake_case(name) + + if self.is_reserved_keyword(name): + return self.unreserve_keyword(name) + + return name + + def print_variablename(self, name: str) -> str: + name = parser.NormalizeStr.snake_case(name) + + if self.is_reserved_keyword(name): + return self.unreserve_keyword(name) + + return name + + def print_scalar( + self, + parent: model.PropertyObject, + item: model.PropertyScalar, + ) -> model.PrintableScalar: + printable = model.PrintableScalar() + printable.value = None + + if item.is_array: + printable.is_array = True + + if item.value is None: + return printable + + printable.value = [] + + for i in item.value: + printable.value.append(self._handle_value(item, i)) + + return printable + + printable.value = self._handle_value(item, item.value) + + return printable + + def print_null(self) -> str: + return "None" + + def _handle_value( + self, + item: model.PropertyScalar, + value: any, + ) -> any: + if item.is_enum: + enum_varname, is_override = self._get_enum_varname(item.schema, value) + + if enum_varname is not None: + return enum_varname + + if isinstance(value, str): + return value + + return self._to_json(value) + + +def scalar_macro_callback(printable: model.PrintableScalar) -> str | None: + if printable.value is None: + return None + + if printable.is_array: + return "[" + ",".join(printable.value) + "]" + + return str(printable.value) + + +def freeform_macro_callback(printable: model.PrintableFreeForm) -> str | None: + if printable.value is None: + return None + + if printable.is_array: + return "[" + ",".join(printable.value) + "]" + + return str(printable.value) + + +def object_macro_callback(printable: model.PrintableObject) -> str | None: + if printable.value is None: + return None + + if printable.is_array: + return ("[" + ",".join(printable.value) + "]").lower() + + return str(printable.value).lower() + + +def print_security_macro_callback(printable: model.PrintableSecurity) -> str: + comment = "# " if not printable.is_primary else "" + + if printable.method == "basic": + return f"{comment}{printable.method}: {printable.value}:{printable.value_2}" + + return f"{comment}{printable.method}: {printable.value}" + + +scalar_mock = mock.MagicMock(spec="__call__") +scalar_mock.side_effect = scalar_macro_callback + +freeform_mock = mock.MagicMock(spec="__call__") +freeform_mock.side_effect = freeform_macro_callback + +object_mock = mock.MagicMock(spec="__call__") +object_mock.side_effect = object_macro_callback + +security_mock = mock.MagicMock(spec="__call__") +security_mock.side_effect = print_security_macro_callback + +JINJA_MACROS: dict[str, Macro] = { + "print_security": security_mock, + "print_object": object_mock, + "print_object_array": object_mock, + "print_scalar": scalar_mock, + "print_scalar_array": scalar_mock, + "print_file": scalar_mock, + "print_file_array": scalar_mock, + "print_free_form": freeform_mock, + "print_free_form_array": freeform_mock, +} diff --git a/oseg/tests/fixtures/operation.yaml b/oseg/tests/fixtures/operation.yaml new file mode 100644 index 000000000..9bb2e7a77 --- /dev/null +++ b/oseg/tests/fixtures/operation.yaml @@ -0,0 +1,48 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Operation Examples +tags: + - name: pet +paths: + /no_tags: + post: + operationId: no_tags + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + /with_tags: + post: + tags: + - pet + - some_other + operationId: with_tags + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + /operation_id_with_special_chars: + post: + tags: + - some_other + operationId: security-advisories/list-global-advisories/some_value + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + type: + type: string diff --git a/oseg/tests/fixtures/properties.yaml b/oseg/tests/fixtures/properties.yaml new file mode 100644 index 000000000..6358101ab --- /dev/null +++ b/oseg/tests/fixtures/properties.yaml @@ -0,0 +1,941 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Property Examples +tags: + - name: pet +paths: + /default: + post: + tags: + - pet + operationId: default + parameters: + # generates class, expected name default_paramObject_parameter + - name: paramObject + in: path + required: true + schema: + type: object + properties: + id: + type: integer + # generates class, expected name default_paramArrayObject_parameter + - name: paramArrayObject + in: path + required: true + schema: + type: array + items: + type: object + properties: + id: + type: integer + # does not generate class + - name: paramString + in: query + schema: + type: string + # does not generate class + - $ref: "#/components/parameters/ParamComponentObject" + # does not generate class + - $ref: "#/components/parameters/ParamComponentArrayObject" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '200': + description: Successful operation + /inline_request_body_properties: + post: + tags: + - pet + operationId: inline_request_body_properties + requestBody: + content: + application/json: + # class inline_request_body_properties_request + schema: + type: object + properties: + # inline_request_body_properties_request_prop_object + prop_object: + type: object + properties: + key_1: + type: string + description: some random description to make this object unique - 1 + prop_ref_object: + $ref: '#/components/schemas/PropRefObject' + prop_array_ref_object: + type: array + items: + $ref: '#/components/schemas/PropRefObject' + # inline_request_body_properties_request_prop_nested_object + prop_nested_object: + type: object + description: some random description to make this object unique - 2 + properties: + # inline_request_body_properties_request_prop_nested_object_key_1 + key_1: + type: object + description: some random description to make this object unique - 3 + properties: + key_2: + type: string + prop_ref_nested_object: + $ref: '#/components/schemas/PropRefNestedObject' + prop_array_ref_nested_object: + type: array + items: + $ref: '#/components/schemas/PropRefNestedObject' + prop_string: + type: string + prop_array_string: + type: array + items: + type: string + prop_ref_string: + $ref: '#/components/schemas/PropRefString' + prop_array_ref_string: + type: array + items: + $ref: '#/components/schemas/PropRefString' + prop_integer: + type: integer + prop_array_integer: + type: array + items: + type: integer + prop_ref_integer: + $ref: '#/components/schemas/PropRefInteger' + prop_array_ref_integer: + type: array + items: + $ref: '#/components/schemas/PropRefInteger' + prop_number: + type: number + prop_array_number: + type: array + items: + type: number + prop_ref_number: + $ref: '#/components/schemas/PropRefNumber' + prop_array_ref_number: + type: array + items: + $ref: '#/components/schemas/PropRefNumber' + prop_boolean: + type: boolean + prop_array_boolean: + type: array + items: + type: boolean + prop_ref_boolean: + $ref: '#/components/schemas/PropRefBoolean' + prop_array_ref_boolean: + type: array + items: + $ref: '#/components/schemas/PropRefBoolean' + prop_file: + type: string + format: binary + prop_array_file: + type: array + items: + type: string + format: binary + prop_ref_file: + $ref: '#/components/schemas/PropRefFile' + prop_array_ref_file: + type: array + items: + $ref: '#/components/schemas/PropRefFile' + prop_free_form: + type: object + additionalProperties: {} + prop_array_free_form: + type: array + items: + type: object + additionalProperties: {} + prop_ref_free_form: + $ref: '#/components/schemas/PropRefFreeForm' + prop_array_ref_free_form: + type: array + items: + $ref: '#/components/schemas/PropRefFreeForm' + responses: + '200': + description: Successful operation + /response_named_response: + post: + tags: + - pet + operationId: response_named_response + requestBody: + content: + application/json: {} + responses: + '200': + $ref: "#/components/responses/PropRefResponse" + /response_inline_response_named_object: + post: + tags: + - pet + operationId: response_inline_response_named_object + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/PropRefObject' + /response_inline_response_inline_object: + post: + tags: + - pet + operationId: response_inline_response_inline_object + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + content: + application/json: + # class post_response_inline_response_inline_object_200_response + schema: + type: object + properties: + key_1: + type: string + /sorted: + post: + tags: + - pet + operationId: sorted + responses: + '200': + description: Successful operation + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + - name: queryParam + in: query + required: false + schema: + type: integer + - name: try + in: query + schema: + type: string + default: "foo" + - name: while + in: query + schema: + type: string + default: "foo" + - name: with + in: query + schema: + type: string + default: "foo" + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Dog' + /sorted_formdata: + post: + tags: + - pet + operationId: sorted_formdata + responses: + '200': + description: Successful operation + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + - name: queryParam + in: query + required: false + schema: + type: integer + - name: try + in: query + schema: + type: string + default: "foo" + - name: while + in: query + schema: + type: string + default: "foo" + - name: with + in: query + schema: + type: string + default: "foo" + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/Dog' + /using_title: + post: + tags: + - pet + operationId: using_title + parameters: + # generates class, expected name using_title_paramObject_parameter + - name: paramObject + in: path + required: true + schema: + type: object + properties: + id: + type: integer + # generates class using title + - name: paramObjectCustom + in: path + required: true + schema: + title: custom_paramObject_parameter + type: object + properties: + id: + type: integer + # generates class using title + - name: paramArrayObject + in: path + required: true + schema: + title: custom_paramArrayObject_parameter + type: array + items: + type: object + properties: + id: + type: integer + # does not generate class, ignores title + - name: paramString + in: query + schema: + title: custom_paramString_parameter + type: string + - $ref: "#/components/parameters/ParamComponentObject" + requestBody: + content: + application/json: + schema: + type: object + title: "MyCustomRequestBodyClass" + properties: + # MyCustomRequestBodyClass_prop_object + prop_object: + type: object + description: some random description to make this object unique - 4 + properties: + key_1: + type: string + prop_object_2: + title: "CustomPropObjectName" + type: object + properties: + key_1: + type: string + responses: + '200': + description: Successful operation + /using_title_formdata: + post: + tags: + - pet + operationId: using_title_formdata + requestBody: + content: + multipart/form-data: + schema: + type: object + title: "MyCustomRequestBodyClass" # used but endpoint does not use it + properties: + # MyCustomRequestBodyClass_prop_object + prop_object: + type: object + description: some random description to make this object unique - 5 + properties: + key_1: + type: string + prop_object_2: + title: "CustomPropObjectName" + type: object + properties: + key_1: + type: string + responses: + '200': + description: Successful operation + /multiple_dogs: + post: + tags: + - pet + operationId: multiple_dogs + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MultipleDogs' + /array_dogs: + post: + tags: + - pet + operationId: array_dogs + responses: + '200': + description: Successful operation + requestBody: + $ref: '#/components/requestBodies/DogArray' + /parameters_no_values_not_required: + post: + tags: + - pet + operationId: parameters_no_values_not_required + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + schema: + type: string + - name: param_3 + in: query + schema: + type: string + responses: + '200': + description: Successful operation + /parameters_no_values_required: + post: + tags: + - pet + operationId: parameters_no_values_required + parameters: + - name: param_1 + in: query + schema: + type: string + - name: param_2 + in: query + required: true + schema: + type: string + - name: param_3 + in: query + schema: + type: string + responses: + '200': + description: Successful operation + /parameters_and_required_body: + post: + tags: + - pet + operationId: parameters_and_required_body + parameters: + - name: param_1 + in: query + schema: + type: string + responses: + '200': + description: Successful operation + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/requestBodies/PropRefNestedObject' + /codegen_request_body_name_json: + post: + tags: + - pet + operationId: codegen_request_body_name_json + responses: + '200': + description: Successful operation + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + - name: queryParam + in: query + required: false + schema: + type: integer + - name: try + in: query + schema: + type: string + default: "foo" + - name: while + in: query + schema: + type: string + default: "foo" + - name: with + in: query + schema: + type: string + default: "foo" + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Dog' + x-codegen-request-body-name: some_new_name + /codegen_request_body_name_formdata: + post: + tags: + - pet + operationId: codegen_request_body_name_formdata + responses: + '200': + description: Successful operation + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + - name: queryParam + in: query + required: false + schema: + type: integer + - name: try + in: query + schema: + type: string + default: "foo" + - name: while + in: query + schema: + type: string + default: "foo" + - name: with + in: query + schema: + type: string + default: "foo" + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/Dog' + x-codegen-request-body-name: some_new_name + /free_form_string_object_value: + post: + tags: + - pet + operationId: free_form_string_object_value + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/FreeFormWithStringObjectValue" + responses: + '200': + description: Successful operation + /property_with_all_required_for_default_value: + post: + tags: + - pet + operationId: property_with_all_required_for_default_value + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + - name: queryParam + in: query + required: false + schema: + type: integer + - name: try + in: query + schema: + type: string + default: "foo" + - name: while + in: query + schema: + type: string + default: "foo" + - name: with + in: query + schema: + type: string + default: "foo" + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PropertyWithAllRequiredForDefaultValue' +components: + schemas: + Pet: + type: object + properties: + # class, Pet_prop_object + prop_object: + type: object + properties: + key_1: + type: string + # class, PropRefObject + prop_ref_object: + $ref: '#/components/schemas/PropRefObject' + # class, array + prop_array_ref_object: + type: array + items: + $ref: '#/components/schemas/PropRefObject' + # class, Pet_prop_nested_object + prop_nested_object: + type: object + properties: + # class, Pet_prop_nested_object_key_1 + key_1: + type: object + properties: + key_2: + type: string + prop_ref_nested_object: + $ref: '#/components/schemas/PropRefNestedObject' + prop_array_ref_nested_object: + type: array + items: + $ref: '#/components/schemas/PropRefNestedObject' + prop_string: + type: string + prop_array_string: + type: array + items: + type: string + prop_ref_string: + $ref: '#/components/schemas/PropRefString' + prop_array_ref_string: + type: array + items: + $ref: '#/components/schemas/PropRefString' + prop_integer: + type: integer + prop_array_integer: + type: array + items: + type: integer + prop_ref_integer: + $ref: '#/components/schemas/PropRefInteger' + prop_array_ref_integer: + type: array + items: + $ref: '#/components/schemas/PropRefInteger' + prop_number: + type: number + prop_array_number: + type: array + items: + type: number + prop_ref_number: + $ref: '#/components/schemas/PropRefNumber' + prop_array_ref_number: + type: array + items: + $ref: '#/components/schemas/PropRefNumber' + prop_boolean: + type: boolean + prop_array_boolean: + type: array + items: + type: boolean + prop_ref_boolean: + $ref: '#/components/schemas/PropRefBoolean' + prop_array_ref_boolean: + type: array + items: + $ref: '#/components/schemas/PropRefBoolean' + prop_file: + type: string + format: binary + prop_array_file: + type: array + items: + type: string + format: binary + prop_ref_file: + $ref: '#/components/schemas/PropRefFile' + prop_array_ref_file: + type: array + items: + $ref: '#/components/schemas/PropRefFile' + prop_free_form: + type: object + additionalProperties: {} + prop_array_free_form: + type: array + items: + type: object + additionalProperties: {} + prop_ref_free_form: + $ref: '#/components/schemas/PropRefFreeForm' + prop_array_ref_free_form: + type: array + items: + $ref: '#/components/schemas/PropRefFreeForm' + PropRefObject: + type: object + properties: + key_1: + type: string + PropRefNestedObject: + type: object + properties: + key_1: + type: object + description: some random description to make this object unique - 6 + properties: + key_2: + type: string + # no class + PropRefString: + type: string + PropRefInteger: + type: integer + # no class + PropRefNumber: + type: number + # no class + PropRefBoolean: + type: boolean + # no class + PropRefFile: + type: string + format: binary + # no class + PropRefFreeForm: + type: object + additionalProperties: {} + Dog: + title: a dog + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + items: + type: string + tags: + type: array + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + deprecated: true + enum: + - available + - pending + - sold + try: + type: string + while: + type: string + with: + type: string + configuration: + type: string + version: + type: string + MultipleDogs: + type: object + properties: + dog_1: + $ref: '#/components/schemas/Dog' + dog_2: + $ref: '#/components/schemas/Dog' + Tag: + title: Pet Tag + description: A tag for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + Category: + title: Pet category + description: A category for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$' + PropertyForFormData: + title: a dog + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + items: + type: string + tags: + type: array + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + deprecated: true + enum: + - available + - pending + - sold + try: + type: string + while: + type: string + with: + type: string + PropertyWithAllRequiredForDefaultValue: + type: object + required: + - id + - name + - is_available + - photoUrls + - status + properties: + id: + type: integer + name: + type: string + is_available: + type: boolean + photoUrls: + type: array + items: + type: string + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + FreeFormWithStringObjectValue: + type: object + properties: + prop_object: + type: object + example: "{}" + parameters: + ParamString: + name: paramString + in: query + schema: + type: string + ParamComponentObject: + name: paramComponentObject + in: query + schema: + title: "title is ignored" + type: object + properties: + id: + type: integer + ParamComponentArrayObject: + name: paramComponentArrayObject + in: query + schema: + type: array + items: + type: object + properties: + id: + type: integer + requestBodies: + DogArray: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Dog' + responses: + PropRefResponse: + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/PropRefObject' + PropRefFileResponse: + description: Successful operation + content: + application/pdf: + schema: + $ref: '#/components/schemas/PropRefFile' diff --git a/oseg/tests/fixtures/property_container-flatten.yaml b/oseg/tests/fixtures/property_container-flatten.yaml new file mode 100644 index 000000000..8dfb50fec --- /dev/null +++ b/oseg/tests/fixtures/property_container-flatten.yaml @@ -0,0 +1,75 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Property Container - Flatten +tags: + - name: pet +paths: + /default: + post: + tags: + - pet + operationId: default + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' +components: + schemas: + Pet: + title: a Pet + description: A pet for sale in the pet store + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + items: + type: string + tags: + type: array + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + deprecated: true + enum: + - available + - pending + - sold + Category: + title: Pet category + description: A category for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$' + Tag: + title: Pet Tag + description: A tag for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string diff --git a/oseg/tests/fixtures/property_container.yaml b/oseg/tests/fixtures/property_container.yaml new file mode 100644 index 000000000..b5a017557 --- /dev/null +++ b/oseg/tests/fixtures/property_container.yaml @@ -0,0 +1,200 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Property Container +tags: + - name: pet +paths: + /unique_names_all_required: + post: + tags: + - pet + operationId: unique_names_all_required + parameters: + - name: param_prop_1 + in: path + required: true + schema: + type: string + - name: param_prop_2 + in: query + required: true + schema: + type: string + - name: param_prop_3 + in: header + required: true + schema: + type: string + - name: param_prop_4 + in: cookie + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '200': + description: Successful operation + /unique_names_some_required: + post: + tags: + - pet + operationId: unique_names_some_required + parameters: + - name: param_prop_1 + in: path + required: true + schema: + type: string + - name: param_prop_2 + in: query + required: false + schema: + type: string + - name: param_prop_3 + in: header + required: false + schema: + type: string + - name: param_prop_4 + in: cookie + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '200': + description: Successful operation + /conflicting_names: + post: + tags: + - pet + operationId: conflicting_names + parameters: + - name: param_prop + in: path + required: true + schema: + type: string + default: path_prop + - name: param_prop + in: query + required: true + schema: + type: string + default: query_prop + - name: param_prop + in: header + required: true + schema: + type: string + default: header_prop + - name: param_prop + in: cookie + required: true + schema: + type: string + default: cookie_prop + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '200': + description: Successful operation + /conflicting_names_with_formdata: + post: + tags: + - pet + operationId: conflicting_names_with_formdata + parameters: + - name: param_prop + in: path + required: true + schema: + type: string + default: path_prop + - name: param_prop + in: query + required: true + schema: + type: string + default: query_prop + - name: param_prop + in: header + required: true + schema: + type: string + default: header_prop + - name: param_prop + in: cookie + required: true + schema: + type: string + default: cookie_prop + - name: type + in: query + required: false + schema: + type: string + default: query_type_prop + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/Pet" + responses: + '200': + description: Successful operation + /conflicting_names_with_no_formdata: + post: + tags: + - pet + operationId: conflicting_names_with_no_formdata + parameters: + - name: param_prop + in: path + required: true + schema: + type: string + default: path_prop + - name: pet + in: query + required: true + schema: + type: string + default: query_prop + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '200': + description: Successful operation +components: + schemas: + Pet: + type: object + required: + - type + properties: + id: + type: integer + default: 100 + type: + type: string + default: dog diff --git a/oseg/tests/fixtures/recursive_ref.yaml b/oseg/tests/fixtures/recursive_ref.yaml new file mode 100644 index 000000000..6cf3fd8c4 --- /dev/null +++ b/oseg/tests/fixtures/recursive_ref.yaml @@ -0,0 +1,37 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Recursive Ref +tags: + - name: pet +paths: + /default: + post: + tags: + - pet + operationId: default + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + default: 100 + dog: + $ref: '#/components/schemas/Dog' + Dog: + type: object + properties: + id: + type: integer + pet: + $ref: '#/components/schemas/Pet' diff --git a/oseg/tests/fixtures/requests.yaml b/oseg/tests/fixtures/requests.yaml new file mode 100644 index 000000000..7c57029c9 --- /dev/null +++ b/oseg/tests/fixtures/requests.yaml @@ -0,0 +1,214 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - OperationParser +tags: + - name: pet +paths: + /request_x_www_form_urlencoded: + post: + tags: + - pet + operationId: request_x_www_form_urlencoded + responses: + '200': + description: Successful operation + requestBody: + content: + application/x-www-form-urlencoded: {} + /request_multipart_form_data: + post: + tags: + - pet + operationId: request_multipart_form_data + responses: + '200': + description: Successful operation + requestBody: + content: + multipart/form-data: {} + /request_x_www_form_urlencoded_with_ref: + post: + tags: + - pet + operationId: request_x_www_form_urlencoded_with_ref + responses: + '200': + description: Successful operation + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + /request_multipart_form_data_with_ref: + post: + tags: + - pet + operationId: request_multipart_form_data_with_ref + responses: + '200': + description: Successful operation + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/Pet' + /request_x_www_form_urlencoded_and_multipart_form_data: + post: + tags: + - pet + operationId: request_x_www_form_urlencoded_and_multipart_form_data + responses: + '200': + description: Successful operation + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + multipart/form-data: + schema: + $ref: '#/components/schemas/Pet' + /request_multipart_form_data_and_x_www_form_urlencoded: + post: + tags: + - pet + operationId: request_multipart_form_data_and_x_www_form_urlencoded + responses: + '200': + description: Successful operation + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/Pet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + /request_x_www_form_urlencoded_and_application_json: + post: + tags: + - pet + operationId: request_x_www_form_urlencoded_and_application_json + responses: + '200': + description: Successful operation + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + /request_multipart_form_data_and_application_json: + post: + tags: + - pet + operationId: request_multipart_form_data_and_application_json + responses: + '200': + description: Successful operation + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + # not treated as form-data by SDKs + /request_octet_stream: + post: + tags: + - pet + operationId: request_octet_stream + responses: + '200': + description: Successful operation + requestBody: + content: + application/octet-stream: {} + /body_data_1: + post: + tags: + - pet + operationId: body_data_1 + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + /body_data_2: + post: + tags: + - pet + operationId: body_data_2 + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + multipart/form-data: + schema: + $ref: '#/components/schemas/Pet' + /parameter_data: + get: + tags: + - pet + operationId: parameter_data + parameters: + - + name: param_name_1 + in: query + schema: + type: string + responses: + '200': + description: Successful operation + /request_body_ref_1: + post: + tags: + - pet + operationId: request_body_ref_1 + responses: + '200': + description: Successful operation + requestBody: + $ref: '#/components/requestBodies/RequestBodyRef1' + /request_body_ref_2: + post: + tags: + - pet + operationId: request_body_ref_2 + responses: + '200': + description: Successful operation + requestBody: + $ref: '#/components/requestBodies/RequestBodyRef2' +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + type: + type: string + requestBodies: + RequestBodyRef1: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/Pet' + RequestBodyRef2: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' diff --git a/oseg/tests/fixtures/responses.yaml b/oseg/tests/fixtures/responses.yaml new file mode 100644 index 000000000..e6a294665 --- /dev/null +++ b/oseg/tests/fixtures/responses.yaml @@ -0,0 +1,132 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Different Responses +tags: + - name: pet +paths: + /single_response: + get: + tags: + - pet + operationId: single_response + responses: + '200': + description: 'successful operation' + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + /single_response_with_error: + get: + tags: + - pet + operationId: single_response_with_error + responses: + '200': + description: 'successful operation' + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + /single_response_with_error_first: + get: + tags: + - pet + operationId: single_response_with_error_first + responses: + '400': + description: Invalid ID supplied + '200': + description: 'successful operation' + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + /multi_response: + get: + tags: + - pet + operationId: multi_response + responses: + '200': + description: 'successful operation' + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + /only_400_response: + get: + tags: + - pet + operationId: only_400_response + responses: + '400': + description: Invalid ID supplied + /binary_response: + get: + tags: + - pet + operationId: binary_response + responses: + '200': + description: 'successful operation' + content: + application/zip: + schema: + type: string + format: binary + /no_response: + get: + tags: + - pet + operationId: no_response + /response_ref_1: + get: + tags: + - pet + operationId: response_ref_1 + responses: + '200': + $ref: '#/components/responses/ResponseRef1' + /response_ref_2: + get: + tags: + - pet + operationId: response_ref_2 + responses: + '200': + $ref: '#/components/responses/ResponseRef2' +components: + schemas: + Pet: + type: object + required: + - id + - type + properties: + id: + type: integer + type: + type: string + FileSchema: + type: string + format: binary + responses: + ResponseRef1: + description: 'successful operation' + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + ResponseRef2: + description: 'successful operation' + content: + application/zip: + schema: + $ref: '#/components/schemas/FileSchema' diff --git a/oseg/tests/fixtures/root_level_non_objects.yaml b/oseg/tests/fixtures/root_level_non_objects.yaml new file mode 100644 index 000000000..eb9d7eaaf --- /dev/null +++ b/oseg/tests/fixtures/root_level_non_objects.yaml @@ -0,0 +1,178 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Root Level Non-Objects +tags: + - name: pet +paths: + /root_level_free_form: + post: + tags: + - pet + operationId: root_level_free_form + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FreeFormSchema' + /root_level_free_form_array: + post: + tags: + - pet + operationId: root_level_free_form_array + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FreeFormSchemaArray' + /root_level_string: + post: + tags: + - pet + operationId: root_level_string + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/StringSchema' + /root_level_string_array: + post: + tags: + - pet + operationId: root_level_string_array + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/StringSchemaArray' + /root_level_int: + post: + tags: + - pet + operationId: root_level_int + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IntSchema' + /root_level_int_array: + post: + tags: + - pet + operationId: root_level_int_array + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IntSchemaArray' + /root_level_file: + post: + tags: + - pet + operationId: root_level_file + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FileSchema' + /root_level_file_array: + post: + tags: + - pet + operationId: root_level_file_array + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/FileSchemaArray' + /root_level_bool: + post: + tags: + - pet + operationId: root_level_bool + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BoolSchema' + /root_level_bool_array: + post: + tags: + - pet + operationId: root_level_bool_array + responses: + '200': + description: Successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BoolSchemaArray' +components: + schemas: + FreeFormSchema: + type: object + additionalProperties: {} + example: + foo: bar + bam: baz + FreeFormSchemaArray: + type: array + items: + $ref: '#/components/schemas/FreeFormSchema' + StringSchema: + type: string + example: "some string value" + StringSchemaArray: + type: array + items: + $ref: '#/components/schemas/StringSchema' + IntSchema: + type: integer + example: 12345 + IntSchemaArray: + type: array + items: + $ref: '#/components/schemas/IntSchema' + FileSchema: + type: string + format: binary + example: "/some/file/path.pdf" + FileSchemaArray: + type: array + items: + $ref: '#/components/schemas/FileSchema' + BoolSchema: + type: boolean + example: true + BoolSchemaArray: + type: array + items: + $ref: '#/components/schemas/BoolSchema' diff --git a/oseg/tests/fixtures/security_schemes.yaml b/oseg/tests/fixtures/security_schemes.yaml new file mode 100644 index 000000000..356c6d9be --- /dev/null +++ b/oseg/tests/fixtures/security_schemes.yaml @@ -0,0 +1,107 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Property Examples +tags: + - name: pet +paths: + /security_all: + post: + tags: + - pet + operationId: security_all + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + /security_optional: + post: + tags: + - pet + operationId: security_optional + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + security: + - api_key_scheme: [] + - http_basic_scheme: [] + - http_bearer_scheme: [] + - oauth2_scheme: + - some_permission + - {} + /security_override: + post: + tags: + - pet + operationId: security_override + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + security: + - http_basic_scheme: [] + /security_disabled: + post: + tags: + - pet + operationId: security_disabled + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + security: [] + /security_and: + post: + tags: + - pet + operationId: security_and + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + security: + - api_key_scheme: [] + http_basic_scheme: [] + /security_or: + post: + tags: + - pet + operationId: security_or + requestBody: + content: + application/json: {} + responses: + '200': + description: Successful operation + security: + - api_key_scheme: [] + - http_basic_scheme: [] +components: + securitySchemes: + api_key_scheme: + type: apiKey + http_basic_scheme: + type: http + scheme: basic + http_bearer_scheme: + type: http + scheme: bearer + oauth2_scheme: + type: oauth2 +security: + - api_key_scheme: [] + - http_basic_scheme: [] + - http_bearer_scheme: [] + - oauth2_scheme: + - some_permission diff --git a/oseg/tests/fixtures/type_checker-3.0.yaml b/oseg/tests/fixtures/type_checker-3.0.yaml new file mode 100644 index 000000000..4e7497f77 --- /dev/null +++ b/oseg/tests/fixtures/type_checker-3.0.yaml @@ -0,0 +1,28 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: Fixture - Type Checker OAS v3.0 +tags: + - name: pet +paths: + /default: + post: + tags: + - pet + operationId: default + responses: + '200': + description: Successful operation +components: + schemas: + Together: + type: object + properties: + prop_nullable: + type: string + nullable: true + prop_nullable_array: + type: array + nullable: true + items: + type: string diff --git a/oseg/tests/fixtures/type_checker.yaml b/oseg/tests/fixtures/type_checker.yaml new file mode 100644 index 000000000..7e5023be3 --- /dev/null +++ b/oseg/tests/fixtures/type_checker.yaml @@ -0,0 +1,179 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + title: Fixture - Type Checker +tags: + - name: pet +paths: + /default: + post: + tags: + - pet + operationId: default + responses: + '200': + description: Successful operation +components: + schemas: + Together: + type: object + properties: + prop_ref: + $ref: '#/components/schemas/Pet' + prop_ref_array: + type: array + items: + $ref: '#/components/schemas/Pet' + prop_object: + type: object + properties: + id: + type: integer + type: + type: string + prop_discriminator: + $ref: '#/components/schemas/Dog' + # considered string(s) by SDKs + prop_file_base64: + type: string + format: base64 + # considered string(s) by SDKs + prop_file_base64_array: + type: array + items: + type: string + format: base64 + prop_file_binary: + type: string + format: binary + prop_file_binary_array: + type: array + items: + type: string + format: binary + prop_file_byte: + type: string + format: byte + prop_file_byte_array: + type: array + items: + type: string + format: byte + # considered string(s) by SDKs + prop_file_contentMediaType: + type: string + contentMediaType: application/octet-stream + # considered string(s) by SDKs + prop_file_contentMediaType_array: + type: array + items: + type: string + contentMediaType: application/octet-stream + # considered string(s) by SDKs + prop_file_contentEncoding: + type: string + contentEncoding: base64 + # considered string(s) by SDKs + prop_file_contentEncoding_array: + type: array + items: + type: string + contentEncoding: base64 + prop_free_form: + type: object + additionalProperties: {} + prop_free_form_array: + type: array + items: + type: object + additionalProperties: {} + prop_free_form_no_additional_properties: + type: object + prop_free_form_no_additional_properties_array: + type: array + items: + type: object + prop_free_form_additional_properties_true: + type: object + additionalProperties: true + prop_free_form_additional_properties_true_array: + type: array + items: + type: object + additionalProperties: true + prop_scalar_bool: + type: boolean + prop_scalar_integer: + type: integer + prop_scalar_number: + type: number + prop_scalar_string: + type: string + prop_scalar_bool_array: + type: array + items: + type: boolean + prop_scalar_integer_array: + type: array + items: + type: integer + prop_scalar_number_array: + type: array + items: + type: number + prop_scalar_string_array: + type: array + items: + type: string + prop_scalar_string_contentMediaType: + type: string + contentMediaType: text/plain + # different in 3.0 + prop_nullable: + type: + - string + - "null" + # different in 3.1 + prop_nullable_array: + type: + - array + - "null" + items: + type: string + Pet: + type: object + properties: + id: + type: integer + type: + type: string + Dog: + type: object + properties: + id: + type: integer + breed: + type: string + discriminator: + propertyName: breed + mapping: + beagle: '#/components/schemas/Beagle' + terrier: '#/components/schemas/Terrier' + Beagle: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hound + Terrier: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hunting diff --git a/oseg/tests/test_component_resolver.py b/oseg/tests/test_component_resolver.py new file mode 100644 index 000000000..c50fd5699 --- /dev/null +++ b/oseg/tests/test_component_resolver.py @@ -0,0 +1,734 @@ +import openapi_pydantic as oa +from oseg import parser +from test_utils import TestUtils, TestCase + + +class TestComponentResolver(TestCase): + def test_parameters(self): + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["default"] + + data = [ + { + "property": "paramObject", + "type": "default_paramObject_parameter", + "schema": operation.request.parameters[0], + }, + { + "property": "paramArrayObject", + "type": "default_paramArrayObject_parameter", + "schema": operation.request.parameters[1], + }, + { + "property": "paramString", + "type": None, + "schema": operation.request.parameters[2], + }, + { + "property": "paramComponentObject", + "type": "", + "schema": operation.request.parameters[3], + }, + { + "property": "paramComponentArrayObject", + "type": "", + "schema": operation.request.parameters[4], + }, + ] + + for expected in data: + with self.subTest(expected["property"]): + parameter: oa.Parameter = expected["schema"] + + self.assertEqual(expected["property"], parameter.name) + self.assertEqual( + expected["type"], + oa_parser.get_component_name(parameter), + ) + + def test_request_with_named_body_properties(self): + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["default"] + body = operation.request.body + + self.assertEqual( + "Pet", + operation.request.body_type, + ) + + data = [ + { + "property": "prop_object", + "property_type": "Pet_prop_object", + }, + { + "property": "prop_ref_object", + "property_type": "PropRefObject", + }, + { + "property": "prop_array_ref_object", + "items_type": "PropRefObject", + }, + { + "property": "prop_nested_object", + "property_type": "Pet_prop_nested_object", + }, + { + "property": "prop_ref_nested_object", + "property_type": "PropRefNestedObject", + }, + { + "property": "prop_array_ref_nested_object", + "items_type": "PropRefNestedObject", + }, + { + "property": "prop_string", + "property_type": None, + }, + { + "property": "prop_array_string", + "items_type": None, + }, + { + "property": "prop_ref_string", + "property_type": None, + }, + { + "property": "prop_array_ref_string", + "items_type": None, + }, + { + "property": "prop_integer", + "property_type": None, + }, + { + "property": "prop_array_integer", + "items_type": None, + }, + { + "property": "prop_ref_integer", + "property_type": None, + }, + { + "property": "prop_array_ref_integer", + "items_type": None, + }, + { + "property": "prop_number", + "property_type": None, + }, + { + "property": "prop_array_number", + "items_type": None, + }, + { + "property": "prop_ref_number", + "property_type": None, + }, + { + "property": "prop_array_ref_number", + "items_type": None, + }, + { + "property": "prop_boolean", + "property_type": None, + }, + { + "property": "prop_array_boolean", + "items_type": None, + }, + { + "property": "prop_ref_boolean", + "property_type": None, + }, + { + "property": "prop_array_ref_boolean", + "items_type": None, + }, + { + "property": "prop_file", + "property_type": None, + }, + { + "property": "prop_array_file", + "items_type": None, + }, + { + "property": "prop_ref_file", + "property_type": None, + }, + { + "property": "prop_array_ref_file", + "items_type": None, + }, + { + "property": "prop_free_form", + "property_type": None, + }, + { + "property": "prop_array_free_form", + "items_type": None, + }, + { + "property": "prop_ref_free_form", + "property_type": None, + }, + { + "property": "prop_array_ref_free_form", + "items_type": None, + }, + ] + + for expected in data: + with self.subTest(expected["property"]): + property_schema = body.properties.get(expected["property"]) + + if parser.TypeChecker.is_array(property_schema): + self.assertEqual( + None, + oa_parser.get_component_name(property_schema), + ) + + self.assertEqual( + expected["items_type"], + oa_parser.get_component_name(property_schema.items), + ) + else: + self.assertEqual( + expected["property_type"], + oa_parser.get_component_name(property_schema), + ) + + prop_nested_object_schema = body.properties.get("prop_nested_object") + prop_nested_object_schema_key_1 = prop_nested_object_schema.properties.get( + "key_1" + ) + + self.assertEqual( + "Pet_prop_nested_object_key_1", + oa_parser.get_component_name(prop_nested_object_schema_key_1), + ) + + def test_request_with_non_named_body_properties(self): + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["inline_request_body_properties"] + body = operation.request.body + + self.assertEqual( + "inline_request_body_properties_request", + operation.request.body_type, + ) + + data = [ + { + "property": "prop_object", + "property_name": "inline_request_body_properties_request_prop_object", + }, + { + "property": "prop_ref_object", + "property_name": "PropRefObject", + }, + { + "property": "prop_array_ref_object", + "items_name": "PropRefObject", + }, + { + "property": "prop_nested_object", + "property_name": "inline_request_body_properties_request_prop_nested_object", + }, + { + "property": "prop_ref_nested_object", + "property_name": "PropRefNestedObject", + }, + { + "property": "prop_array_ref_nested_object", + "items_name": "PropRefNestedObject", + }, + { + "property": "prop_string", + "property_name": None, + }, + { + "property": "prop_array_string", + "items_name": None, + }, + { + "property": "prop_ref_string", + "property_name": None, + }, + { + "property": "prop_array_ref_string", + "items_name": None, + }, + { + "property": "prop_integer", + "property_name": None, + }, + { + "property": "prop_array_integer", + "items_name": None, + }, + { + "property": "prop_ref_integer", + "property_name": None, + }, + { + "property": "prop_array_ref_integer", + "items_name": None, + }, + { + "property": "prop_number", + "property_name": None, + }, + { + "property": "prop_array_number", + "items_name": None, + }, + { + "property": "prop_ref_number", + "property_name": None, + }, + { + "property": "prop_array_ref_number", + "items_name": None, + }, + { + "property": "prop_boolean", + "property_name": None, + }, + { + "property": "prop_array_boolean", + "items_name": None, + }, + { + "property": "prop_ref_boolean", + "property_name": None, + }, + { + "property": "prop_array_ref_boolean", + "items_name": None, + }, + { + "property": "prop_file", + "property_name": None, + }, + { + "property": "prop_array_file", + "items_name": None, + }, + { + "property": "prop_ref_file", + "property_name": None, + }, + { + "property": "prop_array_ref_file", + "items_name": None, + }, + { + "property": "prop_free_form", + "property_name": None, + }, + { + "property": "prop_array_free_form", + "items_name": None, + }, + { + "property": "prop_ref_free_form", + "property_name": None, + }, + { + "property": "prop_array_ref_free_form", + "items_name": None, + }, + ] + + for expected in data: + with self.subTest(expected["property"]): + property_schema = body.properties.get(expected["property"]) + + if parser.TypeChecker.is_array(property_schema): + self.assertEqual( + None, + oa_parser.get_component_name(property_schema), + ) + + self.assertEqual( + expected["items_name"], + oa_parser.get_component_name(property_schema.items), + ) + else: + self.assertEqual( + expected["property_name"], + oa_parser.get_component_name(property_schema), + ) + + prop_nested_object_schema = body.properties.get("prop_nested_object") + prop_nested_object_schema_key_1 = prop_nested_object_schema.properties.get( + "key_1" + ) + + self.assertEqual( + "inline_request_body_properties_request_prop_nested_object_key_1", + oa_parser.get_component_name(prop_nested_object_schema_key_1), + ) + + def test_responses(self): + oa_parser = TestUtils.oa_parser("properties") + + data = [ + { + "operation_id": "response_named_response", + "type": "PropRefObject", + }, + { + "operation_id": "response_inline_response_named_object", + "type": "PropRefObject", + }, + { + "operation_id": "response_inline_response_inline_object", + "type": None, + }, + ] + + for expected in data: + with self.subTest(expected["operation_id"]): + operation = oa_parser.operations[expected["operation_id"]] + response = operation.response + + self.assertEqual( + expected["type"], + oa_parser.get_component_name(response.body), + ) + + def test_title_used(self): + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["using_title"] + body = operation.request.body + + data = [ + { + "property": "paramObject", + "type": "using_title_paramObject_parameter", + "schema": operation.request.parameters[0], + }, + { + "property": "paramObjectCustom", + "type": "custom_paramObject_parameter", + "schema": operation.request.parameters[1], + }, + { + "property": "paramArrayObject", + "type": "custom_paramArrayObject_parameter", + "schema": operation.request.parameters[2], + }, + { + "property": "paramString", + "type": None, + "schema": operation.request.parameters[3], + }, + { + "property": "paramComponentObject", + "type": "", + "schema": operation.request.parameters[4], + }, + ] + + for expected in data: + with self.subTest(expected["property"]): + parameter: oa.Parameter = expected["schema"] + + self.assertEqual(expected["property"], parameter.name) + self.assertEqual( + expected["type"], + oa_parser.get_component_name(parameter), + ) + + expected_body_type = "MyCustomRequestBodyClass" + self.assertEqual( + expected_body_type, + oa_parser.get_component_name(body), + ) + + expected_prop_1_type = "MyCustomRequestBodyClass_prop_object" + self.assertEqual( + expected_prop_1_type, + oa_parser.get_component_name(body.properties.get("prop_object")), + ) + + expected_prop_2_type = "CustomPropObjectName" + self.assertEqual( + expected_prop_2_type, + oa_parser.get_component_name(body.properties.get("prop_object_2")), + ) + + def test_title_used_formdata(self): + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["using_title_formdata"] + body = operation.request.body + + expected_prop_1_type = "MyCustomRequestBodyClass_prop_object" + self.assertEqual( + expected_prop_1_type, + oa_parser.get_component_name(body.properties.get("prop_object")), + ) + + expected_prop_2_type = "CustomPropObjectName" + self.assertEqual( + expected_prop_2_type, + oa_parser.get_component_name(body.properties.get("prop_object_2")), + ) + + def test_refs_are_resolved(self): + oa_parser = TestUtils.oa_parser("component_resolver") + + data = [ + { + "component": oa_parser.components.responses, + "schema_1": "SomeResponse", + "schema_2": "SomeResponseRef", + }, + { + "component": oa_parser.components.schemas, + "schema_1": "SomeSchema", + "schema_2": "SomeSchemaRef", + }, + { + "component": oa_parser.components.parameters, + "schema_1": "SomeParameter", + "schema_2": "SomeParameterRef", + }, + { + "component": oa_parser.components.examples, + "schema_1": "SomeExample", + "schema_2": "SomeExampleRef", + }, + { + "component": oa_parser.components.securitySchemes, + "schema_1": "petstore_auth", + "schema_2": "petstore_auth_ref", + }, + { + "component": oa_parser.components.securitySchemes, + "schema_1": "api_key", + "schema_2": "api_key_ref", + }, + ] + + for expected in data: + with self.subTest(f"{expected["schema_1"]} - {expected["schema_2"]}"): + schema_1 = expected["component"].get(expected["schema_1"]) + schema_2 = expected["component"].get(expected["schema_2"]) + + self.assertIsNotNone(schema_1) + self.assertIsNotNone(schema_2) + self.assertEqual(schema_1, schema_2) + + name_1 = oa_parser.get_component_name(schema_1) + name_2 = oa_parser.get_component_name(schema_2) + + self.assertIsNotNone(name_1) + self.assertIsNotNone(name_2) + self.assertEqual(name_1, name_2) + + def test_common_parameters(self): + oa_parser = TestUtils.oa_parser("common_parameters") + + data_provider = { + "additional_parameter_at_start": { + "param_1": "string", + "param_2": "integer", + "param_3": "string", + "param_4": "string", + "additional_parameter": "string", + }, + "additional_parameter_in_middle": { + "param_1": "string", + "param_2": "integer", + "param_3": "string", + "param_4": "string", + "additional_parameter": "string", + }, + "additional_parameter_at_end": { + "param_1": "string", + "param_2": "integer", + "param_3": "string", + "param_4": "string", + "additional_parameter": "string", + }, + "parameters_in_different_order": { + "param_1": "string", + "param_2": "integer", + "param_3": "string", + "param_4": "string", + "additional_parameter": "string", + }, + "override_parameter_data": { + "param_1": "integer", + "param_2": "string", + "param_3": "string", + "param_4": "string", + }, + "no_parameter_data": { + "param_1": "string", + "param_2": "integer", + "param_3": "string", + "param_4": "string", + }, + } + + for operation_id, expected_parameters in data_provider.items(): + with self.subTest(operation_id): + operation = oa_parser.operations[operation_id] + + result = {} + for parameter in operation.request.parameters: + result[parameter.name] = parameter.param_schema.type.value + + self.assertEqual(expected_parameters, result) + + def test_inline_schema_name_reuse(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("component_resolver") + + operation_1 = { + "operation_id": "inline_nested_schema_root", + "data": { + "labels": ["label 1", "label 2"], + }, + "expected_name": "inline_nested_schema_root_request", + } + + operation_2 = { + "operation_id": "another_inline_nested_schema_root_2", + "data": { + "labels": ["label 1", "label 2"], + }, + "expected_name": "inline_nested_schema_root_request", + } + + operation_3 = { + "operation_id": "inline_nested_schema_nested", + "data": { + "nested_inline": { + "labels": ["label 1", "label 2"], + } + }, + "expected_name": "inline_nested_schema_root_request", + } + + for data in [operation_1, operation_2]: + with self.subTest(data["operation_id"]): + operation = oa_parser.operations.get(data["operation_id"]) + operation.request.example_data = {example_name: {"body": data["data"]}} + container = operation.request.example_data[example_name] + + self.assertEqual( + data["expected_name"], + container.body_type, + ) + + self.assertEqual( + data["expected_name"], + oa_parser.get_component_name(container.body.schema), + ) + + operation.request.example_data = None + + operation = oa_parser.operations.get(operation_3["operation_id"]) + operation.request.example_data = {example_name: {"body": operation_3["data"]}} + container = operation.request.example_data[example_name] + + self.assertEqual( + operation_3["expected_name"], + oa_parser.get_component_name( + container.body.properties.get("nested_inline").schema + ), + ) + + operation.request.example_data = None + + def test_request_body_inline_schema_name_used_for_inline_component_schema(self): + oa_parser = TestUtils.oa_parser("component_resolver") + + schema_1 = oa_parser.components.schemas.get("SomeSchemaWithDupe1") + schema_2 = oa_parser.components.schemas.get("SomeSchemaWithDupe2") + + prop_1 = schema_1.properties.get("prop_1") + prop_2 = schema_2.properties.get("prop_1").properties.get("prop_2") + + expected_name = ( + "inline_nested_schema_identical_name_1_request_some_property_name" + ) + + self.assertEqual( + expected_name, + oa_parser.get_component_name(prop_1), + ) + + self.assertEqual( + expected_name, + oa_parser.get_component_name(prop_2), + ) + + def test_schema_with_inner(self): + oa_parser = TestUtils.oa_parser("component_resolver") + + schema_1 = oa_parser.components.schemas.get("SchemaWithInner") + + prop_1 = schema_1.properties.get("prop_1") + prop_1_prop_2 = prop_1.properties.get("prop_2").items + prop_1_prop_2_prop_3 = prop_1_prop_2.properties.get("prop_3") + + expected_name_1 = "SchemaWithInner_prop_1" + expected_name_2 = "SchemaWithInner_prop_1_prop_2_inner" + expected_name_3 = "SchemaWithInner_prop_1_prop_2_inner_prop_3" + + self.assertEqual( + expected_name_1, + oa_parser.get_component_name(prop_1), + ) + + self.assertEqual( + expected_name_2, + oa_parser.get_component_name(prop_1_prop_2), + ) + + self.assertEqual( + expected_name_3, + oa_parser.get_component_name(prop_1_prop_2_prop_3), + ) + + def test_schema_with_inner_inner(self): + oa_parser = TestUtils.oa_parser("component_resolver") + + schema_1 = oa_parser.components.schemas.get("SchemaWithInnerInner") + + prop_1 = schema_1.properties.get("prop_1") + prop_1_prop_2 = prop_1.properties.get("prop_2").items + prop_1_prop_2_prop_3 = prop_1_prop_2.properties.get("prop_3").items + prop_1_prop_2_prop_3_prop_4 = prop_1_prop_2_prop_3.properties.get("prop_4") + + expected_name_1 = "SchemaWithInnerInner_prop_1" + expected_name_2 = "SchemaWithInnerInner_prop_1_prop_2_inner" + expected_name_3 = "SchemaWithInnerInner_prop_1_prop_2_inner_prop_3_inner" + expected_name_4 = "SchemaWithInnerInner_prop_1_prop_2_inner_prop_3_inner_prop_4" + + self.assertEqual( + expected_name_1, + oa_parser.get_component_name(prop_1), + ) + + self.assertEqual( + expected_name_2, + oa_parser.get_component_name(prop_1_prop_2), + ) + + self.assertEqual( + expected_name_3, + oa_parser.get_component_name(prop_1_prop_2_prop_3), + ) + + self.assertEqual( + expected_name_4, + oa_parser.get_component_name(prop_1_prop_2_prop_3_prop_4), + ) diff --git a/oseg/tests/test_example_data_parser.py b/oseg/tests/test_example_data_parser.py new file mode 100644 index 000000000..4856a492e --- /dev/null +++ b/oseg/tests/test_example_data_parser.py @@ -0,0 +1,848 @@ +import uuid +import openapi_pydantic as oa +from oseg import model, parser +from test_utils import TestUtils, TestCase + + +class TestExampleDataParser(TestCase): + def test_common_path_query_param_scenarios(self): + data_provider = { + # Always use example value if set + "param_with_example": { + "name": "param_name_1", + "value": "value_1", + "required": False, + }, + # If example value is set, ignore default value + "param_with_example_with_default": { + "name": "param_name_1", + "value": "value_1", + "required": False, + }, + # Use default value if no example value, and is required + "param_without_example_with_default_is_required": { + "name": "param_name_1", + "value": "value_2", + "required": True, + }, + # No example value and no default value and required + "param_without_example_without_default_is_required": { + "name": "param_name_1", + "value": "param_name_1_string", + "required": True, + }, + # No example value and no default value and not required + "param_without_example_without_default_not_required": { + "name": "param_name_1", + "value": None, + "required": False, + }, + # Test array type + "param_as_array": { + "name": "param_name_1", + "value": ["value_1", "value_2"], + "required": False, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-path-query-parameters") + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + for operation_id, expected in data_provider.items(): + with self.subTest(operation_id): + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[example_name] + + parameter = container.query.properties.get(expected["name"]) + + self.assertIsNone(container.body) + self.assertEqual(expected["value"], parameter.value) + self.assertEqual(expected["required"], parameter.is_required) + + def test_different_param_in(self): + oa_parser = TestUtils.oa_parser("example_data_parser-path-query-parameters") + + operation = oa_parser.operations.get("different_param_in") + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + container = operation.request.example_data[example_name] + param_path = container.path.properties.get("param_name_1") + param_query = container.query.properties.get("param_name_1") + param_header = container.header.properties.get("param_name_1") + param_cookie = container.cookie.properties.get("param_name_1") + + self.assertEqual("path_value", param_path.value) + self.assertEqual("query_value", param_query.value) + self.assertEqual("header_value", param_header.value) + self.assertEqual("cookie_value", param_cookie.value) + + def test_mixed_params(self): + """Test mixed params""" + + expected_result = [ + { + "name": "param_with_example", + "value": "value_1", + "required": False, + }, + { + "name": "param_with_example_with_default", + "value": "value_1", + "required": False, + }, + { + "name": "param_without_example_with_default_is_required", + "value": "value_2", + "required": True, + }, + { + "name": "param_without_example_with_default_not_required", + "value": "value_2", + "required": False, + }, + { + "name": "param_without_example_without_default_is_required", + "value": "param_without_example_without_default_is_required_string", + "required": True, + }, + { + "name": "param_without_example_without_default_not_required", + "value": None, + "required": False, + }, + { + "name": "param_as_array", + "value": ["value_1", "value_2"], + "required": False, + }, + ] + + operation_id = "mixed_params" + + oa_parser = TestUtils.oa_parser("example_data_parser-path-query-parameters") + operation = oa_parser.operations.get(operation_id) + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + container = operation.request.example_data[example_name] + + for expected in expected_result: + parameter = container.query.properties.get(expected["name"]) + + self.assertEqual(expected["value"], parameter.value) + self.assertEqual(expected["required"], parameter.is_required) + + def test_common_request_body_param_scenarios(self): + data_provider = { + # If single requestBody is defined, use it + "single_request_body": { + "name": "default_example", + "body_type": "Pet", + }, + # Only ever use the first requestBody no matter how many are defined + "multiple_request_body": { + "name": "default_example", + "body_type": "Customer", + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-single-requestBody") + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + for operation_id, expected in data_provider.items(): + with self.subTest(operation_id): + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[example_name] + + self.assertIsNotNone(container.body) + self.assertIsNone(container.path) + self.assertIsNone(container.query) + self.assertIsNone(container.header) + self.assertIsNone(container.cookie) + + self.assertEqual(expected["body_type"], container.body.type) + + def test_array_body(self): + oa_parser = TestUtils.oa_parser("example_data_parser-body") + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + operation = oa_parser.operations.get("array_body") + container = operation.request.example_data[example_name] + body = container.body + + assert isinstance(body, model.PropertyObjectArray) + + body_1 = body.properties[0] + + self.assertEqual(10, body_1.scalars["id"].value) + + def test_different_param_in_default_data(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + expected = { + example_name: { + "path": { + "param_name_1": "path_value", + }, + "query": { + "param_name_1": "query_value", + }, + "header": { + "param_name_1": "header_value", + }, + "cookie": { + "param_name_1": "cookie_value", + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-path-query-parameters") + operation = oa_parser.operations.get("different_param_in") + + container_1 = operation.request.example_data[example_name] + + results_1 = { + "path": { + "param_name_1": container_1.path.scalars["param_name_1"].value, + }, + "query": { + "param_name_1": container_1.query.scalars["param_name_1"].value, + }, + "header": { + "param_name_1": container_1.header.scalars["param_name_1"].value, + }, + "cookie": { + "param_name_1": container_1.cookie.scalars["param_name_1"].value, + }, + } + + self.assertEqual(expected[example_name], results_1) + + def test_different_param_in_custom_data(self): + example_data: model.EXAMPLE_DATA_BY_NAME = { + "example_1": { + "path": { + "param_name_1": str(uuid.uuid4()), + }, + "query": { + "param_name_1": str(uuid.uuid4()), + }, + "header": { + "param_name_1": str(uuid.uuid4()), + }, + "cookie": { + "param_name_1": str(uuid.uuid4()), + }, + }, + "example_2": { + "path": { + "param_name_1": str(uuid.uuid4()), + }, + "query": { + "param_name_1": str(uuid.uuid4()), + }, + "header": { + "param_name_1": str(uuid.uuid4()), + }, + "cookie": { + "param_name_1": str(uuid.uuid4()), + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-path-query-parameters") + operation = oa_parser.operations.get("different_param_in") + operation.request.example_data = example_data + + container_1 = operation.request.example_data["example_1"] + container_2 = operation.request.example_data["example_2"] + + results_1 = { + "path": { + "param_name_1": container_1.path.scalars["param_name_1"].value, + }, + "query": { + "param_name_1": container_1.query.scalars["param_name_1"].value, + }, + "header": { + "param_name_1": container_1.header.scalars["param_name_1"].value, + }, + "cookie": { + "param_name_1": container_1.cookie.scalars["param_name_1"].value, + }, + } + + results_2 = { + "path": { + "param_name_1": container_2.path.scalars["param_name_1"].value, + }, + "query": { + "param_name_1": container_2.query.scalars["param_name_1"].value, + }, + "header": { + "param_name_1": container_2.header.scalars["param_name_1"].value, + }, + "cookie": { + "param_name_1": container_2.cookie.scalars["param_name_1"].value, + }, + } + + self.assertEqual(example_data["example_1"], results_1) + self.assertEqual(example_data["example_2"], results_2) + + # reset data + operation.request.example_data = None + + def test_single_body_with_default_data(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + expected = { + example_name: { + "body": { + "id": 10, + "name": "doggie", + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("single_body") + + container_1 = operation.request.example_data[example_name] + + results_1 = { + "id": container_1.body.scalars["id"].value, + "name": container_1.body.scalars["name"].value, + } + + self.assertEqual(expected[example_name]["body"], results_1) + + def test_single_body_with_custom_data(self): + example_data: model.EXAMPLE_DATA_BY_NAME = { + "example_1": { + "body": { + "id": 100, + "name": str(uuid.uuid4()), + }, + }, + "example_2": { + "body": { + "id": 100, + "name": str(uuid.uuid4()), + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("single_body") + operation.request.example_data = example_data + + container_1 = operation.request.example_data["example_1"] + container_2 = operation.request.example_data["example_2"] + + results_1 = { + "id": container_1.body.scalars["id"].value, + "name": container_1.body.scalars["name"].value, + } + + results_2 = { + "id": container_2.body.scalars["id"].value, + "name": container_2.body.scalars["name"].value, + } + + self.assertEqual(example_data["example_1"]["body"], results_1) + self.assertEqual(example_data["example_2"]["body"], results_2) + + # reset data + operation.request.example_data = None + + def test_array_body_with_default_data(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + expected = { + example_name: { + "body": [ + { + "id": 10, + "name": "doggie", + } + ], + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("array_body") + + container_1 = operation.request.example_data[example_name] + body = container_1.body + assert isinstance(body, model.PropertyObjectArray) + + results_1 = [ + { + "id": body.properties[0].scalars["id"].value, + "name": body.properties[0].scalars["name"].value, + }, + ] + + self.assertEqual(expected[example_name]["body"], results_1) + + def test_array_body_with_custom_data(self): + example_data: model.EXAMPLE_DATA_BY_NAME = { + "example_1": { + "body": [ + { + "id": 100, + "name": str(uuid.uuid4()), + }, + { + "id": 200, + "name": str(uuid.uuid4()), + }, + ], + }, + "example_2": { + "body": [ + { + "id": 300, + "name": str(uuid.uuid4()), + }, + { + "id": 400, + "name": str(uuid.uuid4()), + }, + ], + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("array_body") + operation.request.example_data = example_data + + container_1 = operation.request.example_data["example_1"] + container_2 = operation.request.example_data["example_2"] + + body_1 = container_1.body + body_2 = container_2.body + + assert isinstance(body_1, model.PropertyObjectArray) + assert isinstance(body_2, model.PropertyObjectArray) + + results_1 = [ + { + "id": body_1.properties[0].scalars["id"].value, + "name": body_1.properties[0].scalars["name"].value, + }, + { + "id": body_1.properties[1].scalars["id"].value, + "name": body_1.properties[1].scalars["name"].value, + }, + ] + + results_2 = [ + { + "id": body_2.properties[0].scalars["id"].value, + "name": body_2.properties[0].scalars["name"].value, + }, + { + "id": body_2.properties[1].scalars["id"].value, + "name": body_2.properties[1].scalars["name"].value, + }, + ] + + self.assertEqual(example_data["example_1"]["body"], results_1) + self.assertEqual(example_data["example_2"]["body"], results_2) + + # reset data + operation.request.example_data = None + + def test_discriminator_with_default_data(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + expected = { + example_name: { + "body": { + "id": 10, + "breed": "terrier", + "group": "hunting", + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("discriminator") + + container_1 = operation.request.example_data[example_name] + + results_1 = { + "id": container_1.body.scalars["id"].value, + "breed": container_1.body.scalars["breed"].value, + "group": container_1.body.scalars["group"].value, + } + + self.assertEqual(expected[example_name]["body"], results_1) + + def test_discriminator_with_custom_data(self): + example_data: model.EXAMPLE_DATA_BY_NAME = { + "example_1": { + "body": { + "id": 100, + "breed": "terrier", + "group": "hunting", + }, + }, + "example_2": { + "body": { + "id": 200, + "breed": "beagle", + "group": "hound", + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("discriminator") + operation.request.example_data = example_data + + container_1 = operation.request.example_data["example_1"] + container_2 = operation.request.example_data["example_2"] + + results_1 = { + "id": container_1.body.scalars["id"].value, + "breed": container_1.body.scalars["breed"].value, + "group": container_1.body.scalars["group"].value, + } + + results_2 = { + "id": container_2.body.scalars["id"].value, + "breed": container_2.body.scalars["breed"].value, + "group": container_2.body.scalars["group"].value, + } + + self.assertEqual(example_data["example_1"]["body"], results_1) + self.assertEqual(example_data["example_2"]["body"], results_2) + + # reset data + operation.request.example_data = None + + def test_allof_with_default_data(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + expected = { + example_name: { + "body": { + "id": 10, + "breed": "terrier", + "group": "hunting", + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("all_of") + + container_1 = operation.request.example_data[example_name] + + results_1 = { + "id": container_1.body.scalars["id"].value, + "breed": container_1.body.scalars["breed"].value, + "group": container_1.body.scalars["group"].value, + } + + self.assertEqual(expected[example_name]["body"], results_1) + + def test_allof_with_custom_data(self): + example_data: model.EXAMPLE_DATA_BY_NAME = { + "example_1": { + "body": { + "id": 100, + "breed": "terrier", + "group": "hunting", + }, + }, + } + + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("all_of") + operation.request.example_data = example_data + + container_1 = operation.request.example_data["example_1"] + + results_1 = { + "id": container_1.body.scalars["id"].value, + "breed": container_1.body.scalars["breed"].value, + "group": container_1.body.scalars["group"].value, + } + + self.assertEqual(example_data["example_1"]["body"], results_1) + + # reset data + operation.request.example_data = None + + def test_external_file_example_data_operation(self): + expected_1: model.ExampleDataDef = { + "body": { + "id": 100, + "breed": "terrier", + "group": "hunting", + } + } + + expected_2: model.ExampleDataDef = { + "body": { + "id": 200, + "breed": "beagle", + "group": "hound", + } + } + + oa_parser = TestUtils.oa_parser("example_data_parser-external_example") + operation = oa_parser.operations.get("operation_example") + + container_1 = operation.request.example_data["example_1"] + container_2 = operation.request.example_data["example_2"] + + results_1 = { + "body": { + "id": container_1.body.scalars["id"].value, + "breed": container_1.body.scalars["breed"].value, + "group": container_1.body.scalars["group"].value, + } + } + + results_2 = { + "body": { + "id": container_2.body.scalars["id"].value, + "breed": container_2.body.scalars["breed"].value, + "group": container_2.body.scalars["group"].value, + } + } + + self.assertEqual(expected_1, results_1) + self.assertEqual(expected_2, results_2) + + def test_external_file_example_data_content(self): + expected_1: model.EXAMPLE_DATA_BODY = { + "id": 100, + "breed": "terrier", + "group": "hunting", + } + + expected_2: model.EXAMPLE_DATA_BODY = { + "id": 200, + "breed": "beagle", + "group": "hound", + } + + oa_parser = TestUtils.oa_parser("example_data_parser-external_example") + operation = oa_parser.operations.get("content_example") + + container_1 = operation.request.example_data["example_1"] + container_2 = operation.request.example_data["example_2"] + + results_1 = { + "id": container_1.body.scalars["id"].value, + "breed": container_1.body.scalars["breed"].value, + "group": container_1.body.scalars["group"].value, + } + + results_2 = { + "id": container_2.body.scalars["id"].value, + "breed": container_2.body.scalars["breed"].value, + "group": container_2.body.scalars["group"].value, + } + + self.assertEqual(expected_1, results_1) + self.assertEqual(expected_2, results_2) + + def test_content_example(self): + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("content_example") + container = operation.request.example_data["example"] + + self.assertEqual(container.body.scalars["id"].value, 50) + self.assertEqual(container.body.scalars["name"].value, "fish") + + def test_content_examples(self): + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations.get("content_examples") + container = operation.request.example_data["example_name"] + + self.assertEqual(container.body.scalars["id"].value, 500) + self.assertEqual(container.body.scalars["name"].value, "birds") + + def test_schema_with_examples(self): + oa_parser = TestUtils.oa_parser("example_data_parser-body") + operation = oa_parser.operations["body_with_examples"] + container = operation.request.example_data["example"] + + # We expect to see only the first example in examples + self.assertEqual(len(list(operation.request.example_data)), 1) + self.assertEqual(container.body.scalars["key_1"].value, "value_1") + + schema = oa_parser.components.schemas.get("SchemaWithExamples") + self.assertEqual(len(list(schema.examples)), 2) + + def test_non_objects_hydrated(self): + data_provider = { + "root_level_free_form": { + "type": oa.DataType.OBJECT, + "name": "request_body", + "value": {"foo": "bar", "bam": "baz"}, + "is_array": False, + }, + "root_level_free_form_array": { + "type": oa.DataType.OBJECT, + "name": "request_body", + "value": [{"foo": "bar", "bam": "baz"}], + "is_array": True, + }, + "root_level_string": { + "type": oa.DataType.STRING, + "name": "body", + "value": "some string value", + "is_array": False, + }, + "root_level_string_array": { + "type": oa.DataType.STRING, + "name": "request_body", + "value": ["some string value"], + "is_array": True, + }, + "root_level_int": { + "type": oa.DataType.INTEGER, + "name": "body", + "value": 12345, + "is_array": False, + }, + "root_level_int_array": { + "type": oa.DataType.INTEGER, + "name": "request_body", + "value": [12345], + "is_array": True, + }, + "root_level_file": { + "type": oa.DataType.STRING, + "name": "body", + "value": "/some/file/path.pdf", + "is_array": False, + }, + "root_level_file_array": { + "type": oa.DataType.STRING, + "name": "request_body", + "value": ["/some/file/path.pdf"], + "is_array": True, + }, + "root_level_bool": { + "type": oa.DataType.BOOLEAN, + "name": "body", + "value": True, + "is_array": False, + }, + "root_level_bool_array": { + "type": oa.DataType.BOOLEAN, + "name": "request_body", + "value": [True], + "is_array": True, + }, + } + + oa_parser = TestUtils.oa_parser("root_level_non_objects") + + for operation_id, expected in data_provider.items(): + with self.subTest(operation_id): + operation = oa_parser.operations[operation_id] + container = operation.request.example_data["example"] + + if expected["is_array"]: + self.assertEqual( + expected["type"], + operation.request.body.items.type, + ) + else: + self.assertEqual( + expected["type"], + operation.request.body.type, + ) + + self.assertEqual( + expected["name"], + container.request.example_data["example"].body.name, + ) + + self.assertEqual( + expected["value"], + container.body.value, + ) + + def test_recursive_ref(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + example_data = { + example_name: { + "body": { + "id": 123, + "dog": { + "id": 456, + "pet": { + "id": 321, + "dog": { + "id": 654, + }, + }, + }, + }, + }, + } + + oa_parser = TestUtils.oa_parser("recursive_ref") + operation = oa_parser.operations.get("default") + operation.request.example_data = example_data + container = operation.request.example_data[example_name] + body_data = example_data[example_name]["body"] + + pet_1 = container.body + dog_1 = pet_1.properties.get("dog") + pet_2 = dog_1.properties.get("pet") + dog_2 = pet_2.properties.get("dog") + pet_3 = dog_2.properties.get("pet") + + self.assertEqual( + body_data["id"], + pet_1.properties.get("id").value, + ) + self.assertTrue(pet_1.is_set) + + self.assertEqual( + body_data["dog"]["id"], + dog_1.properties.get("id").value, + ) + self.assertTrue(dog_1.is_set) + + self.assertEqual( + body_data["dog"]["pet"]["id"], + pet_2.properties.get("id").value, + ) + self.assertTrue(pet_2.is_set) + + self.assertEqual( + body_data["dog"]["pet"]["dog"]["id"], + dog_2.properties.get("id").value, + ) + self.assertTrue(dog_2.is_set) + + self.assertFalse(pet_3.is_set) + + operation.request.example_data = None + + def test_recursive_ref_default_data(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("recursive_ref") + operation = oa_parser.operations.get("default") + container = operation.request.example_data[example_name] + + pet_1 = container.body + dog_1 = pet_1.properties.get("dog") + pet_2 = dog_1.properties.get("pet") + dog_2 = pet_2.properties.get("dog") + + self.assertTrue(pet_1.is_set) + self.assertFalse(dog_1.is_set) + self.assertFalse(pet_2.is_set) + self.assertIsNone(dog_2) diff --git a/oseg/tests/test_generator.py b/oseg/tests/test_generator.py new file mode 100644 index 000000000..8fb0dac4b --- /dev/null +++ b/oseg/tests/test_generator.py @@ -0,0 +1,48 @@ +from test_utils import TestUtils, TestCase +from fixtures.mock_generator import MockConfig, MockGenerator, JINJA_MACROS +from oseg import model, parser + + +class TestGenerator(TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.jinja_macros = model.JinjaMacros(JINJA_MACROS) + config_data = parser.FileLoader.get_file_contents( + f"{TestUtils._BASE_DIR}/fixtures/config-mock.yaml" + ) + cls.config = MockConfig(config_data.get("additionalProperties", {})) + cls.example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + def test_enum_name(self): + operation_id = "default" + oa_parser = TestUtils.oa_parser("enums") + operation = oa_parser.operations.get(operation_id) + + operation.request.example_data = { + self.example_name: { + "body": { + "enum_prop_1": "value_1", + "enum_prop_2": "value_2", + "enum_prop_3": "value_3", + }, + }, + } + + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + properties = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=container.body, + indent_count=0, + ) + + expected = { + "enum_prop_1": "value_1", + "enum_prop_2": "ENUM_VARNAME_2", + "enum_prop_3": "ENUM_VARNAME_OVERRIDE_MOCK_3", + } + + self.assertDictEqual(expected, properties) + + operation.request.example_data = None diff --git a/oseg/tests/test_generator_config.py b/oseg/tests/test_generator_config.py new file mode 100644 index 000000000..342e3924d --- /dev/null +++ b/oseg/tests/test_generator_config.py @@ -0,0 +1,25 @@ +from test_utils import TestUtils, TestCase +from fixtures.mock_generator import MockConfig, JINJA_MACROS +from oseg import model, parser + + +class TestGeneratorConfig(TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.jinja_macros = model.JinjaMacros(JINJA_MACROS) + cls.config_data = parser.FileLoader.get_file_contents( + f"{TestUtils._BASE_DIR}/fixtures/config-mock.yaml" + ) + + def test_security(self): + config = MockConfig(self.config_data.get("additionalProperties", {})) + + expected = { + "api_key_scheme.api_key": "YOUR_API_KEY", + "http_basic_scheme.username": "YOUR_USERNAME", + "http_basic_scheme.password": "YOUR_PASSWORD", + "http_bearer_scheme.access_token": "YOUR_ACCESS_TOKEN_1", + "oauth2_scheme.access_token": "YOUR_ACCESS_TOKEN_2", + } + + self.assertDictEqual(expected, config.oseg.security) diff --git a/oseg/tests/test_normalize_str.py b/oseg/tests/test_normalize_str.py new file mode 100644 index 000000000..c76255987 --- /dev/null +++ b/oseg/tests/test_normalize_str.py @@ -0,0 +1,1117 @@ +from oseg import parser +from test_utils import TestCase + + +class TestNormalizeStr(TestCase): + def test_underscore(self): + data = { + "A": { + "v1": "A", + "v2": "A", + }, + "a": { + "v1": "a", + "v2": "a", + }, + "Ab": { + "v1": "Ab", + "v2": "Ab", + }, + "AB": { + "v1": "AB", + "v2": "A_B", + }, + "aB": { + "v1": "a_B", + "v2": "a_B", + }, + "ABC": { + "v1": "ABC", + "v2": "A_BC", + }, + "OAuthName": { + "v1": "O_Auth_Name", + "v2": "O_Auth_Name", + }, + "abcdefg123hij456": { + "v1": "abcdefg123hij456", + "v2": "abcdefg123hij456", + }, + "Abcdefg123hij456": { + "v1": "Abcdefg123hij456", + "v2": "Abcdefg123hij456", + }, + "ABcdefg123hij456": { + "v1": "A_Bcdefg123hij456", + "v2": "A_Bcdefg123hij456", + }, + "ABCdefg123hij456": { + "v1": "AB_Cdefg123hij456", + "v2": "A_B_Cdefg123hij456", + }, + "ABCDefg123hij456": { + "v1": "ABC_Defg123hij456", + "v2": "A_BC_Defg123hij456", + }, + "ABCDEfg123hij456": { + "v1": "ABCD_Efg123hij456", + "v2": "A_BCD_Efg123hij456", + }, + "ABCDEFg123hij456": { + "v1": "ABCDEFg123hij456", + "v2": "A_BCDEFg123hij456", + }, + "ABCDEFG123hij456": { + "v1": "ABCDEFG123hij456", + "v2": "A_BCDEFG123hij456", + }, + "ABCDEFG123Hij456": { + "v1": "ABCDEFG123_Hij456", + "v2": "A_BCDEFG123_Hij456", + }, + "ABCDEFG123HIj456": { + "v1": "ABCDEFG123_HIj456", + "v2": "A_BCDEFG123_HIj456", + }, + "ABCDEFG123HIJ456": { + "v1": "ABCDEFG123_HIJ456", + "v2": "A_BCDEFG123_HIJ456", + }, + "ABCDEFG123HiJ456": { + "v1": "ABCDEFG123_Hi_J456", + "v2": "A_BCDEFG123_Hi_J456", + }, + "ABCDEFG123hiJ456": { + "v1": "ABCDEFG123hi_J456", + "v2": "A_BCDEFG123hi_J456", + }, + "ABCDEFG123hIJ456": { + "v1": "ABCDEFG123h_IJ456", + "v2": "A_BCDEFG123h_IJ456", + }, + "aBcdefg123hij456": { + "v1": "a_Bcdefg123hij456", + "v2": "a_Bcdefg123hij456", + }, + "aBCdefg123hij456": { + "v1": "a_B_Cdefg123hij456", + "v2": "a_B_Cdefg123hij456", + }, + "aBCDefg123hij456": { + "v1": "a_BC_Defg123hij456", + "v2": "a_BC_Defg123hij456", + }, + "aBCDEfg123hij456": { + "v1": "a_BCD_Efg123hij456", + "v2": "a_BCD_Efg123hij456", + }, + "aBCDEFg123hij456": { + "v1": "a_BCDEFg123hij456", + "v2": "a_BCDEFg123hij456", + }, + "aBCDEFG123hij456": { + "v1": "a_BCDEFG123hij456", + "v2": "a_BCDEFG123hij456", + }, + "aBcDeFg123hIj456": { + "v1": "a_Bc_De_Fg123h_Ij456", + "v2": "a_Bc_De_Fg123h_Ij456", + }, + "HelloWorld!123": { + "v1": "Hello_World_123", + "v2": "Hello_World_123", + }, + "MixEDCase$#42": { + "v1": "Mix_ED_Case__42", + "v2": "Mix_ED_Case__42", + }, + "Snake_Case-Test": { + "v1": "Snake_Case_Test", + "v2": "Snake_Case_Test", + }, + "CamelCase99!": { + "v1": "Camel_Case99", + "v2": "Camel_Case99", + }, + "Python@Rocks2024": { + "v1": "Python_Rocks2024", + "v2": "Python_Rocks2024", + }, + "myVariable&*()": { + "v1": "my_Variable", + "v2": "my_Variable", + }, + "Some-Thing#Here": { + "v1": "Some_Thing_Here", + "v2": "Some_Thing_Here", + }, + "No$SpacesAllowed99": { + "v1": "No_Spaces_Allowed99", + "v2": "No_Spaces_Allowed99", + }, + "justA_TestString!": { + "v1": "just_A_Test_String", + "v2": "just_A_Test_String", + }, + "What?Ever*YouSay": { + "v1": "What_Ever_You_Say", + "v2": "What_Ever_You_Say", + }, + "UserID_789": { + "v1": "User_ID_789", + "v2": "User_ID_789", + }, + "Go4It-Now!": { + "v1": "Go4_It_Now", + "v2": "Go4_It_Now", + }, + "Check_ME@THIS": { + "v1": "Check_ME_THIS", + "v2": "Check_ME_THIS", + }, + "JavaScript$Rules!": { + "v1": "Java_Script_Rules", + "v2": "Java_Script_Rules", + }, + "Best_Choice_2025*": { + "v1": "Best_Choice_2025", + "v2": "Best_Choice_2025", + }, + "Happy_Days": { + "v1": "Happy_Days", + "v2": "Happy_Days", + }, + "Let's-Try_This-One!": { + "v1": "Let_s_Try_This_One", + "v2": "Let_s_Try_This_One", + }, + "Make$It$Count24": { + "v1": "Make_It_Count24", + "v2": "Make_It_Count24", + }, + "Code-Lover@Heart": { + "v1": "Code_Lover_Heart", + "v2": "Code_Lover_Heart", + }, + "Dev&Ops-24/7": { + "v1": "Dev_Ops_24_7", + "v2": "Dev_Ops_24_7", + }, + "Super#Cool_Project": { + "v1": "Super_Cool_Project", + "v2": "Super_Cool_Project", + }, + "WhatIs_This?": { + "v1": "What_Is_This", + "v2": "What_Is_This", + }, + "42AnswerToEverything!": { + "v1": "42_Answer_To_Everything", + "v2": "42_Answer_To_Everything", + }, + "API@Version_3.0": { + "v1": "API_Version_3_0", + "v2": "A_PI_Version_3_0", + }, + "Let'sDo_This-Again!": { + "v1": "Let_s_Do_This_Again", + "v2": "Let_s_Do_This_Again", + }, + "AI configs (beta) Api": { + "v1": "AI_configs_beta_Api", + "v2": "A_I_configs_beta_Api", + }, + "AI Configs (beta) Api": { + "v1": "AI_Configs_beta_Api", + "v2": "A_I_Configs_beta_Api", + }, + "AIconfigs (beta) Api": { + "v1": "A_Iconfigs_beta_Api", + "v2": "A_Iconfigs_beta_Api", + }, + "AIConfigs (beta) Api": { + "v1": "AI_Configs_beta_Api", + "v2": "A_I_Configs_beta_Api", + }, + "AIConfigs(beta) Api": { + "v1": "AI_Configs_beta_Api", + "v2": "A_I_Configs_beta_Api", + }, + "AIConfigs(Beta) Api": { + "v1": "AI_Configs_Beta_Api", + "v2": "A_I_Configs_Beta_Api", + }, + "AIConfigsBeta) Api": { + "v1": "AI_Configs_Beta_Api", + "v2": "A_I_Configs_Beta_Api", + }, + "AI Configs Beta Api": { + "v1": "AI_Configs_Beta_Api", + "v2": "A_I_Configs_Beta_Api", + }, + "AI configs (BETA) Api": { + "v1": "AI_configs_BETA_Api", + "v2": "A_I_configs_BETA_Api", + }, + "abcd": { + "v1": "abcd", + "v2": "abcd", + }, + "some-value": { + "v1": "some_value", + "v2": "some_value", + }, + "some_value": { + "v1": "some_value", + "v2": "some_value", + }, + "LD-API-Version": { + "v1": "LD_API_Version", + "v2": "L_D_API_Version", + }, + } + + for provided, expected in data.items(): + with self.subTest(provided): + v1 = parser.NormalizeStr.underscore( + provided, + option=parser.UnderscoreOption.FIRST_CHAR_JOIN, + ) + + self.assertEqual( + first=expected["v1"], + second=v1, + msg=f"v1 - Provided: {provided}, Expected: {expected["v1"]}, Result: {v1}", + ) + + v2 = parser.NormalizeStr.underscore( + provided, + option=parser.UnderscoreOption.FIRST_CHAR_SEPARATE, + ) + + self.assertEqual( + first=expected["v2"], + second=v2, + msg=f"v2 - Provided: {provided}, Expected: {expected["v2"]}, Result: {v2}", + ) + + def test_camel_case(self): + data = { + "A": { + "v1": "a", + "v2": "a", + "v3": "a", + }, + "a": { + "v1": "a", + "v2": "a", + "v3": "a", + }, + "Ab": { + "v1": "ab", + "v2": "ab", + "v3": "ab", + }, + "AB": { + "v1": "aB", + "v2": "ab", + "v3": "ab", + }, + "aB": { + "v1": "aB", + "v2": "aB", + "v3": "aB", + }, + "ABC": { + "v1": "aBC", + "v2": "abc", + "v3": "abc", + }, + "OAuthName": { + "v1": "oAuthName", + "v2": "oAuthName", + "v3": "oAuthName", + }, + "abcdefg123hij456": { + "v1": "abcdefg123hij456", + "v2": "abcdefg123hij456", + "v3": "abcdefg123hij456", + }, + "Abcdefg123hij456": { + "v1": "abcdefg123hij456", + "v2": "abcdefg123hij456", + "v3": "abcdefg123hij456", + }, + "ABcdefg123hij456": { + "v1": "aBcdefg123hij456", + "v2": "aBcdefg123hij456", + "v3": "aBcdefg123hij456", + }, + "ABCdefg123hij456": { + "v1": "aBCdefg123hij456", + "v2": "abCdefg123hij456", + "v3": "abCdefg123hij456", + }, + "ABCDefg123hij456": { + "v1": "aBCDefg123hij456", + "v2": "abcDefg123hij456", + "v3": "abcDefg123hij456", + }, + "ABCDEfg123hij456": { + "v1": "aBCDEfg123hij456", + "v2": "abcdEfg123hij456", + "v3": "abcdEfg123hij456", + }, + "ABCDEFg123hij456": { + "v1": "aBCDEFg123hij456", + "v2": "abcdefg123hij456", + "v3": "abcdefg123hij456", + }, + "ABCDEFG123hij456": { + "v1": "aBCDEFG123hij456", + "v2": "abcdefg123hij456", + "v3": "abcdefg123hij456", + }, + "ABCDEFG123Hij456": { + "v1": "aBCDEFG123Hij456", + "v2": "abcdefg123Hij456", + "v3": "abcdefg123Hij456", + }, + "ABCDEFG123HIj456": { + "v1": "aBCDEFG123HIj456", + "v2": "abcdefg123Hij456", + "v3": "abcdefg123HIj456", + }, + "ABCDEFG123HIJ456": { + "v1": "aBCDEFG123HIJ456", + "v2": "abcdefg123Hij456", + "v3": "abcdefg123HIJ456", + }, + "ABCDEFG123HiJ456": { + "v1": "aBCDEFG123HiJ456", + "v2": "abcdefg123HiJ456", + "v3": "abcdefg123HiJ456", + }, + "ABCDEFG123hiJ456": { + "v1": "aBCDEFG123hiJ456", + "v2": "abcdefg123hiJ456", + "v3": "abcdefg123hiJ456", + }, + "ABCDEFG123hIJ456": { + "v1": "aBCDEFG123hIJ456", + "v2": "abcdefg123hIj456", + "v3": "abcdefg123hIJ456", + }, + "aBcdefg123hij456": { + "v1": "aBcdefg123hij456", + "v2": "aBcdefg123hij456", + "v3": "aBcdefg123hij456", + }, + "aBCdefg123hij456": { + "v1": "aBCdefg123hij456", + "v2": "aBCdefg123hij456", + "v3": "aBCdefg123hij456", + }, + "aBCDefg123hij456": { + "v1": "aBCDefg123hij456", + "v2": "aBcDefg123hij456", + "v3": "aBCDefg123hij456", + }, + "aBCDEfg123hij456": { + "v1": "aBCDEfg123hij456", + "v2": "aBcdEfg123hij456", + "v3": "aBCDEfg123hij456", + }, + "aBCDEFg123hij456": { + "v1": "aBCDEFg123hij456", + "v2": "aBcdefg123hij456", + "v3": "aBCDEFg123hij456", + }, + "aBCDEFG123hij456": { + "v1": "aBCDEFG123hij456", + "v2": "aBcdefg123hij456", + "v3": "aBCDEFG123hij456", + }, + "aBcDeFg123hIj456": { + "v1": "aBcDeFg123hIj456", + "v2": "aBcDeFg123hIj456", + "v3": "aBcDeFg123hIj456", + }, + "HelloWorld!123": { + "v1": "helloWorld123", + "v2": "helloWorld123", + "v3": "helloWorld123", + }, + "MixEDCase$#42": { + "v1": "mixEDCase42", + "v2": "mixEdCase42", + "v3": "mixEDCase42", + }, + "Snake_Case-Test": { + "v1": "snakeCaseTest", + "v2": "snakeCaseTest", + "v3": "snakeCaseTest", + }, + "CamelCase99!": { + "v1": "camelCase99", + "v2": "camelCase99", + "v3": "camelCase99", + }, + "Python@Rocks2024": { + "v1": "pythonRocks2024", + "v2": "pythonRocks2024", + "v3": "pythonRocks2024", + }, + "myVariable&*()": { + "v1": "myVariable", + "v2": "myVariable", + "v3": "myVariable", + }, + "Some-Thing#Here": { + "v1": "someThingHere", + "v2": "someThingHere", + "v3": "someThingHere", + }, + "No$SpacesAllowed99": { + "v1": "noSpacesAllowed99", + "v2": "noSpacesAllowed99", + "v3": "noSpacesAllowed99", + }, + "justA_TestString!": { + "v1": "justATestString", + "v2": "justATestString", + "v3": "justATestString", + }, + "What?Ever*YouSay": { + "v1": "whatEverYouSay", + "v2": "whatEverYouSay", + "v3": "whatEverYouSay", + }, + "UserID_789": { + "v1": "userID789", + "v2": "userId789", + "v3": "userID789", + }, + "Go4It-Now!": { + "v1": "go4ItNow", + "v2": "go4ItNow", + "v3": "go4ItNow", + }, + "Check_ME@THIS": { + "v1": "checkMETHIS", + "v2": "checkMeThis", + "v3": "checkMETHIS", + }, + "JavaScript$Rules!": { + "v1": "javaScriptRules", + "v2": "javaScriptRules", + "v3": "javaScriptRules", + }, + "Best_Choice_2025*": { + "v1": "bestChoice2025", + "v2": "bestChoice2025", + "v3": "bestChoice2025", + }, + "Happy_Days": { + "v1": "happyDays", + "v2": "happyDays", + "v3": "happyDays", + }, + "Let's-Try_This-One!": { + "v1": "letSTryThisOne", + "v2": "letSTryThisOne", + "v3": "letSTryThisOne", + }, + "Make$It$Count24": { + "v1": "makeItCount24", + "v2": "makeItCount24", + "v3": "makeItCount24", + }, + "Code-Lover@Heart": { + "v1": "codeLoverHeart", + "v2": "codeLoverHeart", + "v3": "codeLoverHeart", + }, + "Dev&Ops-24/7": { + "v1": "devOps247", + "v2": "devOps247", + "v3": "devOps247", + }, + "Super#Cool_Project": { + "v1": "superCoolProject", + "v2": "superCoolProject", + "v3": "superCoolProject", + }, + "WhatIs_This?": { + "v1": "whatIsThis", + "v2": "whatIsThis", + "v3": "whatIsThis", + }, + "42AnswerToEverything!": { + "v1": "42AnswerToEverything", + "v2": "42AnswerToEverything", + "v3": "42AnswerToEverything", + }, + "API@Version_3.0": { + "v1": "aPIVersion30", + "v2": "apiVersion30", + "v3": "apiVersion30", + }, + "Let'sDo_This-Again!": { + "v1": "letSDoThisAgain", + "v2": "letSDoThisAgain", + "v3": "letSDoThisAgain", + }, + "AI configs (beta) Api": { + "v1": "aIConfigsBetaApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBetaApi", + }, + "AI Configs (beta) Api": { + "v1": "aIConfigsBetaApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBetaApi", + }, + "AIconfigs (beta) Api": { + "v1": "aIconfigsBetaApi", + "v2": "aIconfigsBetaApi", + "v3": "aIconfigsBetaApi", + }, + "AIConfigs (beta) Api": { + "v1": "aIConfigsBetaApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBetaApi", + }, + "AIConfigs(beta) Api": { + "v1": "aIConfigsBetaApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBetaApi", + }, + "AIConfigs(Beta) Api": { + "v1": "aIConfigsBetaApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBetaApi", + }, + "AIConfigsBeta) Api": { + "v1": "aIConfigsBetaApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBetaApi", + }, + "AI Configs Beta Api": { + "v1": "aIConfigsBetaApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBetaApi", + }, + "AI configs (BETA) Api": { + "v1": "aIConfigsBETAApi", + "v2": "aiConfigsBetaApi", + "v3": "aiConfigsBETAApi", + }, + "abcd": { + "v1": "abcd", + "v2": "abcd", + "v3": "abcd", + }, + "some-value": { + "v1": "someValue", + "v2": "someValue", + "v3": "someValue", + }, + "some_value": { + "v1": "someValue", + "v2": "someValue", + "v3": "someValue", + }, + "LD-API-Version": { + "v1": "lDAPIVersion", + "v2": "ldApiVersion", + "v3": "ldAPIVersion", + }, + } + + for provided, expected in data.items(): + with self.subTest(provided): + v1 = parser.NormalizeStr.camel_case( + provided, + option=parser.CamelCaseOption.UPPERCASE_KEEP, + ) + + self.assertEqual( + first=expected["v1"], + second=v1, + msg=f"v1 - Provided: {provided}, Expected: {expected["v1"]}, Result: {v1}", + ) + + v2 = parser.NormalizeStr.camel_case( + provided, + option=parser.CamelCaseOption.LOWERCASE_CONTIGUOUS, + ) + + self.assertEqual( + first=expected["v2"], + second=v2, + msg=f"v2 - Provided: {provided}, Expected: {expected["v2"]}, Result: {v2}", + ) + + v3 = parser.NormalizeStr.camel_case( + provided, + option=parser.CamelCaseOption.LOWERCASE_FIRST_SECTION, + ) + + self.assertEqual( + first=expected["v3"], + second=v3, + msg=f"v3 - Provided: {provided}, Expected: {expected["v3"]}, Result: {v3}", + ) + + def test_pascal_case(self): + data = { + "A": { + "v1": "A", + "v2": "A", + }, + "a": { + "v1": "A", + "v2": "A", + }, + "Ab": { + "v1": "Ab", + "v2": "Ab", + }, + "AB": { + "v1": "AB", + "v2": "Ab", + }, + "aB": { + "v1": "AB", + "v2": "AB", + }, + "ABC": { + "v1": "ABC", + "v2": "Abc", + }, + "OAuthName": { + "v1": "OAuthName", + "v2": "OAuthName", + }, + "abcdefg123hij456": { + "v1": "Abcdefg123hij456", + "v2": "Abcdefg123hij456", + }, + "Abcdefg123hij456": { + "v1": "Abcdefg123hij456", + "v2": "Abcdefg123hij456", + }, + "ABcdefg123hij456": { + "v1": "ABcdefg123hij456", + "v2": "ABcdefg123hij456", + }, + "ABCdefg123hij456": { + "v1": "ABCdefg123hij456", + "v2": "AbCdefg123hij456", + }, + "ABCDefg123hij456": { + "v1": "ABCDefg123hij456", + "v2": "AbcDefg123hij456", + }, + "ABCDEfg123hij456": { + "v1": "ABCDEfg123hij456", + "v2": "AbcdEfg123hij456", + }, + "ABCDEFg123hij456": { + "v1": "ABCDEFg123hij456", + "v2": "Abcdefg123hij456", + }, + "ABCDEFG123hij456": { + "v1": "ABCDEFG123hij456", + "v2": "Abcdefg123hij456", + }, + "ABCDEFG123Hij456": { + "v1": "ABCDEFG123Hij456", + "v2": "Abcdefg123Hij456", + }, + "ABCDEFG123HIj456": { + "v1": "ABCDEFG123HIj456", + "v2": "Abcdefg123Hij456", + }, + "ABCDEFG123HIJ456": { + "v1": "ABCDEFG123HIJ456", + "v2": "Abcdefg123Hij456", + }, + "ABCDEFG123HiJ456": { + "v1": "ABCDEFG123HiJ456", + "v2": "Abcdefg123HiJ456", + }, + "ABCDEFG123hiJ456": { + "v1": "ABCDEFG123hiJ456", + "v2": "Abcdefg123hiJ456", + }, + "ABCDEFG123hIJ456": { + "v1": "ABCDEFG123hIJ456", + "v2": "Abcdefg123hIj456", + }, + "aBcdefg123hij456": { + "v1": "ABcdefg123hij456", + "v2": "ABcdefg123hij456", + }, + "aBCdefg123hij456": { + "v1": "ABCdefg123hij456", + "v2": "ABCdefg123hij456", + }, + "aBCDefg123hij456": { + "v1": "ABCDefg123hij456", + "v2": "ABcDefg123hij456", + }, + "aBCDEfg123hij456": { + "v1": "ABCDEfg123hij456", + "v2": "ABcdEfg123hij456", + }, + "aBCDEFg123hij456": { + "v1": "ABCDEFg123hij456", + "v2": "ABcdefg123hij456", + }, + "aBCDEFG123hij456": { + "v1": "ABCDEFG123hij456", + "v2": "ABcdefg123hij456", + }, + "aBcDeFg123hIj456": { + "v1": "ABcDeFg123hIj456", + "v2": "ABcDeFg123hIj456", + }, + "HelloWorld!123": { + "v1": "HelloWorld123", + "v2": "HelloWorld123", + }, + "MixEDCase$#42": { + "v1": "MixEDCase42", + "v2": "MixEdCase42", + }, + "Snake_Case-Test": { + "v1": "SnakeCaseTest", + "v2": "SnakeCaseTest", + }, + "CamelCase99!": { + "v1": "CamelCase99", + "v2": "CamelCase99", + }, + "Python@Rocks2024": { + "v1": "PythonRocks2024", + "v2": "PythonRocks2024", + }, + "myVariable&*()": { + "v1": "MyVariable", + "v2": "MyVariable", + }, + "Some-Thing#Here": { + "v1": "SomeThingHere", + "v2": "SomeThingHere", + }, + "No$SpacesAllowed99": { + "v1": "NoSpacesAllowed99", + "v2": "NoSpacesAllowed99", + }, + "justA_TestString!": { + "v1": "JustATestString", + "v2": "JustATestString", + }, + "What?Ever*YouSay": { + "v1": "WhatEverYouSay", + "v2": "WhatEverYouSay", + }, + "UserID_789": { + "v1": "UserID789", + "v2": "UserId789", + }, + "Go4It-Now!": { + "v1": "Go4ItNow", + "v2": "Go4ItNow", + }, + "Check_ME@THIS": { + "v1": "CheckMETHIS", + "v2": "CheckMeThis", + }, + "JavaScript$Rules!": { + "v1": "JavaScriptRules", + "v2": "JavaScriptRules", + }, + "Best_Choice_2025*": { + "v1": "BestChoice2025", + "v2": "BestChoice2025", + }, + "Happy_Days": { + "v1": "HappyDays", + "v2": "HappyDays", + }, + "Let's-Try_This-One!": { + "v1": "LetSTryThisOne", + "v2": "LetSTryThisOne", + }, + "Make$It$Count24": { + "v1": "MakeItCount24", + "v2": "MakeItCount24", + }, + "Code-Lover@Heart": { + "v1": "CodeLoverHeart", + "v2": "CodeLoverHeart", + }, + "Dev&Ops-24/7": { + "v1": "DevOps247", + "v2": "DevOps247", + }, + "Super#Cool_Project": { + "v1": "SuperCoolProject", + "v2": "SuperCoolProject", + }, + "WhatIs_This?": { + "v1": "WhatIsThis", + "v2": "WhatIsThis", + }, + "42AnswerToEverything!": { + "v1": "42AnswerToEverything", + "v2": "42AnswerToEverything", + }, + "API@Version_3.0": { + "v1": "APIVersion30", + "v2": "ApiVersion30", + }, + "Let'sDo_This-Again!": { + "v1": "LetSDoThisAgain", + "v2": "LetSDoThisAgain", + }, + "AI configs (beta) Api": { + "v1": "AIConfigsBetaApi", + "v2": "AiConfigsBetaApi", + }, + "AI Configs (beta) Api": { + "v1": "AIConfigsBetaApi", + "v2": "AiConfigsBetaApi", + }, + "AIconfigs (beta) Api": { + "v1": "AIconfigsBetaApi", + "v2": "AIconfigsBetaApi", + }, + "AIConfigs (beta) Api": { + "v1": "AIConfigsBetaApi", + "v2": "AiConfigsBetaApi", + }, + "AIConfigs(beta) Api": { + "v1": "AIConfigsBetaApi", + "v2": "AiConfigsBetaApi", + }, + "AIConfigs(Beta) Api": { + "v1": "AIConfigsBetaApi", + "v2": "AiConfigsBetaApi", + }, + "AIConfigsBeta) Api": { + "v1": "AIConfigsBetaApi", + "v2": "AiConfigsBetaApi", + }, + "AI Configs Beta Api": { + "v1": "AIConfigsBetaApi", + "v2": "AiConfigsBetaApi", + }, + "AI configs (BETA) Api": { + "v1": "AIConfigsBETAApi", + "v2": "AiConfigsBetaApi", + }, + "abcd": { + "v1": "Abcd", + "v2": "Abcd", + }, + "some-value": { + "v1": "SomeValue", + "v2": "SomeValue", + }, + "some_value": { + "v1": "SomeValue", + "v2": "SomeValue", + }, + "LD-API-Version": { + "v1": "LDAPIVersion", + "v2": "LdApiVersion", + }, + } + + for provided, expected in data.items(): + with self.subTest(provided): + v1 = parser.NormalizeStr.pascal_case( + provided, + option=parser.PascalCaseOption.UPPERCASE_KEEP, + ) + + self.assertEqual( + first=expected["v1"], + second=v1, + msg=f"v1 - Provided: {provided}, Expected: {expected["v1"]}, Result: {v1}", + ) + + v2 = parser.NormalizeStr.pascal_case( + provided, + option=parser.PascalCaseOption.LOWERCASE_CONTIGUOUS, + ) + + self.assertEqual( + first=expected["v2"], + second=v2, + msg=f"v2 - Provided: {provided}, Expected: {expected["v2"]}, Result: {v2}", + ) + + def test_snake_case(self): + data = { + "A": "a", + "a": "a", + "Ab": "ab", + "AB": "ab", + "aB": "a_b", + "ABC": "abc", + "OAuthName": "o_auth_name", + "abcdefg123hij456": "abcdefg123hij456", + "Abcdefg123hij456": "abcdefg123hij456", + "ABcdefg123hij456": "a_bcdefg123hij456", + "ABCdefg123hij456": "ab_cdefg123hij456", + "ABCDefg123hij456": "abc_defg123hij456", + "ABCDEfg123hij456": "abcd_efg123hij456", + "ABCDEFg123hij456": "abcdefg123hij456", + "ABCDEFG123hij456": "abcdefg123hij456", + "ABCDEFG123Hij456": "abcdefg123_hij456", + "ABCDEFG123HIj456": "abcdefg123_hij456", + "ABCDEFG123HIJ456": "abcdefg123_hij456", + "ABCDEFG123HiJ456": "abcdefg123_hi_j456", + "ABCDEFG123hiJ456": "abcdefg123hi_j456", + "ABCDEFG123hIJ456": "abcdefg123h_ij456", + "aBcdefg123hij456": "a_bcdefg123hij456", + "aBCdefg123hij456": "a_b_cdefg123hij456", + "aBCDefg123hij456": "a_bc_defg123hij456", + "aBCDEfg123hij456": "a_bcd_efg123hij456", + "aBCDEFg123hij456": "a_bcdefg123hij456", + "aBCDEFG123hij456": "a_bcdefg123hij456", + "aBcDeFg123hIj456": "a_bc_de_fg123h_ij456", + "HelloWorld!123": "hello_world_123", + "MixEDCase$#42": "mix_ed_case__42", + "Snake_Case-Test": "snake_case_test", + "CamelCase99!": "camel_case99", + "Python@Rocks2024": "python_rocks2024", + "myVariable&*()": "my_variable", + "Some-Thing#Here": "some_thing_here", + "No$SpacesAllowed99": "no_spaces_allowed99", + "justA_TestString!": "just_a_test_string", + "What?Ever*YouSay": "what_ever_you_say", + "UserID_789": "user_id_789", + "Go4It-Now!": "go4_it_now", + "Check_ME@THIS": "check_me_this", + "JavaScript$Rules!": "java_script_rules", + "Best_Choice_2025*": "best_choice_2025", + "Happy_Days": "happy_days", + "Let's-Try_This-One!": "let_s_try_this_one", + "Make$It$Count24": "make_it_count24", + "Code-Lover@Heart": "code_lover_heart", + "Dev&Ops-24/7": "dev_ops_24_7", + "Super#Cool_Project": "super_cool_project", + "WhatIs_This?": "what_is_this", + "42AnswerToEverything!": "42_answer_to_everything", + "API@Version_3.0": "api_version_3_0", + "Let'sDo_This-Again!": "let_s_do_this_again", + "AI configs (beta) Api": "ai_configs_beta_api", + "AI Configs (beta) Api": "ai_configs_beta_api", + "AIconfigs (beta) Api": "a_iconfigs_beta_api", + "AIConfigs (beta) Api": "ai_configs_beta_api", + "AIConfigs(beta) Api": "ai_configs_beta_api", + "AIConfigs(Beta) Api": "ai_configs_beta_api", + "AIConfigsBeta) Api": "ai_configs_beta_api", + "AI Configs Beta Api": "ai_configs_beta_api", + "AI configs (BETA) Api": "ai_configs_beta_api", + "abcd": "abcd", + "some-value": "some_value", + "some_value": "some_value", + "LD-API-Version": "ld_api_version", + } + + for provided, expected in data.items(): + with self.subTest(provided): + result = parser.NormalizeStr.snake_case(provided) + + self.assertEqual( + first=expected, + second=result, + msg=f"Provided: {provided}, Expected: {expected}, Result: {result}", + ) + + def test_uc_first(self): + data = { + "A": "A", + "a": "A", + "Ab": "Ab", + "AB": "AB", + "aB": "AB", + "ABC": "ABC", + "OAuthName": "OAuthName", + "abcdefg123hij456": "Abcdefg123hij456", + "Abcdefg123hij456": "Abcdefg123hij456", + "ABcdefg123hij456": "ABcdefg123hij456", + "ABCdefg123hij456": "ABCdefg123hij456", + "ABCDefg123hij456": "ABCDefg123hij456", + "ABCDEfg123hij456": "ABCDEfg123hij456", + "ABCDEFg123hij456": "ABCDEFg123hij456", + "ABCDEFG123hij456": "ABCDEFG123hij456", + "ABCDEFG123Hij456": "ABCDEFG123Hij456", + "ABCDEFG123HIj456": "ABCDEFG123HIj456", + "ABCDEFG123HIJ456": "ABCDEFG123HIJ456", + "ABCDEFG123HiJ456": "ABCDEFG123HiJ456", + "ABCDEFG123hiJ456": "ABCDEFG123hiJ456", + "ABCDEFG123hIJ456": "ABCDEFG123hIJ456", + "aBcdefg123hij456": "ABcdefg123hij456", + "aBCdefg123hij456": "ABCdefg123hij456", + "aBCDefg123hij456": "ABCDefg123hij456", + "aBCDEfg123hij456": "ABCDEfg123hij456", + "aBCDEFg123hij456": "ABCDEFg123hij456", + "aBCDEFG123hij456": "ABCDEFG123hij456", + "aBcDeFg123hIj456": "ABcDeFg123hIj456", + "HelloWorld!123": "HelloWorld!123", + "MixEDCase$#42": "MixEDCase$#42", + "Snake_Case-Test": "Snake_Case-Test", + "CamelCase99!": "CamelCase99!", + "Python@Rocks2024": "Python@Rocks2024", + "myVariable&*()": "MyVariable&*()", + "Some-Thing#Here": "Some-Thing#Here", + "No$SpacesAllowed99": "No$SpacesAllowed99", + "justA_TestString!": "JustA_TestString!", + "What?Ever*YouSay": "What?Ever*YouSay", + "UserID_789": "UserID_789", + "Go4It-Now!": "Go4It-Now!", + "Check_ME@THIS": "Check_ME@THIS", + "JavaScript$Rules!": "JavaScript$Rules!", + "Best_Choice_2025*": "Best_Choice_2025*", + "Happy_Days": "Happy_Days", + "Let's-Try_This-One!": "Let's-Try_This-One!", + "Make$It$Count24": "Make$It$Count24", + "Code-Lover@Heart": "Code-Lover@Heart", + "Dev&Ops-24/7": "Dev&Ops-24/7", + "Super#Cool_Project": "Super#Cool_Project", + "WhatIs_This?": "WhatIs_This?", + "42AnswerToEverything!": "42AnswerToEverything!", + "API@Version_3.0": "API@Version_3.0", + "Let'sDo_This-Again!": "Let'sDo_This-Again!", + "AI configs (beta) Api": "AI configs (beta) Api", + "AI Configs (beta) Api": "AI Configs (beta) Api", + "AIconfigs (beta) Api": "AIconfigs (beta) Api", + "AIConfigs (beta) Api": "AIConfigs (beta) Api", + "AIConfigs(beta) Api": "AIConfigs(beta) Api", + "AIConfigs(Beta) Api": "AIConfigs(Beta) Api", + "AIConfigsBeta) Api": "AIConfigsBeta) Api", + "AI Configs Beta Api": "AI Configs Beta Api", + "AI configs (BETA) Api": "AI configs (BETA) Api", + "abcd": "Abcd", + "some-value": "Some-value", + "some_value": "Some_value", + "LD-API-Version": "LD-API-Version", + } + + for provided, expected in data.items(): + with self.subTest(provided): + result = parser.NormalizeStr.uc_first(provided) + + self.assertEqual( + first=expected, + second=result, + msg=f"Provided: {provided}, Expected: {expected}, Result: {result}", + ) diff --git a/oseg/tests/test_operation_parser.py b/oseg/tests/test_operation_parser.py new file mode 100644 index 000000000..5ffe29c49 --- /dev/null +++ b/oseg/tests/test_operation_parser.py @@ -0,0 +1,113 @@ +from oseg import parser +from test_utils import TestUtils, TestCase + + +class TestOperationParser(TestCase): + def test_has_form_data(self): + data = [ + "request_x_www_form_urlencoded", + "request_multipart_form_data", + "request_x_www_form_urlencoded_with_ref", + "request_multipart_form_data_with_ref", + "request_x_www_form_urlencoded_and_multipart_form_data", + "request_multipart_form_data_and_x_www_form_urlencoded", + "request_x_www_form_urlencoded_and_application_json", + "request_multipart_form_data_and_application_json", + "request_body_ref_1", + ] + + oa_parser = TestUtils.oa_parser("requests") + + for operation_id in data: + with self.subTest(operation_id): + operation = oa_parser.operations[operation_id] + self.assertTrue(operation.request.has_formdata) + + def test_octet_stream_not_form_data(self): + oa_parser = TestUtils.oa_parser("requests") + operation = oa_parser.operations["request_octet_stream"] + self.assertFalse(operation.request.has_formdata) + + def test_different_responses(self): + data_provider = { + # Most common single response + "single_response": { + "has_response": True, + "is_binary_response": False, + }, + # Most common single response, with error + "single_response_with_error": { + "has_response": True, + "is_binary_response": False, + }, + # Most common single response, with 400 listed before 200 + "single_response_with_error_first": { + "has_response": True, + "is_binary_response": False, + }, + # Multiple response types, all 200s + "multi_response": { + "has_response": True, + "is_binary_response": False, + }, + # Only contains a single 4xx response, should be handled as an exception + "only_400_response": { + "has_response": True, + "is_binary_response": False, + }, + # With binary response, aka file download + "binary_response": { + "has_response": True, + "is_binary_response": True, + }, + # No response + "no_response": { + "has_response": False, + "is_binary_response": False, + }, + # With $ref, single response + "response_ref_1": { + "has_response": True, + "is_binary_response": False, + }, + # With $ref, binary response + "response_ref_2": { + "has_response": True, + "is_binary_response": True, + }, + } + + oa_parser = TestUtils.oa_parser("responses") + + for operation_id, expected in data_provider.items(): + with self.subTest(operation_id): + operation = oa_parser.operations[operation_id] + + self.assertEqual( + bool(operation.response), + expected["has_response"], + ) + + self.assertEqual( + bool(operation.response) and bool(operation.response.is_binary), + expected["is_binary_response"], + ) + + def test_tags(self): + oa_parser = TestUtils.oa_parser("operation") + operation = oa_parser.operations["no_tags"] + self.assertEqual(parser.OperationParser.DEFAULT_API_NAME, operation.api_name) + + expected = "pet" + operation = oa_parser.operations["with_tags"] + self.assertEqual(expected, operation.api_name) + + def test_operation_id_with_special_chars(self): + oa_parser = TestUtils.oa_parser("operation") + operation = oa_parser.operations[ + "security-advisories/list-global-advisories/some_value" + ] + + expected = "security-advisories/list-global-advisories/some_value" + + self.assertEqual(expected, operation.operation_id) diff --git a/oseg/tests/test_property_container.py b/oseg/tests/test_property_container.py new file mode 100644 index 000000000..e9388df26 --- /dev/null +++ b/oseg/tests/test_property_container.py @@ -0,0 +1,283 @@ +from random import randrange +from oseg import model, parser +from test_utils import TestUtils, TestCase + + +class TestPropertyContainer(TestCase): + def test_unique_names_all_required(self): + operation_id = "unique_names_all_required" + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("property_container") + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[example_name] + + properties = container.properties() + + expected = [ + "param_prop_1", + "param_prop_2", + "param_prop_3", + "param_prop_4", + "Pet", + ] + + self.assertListEqual(expected, list(properties)) + + def test_unique_names_some_required(self): + operation_id = "unique_names_some_required" + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("property_container") + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[example_name] + + properties = container.properties() + + expected = [ + "param_prop_1", + "param_prop_4", + "Pet", + "param_prop_2", + "param_prop_3", + ] + + self.assertListEqual(expected, list(properties)) + + def test_conflicting_names(self): + operation_id = "conflicting_names" + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("property_container") + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[example_name] + + properties = container.properties() + + expected = [ + "param_prop", + "param_prop2", + "param_prop3", + "param_prop4", + "Pet", + ] + + self.assertListEqual(expected, list(properties)) + + self.assertEqual("path_prop", properties.get("param_prop").value) + self.assertEqual("query_prop", properties.get("param_prop2").value) + self.assertEqual("header_prop", properties.get("param_prop3").value) + self.assertEqual("cookie_prop", properties.get("param_prop4").value) + + def test_conflicting_names_with_formdata(self): + operation_id = "conflicting_names_with_formdata" + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("property_container") + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[example_name] + + properties = container.properties() + + expected = [ + "param_prop", + "param_prop2", + "param_prop3", + "param_prop4", + "type", # from body object + "type2", # from parameters + "id", + ] + + self.assertListEqual(expected, list(properties)) + + self.assertEqual("path_prop", properties.get("param_prop").value) + self.assertEqual("query_prop", properties.get("param_prop2").value) + self.assertEqual("header_prop", properties.get("param_prop3").value) + self.assertEqual("cookie_prop", properties.get("param_prop4").value) + self.assertEqual("dog", properties.get("type").value) + self.assertEqual(100, properties.get("id").value) + self.assertEqual("query_type_prop", properties.get("type2").value) + + def test_conflicting_names_with_no_formdata(self): + operation_id = "conflicting_names_with_no_formdata" + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("property_container") + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[example_name] + + properties = container.properties() + + expected = [ + "param_prop", + "pet", # from parameters + "Pet2", # body object + ] + + self.assertListEqual(expected, list(properties)) + + self.assertEqual("path_prop", properties.get("param_prop").value) + self.assertEqual("query_prop", properties.get("pet").value) + + self.assertIsInstance( + properties.get("Pet2"), + model.PropertyObject, + ) + + def test_flatten_objects(self): + example_data = { + "example_1": { + "body": { + "id": randrange(1, 100), + "name": "My pet name", + "status": "available", + "photoUrls": [ + "https://example.com/picture_1.jpg", + "https://example.com/picture_2.jpg", + ], + "category": {"id": randrange(1, 100), "name": "Category_Name"}, + "tags": [ + {"id": randrange(1, 100), "name": "tag_1"}, + {"id": randrange(1, 100), "name": "tag_2"}, + ], + } + }, + "example_2": { + "body": { + "id": randrange(1, 100), + "name": "My pet name", + "status": "available", + "photoUrls": [ + "https://example.com/picture_1.jpg", + "https://example.com/picture_2.jpg", + ], + "category": {"id": randrange(1, 100), "name": "Category_Name"}, + } + }, + } + + oa_parser = TestUtils.oa_parser("property_container-flatten") + operation = oa_parser.operations["default"] + operation.request.example_data = example_data + + container_1 = operation.request.example_data.get("example_1") + container_2 = operation.request.example_data.get("example_2") + + parsed_request_objects_1 = container_1.flattened_objects() + parsed_request_objects_2 = container_2.flattened_objects() + + expected_properties_1 = [ + "category", + "tags_1", + "tags_2", + "tags", + "Pet", + ] + + expected_properties_2 = [ + "category", + "tags", + "Pet", + ] + + self.assertListEqual(expected_properties_1, list(parsed_request_objects_1)) + self.assertListEqual(expected_properties_2, list(parsed_request_objects_2)) + + self.assertEqual( + example_data["example_1"]["body"]["category"]["id"], + parsed_request_objects_1.get("category").scalars.get("id").value, + ) + + self.assertEqual( + example_data["example_1"]["body"]["tags"][0]["id"], + parsed_request_objects_1.get("tags_1").scalars.get("id").value, + ) + + self.assertEqual( + example_data["example_1"]["body"]["tags"][1]["id"], + parsed_request_objects_1.get("tags_2").scalars.get("id").value, + ) + + self.assertEqual( + example_data["example_2"]["body"]["category"]["id"], + parsed_request_objects_2.get("category").scalars.get("id").value, + ) + + operation.request.example_data = None + + def test_flatten_nonobjects_ignored(self): + data_provider = [ + "root_level_free_form", + "root_level_free_form_array", + "root_level_string", + "root_level_string_array", + "root_level_int", + "root_level_int_array", + "root_level_file", + "root_level_file_array", + "root_level_bool", + "root_level_bool_array", + ] + + oa_parser = TestUtils.oa_parser("root_level_non_objects") + + for operation_id in data_provider: + with self.subTest(operation_id): + operation = oa_parser.operations[operation_id] + container = operation.request.example_data["example"] + + self.assertEqual({}, container.flattened_objects()) + self.assertTrue(container.has_data) + + def test_sort_nonobjects(self): + data_provider = { + "root_level_free_form": { + "name": "request_body", + "value": {"foo": "bar", "bam": "baz"}, + }, + "root_level_free_form_array": { + "name": "request_body", + "value": [{"foo": "bar", "bam": "baz"}], + }, + "root_level_string": { + "name": "body", + "value": "some string value", + }, + "root_level_string_array": { + "name": "request_body", + "value": ["some string value"], + }, + "root_level_int": { + "name": "body", + "value": 12345, + }, + "root_level_int_array": { + "name": "request_body", + "value": [12345], + }, + "root_level_file": { + "name": "body", + "value": "/some/file/path.pdf", + }, + "root_level_file_array": { + "name": "request_body", + "value": ["/some/file/path.pdf"], + }, + "root_level_bool": { + "name": "body", + "value": True, + }, + "root_level_bool_array": { + "name": "request_body", + "value": [True], + }, + } + + oa_parser = TestUtils.oa_parser("root_level_non_objects") + + for operation_id, expected in data_provider.items(): + with self.subTest(operation_id): + operation = oa_parser.operations[operation_id] + container = operation.request.example_data["example"] + + self.assertEqual( + expected["value"], + container.properties().get(expected["name"]).value, + ) + self.assertTrue(container.has_data) diff --git a/oseg/tests/test_property_parser.py b/oseg/tests/test_property_parser.py new file mode 100644 index 000000000..f666c93a4 --- /dev/null +++ b/oseg/tests/test_property_parser.py @@ -0,0 +1,606 @@ +from oseg import model, parser +from test_utils import TestUtils, TestCase + + +class TestPropertyParser(TestCase): + def test_discriminator(self): + oa_parser = TestUtils.oa_parser("discriminator") + property_parser = parser.PropertyParser(oa_parser) + + data = { + "id": 10000, + "breed": "terrier", + "group": "hunting", + } + + schema = oa_parser.components.schemas.get("Dog") + dog = property_parser.parse( + schema=schema, + data=data, + ) + + expected_properties = [ + "id", + "breed", + "mans_best_friend", + "group", + ] + expected_type = "Terrier" + expected_base_type = "Dog" + + self.assertEqual(set(expected_properties), set(dog.properties)) + self.assertEqual(expected_type, dog.type) + self.assertEqual( + expected_base_type, + dog.base_type, + ) + + self.assertEqual(data["id"], dog.scalars.get("id").value) + self.assertEqual(data["breed"], dog.scalars.get("breed").value) + self.assertEqual(data["group"], dog.scalars.get("group").value) + + def test_discriminator_array(self): + oa_parser = TestUtils.oa_parser("discriminator") + property_parser = parser.PropertyParser(oa_parser) + + data = { + "dogs": [ + { + "id": 10000, + "breed": "terrier", + "group": "hunting", + }, + { + "id": 20000, + "breed": "beagle", + "group": "hound", + }, + ], + } + + schema = oa_parser.components.schemas.get("Dogs") + dogs = property_parser.parse( + schema=schema, + data=data, + ) + + expected_properties = ["dogs"] + expected_type = "Dogs" + expected_base_type = None + expected_property_count = 1 + + self.assertEqual(set(expected_properties), set(dogs.properties)) + self.assertEqual(expected_type, dogs.type) + self.assertEqual( + expected_base_type, + dogs.base_type, + ) + self.assertEqual(expected_property_count, len(dogs.properties)) + + expected_dog_properties = [ + "id", + "breed", + "mans_best_friend", + "group", + ] + + data_provider = [ + { + "type": "Terrier", + "base_type": "Dog", + }, + { + "type": "Beagle", + "base_type": "Dog", + }, + ] + + i = 0 + for datum in data_provider: + with self.subTest(datum["type"]): + dog = dogs.array_objects.get("dogs").properties[i] + expected = data["dogs"][i] + + self.assertEqual( + set(expected_dog_properties), + set(dog.properties), + ) + self.assertEqual(datum["type"], dog.type) + self.assertEqual( + datum["base_type"], + dog.base_type, + ) + + self.assertEqual(expected["id"], dog.scalars.get("id").value) + self.assertEqual( + expected["breed"], + dog.scalars.get("breed").value, + ) + self.assertEqual( + expected["group"], + dog.scalars.get("group").value, + ) + + i += 1 + + def test_discriminator_no_data(self): + """When discriminator field has no value or is not in "mapping" list + instantiate the base Schema without setting discriminator data + """ + + oa_parser = TestUtils.oa_parser("discriminator") + property_parser = parser.PropertyParser(oa_parser) + + data_provider = [ + { + "id": 10000, + }, + { + "id": 10000, + "breed": None, + }, + { + "id": 10000, + "breed": "invalid_breed", + }, + ] + + expected_breed_values = [ + None, + None, + "invalid_breed", + ] + + schema = oa_parser.components.schemas.get("Dog") + + i = 0 + for data in data_provider: + with self.subTest(i): + dog = property_parser.parse( + schema=schema, + data=data, + ) + + expected_properties = [ + "id", + "breed", + "mans_best_friend", + ] + expected_type = "Dog" + expected_base_type = None + + self.assertEqual(set(expected_properties), set(dog.properties)) + self.assertEqual(expected_type, dog.type) + self.assertEqual( + expected_base_type, + dog.base_type, + ) + + self.assertEqual(data["id"], dog.scalars.get("id").value) + self.assertEqual( + expected_breed_values[i], dog.scalars.get("breed").value + ) + + i += 1 + + def test_all_of(self): + """allOf without a discriminator""" + + oa_parser = TestUtils.oa_parser("discriminator") + property_parser = parser.PropertyParser(oa_parser) + + data = { + "id": 10000, + "breed": "terrier", + "group": "hunting", + } + + schema = oa_parser.components.schemas.get("Terrier") + terrier = property_parser.parse( + schema=schema, + data=data, + ) + + expected_properties = [ + "id", + "breed", + "mans_best_friend", + "group", + ] + expected_type = "Terrier" + expected_base_type = None + + self.assertEqual(set(expected_properties), set(terrier.properties)) + self.assertEqual(expected_type, terrier.type) + self.assertEqual( + expected_base_type, + terrier.base_type, + ) + + self.assertEqual(data["id"], terrier.scalars.get("id").value) + self.assertEqual(data["breed"], terrier.scalars.get("breed").value) + self.assertEqual(data["group"], terrier.scalars.get("group").value) + + def test_all_of_array(self): + oa_parser = TestUtils.oa_parser("discriminator") + property_parser = parser.PropertyParser(oa_parser) + + data = { + "terriers": [ + { + "id": 10000, + "breed": "terrier", + "group": "hunting", + }, + { + "id": 20000, + "breed": "terrier", + "group": "hunting", + }, + ], + } + + schema = oa_parser.components.schemas.get("Terriers") + parsed = property_parser.parse( + schema=schema, + data=data, + ) + + expected_properties = ["terriers"] + expected_type = "Terriers" + expected_base_type = None + expected_property_count = 1 + + self.assertEqual(set(expected_properties), set(parsed.properties)) + self.assertEqual(expected_type, parsed.type) + self.assertEqual( + expected_base_type, + parsed.base_type, + ) + self.assertEqual(expected_property_count, len(parsed.properties)) + + expected_terrier_properties = [ + "id", + "breed", + "mans_best_friend", + "group", + ] + + data_provider = [ + { + "type": "Terrier", + "base_type": None, + }, + { + "type": "Terrier", + "base_type": None, + }, + ] + + i = 0 + for datum in data_provider: + with self.subTest(datum["type"]): + terrier = parsed.array_objects.get("terriers").properties[i] + expected = data["terriers"][i] + + self.assertEqual( + set(expected_terrier_properties), + set(terrier.properties), + ) + self.assertEqual(datum["type"], terrier.type) + self.assertEqual( + datum["base_type"], + terrier.base_type, + ) + + self.assertEqual(expected["id"], terrier.scalars.get("id").value) + self.assertEqual( + expected["breed"], + terrier.scalars.get("breed").value, + ) + self.assertEqual( + expected["group"], + terrier.scalars.get("group").value, + ) + + i += 1 + + def test_combined_properties(self): + oa_parser = TestUtils.oa_parser("properties") + property_parser = parser.PropertyParser(oa_parser) + + val_object = {"key_1": "value"} + val_array_object = [{"key_1": "value_1"}, {"key_1": "value_2"}] + val_nested_object = {"key_1": {"key_2": "value"}} + val_array_nested_object = [ + {"key_1": {"key_2": "value_1"}}, + {"key_1": {"key_2": "value_2"}}, + ] + + val_array_string = ["value_1", "value_2"] + val_array_int = [123, 456] + val_array_bool = [True, False] + val_array_file = ["/path_file_1", "/path_file_2"] + val_free_form = {"key_1": "value"} + val_array_free_form = [{"key_1": "value_1"}, {"key_2": "value_2"}] + + data = { + "prop_object": val_object, + "prop_ref_object": val_object, + "prop_array_ref_object": val_array_object, + "prop_nested_object": val_nested_object, + "prop_ref_nested_object": val_nested_object, + "prop_array_ref_nested_object": val_array_nested_object, + "prop_string": "value", + "prop_array_string": val_array_string, + "prop_ref_string": "value", + "prop_array_ref_string": val_array_string, + "prop_integer": 123, + "prop_array_integer": val_array_int, + "prop_ref_integer": 123, + "prop_array_ref_integer": val_array_int, + "prop_number": 123, + "prop_array_number": val_array_int, + "prop_ref_number": 123, + "prop_array_ref_number": val_array_int, + "prop_boolean": True, + "prop_array_boolean": val_array_bool, + "prop_ref_boolean": True, + "prop_array_ref_boolean": val_array_bool, + "prop_file": "/path_file", + "prop_array_file": val_array_file, + "prop_ref_file": "/path_file", + "prop_array_ref_file": val_array_file, + "prop_free_form": val_free_form, + "prop_array_free_form": val_array_free_form, + "prop_ref_free_form": val_free_form, + "prop_array_ref_free_form": val_array_free_form, + } + + schema = oa_parser.components.schemas.get("Pet") + pet = property_parser.parse( + schema=schema, + data=data, + ) + + self.assertEqual(set(data), set(pet.properties)) + + non_object_props = [ + "prop_string", + "prop_array_string", + "prop_ref_string", + "prop_array_ref_string", + "prop_integer", + "prop_array_integer", + "prop_ref_integer", + "prop_array_ref_integer", + "prop_number", + "prop_array_number", + "prop_ref_number", + "prop_array_ref_number", + "prop_boolean", + "prop_array_boolean", + "prop_ref_boolean", + "prop_array_ref_boolean", + "prop_file", + "prop_array_file", + "prop_ref_file", + "prop_array_ref_file", + "prop_free_form", + "prop_array_free_form", + "prop_ref_free_form", + "prop_array_ref_free_form", + ] + + for name in non_object_props: + with self.subTest(name): + value = data[name] + + self.assertEqual(value, pet.properties.get(name).value) + + prop_object = pet.objects.get("prop_object") + self.assertEqual("Pet_prop_object", prop_object.type) + self.assertEqual( + prop_object.scalars.get("key_1").value, + val_object["key_1"], + ) + + prop_ref_object = pet.objects.get("prop_ref_object") + self.assertEqual("PropRefObject", prop_ref_object.type) + self.assertEqual( + prop_ref_object.scalars.get("key_1").value, + val_object["key_1"], + ) + + prop_array_ref_object_1 = pet.array_objects.get( + "prop_array_ref_object" + ).properties[0] + self.assertEqual("PropRefObject", prop_array_ref_object_1.type) + self.assertEqual( + prop_array_ref_object_1.scalars.get("key_1").value, + val_array_object[0]["key_1"], + ) + + prop_array_ref_object_2 = pet.array_objects.get( + "prop_array_ref_object" + ).properties[1] + self.assertEqual("PropRefObject", prop_array_ref_object_2.type) + self.assertEqual( + prop_array_ref_object_2.scalars.get("key_1").value, + val_array_object[1]["key_1"], + ) + + prop_nested_object = pet.objects.get("prop_nested_object") + self.assertEqual("Pet_prop_nested_object", prop_nested_object.type) + prop_nested_object_key_1 = prop_nested_object.objects.get("key_1") + self.assertEqual("Pet_prop_nested_object_key_1", prop_nested_object_key_1.type) + self.assertEqual( + prop_nested_object_key_1.scalars.get("key_2").value, + val_nested_object["key_1"]["key_2"], + ) + + prop_ref_nested_object = pet.objects.get("prop_ref_nested_object") + self.assertEqual("PropRefNestedObject", prop_ref_nested_object.type) + prop_ref_nested_object_key_1 = prop_ref_nested_object.objects.get("key_1") + self.assertEqual("PropRefNestedObject_key_1", prop_ref_nested_object_key_1.type) + self.assertEqual( + prop_ref_nested_object_key_1.scalars.get("key_2").value, + val_nested_object["key_1"]["key_2"], + ) + + prop_array_ref_nested_object_1 = pet.array_objects.get( + "prop_array_ref_nested_object" + ).properties[0] + self.assertEqual("PropRefNestedObject", prop_array_ref_nested_object_1.type) + prop_array_ref_nested_object_1_key_1 = ( + prop_array_ref_nested_object_1.objects.get("key_1") + ) + self.assertEqual( + "PropRefNestedObject_key_1", prop_array_ref_nested_object_1_key_1.type + ) + self.assertEqual( + prop_array_ref_nested_object_1_key_1.scalars.get("key_2").value, + val_array_nested_object[0]["key_1"]["key_2"], + ) + + prop_array_ref_nested_object_2 = pet.array_objects.get( + "prop_array_ref_nested_object" + ).properties[1] + self.assertEqual("PropRefNestedObject", prop_array_ref_nested_object_2.type) + prop_array_ref_nested_object_2_key_1 = ( + prop_array_ref_nested_object_2.objects.get("key_1") + ) + self.assertEqual( + "PropRefNestedObject_key_1", prop_array_ref_nested_object_2_key_1.type + ) + self.assertEqual( + prop_array_ref_nested_object_2_key_1.scalars.get("key_2").value, + val_array_nested_object[1]["key_1"]["key_2"], + ) + + def test_non_named_parameter_object(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["default"] + example_data = operation.request.example_data[example_name] + + free_form_obj = example_data.query.free_forms["paramComponentObject"] + array_free_form_obj = example_data.query.array_free_forms[ + "paramComponentArrayObject" + ] + + self.assertIsInstance(free_form_obj, model.PropertyFreeForm) + self.assertIsInstance(array_free_form_obj, model.PropertyFreeForm) + + self.assertFalse(free_form_obj.is_array) + self.assertTrue(array_free_form_obj.is_array) + + def test_property_sorting(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["sorted"] + example_data = operation.request.example_data[example_name] + + expected_properties_1 = [ + "petId", + "queryParam", + "try", + "while", + "with", + "Dog", + ] + + self.assertListEqual(expected_properties_1, list(example_data.properties())) + + def test_property_sorting_formdata(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["sorted_formdata"] + example_data = operation.request.example_data[example_name] + + expected_properties_1 = [ + "petId", + "name", + "photoUrls", + "queryParam", + "try", + "while", + "with", + "id", + "category", + "tags", + "status", + "try2", + "while2", + "with2", + "configuration", + "version", + ] + + self.assertListEqual(expected_properties_1, list(example_data.properties())) + + def test_root_level_nonobjects(self): + data_provider = { + "FreeFormSchema": { + "type": model.PropertyFreeForm, + "value": {"some_key": "some_value"}, + }, + "FreeFormSchemaArray": { + "type": model.PropertyFreeForm, + "value": [{"some_key": "some_value"}], + }, + "StringSchema": { + "type": model.PropertyScalar, + "value": "foo bar", + }, + "StringSchemaArray": { + "type": model.PropertyScalar, + "value": ["foo bar"], + }, + "IntSchema": { + "type": model.PropertyScalar, + "value": 654321, + }, + "IntSchemaArray": { + "type": model.PropertyScalar, + "value": [654321], + }, + "FileSchema": { + "type": model.PropertyFile, + "value": "/path.pdf", + }, + "FileSchemaArray": { + "type": model.PropertyFile, + "value": ["/path.pdf"], + }, + "BoolSchema": { + "type": model.PropertyScalar, + "value": False, + }, + "BoolSchemaArray": { + "type": model.PropertyScalar, + "value": [False], + }, + } + + oa_parser = TestUtils.oa_parser("root_level_non_objects") + property_parser = parser.PropertyParser(oa_parser) + + for name, expected in data_provider.items(): + with self.subTest(name): + schema = oa_parser.components.schemas.get(name) + parsed = property_parser.parse(schema, expected["value"]) + + self.assertEqual(expected["value"], parsed.value) + self.assertIsInstance(parsed, expected["type"]) + + def test_free_form_string_object_value(self): + example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations["free_form_string_object_value"] + example_data = operation.request.example_data[example_name] + + result = example_data.body.free_forms.get("prop_object").value + expected = {} + + self.assertEqual(expected, result) diff --git a/oseg/tests/test_schema_joiner.py b/oseg/tests/test_schema_joiner.py new file mode 100644 index 000000000..4fa9fb2da --- /dev/null +++ b/oseg/tests/test_schema_joiner.py @@ -0,0 +1,154 @@ +from oseg import parser +from test_utils import TestUtils, TestCase + + +class TestSchemaJoiner(TestCase): + def test_no_all_of_no_discriminator(self): + data = { + "id": 123, + "type": "dog", + } + + oa_parser = TestUtils.oa_parser("discriminator") + schema_joiner = parser.SchemaJoiner(oa_parser) + pet = oa_parser.components.schemas.get("Pet") + joined = schema_joiner.merge_schemas_and_properties(pet, data) + + expected_discriminator_target_type = None + expected_schema_count = 1 + + self.assertEqual( + expected_discriminator_target_type, + joined.discriminator_target_type, + ) + self.assertListEqual(list(data), list(joined.properties)) + self.assertEqual(expected_schema_count, len(joined.schemas)) + self.assertEqual(pet, joined.schemas[0]) + + def test_discriminator(self): + """When using a Discriminator, the joined schemas will reference the + target's "allOff" values. + + Any $ref will be resolved, so the actual Schema definition in the OAS + file will not match the result from SchemaJoiner. + + This is why below we assert that the first schema is Dog and second + schema we reference Terrier.allOf[1] instead of schema Terrier. + + Terrier: + allOf: + - $ref: '#/components/schemas/Dog' + - + type: object + properties: + group: + type: string + default: hunting + + We resolve "$ref: '#/components/schemas/Dog'" to schema Dog, + and say that joined.schemas[1] == terrier.allOf[1] + """ + + data = { + "id": 123, + "breed": "terrier", + "group": "hunting", + "mans_best_friend": True, + } + + oa_parser = TestUtils.oa_parser("discriminator") + schema_joiner = parser.SchemaJoiner(oa_parser) + dog = oa_parser.components.schemas.get("Dog") + terrier = oa_parser.components.schemas.get("Terrier") + joined = schema_joiner.merge_schemas_and_properties(dog, data) + + expected_discriminator_target_type = "Terrier" + expected_schema_count = 2 + + self.assertEqual( + expected_discriminator_target_type, + joined.discriminator_target_type, + ) + self.assertEqual(set(data), set(joined.properties)) + self.assertEqual(expected_schema_count, len(joined.schemas)) + self.assertEqual(dog, joined.schemas[0]) + self.assertEqual(terrier.allOf[1], joined.schemas[1]) + + def test_discriminator_no_data(self): + """Invalid discriminator value will simply return the discriminator + Schema.""" + + datum = [ + None, + {"breed": "invalid_breed"}, + ] + + oa_parser = TestUtils.oa_parser("discriminator") + schema_joiner = parser.SchemaJoiner(oa_parser) + dog = oa_parser.components.schemas.get("Dog") + + i = 0 + for data in datum: + with self.subTest(i): + joined = schema_joiner.merge_schemas_and_properties(dog, data) + + expected_discriminator_target_type = None + expected_properties = [ + "id", + "breed", + "mans_best_friend", + ] + expected_schema_count = 1 + + self.assertEqual( + expected_discriminator_target_type, + joined.discriminator_target_type, + ) + self.assertEqual(set(expected_properties), set(joined.properties)) + self.assertEqual(expected_schema_count, len(joined.schemas)) + self.assertEqual(dog, joined.schemas[0]) + + i += 1 + + def test_all_of(self): + """allOf without a discriminator""" + + datum = [ + None, + { + "id": 123, + "breed": "terrier", + "group": "hunting", + "mans_best_friend": True, + }, + ] + + oa_parser = TestUtils.oa_parser("discriminator") + schema_joiner = parser.SchemaJoiner(oa_parser) + dog = oa_parser.components.schemas.get("Dog") + terrier = oa_parser.components.schemas.get("Terrier") + + i = 0 + for data in datum: + with self.subTest(i): + joined = schema_joiner.merge_schemas_and_properties(terrier, data) + + expected_discriminator_target_type = None + expected_properties = [ + "id", + "breed", + "group", + "mans_best_friend", + ] + expected_schema_count = 2 + + self.assertEqual( + expected_discriminator_target_type, + joined.discriminator_target_type, + ) + self.assertEqual(set(expected_properties), set(joined.properties)) + self.assertEqual(expected_schema_count, len(joined.schemas)) + self.assertEqual(dog, joined.schemas[0]) + self.assertEqual(terrier.allOf[1], joined.schemas[1]) + + i += 1 diff --git a/oseg/tests/test_security.py b/oseg/tests/test_security.py new file mode 100644 index 000000000..1ebc05d22 --- /dev/null +++ b/oseg/tests/test_security.py @@ -0,0 +1,113 @@ +from oseg import model +from test_utils import TestUtils, TestCase + + +class TestSecurity(TestCase): + def test_security_all(self): + oa_parser = TestUtils.oa_parser("security_schemes") + operation = oa_parser.operations.get("security_all") + + expected = [ + ["api_key_scheme"], + ["http_basic_scheme"], + ["http_bearer_scheme"], + ["oauth2_scheme"], + ] + + result = [ + list(operation.security.schemes[0]), + list(operation.security.schemes[1]), + list(operation.security.schemes[2]), + list(operation.security.schemes[3]), + ] + + self.assertEqual(expected, result) + self.assertFalse(operation.security.is_optional) + self.assertTrue(len(operation.security.schemes) == 4) + + def test_correct_method(self): + oa_parser = TestUtils.oa_parser("security_schemes") + operation = oa_parser.operations.get("security_all") + + self.assertEqual( + model.SecurityMethod.API_KEY, + operation.security.schemes[0]["api_key_scheme"].method, + ) + + self.assertEqual( + model.SecurityMethod.BASIC, + operation.security.schemes[1]["http_basic_scheme"].method, + ) + + self.assertEqual( + model.SecurityMethod.ACCESS_TOKEN, + operation.security.schemes[2]["http_bearer_scheme"].method, + ) + + self.assertEqual( + model.SecurityMethod.ACCESS_TOKEN, + operation.security.schemes[3]["oauth2_scheme"].method, + ) + + def test_security_optional(self): + oa_parser = TestUtils.oa_parser("security_schemes") + operation = oa_parser.operations.get("security_optional") + + self.assertTrue(operation.security.is_optional) + self.assertTrue(len(operation.security.schemes) == 4) + + def test_security_override(self): + oa_parser = TestUtils.oa_parser("security_schemes") + operation = oa_parser.operations.get("security_override") + + expected = [ + ["http_basic_scheme"], + ] + + result = [ + list(operation.security.schemes[0]), + ] + + self.assertEqual(expected, result) + self.assertFalse(operation.security.is_optional) + self.assertTrue(len(operation.security.schemes) == 1) + + def test_security_disabled(self): + oa_parser = TestUtils.oa_parser("security_schemes") + operation = oa_parser.operations.get("security_disabled") + + self.assertTrue(len(operation.security.schemes) == 0) + + def test_security_and(self): + oa_parser = TestUtils.oa_parser("security_schemes") + operation = oa_parser.operations.get("security_and") + + expected = [ + ["api_key_scheme", "http_basic_scheme"], + ] + + result = [ + list(operation.security.schemes[0]), + ] + + self.assertEqual(expected, result) + self.assertFalse(operation.security.is_optional) + self.assertTrue(len(operation.security.schemes) == 1) + + def test_security_or(self): + oa_parser = TestUtils.oa_parser("security_schemes") + operation = oa_parser.operations.get("security_or") + + expected = [ + ["api_key_scheme"], + ["http_basic_scheme"], + ] + + result = [ + list(operation.security.schemes[0]), + list(operation.security.schemes[1]), + ] + + self.assertEqual(expected, result) + self.assertFalse(operation.security.is_optional) + self.assertTrue(len(operation.security.schemes) == 2) diff --git a/oseg/tests/test_template_parser.py b/oseg/tests/test_template_parser.py new file mode 100644 index 000000000..a2a25a7ea --- /dev/null +++ b/oseg/tests/test_template_parser.py @@ -0,0 +1,1020 @@ +from test_utils import TestUtils, TestCase +from fixtures.mock_generator import MockConfig, MockGenerator, JINJA_MACROS +from oseg import model, parser + + +class TestTemplateParser(TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.jinja_macros = model.JinjaMacros(JINJA_MACROS) + config_data = parser.FileLoader.get_file_contents( + f"{TestUtils._BASE_DIR}/fixtures/config-mock.yaml" + ) + cls.config = MockConfig(config_data.get("additionalProperties", {})) + cls.example_name = parser.ExampleDataParser.DEFAULT_EXAMPLE_NAME + + def test_parse_objects(self): + operation_id = "sorted" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_data() + container = operation.request.example_data[self.example_name] + + sdk_generator = MockGenerator(self.config, operation, container) + + expected = { + "category": "Category", + "tags_1": "Tag", + "tags_2": "Tag", + "tags": "Tag", + "Dog": "Dog", + } + + result = sdk_generator.template_parser.parse_objects() + + self.assertEqual(list(expected), list(result)) + + for name, original_name in expected.items(): + self.assertEqual(original_name, result[name].original_name) + + operation.request.example_data = None + + def test_parse_objects_skips_null_objects(self): + data_provider = { + "category": { + "tags_1": "Tag", + "tags_2": "Tag", + "tags": "Tag", + "Dog": "Dog", + }, + "tags": { + "category": "Category", + "Dog": "Dog", + }, + } + + oa_parser = TestUtils.oa_parser("properties") + + for to_delete, expected in data_provider.items(): + with self.subTest(to_delete): + example_name = self.example_name + example_data = self._example_data() + + del example_data[example_name]["body"][to_delete] + + operation_id = "sorted" + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = example_data + container = operation.request.example_data[example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + result = sdk_generator.template_parser.parse_objects() + + self.assertEqual(list(expected), list(result)) + + for name, original_name in expected.items(): + self.assertEqual(original_name, result[name].original_name) + + operation.request.example_data = None + + def test_parse_objects_does_not_use_same_name_when_multiple_of_object(self): + operation_id = "multiple_dogs" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_multiple_dog_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected = { + "dog_2_category": "Category", + "dog_2_tags_1": "Tag", + "dog_2_tags_2": "Tag", + "dog_2_tags": "Tag", + "dog_1_category": "Category", + "dog_1_tags_1": "Tag", + "dog_1_tags_2": "Tag", + "dog_1_tags": "Tag", + "dog_1": "Dog", + "dog_2": "Dog", + "MultipleDogs": "MultipleDogs", + } + + result = sdk_generator.template_parser.parse_objects() + + self.assertEqual(list(expected), list(result)) + + for name, original_name in expected.items(): + self.assertEqual(original_name, result[name].original_name) + + operation.request.example_data = None + + def test_parse_objects_does_not_use_same_name_when_array_of_object(self): + operation_id = "array_dogs" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_array_dog_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected = { + "Dog_2_category": "Category", + "Dog_2_tags_1": "Tag", + "Dog_2_tags_2": "Tag", + "Dog_2_tags": "Tag", + "Dog_1_category": "Category", + "Dog_1_tags_1": "Tag", + "Dog_1_tags_2": "Tag", + "Dog_1_tags": "Tag", + "Dog_1": "Dog", + "Dog_2": "Dog", + "Dog": "Dog", + } + + result = sdk_generator.template_parser.parse_objects() + + self.assertEqual(list(expected), list(result)) + + for name, original_name in expected.items(): + self.assertEqual(original_name, result[name].original_name) + + operation.request.example_data = None + + def test_parse_object_properties(self): + operation_id = "sorted" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + body_data = self._example_data()[self.example_name]["body"] + + root_properties = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=container.body, + indent_count=0, + ) + + expected = { + "name": body_data["name"], + "photoUrls": f"[{body_data["photoUrls"][0]},{body_data["photoUrls"][1]}]", + "id": str(body_data["id"]), + "status": body_data["status"], + "category": "category", + "tags": "tags", + "var_try": body_data["try"], + "var_while": body_data["while"], + "var_with": body_data["with"], + "var_configuration": body_data["configuration"], + "var_version": body_data["version"], + } + + self.assertDictEqual(expected, root_properties) + + category_properties = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=container.body.objects.get("category"), + indent_count=0, + ) + + expected = { + "id": str(body_data["category"]["id"]), + "name": body_data["category"]["name"], + } + + self.assertDictEqual(expected, category_properties) + + operation.request.example_data = None + + def test_parse_object_properties_skip_unset(self): + body_data = self._example_data()[self.example_name]["body"] + + default_expected = { + "name": body_data["name"], + "photoUrls": f"[{body_data["photoUrls"][0]},{body_data["photoUrls"][1]}]", + "id": str(body_data["id"]), + "status": body_data["status"], + "category": "category", + "tags": "tags", + "var_try": body_data["try"], + "var_while": body_data["while"], + "var_with": body_data["with"], + "var_configuration": body_data["configuration"], + "var_version": body_data["version"], + } + + data_provider = { + "id": { + "name": default_expected["name"], + "photoUrls": default_expected["photoUrls"], + "status": default_expected["status"], + "category": default_expected["category"], + "tags": default_expected["tags"], + "var_try": default_expected["var_try"], + "var_while": default_expected["var_while"], + "var_with": default_expected["var_with"], + "var_configuration": default_expected["var_configuration"], + "var_version": default_expected["var_version"], + }, + "status": { + "name": default_expected["name"], + "photoUrls": default_expected["photoUrls"], + "id": default_expected["id"], + "category": default_expected["category"], + "tags": default_expected["tags"], + "var_try": default_expected["var_try"], + "var_while": default_expected["var_while"], + "var_with": default_expected["var_with"], + "var_configuration": default_expected["var_configuration"], + "var_version": default_expected["var_version"], + }, + } + + oa_parser = TestUtils.oa_parser("properties") + + for to_delete, expected in data_provider.items(): + with self.subTest(to_delete): + example_name = self.example_name + example_data = self._example_data() + + del example_data[example_name]["body"][to_delete] + + operation_id = "sorted" + operation = oa_parser.operations.get(operation_id) + + operation.request.example_data = example_data + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + root_properties = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=container.body, + indent_count=0, + ) + + self.assertDictEqual(expected, root_properties) + + operation.request.example_data = None + + def test_parse_object_properties_does_not_skip_unset_required(self): + body_data = self._example_data()[self.example_name]["body"] + + expected = { + "name": "name_string", + "photoUrls": f"[{body_data["photoUrls"][0]},{body_data["photoUrls"][1]}]", + "id": str(body_data["id"]), + "status": body_data["status"], + "category": "category", + "tags": "tags", + "var_try": body_data["try"], + "var_while": body_data["while"], + "var_with": body_data["with"], + "var_configuration": body_data["configuration"], + "var_version": body_data["version"], + } + + example_name = self.example_name + example_data = self._example_data() + + del example_data[example_name]["body"]["name"] + + operation_id = "sorted" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + + operation.request.example_data = example_data + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + root_properties = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=container.body, + indent_count=0, + ) + + self.assertDictEqual(expected, root_properties) + + operation.request.example_data = None + + def test_parse_object_properties_skips_null_optional(self): + body_data = self._example_data()[self.example_name]["body"] + + expected = { + "name": body_data["name"], + "photoUrls": f"[{body_data["photoUrls"][0]},{body_data["photoUrls"][1]}]", + "status": body_data["status"], + "category": "category", + "tags": "tags", + "var_try": body_data["try"], + "var_while": body_data["while"], + "var_with": body_data["with"], + "var_configuration": body_data["configuration"], + "var_version": body_data["version"], + } + + example_name = self.example_name + example_data = self._example_data() + + example_data[example_name]["body"]["id"] = None + + operation_id = "sorted" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + + operation.request.example_data = example_data + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + root_properties = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=container.body, + indent_count=0, + ) + + self.assertDictEqual(expected, root_properties) + + operation.request.example_data = None + + def test_parse_object_properties_does_not_use_same_name_when_multiple_of_object( + self, + ): + operation_id = "multiple_dogs" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_multiple_dog_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected = { + "dog_2_category": ["id", "name"], + "dog_2_tags_1": ["id", "name"], + "dog_2_tags_2": ["id", "name"], + "dog_1_category": ["id", "name"], + "dog_1_tags_1": ["id", "name"], + "dog_1_tags_2": ["id", "name"], + "dog_1": [ + "name", + "photoUrls", + "id", + "status", + "var_try", + "var_while", + "var_with", + "category", + "tags", + ], + "dog_2": [ + "name", + "photoUrls", + "id", + "status", + "var_try", + "var_while", + "var_with", + "category", + "tags", + ], + "MultipleDogs": ["dog_1", "dog_2"], + } + + parsed_objects = sdk_generator.template_parser.parse_objects() + + for obj_name, obj in parsed_objects.items(): + if obj.is_array: + continue + + result = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=obj, + indent_count=0, + ) + + self.assertEqual(expected[obj_name], list(result)) + + operation.request.example_data = None + + def test_parse_object_properties_does_not_use_same_name_when_array_of_object( + self, + ): + operation_id = "array_dogs" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_array_dog_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected = { + "Dog_2_category": ["id", "name"], + "Dog_2_tags_1": ["id", "name"], + "Dog_2_tags_2": ["id", "name"], + "Dog_1_category": ["id", "name"], + "Dog_1_tags_1": ["id", "name"], + "Dog_1_tags_2": ["id", "name"], + "Dog_1": [ + "name", + "photoUrls", + "id", + "status", + "var_try", + "var_while", + "var_with", + "category", + "tags", + ], + "Dog_2": [ + "name", + "photoUrls", + "id", + "status", + "var_try", + "var_while", + "var_with", + "category", + "tags", + ], + "Dog": ["dog_1", "dog_2"], + } + + parsed_objects = sdk_generator.template_parser.parse_objects() + + for obj_name, obj in parsed_objects.items(): + if obj.is_array: + continue + + result = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=obj, + indent_count=0, + ) + + self.assertEqual(expected[obj_name], list(result)) + + operation.request.example_data = None + + def test_parse_object_list_properties(self): + operation_id = "sorted" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected = "[tag,tag]" + + tags_properties = sdk_generator.template_parser.parse_object_list_properties( + macros=self.jinja_macros, + parent=container.body.array_objects.get("tags"), + indent_count=0, + ) + + self.assertEqual(expected, tags_properties) + + operation.request.example_data = None + + def test_parse_object_list_properties_does_not_use_same_name_when_multiple_of_object( + self, + ): + operation_id = "multiple_dogs" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_multiple_dog_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected = { + "dog_2_tags": "[dog_2_tags_1,dog_2_tags_2]", + "dog_1_tags": "[dog_1_tags_1,dog_1_tags_2]", + } + + parsed_objects = sdk_generator.template_parser.parse_objects() + + for obj_name, obj in parsed_objects.items(): + if not obj.is_array: + continue + + result = sdk_generator.template_parser.parse_object_list_properties( + macros=self.jinja_macros, + parent=obj, + indent_count=0, + ) + + self.assertEqual(expected[obj_name], result) + + operation.request.example_data = None + + def test_parse_object_list_properties_does_not_use_same_name_when_array_of_object( + self, + ): + operation_id = "array_dogs" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_array_dog_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected = { + "Dog_2_tags": "[dog_2_tags_1,dog_2_tags_2]", + "Dog_1_tags": "[dog_1_tags_1,dog_1_tags_2]", + "Dog": "[dog_1,dog_2]", + } + + parsed_objects = sdk_generator.template_parser.parse_objects() + + for obj_name, obj in parsed_objects.items(): + if not obj.is_array: + continue + + result = sdk_generator.template_parser.parse_object_list_properties( + macros=self.jinja_macros, + parent=obj, + indent_count=0, + ) + + self.assertEqual(expected[obj_name], result) + + operation.request.example_data = None + + def test_parse_api_call_properties(self): + operation_id = "sorted" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + path_data = self._example_data()[self.example_name]["path"] + query_data = self._example_data()[self.example_name]["query"] + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + expected = { + "petId": str(path_data["petId"]), + "queryParam": str(query_data["queryParam"]), + "var_try": query_data["try"], + "var_while": query_data["while"], + "var_with": query_data["with"], + "Dog": "dog", + } + + self.assertDictEqual(expected, api_call_properties) + + operation.request.example_data = None + + def test_parse_api_call_properties_formdata(self): + operation_id = "sorted_formdata" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + body_data = self._example_data()[self.example_name]["body"] + path_data = self._example_data()[self.example_name]["path"] + query_data = self._example_data()[self.example_name]["query"] + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + expected = { + "petId": str(path_data["petId"]), + "name": body_data["name"], + "photoUrls": f"[{body_data["photoUrls"][0]},{body_data["photoUrls"][1]}]", + "queryParam": str(query_data["queryParam"]), + "var_try": query_data["try"], + "var_while": query_data["while"], + "var_with": query_data["with"], + "id": str(body_data["id"]), + "category": "category", + "tags": "tags", + "status": body_data["status"], + "var_try2": body_data["try"], + "var_while2": body_data["while"], + "var_with2": body_data["with"], + "configuration": body_data["configuration"], + "version": body_data["version"], + } + + self.assertEqual(expected, api_call_properties) + + operation.request.example_data = None + + def test_parse_api_call_root_level_non_objects(self): + data_provider = { + "root_level_free_form": { + "name": "request_body", + "value": {"bam": "baz"}, + "expected": {"request_body": "{'bam': 'baz'}"}, + }, + "root_level_string": { + "name": "body", + "value": "some string value", + "expected": {"body": "some string value"}, + }, + "root_level_int": { + "name": "body", + "value": 12345, + "expected": {"body": "12345"}, + }, + "root_level_file": { + "name": "body", + "value": "/some/file/path.pdf", + "expected": {"body": "/some/file/path.pdf"}, + }, + "root_level_bool": { + "name": "body", + "value": True, + "expected": {"body": "true"}, + }, + } + + oa_parser = TestUtils.oa_parser("root_level_non_objects") + + for operation_id, data in data_provider.items(): + with self.subTest(operation_id): + example_data = { + self.example_name: { + "body": data["value"], + }, + } + + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = example_data + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + api_call_properties = ( + sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + ) + + self.assertEqual(data["expected"], api_call_properties) + + operation.request.example_data = None + + def test_parse_api_call_properties_skip_parameters_no_data_not_required(self): + operation_id = "parameters_no_values_not_required" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + expected = {} + + self.assertDictEqual(expected, api_call_properties) + + def test_parse_api_call_properties_skip_parameters_no_data_required(self): + operation_id = "parameters_no_values_required" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + expected = { + "param_2": "param_2_string", + "param_1": "null", + "param_3": "null", + } + + self.assertDictEqual(expected, api_call_properties) + + def test_parse_api_call_properties_print_none_for_empty_body_property(self): + operation_id = "parameters_and_required_body" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = { + self.example_name: { + "query": { + "param_1": "foo", + }, + }, + } + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + expected = { + "param_1": "foo", + "key_1": "None", + } + + self.assertDictEqual(expected, api_call_properties) + + operation.request.example_data = None + + def test_parse_security(self): + oa_parser = TestUtils.oa_parser("security_schemes") + security_config = self.config.oseg.security + + schemes = { + "api_key_scheme": f"api_key: {security_config["api_key_scheme.api_key"]}", + "http_basic_scheme": f"basic: {security_config["http_basic_scheme.username"]}:{security_config["http_basic_scheme.password"]}", + "http_bearer_scheme": f"access_token: {security_config["http_bearer_scheme.access_token"]}", + "oauth2_scheme": f"access_token: {security_config["oauth2_scheme.access_token"]}", + } + + schemes_commented = { + "api_key_scheme": f"# api_key: {security_config["api_key_scheme.api_key"]}", + "http_basic_scheme": f"# basic: {security_config["http_basic_scheme.username"]}:{security_config["http_basic_scheme.password"]}", + "http_bearer_scheme": f"# access_token: {security_config["http_bearer_scheme.access_token"]}", + "oauth2_scheme": f"# access_token: {security_config["oauth2_scheme.access_token"]}", + } + + data_provider = { + "security_all": { + "api_key_scheme": schemes["api_key_scheme"], + "http_basic_scheme": schemes_commented["http_basic_scheme"], + "http_bearer_scheme": schemes_commented["http_bearer_scheme"], + "oauth2_scheme": schemes_commented["oauth2_scheme"], + }, + "security_disabled": {}, + "security_and": { + "api_key_scheme": schemes["api_key_scheme"], + "http_basic_scheme": schemes["http_basic_scheme"], + }, + } + + for operation_id, expected in data_provider.items(): + with self.subTest(operation_id): + operation = oa_parser.operations.get(operation_id) + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + result = sdk_generator.template_parser.parse_security( + macros=self.jinja_macros, + indent_count=0, + ) + + self.assertEqual(expected, result) + + def test_codegen_request_body_name(self): + operation_id = "codegen_request_body_name_json" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + path_data = self._example_data()[self.example_name]["path"] + query_data = self._example_data()[self.example_name]["query"] + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + expected = { + "petId": str(path_data["petId"]), + "queryParam": str(query_data["queryParam"]), + "var_try": query_data["try"], + "var_while": query_data["while"], + "var_with": query_data["with"], + "some_new_name": "dog", + } + + self.assertDictEqual(expected, api_call_properties) + + operation.request.example_data = None + + def test_codegen_request_body_name_formdata(self): + operation_id = "codegen_request_body_name_formdata" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + operation.request.example_data = self._example_data() + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + body_data = self._example_data()[self.example_name]["body"] + path_data = self._example_data()[self.example_name]["path"] + query_data = self._example_data()[self.example_name]["query"] + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + expected = { + "petId": str(path_data["petId"]), + "name": body_data["name"], + "photoUrls": f"[{body_data["photoUrls"][0]},{body_data["photoUrls"][1]}]", + "queryParam": str(query_data["queryParam"]), + "var_try": query_data["try"], + "var_while": query_data["while"], + "var_with": query_data["with"], + "id": str(body_data["id"]), + "category": "category", + "tags": "tags", + "status": body_data["status"], + "var_try2": body_data["try"], + "var_while2": body_data["while"], + "var_with2": body_data["with"], + "configuration": body_data["configuration"], + "version": body_data["version"], + } + + self.assertEqual(expected, api_call_properties) + + operation.request.example_data = None + + def test_non_nullable_non_object_gets_default_value(self): + operation_id = "property_with_all_required_for_default_value" + oa_parser = TestUtils.oa_parser("properties") + operation = oa_parser.operations.get(operation_id) + + container = operation.request.example_data[self.example_name] + sdk_generator = MockGenerator(self.config, operation, container) + + expected_api_properties = { + "petId": "0", + "queryParam": "null", + "var_try": "foo", + "var_while": "foo", + "var_with": "foo", + "PropertyWithAllRequiredForDefaultValue": "property_with_all_required_for_default_value", + } + + expected_object_properties = { + "id": "0", + "name": "name_string", + "is_available": "false", + "status": "available", + "photoUrls": "[]", + } + + api_call_properties = sdk_generator.template_parser.parse_api_call_properties( + macros=self.jinja_macros, + indent_count=0, + ) + + object_properties = sdk_generator.template_parser.parse_object_properties( + macros=self.jinja_macros, + parent=container.body, + indent_count=0, + ) + + self.assertEqual(expected_api_properties, api_call_properties) + self.assertEqual(expected_object_properties, object_properties) + + # todo test print_file + + # todo test print_free_form + + # todo test _get_enum_varname + + # todo test _get_enum_varname_override + + @classmethod + def _example_data(cls) -> dict[str, dict[str, any]]: + return { + cls.example_name: { + "path": { + "petId": 101, + }, + "query": { + "queryParam": 102, + "try": "query_try_value", + "while": "query_while_value", + "with": "query_with_value", + }, + "body": { + "id": 103, + "name": "My pet name", + "status": "available", + "photoUrls": [ + "https://example.com/picture_1.jpg", + "https://example.com/picture_2.jpg", + ], + "category": { + "id": 104, + "name": "Category_Name", + }, + "tags": [ + {"id": 105, "name": "tag_1"}, + {"id": 106, "name": "tag_2"}, + ], + "try": "body_try_value", + "while": "body_while_value", + "with": "body_with_value", + "configuration": "configuration_value", + "version": "version_value", + }, + } + } + + @classmethod + def _example_multiple_dog_data(cls) -> dict[str, dict[str, any]]: + return { + cls.example_name: { + "body": { + "dog_1": { + "id": 103, + "name": "My pet name #1", + "status": "available", + "photoUrls": [ + "https://example.com/picture_1.jpg", + "https://example.com/picture_2.jpg", + ], + "category": { + "id": 104, + "name": "Category_Name_1", + }, + "tags": [ + {"id": 105, "name": "tag_1"}, + {"id": 106, "name": "tag_2"}, + ], + "try": "body_try_value_1", + "while": "body_while_value_1", + "with": "body_with_value_1", + }, + "dog_2": { + "id": 107, + "name": "My pet name #2", + "status": "pending", + "photoUrls": [ + "https://example.com/picture_3.jpg", + "https://example.com/picture_4.jpg", + ], + "category": { + "id": 108, + "name": "Category_Name_2", + }, + "tags": [ + {"id": 109, "name": "tag_3"}, + {"id": 110, "name": "tag_4"}, + ], + "try": "body_try_value_2", + "while": "body_while_value_2", + "with": "body_with_value_2", + }, + } + } + } + + @classmethod + def _example_array_dog_data(cls) -> dict[str, dict[str, any]]: + return { + cls.example_name: { + "body": [ + { + "id": 103, + "name": "My pet name #1", + "status": "available", + "photoUrls": [ + "https://example.com/picture_1.jpg", + "https://example.com/picture_2.jpg", + ], + "category": { + "id": 104, + "name": "Category_Name_1", + }, + "tags": [ + {"id": 105, "name": "tag_1"}, + {"id": 106, "name": "tag_2"}, + ], + "try": "body_try_value_1", + "while": "body_while_value_1", + "with": "body_with_value_1", + }, + { + "id": 107, + "name": "My pet name #2", + "status": "pending", + "photoUrls": [ + "https://example.com/picture_3.jpg", + "https://example.com/picture_4.jpg", + ], + "category": { + "id": 108, + "name": "Category_Name_2", + }, + "tags": [ + {"id": 109, "name": "tag_3"}, + {"id": 110, "name": "tag_4"}, + ], + "try": "body_try_value_2", + "while": "body_while_value_2", + "with": "body_with_value_2", + }, + ] + } + } diff --git a/oseg/tests/test_type_checker.py b/oseg/tests/test_type_checker.py new file mode 100644 index 000000000..c314a48dc --- /dev/null +++ b/oseg/tests/test_type_checker.py @@ -0,0 +1,201 @@ +from oseg import parser +from test_utils import TestUtils, TestCase + + +class TestTypeChecker(TestCase): + def test_is_array(self): + oa_parser = TestUtils.oa_parser("type_checker") + together = oa_parser.components.schemas.get("Together") + func_array = parser.TypeChecker.is_array + + expected_true_array = [ + "prop_ref_array", + "prop_file_base64_array", + "prop_file_binary_array", + "prop_file_byte_array", + "prop_file_contentMediaType_array", + "prop_file_contentEncoding_array", + "prop_free_form_array", + "prop_free_form_no_additional_properties_array", + "prop_free_form_additional_properties_true_array", + "prop_scalar_bool_array", + "prop_scalar_integer_array", + "prop_scalar_number_array", + "prop_scalar_string_array", + "prop_nullable_array", + ] + + for name, prop in together.properties.items(): + with self.subTest(name): + if name in expected_true_array: + self.assertTrue(func_array(prop)) + else: + self.assertFalse(func_array(prop)) + + def test_is_file(self): + oa_parser = TestUtils.oa_parser("type_checker") + together = oa_parser.components.schemas.get("Together") + func_single = parser.TypeChecker.is_file + func_array = parser.TypeChecker.is_file_array + + expected_true_single = [ + "prop_file_binary", + "prop_file_byte", + ] + expected_true_array = [ + "prop_file_binary_array", + "prop_file_byte_array", + ] + + for name, prop in together.properties.items(): + with self.subTest(name): + if name in expected_true_single: + self.assertTrue(func_single(prop)) + elif name in expected_true_array: + self.assertTrue(func_array(prop)) + else: + self.assertFalse(func_single(prop)) + self.assertFalse(func_array(prop)) + + def test_is_free_form(self): + oa_parser = TestUtils.oa_parser("type_checker") + together = oa_parser.components.schemas.get("Together") + func_single = parser.TypeChecker.is_free_form + func_array = parser.TypeChecker.is_free_form_array + + expected_true_single = [ + "prop_free_form", + "prop_free_form_no_additional_properties", + "prop_free_form_additional_properties_true", + ] + expected_true_array = [ + "prop_free_form_array", + "prop_free_form_no_additional_properties_array", + "prop_free_form_additional_properties_true_array", + ] + + for name, prop in together.properties.items(): + with self.subTest(name): + if name in expected_true_single: + self.assertTrue(func_single(prop)) + elif name in expected_true_array: + self.assertTrue(func_array(prop)) + else: + self.assertFalse(func_single(prop)) + self.assertFalse(func_array(prop)) + + def test_is_scalar(self): + oa_parser = TestUtils.oa_parser("type_checker") + together = oa_parser.components.schemas.get("Together") + func_single = parser.TypeChecker.is_scalar + func_array = parser.TypeChecker.is_scalar_array + + expected_true_single = [ + "prop_file_base64", + "prop_file_contentEncoding", + "prop_file_contentMediaType", + "prop_scalar_bool", + "prop_scalar_integer", + "prop_scalar_number", + "prop_scalar_string", + "prop_scalar_string_contentMediaType", + "prop_nullable", + ] + + expected_true_array = [ + "prop_file_base64_array", + "prop_file_contentEncoding_array", + "prop_file_contentMediaType_array", + "prop_scalar_bool_array", + "prop_scalar_integer_array", + "prop_scalar_number_array", + "prop_scalar_string_array", + "prop_nullable_array", + ] + + for name, prop in together.properties.items(): + with self.subTest(name): + if name in expected_true_single: + self.assertTrue(func_single(prop)) + elif name in expected_true_array: + self.assertTrue(func_array(prop)) + else: + self.assertFalse(func_single(prop)) + self.assertFalse(func_array(prop)) + + def test_is_object(self): + oa_parser = TestUtils.oa_parser("type_checker") + together = oa_parser.components.schemas.get("Together") + func_single = parser.TypeChecker.is_object + func_array = parser.TypeChecker.is_object_array + + expected_true_single = [ + "prop_discriminator", + "prop_ref", + "prop_object", + ] + expected_true_array = [ + "prop_ref_array", + ] + + for name, prop in together.properties.items(): + with self.subTest(name): + if name in expected_true_single: + self.assertTrue(func_single(prop)) + elif name in expected_true_array: + self.assertTrue(func_array(prop)) + else: + self.assertFalse(func_single(prop)) + self.assertFalse(func_array(prop)) + + def test_is_nullable(self): + oa_parser = TestUtils.oa_parser("type_checker") + together = oa_parser.components.schemas.get("Together") + func_single = parser.TypeChecker.is_nullable + func_array = parser.TypeChecker.is_nullable_array + + expected_true_single = ["prop_nullable"] + expected_true_array = ["prop_nullable_array"] + + for name, prop in together.properties.items(): + with self.subTest(name): + if name in expected_true_single: + self.assertTrue(func_single(prop)) + elif name in expected_true_array: + self.assertTrue(func_array(prop)) + else: + self.assertFalse(func_single(prop)) + self.assertFalse(func_array(prop)) + + def test_is_nullable_30(self): + oa_parser = TestUtils.oa_parser("type_checker-3.0") + + together = oa_parser.components.schemas.get("Together") + func_single = parser.TypeChecker.is_nullable + func_array = parser.TypeChecker.is_nullable_array + + expected_true_single = ["prop_nullable"] + expected_true_array = ["prop_nullable_array"] + + for name, prop in together.properties.items(): + with self.subTest(name): + if name in expected_true_single: + self.assertTrue(func_single(prop)) + elif name in expected_true_array: + self.assertTrue(func_array(prop)) + else: + self.assertFalse(func_single(prop)) + self.assertFalse(func_array(prop)) + + def test_is_discriminator(self): + oa_parser = TestUtils.oa_parser("type_checker") + together = oa_parser.components.schemas.get("Together") + + expected_true = "prop_discriminator" + + for name, prop in together.properties.items(): + with self.subTest(name): + if name == expected_true: + self.assertTrue(parser.TypeChecker.is_discriminator(prop)) + else: + self.assertFalse(parser.TypeChecker.is_discriminator(prop)) diff --git a/oseg/tests/test_utils.py b/oseg/tests/test_utils.py new file mode 100644 index 000000000..b58079fbf --- /dev/null +++ b/oseg/tests/test_utils.py @@ -0,0 +1,29 @@ +import os +import unittest +from oseg import parser + + +class TestUtils: + _BASE_DIR: str = os.path.dirname(os.path.abspath(__file__)) + cached_oa_parsers: dict[str, parser.OaParser] = {} + + @classmethod + def oa_parser(cls, filename: str) -> parser.OaParser: + if filename in cls.cached_oa_parsers: + return cls.cached_oa_parsers[filename] + + if not filename.startswith("/"): + filepath = f"{TestUtils._BASE_DIR}/fixtures/{filename}.yaml" + else: + filepath = filename + + cls.cached_oa_parsers[filename] = parser.OaParser(filepath) + + return cls.cached_oa_parsers[filename] + + +class TestCase(unittest.TestCase): + def setUp(self): + super().setUp() + + self.maxDiff = None diff --git a/oseg/uv.lock b/oseg/uv.lock new file mode 100644 index 000000000..4872d7ff7 --- /dev/null +++ b/oseg/uv.lock @@ -0,0 +1,330 @@ +version = 1 +revision = 1 +requires-python = ">=3.13" + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, +] + +[[package]] +name = "black" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673 }, + { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190 }, + { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926 }, + { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613 }, + { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 }, +] + +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "coverage" +version = "7.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/76/17780846fc7aade1e66712e1e27dd28faa0a5d987a1f433610974959eaa8/coverage-7.10.2.tar.gz", hash = "sha256:5d6e6d84e6dd31a8ded64759626627247d676a23c1b892e1326f7c55c8d61055", size = 820754 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/04/9b7a741557f93c0ed791b854d27aa8d9fe0b0ce7bb7c52ca1b0f2619cb74/coverage-7.10.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:aca7b5645afa688de6d4f8e89d30c577f62956fefb1bad021490d63173874186", size = 215337 }, + { url = "https://files.pythonhosted.org/packages/02/a4/8d1088cd644750c94bc305d3cf56082b4cdf7fb854a25abb23359e74892f/coverage-7.10.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:96e5921342574a14303dfdb73de0019e1ac041c863743c8fe1aa6c2b4a257226", size = 215596 }, + { url = "https://files.pythonhosted.org/packages/01/2f/643a8d73343f70e162d8177a3972b76e306b96239026bc0c12cfde4f7c7a/coverage-7.10.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:11333094c1bff621aa811b67ed794865cbcaa99984dedea4bd9cf780ad64ecba", size = 246145 }, + { url = "https://files.pythonhosted.org/packages/1f/4a/722098d1848db4072cda71b69ede1e55730d9063bf868375264d0d302bc9/coverage-7.10.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6eb586fa7d2aee8d65d5ae1dd71414020b2f447435c57ee8de8abea0a77d5074", size = 248492 }, + { url = "https://files.pythonhosted.org/packages/3f/b0/8a6d7f326f6e3e6ed398cde27f9055e860a1e858317001835c521673fb60/coverage-7.10.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d358f259d8019d4ef25d8c5b78aca4c7af25e28bd4231312911c22a0e824a57", size = 249927 }, + { url = "https://files.pythonhosted.org/packages/bb/21/1aaadd3197b54d1e61794475379ecd0f68d8fc5c2ebd352964dc6f698a3d/coverage-7.10.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5250bda76e30382e0a2dcd68d961afcab92c3a7613606e6269855c6979a1b0bb", size = 248138 }, + { url = "https://files.pythonhosted.org/packages/48/65/be75bafb2bdd22fd8bf9bf63cd5873b91bb26ec0d68f02d4b8b09c02decb/coverage-7.10.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a91e027d66eff214d88d9afbe528e21c9ef1ecdf4956c46e366c50f3094696d0", size = 246111 }, + { url = "https://files.pythonhosted.org/packages/5e/30/a4f0c5e249c3cc60e6c6f30d8368e372f2d380eda40e0434c192ac27ccf5/coverage-7.10.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:228946da741558904e2c03ce870ba5efd9cd6e48cbc004d9a27abee08100a15a", size = 247493 }, + { url = "https://files.pythonhosted.org/packages/85/99/f09b9493e44a75cf99ca834394c12f8cb70da6c1711ee296534f97b52729/coverage-7.10.2-cp313-cp313-win32.whl", hash = "sha256:95e23987b52d02e7c413bf2d6dc6288bd5721beb518052109a13bfdc62c8033b", size = 217756 }, + { url = "https://files.pythonhosted.org/packages/2d/bb/cbcb09103be330c7d26ff0ab05c4a8861dd2e254656fdbd3eb7600af4336/coverage-7.10.2-cp313-cp313-win_amd64.whl", hash = "sha256:f35481d42c6d146d48ec92d4e239c23f97b53a3f1fbd2302e7c64336f28641fe", size = 218526 }, + { url = "https://files.pythonhosted.org/packages/37/8f/8bfb4e0bca52c00ab680767c0dd8cfd928a2a72d69897d9b2d5d8b5f63f5/coverage-7.10.2-cp313-cp313-win_arm64.whl", hash = "sha256:65b451949cb789c346f9f9002441fc934d8ccedcc9ec09daabc2139ad13853f7", size = 217176 }, + { url = "https://files.pythonhosted.org/packages/1e/25/d458ba0bf16a8204a88d74dbb7ec5520f29937ffcbbc12371f931c11efd2/coverage-7.10.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e8415918856a3e7d57a4e0ad94651b761317de459eb74d34cc1bb51aad80f07e", size = 216058 }, + { url = "https://files.pythonhosted.org/packages/0b/1c/af4dfd2d7244dc7610fed6d59d57a23ea165681cd764445dc58d71ed01a6/coverage-7.10.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f287a25a8ca53901c613498e4a40885b19361a2fe8fbfdbb7f8ef2cad2a23f03", size = 216273 }, + { url = "https://files.pythonhosted.org/packages/8e/67/ec5095d4035c6e16368226fa9cb15f77f891194c7e3725aeefd08e7a3e5a/coverage-7.10.2-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:75cc1a3f8c88c69bf16a871dab1fe5a7303fdb1e9f285f204b60f1ee539b8fc0", size = 257513 }, + { url = "https://files.pythonhosted.org/packages/1c/47/be5550b57a3a8ba797de4236b0fd31031f88397b2afc84ab3c2d4cf265f6/coverage-7.10.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ca07fa78cc9d26bc8c4740de1abd3489cf9c47cc06d9a8ab3d552ff5101af4c0", size = 259377 }, + { url = "https://files.pythonhosted.org/packages/37/50/b12a4da1382e672305c2d17cd3029dc16b8a0470de2191dbf26b91431378/coverage-7.10.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2e117e64c26300032755d4520cd769f2623cde1a1d1c3515b05a3b8add0ade1", size = 261516 }, + { url = "https://files.pythonhosted.org/packages/db/41/4d3296dbd33dd8da178171540ca3391af7c0184c0870fd4d4574ac290290/coverage-7.10.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:daaf98009977f577b71f8800208f4d40d4dcf5c2db53d4d822787cdc198d76e1", size = 259110 }, + { url = "https://files.pythonhosted.org/packages/ea/f1/b409959ecbc0cec0e61e65683b22bacaa4a3b11512f834e16dd8ffbc37db/coverage-7.10.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ea8d8fe546c528535c761ba424410bbeb36ba8a0f24be653e94b70c93fd8a8ca", size = 257248 }, + { url = "https://files.pythonhosted.org/packages/48/ab/7076dc1c240412e9267d36ec93e9e299d7659f6a5c1e958f87e998b0fb6d/coverage-7.10.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:fe024d40ac31eb8d5aae70215b41dafa264676caa4404ae155f77d2fa95c37bb", size = 258063 }, + { url = "https://files.pythonhosted.org/packages/1e/77/f6b51a0288f8f5f7dcc7c89abdd22cf514f3bc5151284f5cd628917f8e10/coverage-7.10.2-cp313-cp313t-win32.whl", hash = "sha256:8f34b09f68bdadec122ffad312154eda965ade433559cc1eadd96cca3de5c824", size = 218433 }, + { url = "https://files.pythonhosted.org/packages/7b/6d/547a86493e25270ce8481543e77f3a0aa3aa872c1374246b7b76273d66eb/coverage-7.10.2-cp313-cp313t-win_amd64.whl", hash = "sha256:71d40b3ac0f26fa9ffa6ee16219a714fed5c6ec197cdcd2018904ab5e75bcfa3", size = 219523 }, + { url = "https://files.pythonhosted.org/packages/ff/d5/3c711e38eaf9ab587edc9bed232c0298aed84e751a9f54aaa556ceaf7da6/coverage-7.10.2-cp313-cp313t-win_arm64.whl", hash = "sha256:abb57fdd38bf6f7dcc66b38dafb7af7c5fdc31ac6029ce373a6f7f5331d6f60f", size = 217739 }, + { url = "https://files.pythonhosted.org/packages/71/53/83bafa669bb9d06d4c8c6a055d8d05677216f9480c4698fb183ba7ec5e47/coverage-7.10.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a3e853cc04987c85ec410905667eed4bf08b1d84d80dfab2684bb250ac8da4f6", size = 215328 }, + { url = "https://files.pythonhosted.org/packages/1d/6c/30827a9c5a48a813e865fbaf91e2db25cce990bd223a022650ef2293fe11/coverage-7.10.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0100b19f230df72c90fdb36db59d3f39232391e8d89616a7de30f677da4f532b", size = 215608 }, + { url = "https://files.pythonhosted.org/packages/bb/a0/c92d85948056ddc397b72a3d79d36d9579c53cb25393ed3c40db7d33b193/coverage-7.10.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9c1cd71483ea78331bdfadb8dcec4f4edfb73c7002c1206d8e0af6797853f5be", size = 246111 }, + { url = "https://files.pythonhosted.org/packages/c2/cf/d695cf86b2559aadd072c91720a7844be4fb82cb4a3b642a2c6ce075692d/coverage-7.10.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9f75dbf4899e29a37d74f48342f29279391668ef625fdac6d2f67363518056a1", size = 248419 }, + { url = "https://files.pythonhosted.org/packages/ce/0a/03206aec4a05986e039418c038470d874045f6e00426b0c3879adc1f9251/coverage-7.10.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7df481e7508de1c38b9b8043da48d94931aefa3e32b47dd20277e4978ed5b95", size = 250038 }, + { url = "https://files.pythonhosted.org/packages/ab/9b/b3bd6bd52118c12bc4cf319f5baba65009c9beea84e665b6b9f03fa3f180/coverage-7.10.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:835f39e618099325e7612b3406f57af30ab0a0af350490eff6421e2e5f608e46", size = 248066 }, + { url = "https://files.pythonhosted.org/packages/80/cc/bfa92e261d3e055c851a073e87ba6a3bff12a1f7134233e48a8f7d855875/coverage-7.10.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:12e52b5aa00aa720097d6947d2eb9e404e7c1101ad775f9661ba165ed0a28303", size = 245909 }, + { url = "https://files.pythonhosted.org/packages/12/80/c8df15db4847710c72084164f615ae900af1ec380dce7f74a5678ccdf5e1/coverage-7.10.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:718044729bf1fe3e9eb9f31b52e44ddae07e434ec050c8c628bf5adc56fe4bdd", size = 247329 }, + { url = "https://files.pythonhosted.org/packages/04/6f/cb66e1f7124d5dd9ced69f889f02931419cb448125e44a89a13f4e036124/coverage-7.10.2-cp314-cp314-win32.whl", hash = "sha256:f256173b48cc68486299d510a3e729a96e62c889703807482dbf56946befb5c8", size = 218007 }, + { url = "https://files.pythonhosted.org/packages/8c/e1/3d4be307278ce32c1b9d95cc02ee60d54ddab784036101d053ec9e4fe7f5/coverage-7.10.2-cp314-cp314-win_amd64.whl", hash = "sha256:2e980e4179f33d9b65ac4acb86c9c0dde904098853f27f289766657ed16e07b3", size = 218802 }, + { url = "https://files.pythonhosted.org/packages/ec/66/1e43bbeb66c55a5a5efec70f1c153cf90cfc7f1662ab4ebe2d844de9122c/coverage-7.10.2-cp314-cp314-win_arm64.whl", hash = "sha256:14fb5b6641ab5b3c4161572579f0f2ea8834f9d3af2f7dd8fbaecd58ef9175cc", size = 217397 }, + { url = "https://files.pythonhosted.org/packages/81/01/ae29c129217f6110dc694a217475b8aecbb1b075d8073401f868c825fa99/coverage-7.10.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e96649ac34a3d0e6491e82a2af71098e43be2874b619547c3282fc11d3840a4b", size = 216068 }, + { url = "https://files.pythonhosted.org/packages/a2/50/6e9221d4139f357258f36dfa1d8cac4ec56d9d5acf5fdcc909bb016954d7/coverage-7.10.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1a2e934e9da26341d342d30bfe91422bbfdb3f1f069ec87f19b2909d10d8dcc4", size = 216285 }, + { url = "https://files.pythonhosted.org/packages/eb/ec/89d1d0c0ece0d296b4588e0ef4df185200456d42a47f1141335f482c2fc5/coverage-7.10.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:651015dcd5fd9b5a51ca79ece60d353cacc5beaf304db750407b29c89f72fe2b", size = 257603 }, + { url = "https://files.pythonhosted.org/packages/82/06/c830af66734671c778fc49d35b58339e8f0687fbd2ae285c3f96c94da092/coverage-7.10.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81bf6a32212f9f66da03d63ecb9cd9bd48e662050a937db7199dbf47d19831de", size = 259568 }, + { url = "https://files.pythonhosted.org/packages/60/57/f280dd6f1c556ecc744fbf39e835c33d3ae987d040d64d61c6f821e87829/coverage-7.10.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d800705f6951f75a905ea6feb03fff8f3ea3468b81e7563373ddc29aa3e5d1ca", size = 261691 }, + { url = "https://files.pythonhosted.org/packages/54/2b/c63a0acbd19d99ec32326164c23df3a4e18984fb86e902afdd66ff7b3d83/coverage-7.10.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:248b5394718e10d067354448dc406d651709c6765669679311170da18e0e9af8", size = 259166 }, + { url = "https://files.pythonhosted.org/packages/fd/c5/cd2997dcfcbf0683634da9df52d3967bc1f1741c1475dd0e4722012ba9ef/coverage-7.10.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5c61675a922b569137cf943770d7ad3edd0202d992ce53ac328c5ff68213ccf4", size = 257241 }, + { url = "https://files.pythonhosted.org/packages/16/26/c9e30f82fdad8d47aee90af4978b18c88fa74369ae0f0ba0dbf08cee3a80/coverage-7.10.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:52d708b5fd65589461381fa442d9905f5903d76c086c6a4108e8e9efdca7a7ed", size = 258139 }, + { url = "https://files.pythonhosted.org/packages/c9/99/bdb7bd00bebcd3dedfb895fa9af8e46b91422993e4a37ac634a5f1113790/coverage-7.10.2-cp314-cp314t-win32.whl", hash = "sha256:916369b3b914186b2c5e5ad2f7264b02cff5df96cdd7cdad65dccd39aa5fd9f0", size = 218809 }, + { url = "https://files.pythonhosted.org/packages/eb/5e/56a7852e38a04d1520dda4dfbfbf74a3d6dec932c20526968f7444763567/coverage-7.10.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5b9d538e8e04916a5df63052d698b30c74eb0174f2ca9cd942c981f274a18eaf", size = 219926 }, + { url = "https://files.pythonhosted.org/packages/e0/12/7fbe6b9c52bb9d627e9556f9f2edfdbe88b315e084cdecc9afead0c3b36a/coverage-7.10.2-cp314-cp314t-win_arm64.whl", hash = "sha256:04c74f9ef1f925456a9fd23a7eef1103126186d0500ef9a0acb0bd2514bdc7cc", size = 217925 }, + { url = "https://files.pythonhosted.org/packages/18/d8/9b768ac73a8ac2d10c080af23937212434a958c8d2a1c84e89b450237942/coverage-7.10.2-py3-none-any.whl", hash = "sha256:95db3750dd2e6e93d99fa2498f3a1580581e49c494bddccc6f85c5c21604921f", size = 206973 }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, +] + +[[package]] +name = "mock" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/07/8c/14c2ae915e5f9dca5a22edd68b35be94400719ccfa068a03e0fb63d0f6f6/mock-5.2.0.tar.gz", hash = "sha256:4e460e818629b4b173f32d08bf30d3af8123afbb8e04bb5707a1fd4799e503f0", size = 92796 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/d9/617e6af809bf3a1d468e0d58c3997b1dc219a9a9202e650d30c2fc85d481/mock-5.2.0-py3-none-any.whl", hash = "sha256:7ba87f72ca0e915175596069dbbcc7c75af7b5e9b9bc107ad6349ede0819982f", size = 31617 }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963 }, +] + +[[package]] +name = "openapi-pydantic" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381 }, +] + +[[package]] +name = "oseg" +version = "0.1.dev0" +source = { editable = "." } +dependencies = [ + { name = "click" }, + { name = "jinja2" }, + { name = "openapi-pydantic" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "tabulate" }, +] + +[package.dev-dependencies] +dev = [ + { name = "black" }, + { name = "coverage" }, + { name = "mock" }, +] + +[package.metadata] +requires-dist = [ + { name = "click", specifier = "~=8.1" }, + { name = "jinja2", specifier = "~=3.1" }, + { name = "openapi-pydantic", specifier = "~=0.5" }, + { name = "pydantic", specifier = "~=2.10" }, + { name = "pyyaml", specifier = "~=6.0" }, + { name = "tabulate", specifier = "~=0.9" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "black" }, + { name = "coverage" }, + { name = "mock" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, +] + +[[package]] +name = "platformdirs" +version = "4.3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567 }, +] + +[[package]] +name = "pydantic" +version = "2.11.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782 }, +] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688 }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808 }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580 }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859 }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810 }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498 }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611 }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924 }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196 }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389 }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223 }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473 }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269 }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921 }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162 }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560 }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777 }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, +] + +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252 }, +] + +[[package]] +name = "typing-extensions" +version = "4.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906 }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552 }, +] diff --git a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedExample.cs b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedExample.cs index 7f9786caf..cd3badd87 100644 --- a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedExample.cs +++ b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedExample.cs @@ -22,7 +22,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false ); var signers1 = new SubSignatureRequestSigner( diff --git a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedWithTemplateExample.cs b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedWithTemplateExample.cs index d40f34240..5138e9e69 100644 --- a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedWithTemplateExample.cs +++ b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestCreateEmbeddedWithTemplateExample.cs @@ -22,7 +22,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false ); var signers1 = new SubSignatureRequestTemplateSigner( diff --git a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendExample.cs b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendExample.cs index 2958c264c..d5e8ad896 100644 --- a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendExample.cs +++ b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendExample.cs @@ -26,7 +26,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false, ); var signers1 = new SubSignatureRequestSigner( diff --git a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendWithTemplateExample.cs b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendWithTemplateExample.cs index 024b92ce8..72d43c3d3 100644 --- a/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendWithTemplateExample.cs +++ b/sandbox/dotnet/src/Dropbox.SignSandbox/SignatureRequestSendWithTemplateExample.cs @@ -22,7 +22,8 @@ public static void Run() draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false, ); var signers1 = new SubSignatureRequestTemplateSigner( diff --git a/sandbox/dotnet/src/Dropbox.SignSandbox/TemplateUpdateExample.cs b/sandbox/dotnet/src/Dropbox.SignSandbox/TemplateUpdateExample.cs new file mode 100644 index 000000000..0fc66e5ed --- /dev/null +++ b/sandbox/dotnet/src/Dropbox.SignSandbox/TemplateUpdateExample.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +using Dropbox.Sign.Api; +using Dropbox.Sign.Client; +using Dropbox.Sign.Model; + +namespace Dropbox.SignSandbox; + +public class TemplateUpdateExample +{ + public static void Run() + { + var config = new Configuration(); + config.Username = "YOUR_API_KEY"; + // config.AccessToken = "YOUR_ACCESS_TOKEN"; + + var formFields1 = new SubUpdateFormField( + apiId: "uniqueIdHere_1", + name: "New name 1" + ); + + var formFields2 = new SubUpdateFormField( + apiId: "uniqueIdHere_2", + name: "New name 2" + ); + + var formFields = new List + { + formFields1, + formFields2, + }; + + var templateUpdateRequest = new TemplateUpdateRequest( + title: "Test Title", + subject: "Test Subject", + message: "Test Message", + ccRoles: [ + "CC Role 1", + "CC Role 2", + ], + formFields: formFields + ); + + try + { + var response = new TemplateApi(config).TemplateUpdate( + templateId: "f57db65d3f933b5316d398057a36176831451a35", + templateUpdateRequest: templateUpdateRequest + ); + + Console.WriteLine(response); + } + catch (ApiException e) + { + Console.WriteLine("Exception when calling TemplateApi#TemplateUpdate: " + e.Message); + Console.WriteLine("Status Code: " + e.ErrorCode); + Console.WriteLine(e.StackTrace); + } + } +} diff --git a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedExample.java b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedExample.java index 5193cee20..a432c2f35 100644 --- a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedExample.java +++ b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedExample.java @@ -29,6 +29,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); diff --git a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedWithTemplateExample.java b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedWithTemplateExample.java index 309d422ee..f94b403d2 100644 --- a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedWithTemplateExample.java +++ b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestCreateEmbeddedWithTemplateExample.java @@ -29,6 +29,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); diff --git a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendExample.java b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendExample.java index 313b895b7..7db66e606 100644 --- a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendExample.java +++ b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendExample.java @@ -32,6 +32,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); diff --git a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendWithTemplateExample.java b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendWithTemplateExample.java index f44a67ed9..5c6bd8d6b 100644 --- a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendWithTemplateExample.java +++ b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/SignatureRequestSendWithTemplateExample.java @@ -29,6 +29,7 @@ public static void main(String[] args) signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); diff --git a/sandbox/java/src/main/java/com/dropbox/sign_sandbox/TemplateUpdateExample.java b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/TemplateUpdateExample.java new file mode 100644 index 000000000..25c622553 --- /dev/null +++ b/sandbox/java/src/main/java/com/dropbox/sign_sandbox/TemplateUpdateExample.java @@ -0,0 +1,65 @@ +package com.dropbox.sign_sandbox; + +import com.dropbox.sign.ApiException; +import com.dropbox.sign.Configuration; +import com.dropbox.sign.api.*; +import com.dropbox.sign.auth.*; +import com.dropbox.sign.JSON; +import com.dropbox.sign.model.*; + +import java.io.File; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class TemplateUpdateExample +{ + public static void main(String[] args) + { + var config = Configuration.getDefaultApiClient(); + ((HttpBasicAuth) config.getAuthentication("api_key")).setUsername("YOUR_API_KEY"); + // ((HttpBearerAuth) config.getAuthentication("oauth2")).setBearerToken("YOUR_ACCESS_TOKEN"); + + var formFields1 = new SubUpdateFormField(); + formFields1.apiId("uniqueIdHere_1"); + formFields1.name("New name 1"); + + var formFields2 = new SubUpdateFormField(); + formFields2.apiId("uniqueIdHere_2"); + formFields2.name("New name 2"); + + var formFields = new ArrayList(List.of ( + formFields1, + formFields2 + )); + + var templateUpdateRequest = new TemplateUpdateRequest(); + templateUpdateRequest.title("Test Title"); + templateUpdateRequest.subject("Test Subject"); + templateUpdateRequest.message("Test Message"); + templateUpdateRequest.ccRoles(List.of ( + "CC Role 1", + "CC Role 2" + )); + templateUpdateRequest.formFields(formFields); + + try + { + var response = new TemplateApi(config).templateUpdate( + "f57db65d3f933b5316d398057a36176831451a35", // templateId + templateUpdateRequest + ); + + System.out.println(response); + } catch (ApiException e) { + System.err.println("Exception when calling TemplateApi#templateUpdate"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} diff --git a/sandbox/node/src/SignatureRequestCreateEmbeddedExample.ts b/sandbox/node/src/SignatureRequestCreateEmbeddedExample.ts index a2c620a2e..811c0c7aa 100644 --- a/sandbox/node/src/SignatureRequestCreateEmbeddedExample.ts +++ b/sandbox/node/src/SignatureRequestCreateEmbeddedExample.ts @@ -12,6 +12,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestSigner = { diff --git a/sandbox/node/src/SignatureRequestCreateEmbeddedWithTemplateExample.ts b/sandbox/node/src/SignatureRequestCreateEmbeddedWithTemplateExample.ts index a2ee15e46..3914dfe02 100644 --- a/sandbox/node/src/SignatureRequestCreateEmbeddedWithTemplateExample.ts +++ b/sandbox/node/src/SignatureRequestCreateEmbeddedWithTemplateExample.ts @@ -12,6 +12,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestTemplateSigner = { diff --git a/sandbox/node/src/SignatureRequestSendExample.ts b/sandbox/node/src/SignatureRequestSendExample.ts index 910a66743..064e68ad3 100644 --- a/sandbox/node/src/SignatureRequestSendExample.ts +++ b/sandbox/node/src/SignatureRequestSendExample.ts @@ -16,6 +16,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestSigner = { diff --git a/sandbox/node/src/SignatureRequestSendWithTemplateExample.ts b/sandbox/node/src/SignatureRequestSendWithTemplateExample.ts index 88219107a..d327aec9b 100644 --- a/sandbox/node/src/SignatureRequestSendWithTemplateExample.ts +++ b/sandbox/node/src/SignatureRequestSendWithTemplateExample.ts @@ -12,6 +12,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestTemplateSigner = { diff --git a/sandbox/node/src/TemplateUpdateExample.ts b/sandbox/node/src/TemplateUpdateExample.ts new file mode 100644 index 000000000..92c8d4566 --- /dev/null +++ b/sandbox/node/src/TemplateUpdateExample.ts @@ -0,0 +1,43 @@ +import * as fs from 'fs'; +import api from "@dropbox/sign" +import models from "@dropbox/sign" + +const apiCaller = new api.TemplateApi(); +apiCaller.username = "YOUR_API_KEY"; +// apiCaller.accessToken = "YOUR_ACCESS_TOKEN"; + +const formFields1: models.SubUpdateFormField = { + apiId: "uniqueIdHere_1", + name: "New name 1", +}; + +const formFields2: models.SubUpdateFormField = { + apiId: "uniqueIdHere_2", + name: "New name 2", +}; + +const formFields = [ + formFields1, + formFields2, +]; + +const templateUpdateRequest: models.TemplateUpdateRequest = { + title: "Test Title", + subject: "Test Subject", + message: "Test Message", + ccRoles: [ + "CC Role 1", + "CC Role 2", + ], + formFields: formFields, +}; + +apiCaller.templateUpdate( + "f57db65d3f933b5316d398057a36176831451a35", // templateId + templateUpdateRequest, +).then(response => { + console.log(response.body); +}).catch(error => { + console.log("Exception when calling TemplateApi#templateUpdate:"); + console.log(error.body); +}); diff --git a/sandbox/php/src/SignatureRequestCreateEmbeddedExample.php b/sandbox/php/src/SignatureRequestCreateEmbeddedExample.php index 61d74044e..185e3b749 100644 --- a/sandbox/php/src/SignatureRequestCreateEmbeddedExample.php +++ b/sandbox/php/src/SignatureRequestCreateEmbeddedExample.php @@ -16,7 +16,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestSigner()) ->setName("Jack") diff --git a/sandbox/php/src/SignatureRequestCreateEmbeddedWithTemplateExample.php b/sandbox/php/src/SignatureRequestCreateEmbeddedWithTemplateExample.php index 3ff0454e8..ab2b4f850 100644 --- a/sandbox/php/src/SignatureRequestCreateEmbeddedWithTemplateExample.php +++ b/sandbox/php/src/SignatureRequestCreateEmbeddedWithTemplateExample.php @@ -16,7 +16,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestTemplateSigner()) ->setRole("Client") diff --git a/sandbox/php/src/SignatureRequestSendExample.php b/sandbox/php/src/SignatureRequestSendExample.php index f922a579e..f8ab05ef0 100644 --- a/sandbox/php/src/SignatureRequestSendExample.php +++ b/sandbox/php/src/SignatureRequestSendExample.php @@ -19,7 +19,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestSigner()) ->setName("Jack") diff --git a/sandbox/php/src/SignatureRequestSendWithTemplateExample.php b/sandbox/php/src/SignatureRequestSendWithTemplateExample.php index d68205392..747882e76 100644 --- a/sandbox/php/src/SignatureRequestSendWithTemplateExample.php +++ b/sandbox/php/src/SignatureRequestSendWithTemplateExample.php @@ -16,7 +16,8 @@ ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestTemplateSigner()) ->setRole("Client") diff --git a/sandbox/php/src/TemplateUpdateExample.php b/sandbox/php/src/TemplateUpdateExample.php new file mode 100644 index 000000000..c827bc301 --- /dev/null +++ b/sandbox/php/src/TemplateUpdateExample.php @@ -0,0 +1,46 @@ +setUsername("YOUR_API_KEY"); +// $config->setAccessToken("YOUR_ACCESS_TOKEN"); + +$form_fields_1 = (new Dropbox\Sign\Model\SubUpdateFormField()) + ->setApiId("uniqueIdHere_1") + ->setName("New name 1"); + +$form_fields_2 = (new Dropbox\Sign\Model\SubUpdateFormField()) + ->setApiId("uniqueIdHere_2") + ->setName("New name 2"); + +$form_fields = [ + $form_fields_1, + $form_fields_2, +]; + +$template_update_request = (new Dropbox\Sign\Model\TemplateUpdateRequest()) + ->setTitle("Test Title") + ->setSubject("Test Subject") + ->setMessage("Test Message") + ->setCcRoles([ + "CC Role 1", + "CC Role 2", + ]) + ->setFormFields($form_fields); + +try { + $response = (new Dropbox\Sign\Api\TemplateApi(config: $config))->templateUpdate( + template_id: "f57db65d3f933b5316d398057a36176831451a35", + template_update_request: $template_update_request, + ); + + print_r($response); +} catch (Dropbox\Sign\ApiException $e) { + echo "Exception when calling TemplateApi#templateUpdate: {$e->getMessage()}"; +} diff --git a/sandbox/python/src/SignatureRequestCreateEmbeddedExample.py b/sandbox/python/src/SignatureRequestCreateEmbeddedExample.py index 2e1b93c1d..adf6b8f02 100644 --- a/sandbox/python/src/SignatureRequestCreateEmbeddedExample.py +++ b/sandbox/python/src/SignatureRequestCreateEmbeddedExample.py @@ -16,6 +16,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestSigner( diff --git a/sandbox/python/src/SignatureRequestCreateEmbeddedWithTemplateExample.py b/sandbox/python/src/SignatureRequestCreateEmbeddedWithTemplateExample.py index 6a5835760..885a24811 100644 --- a/sandbox/python/src/SignatureRequestCreateEmbeddedWithTemplateExample.py +++ b/sandbox/python/src/SignatureRequestCreateEmbeddedWithTemplateExample.py @@ -16,6 +16,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestTemplateSigner( diff --git a/sandbox/python/src/SignatureRequestSendExample.py b/sandbox/python/src/SignatureRequestSendExample.py index 21b1bfc26..033e973fe 100644 --- a/sandbox/python/src/SignatureRequestSendExample.py +++ b/sandbox/python/src/SignatureRequestSendExample.py @@ -20,6 +20,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestSigner( diff --git a/sandbox/python/src/SignatureRequestSendWithTemplateExample.py b/sandbox/python/src/SignatureRequestSendWithTemplateExample.py index 468a6b101..7c94fedc6 100644 --- a/sandbox/python/src/SignatureRequestSendWithTemplateExample.py +++ b/sandbox/python/src/SignatureRequestSendWithTemplateExample.py @@ -16,6 +16,7 @@ phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestTemplateSigner( diff --git a/sandbox/python/src/TemplateUpdateExample.py b/sandbox/python/src/TemplateUpdateExample.py new file mode 100644 index 000000000..39e767acb --- /dev/null +++ b/sandbox/python/src/TemplateUpdateExample.py @@ -0,0 +1,47 @@ +import json +from datetime import date, datetime +from pprint import pprint + +from dropbox_sign import ApiClient, ApiException, Configuration, api, models + +configuration = Configuration( + username="YOUR_API_KEY", + # access_token="YOUR_ACCESS_TOKEN", +) + +with ApiClient(configuration) as api_client: + form_fields_1 = models.SubUpdateFormField( + api_id="uniqueIdHere_1", + name="New name 1", + ) + + form_fields_2 = models.SubUpdateFormField( + api_id="uniqueIdHere_2", + name="New name 2", + ) + + form_fields = [ + form_fields_1, + form_fields_2, + ] + + template_update_request = models.TemplateUpdateRequest( + title="Test Title", + subject="Test Subject", + message="Test Message", + cc_roles=[ + "CC Role 1", + "CC Role 2", + ], + form_fields=form_fields, + ) + + try: + response = api.TemplateApi(api_client).template_update( + template_id="f57db65d3f933b5316d398057a36176831451a35", + template_update_request=template_update_request, + ) + + pprint(response) + except ApiException as e: + print("Exception when calling TemplateApi#template_update: %s\n" % e) diff --git a/sandbox/ruby/src/SignatureRequestCreateEmbeddedExample.rb b/sandbox/ruby/src/SignatureRequestCreateEmbeddedExample.rb index 55db08ca7..3b33e2f80 100644 --- a/sandbox/ruby/src/SignatureRequestCreateEmbeddedExample.rb +++ b/sandbox/ruby/src/SignatureRequestCreateEmbeddedExample.rb @@ -12,6 +12,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestSigner.new signers_1.name = "Jack" diff --git a/sandbox/ruby/src/SignatureRequestCreateEmbeddedWithTemplateExample.rb b/sandbox/ruby/src/SignatureRequestCreateEmbeddedWithTemplateExample.rb index 2de72cf8a..18d1d8be4 100644 --- a/sandbox/ruby/src/SignatureRequestCreateEmbeddedWithTemplateExample.rb +++ b/sandbox/ruby/src/SignatureRequestCreateEmbeddedWithTemplateExample.rb @@ -12,6 +12,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestTemplateSigner.new signers_1.role = "Client" diff --git a/sandbox/ruby/src/SignatureRequestSendExample.rb b/sandbox/ruby/src/SignatureRequestSendExample.rb index 28905902d..45958b7a3 100644 --- a/sandbox/ruby/src/SignatureRequestSendExample.rb +++ b/sandbox/ruby/src/SignatureRequestSendExample.rb @@ -15,6 +15,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestSigner.new signers_1.name = "Jack" diff --git a/sandbox/ruby/src/SignatureRequestSendWithTemplateExample.rb b/sandbox/ruby/src/SignatureRequestSendWithTemplateExample.rb index 4ee78fded..237c12fe5 100644 --- a/sandbox/ruby/src/SignatureRequestSendWithTemplateExample.rb +++ b/sandbox/ruby/src/SignatureRequestSendWithTemplateExample.rb @@ -12,6 +12,7 @@ signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestTemplateSigner.new signers_1.role = "Client" diff --git a/sandbox/ruby/src/TemplateUpdateExample.rb b/sandbox/ruby/src/TemplateUpdateExample.rb new file mode 100644 index 000000000..e0332ea8f --- /dev/null +++ b/sandbox/ruby/src/TemplateUpdateExample.rb @@ -0,0 +1,41 @@ +require "json" +require "dropbox-sign" + +Dropbox::Sign.configure do |config| + config.username = "YOUR_API_KEY" + # config.access_token = "YOUR_ACCESS_TOKEN" +end + +form_fields_1 = Dropbox::Sign::SubUpdateFormField.new +form_fields_1.api_id = "uniqueIdHere_1" +form_fields_1.name = "New name 1" + +form_fields_2 = Dropbox::Sign::SubUpdateFormField.new +form_fields_2.api_id = "uniqueIdHere_2" +form_fields_2.name = "New name 2" + +form_fields = [ + form_fields_1, + form_fields_2, +] + +template_update_request = Dropbox::Sign::TemplateUpdateRequest.new +template_update_request.title = "Test Title" +template_update_request.subject = "Test Subject" +template_update_request.message = "Test Message" +template_update_request.cc_roles = [ + "CC Role 1", + "CC Role 2", +] +template_update_request.form_fields = form_fields + +begin + response = Dropbox::Sign::TemplateApi.new.template_update( + "f57db65d3f933b5316d398057a36176831451a35", # template_id + template_update_request, + ) + + p response +rescue Dropbox::Sign::ApiError => e + puts "Exception when calling TemplateApi#template_update: #{e}" +end diff --git a/sdks/dotnet/README.md b/sdks/dotnet/README.md index c8323efa3..74ca42eb0 100644 --- a/sdks/dotnet/README.md +++ b/sdks/dotnet/README.md @@ -214,6 +214,7 @@ Class | Method | HTTP request | Description - [Model.AccountGetResponse](docs/AccountGetResponse.md) - [Model.AccountResponse](docs/AccountResponse.md) - [Model.AccountResponseQuotas](docs/AccountResponseQuotas.md) + - [Model.AccountResponseSettings](docs/AccountResponseSettings.md) - [Model.AccountResponseUsage](docs/AccountResponseUsage.md) - [Model.AccountUpdateRequest](docs/AccountUpdateRequest.md) - [Model.AccountVerifyRequest](docs/AccountVerifyRequest.md) @@ -335,6 +336,7 @@ Class | Method | HTTP request | Description - [Model.SubTemplateRole](docs/SubTemplateRole.md) - [Model.SubUnclaimedDraftSigner](docs/SubUnclaimedDraftSigner.md) - [Model.SubUnclaimedDraftTemplateSigner](docs/SubUnclaimedDraftTemplateSigner.md) + - [Model.SubUpdateFormField](docs/SubUpdateFormField.md) - [Model.SubWhiteLabelingOptions](docs/SubWhiteLabelingOptions.md) - [Model.TeamAddMemberRequest](docs/TeamAddMemberRequest.md) - [Model.TeamCreateRequest](docs/TeamCreateRequest.md) @@ -357,7 +359,6 @@ Class | Method | HTTP request | Description - [Model.TemplateCreateRequest](docs/TemplateCreateRequest.md) - [Model.TemplateCreateResponse](docs/TemplateCreateResponse.md) - [Model.TemplateCreateResponseTemplate](docs/TemplateCreateResponseTemplate.md) - - [Model.TemplateEditResponse](docs/TemplateEditResponse.md) - [Model.TemplateGetResponse](docs/TemplateGetResponse.md) - [Model.TemplateListResponse](docs/TemplateListResponse.md) - [Model.TemplateRemoveUserRequest](docs/TemplateRemoveUserRequest.md) diff --git a/sdks/dotnet/bin/copy-constants.php b/sdks/dotnet/bin/copy-constants.php index 885380501..d99fb7960 100755 --- a/sdks/dotnet/bin/copy-constants.php +++ b/sdks/dotnet/bin/copy-constants.php @@ -13,17 +13,26 @@ }); /** - * Between openapi-generator v7.8.0 and v7.12.0 a change was made to the way - * a few generators create constant names from values. The original way was - * actually broken. For example "change-field-visibility" would generate a - * constant name of "TYPE_FIELD_VISIBILITY", dropping the "change" part. + * Post-generation patch for SubFormFieldRuleAction.cs. * - * The fix now generates the correct name, "TYPE_CHANGE_FIELD_VISIBILITY". - * However, the fix also gets rid of the previous (incorrect) constant names, - * making the fix a BC break. + * Between openapi-generator v7.8.0 and v7.12.0 a change was made to the + * way a few generators create constant names from values. The original + * way was broken: "change-field-visibility" generated a constant named + * "TYPE_FIELD_VISIBILITY", dropping the "change" part. The fix generates + * the correct name, "TYPE_CHANGE_FIELD_VISIBILITY", but also removes the + * previous (incorrect) names, which is a BC break. * - * This simple script just adds the old constant names back, alongside the new - * ones. + * To preserve source compatibility this script adds the old names back + * as aliases (FieldVisibility = ChangeFieldVisibility, etc.). The aliases + * share a numeric value with their canonical counterparts, which breaks + * StringEnumConverter: Enum.GetName is not guaranteed to pick the + * canonical name for ties, and Newtonsoft rejects duplicate + * [EnumMember] values on the same enum. To make the aliases serialize + * to the correct OpenAPI wire values under all circumstances, this + * script also: + * - swaps StringEnumConverter for a dedicated TypeEnumJsonConverter + * that maps by underlying numeric value, and + * - injects that nested converter class into SubFormFieldRuleAction. */ class CopyConstants { @@ -32,6 +41,57 @@ public function run(): void $file = __DIR__ . '/../src/Dropbox.Sign/Model/SubFormFieldRuleAction.cs'; $contents = file_get_contents($file); + $contents = $this->addAliases($contents); + $contents = $this->swapConverter($contents); + $contents = $this->injectConverterClass($contents); + + file_put_contents($file, $contents); + + $this->stopEmittingDefaultIntValues(__DIR__ . '/../src/Dropbox.Sign/Model'); + } + + /** + * For optional non-nullable int properties on request-side models + * openapi-generator emits + * [DataMember(Name = "foo", EmitDefaultValue = true)] + * public int Foo { get; set; } + * which forces `"foo": 0` onto the wire whenever the caller never + * set a value (C# default for int is 0). For fields like font_size + * the server rejects the default with a 400 ("'font_size' must be + * between 7 and 49"), and more generally any optional int whose + * server-side default is not 0 is misrepresented. + * + * Scope: + * - Only request-side models are patched. Response models keep + * EmitDefaultValue = true so that round-trip serialization + * preserves explicit zero values that the server sent (tests + * under Dropbox.Sign.Test.Api rely on this fidelity). Response + * models are identified by the "Response" substring in the + * file name, which is the convention for all generated + * response types in this SDK. + * - Required int properties are left alone: openapi-generator + * inserts `IsRequired = true,` between the Name and + * EmitDefaultValue tokens, which this regex does not match. + */ + private function stopEmittingDefaultIntValues(string $modelDir): void + { + $pattern = '/(\[DataMember\(Name = "[^"]+", EmitDefaultValue = )true(\)\]\s*\r?\n\s+public int [A-Za-z_][A-Za-z0-9_]* \{ get; set; \})/'; + + foreach (glob($modelDir . '/*.cs') as $path) { + if (strpos(basename($path), 'Response') !== false) { + continue; + } + + $contents = file_get_contents($path); + $patched = preg_replace($pattern, '$1false$2', $contents); + if ($patched !== null && $patched !== $contents) { + file_put_contents($path, $patched); + } + } + } + + private function addAliases(string $contents): string + { $constant_1 = " ChangeFieldVisibility = 1,"; $replace_1 = implode("\n", [ $constant_1, @@ -44,21 +104,99 @@ public function run(): void ' GroupVisibility = ChangeGroupVisibility', ]); - $contents = str_replace( - $constant_1, - $replace_1, - $contents, - ); + $contents = str_replace($constant_1, $replace_1, $contents); + $contents = str_replace($constant_2, $replace_2, $contents); - $contents = str_replace( - $constant_2, - $replace_2, - $contents, - ); + return $contents; + } - file_put_contents($file, $contents); + private function swapConverter(string $contents): string + { + $needle = " [JsonConverter(typeof(StringEnumConverter))]\n" + . " public enum TypeEnum"; + + $replacement = <<<'CS' + // A dedicated converter is used instead of StringEnumConverter + // because this enum intentionally carries alias members + // (FieldVisibility, GroupVisibility) that share a numeric value + // with their canonical counterparts. StringEnumConverter goes + // through Enum.GetName, which is not guaranteed to pick the + // canonical name when multiple members share a value, and + // Newtonsoft rejects duplicate [EnumMember] values on the same + // enum. Mapping by numeric value here is unambiguous: both the + // canonical name and its alias produce the same wire string. + [JsonConverter(typeof(TypeEnumJsonConverter))] + public enum TypeEnum +CS; + + return str_replace($needle, $replacement, $contents); + } + + private function injectConverterClass(string $contents): string + { + // Inject the nested converter immediately after the enum's + // closing brace. Anchor on the enum's tail, which is unique in + // the file. + $needle = " GroupVisibility = ChangeGroupVisibility\n" + . " }\n"; + + $converter = <<<'CS' + GroupVisibility = ChangeGroupVisibility + } + + /// + /// Serializes SubFormFieldRuleAction.TypeEnum to and from the + /// OpenAPI wire values (change-field-visibility, + /// change-group-visibility). The switch is driven by the + /// underlying numeric value so that legacy alias members + /// (FieldVisibility, GroupVisibility) serialize identically to + /// their canonical counterparts. + /// + public class TypeEnumJsonConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, TypeEnum value, JsonSerializer serializer) + { + switch (value) + { + case TypeEnum.ChangeFieldVisibility: + writer.WriteValue("change-field-visibility"); + return; + case TypeEnum.ChangeGroupVisibility: + writer.WriteValue("change-group-visibility"); + return; + default: + throw new JsonSerializationException( + $"Unknown value for SubFormFieldRuleAction.TypeEnum: {(int)value}"); + } + } + + public override TypeEnum ReadJson(JsonReader reader, Type objectType, TypeEnum existingValue, bool hasExistingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) + { + throw new JsonSerializationException( + "Cannot deserialize null into SubFormFieldRuleAction.TypeEnum"); + } + + var raw = reader.Value?.ToString(); + switch (raw) + { + case "change-field-visibility": + return TypeEnum.ChangeFieldVisibility; + case "change-group-visibility": + return TypeEnum.ChangeGroupVisibility; + default: + throw new JsonSerializationException( + $"Unknown wire value for SubFormFieldRuleAction.TypeEnum: {raw}"); + } + } + } + +CS; + + return str_replace($needle, $converter, $contents); } } $copier = new CopyConstants(); -$copier->run(); \ No newline at end of file +$copier->run(); diff --git a/sdks/dotnet/docs/AccountResponse.md b/sdks/dotnet/docs/AccountResponse.md index 2f9672466..875aa407d 100644 --- a/sdks/dotnet/docs/AccountResponse.md +++ b/sdks/dotnet/docs/AccountResponse.md @@ -4,7 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**AccountId** | **string** | The ID of the Account | [optional] **EmailAddress** | **string** | The email address associated with the Account. | [optional] **IsLocked** | **bool** | Returns `true` if the user has been locked out of their account by a team admin. | [optional] **IsPaidHs** | **bool** | Returns `true` if the user has a paid Dropbox Sign account. | [optional] **IsPaidHf** | **bool** | Returns `true` if the user has a paid HelloFax account. | [optional] **Quotas** | [**AccountResponseQuotas**](AccountResponseQuotas.md) | | [optional] **CallbackUrl** | **string** | The URL that Dropbox Sign events will `POST` to. | [optional] **RoleCode** | **string** | The membership role for the team. | [optional] **TeamId** | **string** | The id of the team account belongs to. | [optional] **Locale** | **string** | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | [optional] **Usage** | [**AccountResponseUsage**](AccountResponseUsage.md) | | [optional] +**AccountId** | **string** | The ID of the Account | [optional] **EmailAddress** | **string** | The email address associated with the Account. | [optional] **IsLocked** | **bool** | Returns `true` if the user has been locked out of their account by a team admin. | [optional] **IsPaidHs** | **bool** | Returns `true` if the user has a paid Dropbox Sign account. | [optional] **IsPaidHf** | **bool** | Returns `true` if the user has a paid HelloFax account. | [optional] **Quotas** | [**AccountResponseQuotas**](AccountResponseQuotas.md) | | [optional] **CallbackUrl** | **string** | The URL that Dropbox Sign events will `POST` to. | [optional] **RoleCode** | **string** | The membership role for the team. | [optional] **TeamId** | **string** | The id of the team account belongs to. | [optional] **Locale** | **string** | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | [optional] **Usage** | [**AccountResponseUsage**](AccountResponseUsage.md) | | [optional] **Settings** | [**AccountResponseSettings**](AccountResponseSettings.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/dotnet/docs/AccountResponseSettings.md b/sdks/dotnet/docs/AccountResponseSettings.md new file mode 100644 index 000000000..69cc3c20e --- /dev/null +++ b/sdks/dotnet/docs/AccountResponseSettings.md @@ -0,0 +1,11 @@ +# Dropbox.Sign.Model.AccountResponseSettings +Subset of configured settings + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**SignerAccessCodes** | **bool** | Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | [optional] **SmsDelivery** | **bool** | Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | [optional] **SmsAuthentication** | **bool** | Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/sdks/dotnet/docs/SignatureRequestApi.md b/sdks/dotnet/docs/SignatureRequestApi.md index fe084fa62..68b0c2f0a 100644 --- a/sdks/dotnet/docs/SignatureRequestApi.md +++ b/sdks/dotnet/docs/SignatureRequestApi.md @@ -504,7 +504,8 @@ public class SignatureRequestCreateEmbeddedExample draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false ); var signers1 = new SubSignatureRequestSigner( @@ -647,7 +648,8 @@ public class SignatureRequestCreateEmbeddedWithTemplateExample draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false ); var signers1 = new SubSignatureRequestTemplateSigner( @@ -2137,7 +2139,8 @@ public class SignatureRequestSendExample draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false, ); var signers1 = new SubSignatureRequestSigner( @@ -2286,7 +2289,8 @@ public class SignatureRequestSendWithTemplateExample draw: true, phone: false, type: true, - upload: true + upload: true, + force_advanced_signature_details: false, ); var signers1 = new SubSignatureRequestTemplateSigner( diff --git a/sdks/dotnet/docs/SignatureRequestEditRequest.md b/sdks/dotnet/docs/SignatureRequestEditRequest.md index 20f216403..bb50808de 100644 --- a/sdks/dotnet/docs/SignatureRequestEditRequest.md +++ b/sdks/dotnet/docs/SignatureRequestEditRequest.md @@ -4,7 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **Signers** | [**List<SubSignatureRequestSigner>**](SubSignatureRequestSigner.md) | Add Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **GroupedSigners** | [**List<SubSignatureRequestGroupedSigners>**](SubSignatureRequestGroupedSigners.md) | Add Grouped Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**AllowReassign** | **bool** | Allows signers to reassign their signature requests to other signers if set to `true`. Defaults to `false`.

**NOTE:** Only available for Premium plan and higher. | [optional] [default to false]**Attachments** | [**List<SubAttachment>**](SubAttachment.md) | A list describing the attachments | [optional] **CcEmailAddresses** | **List<string>** | The email addresses that should be CCed. | [optional] **ClientId** | **string** | The client id of the API App you want to associate with this request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | When used together with merge fields, `custom_fields` allows users to add pre-filled data to their signature requests.

Pre-filled data can be used with "send-once" signature requests by adding merge fields with `form_fields_per_document` or [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) while passing values back with `custom_fields` together in one API call.

For using pre-filled on repeatable signature requests, merge fields are added to templates in the Dropbox Sign UI or by calling [/template/create_embedded_draft](/api/reference/operation/templateCreateEmbeddedDraft) and then passing `custom_fields` on subsequent signature requests referencing that template. | [optional] **FieldOptions** | [**SubFieldOptions**](SubFieldOptions.md) | | [optional] **FormFieldGroups** | [**List<SubFormFieldGroup>**](SubFormFieldGroup.md) | Group information for fields defined in `form_fields_per_document`. String-indexed JSON array with `group_label` and `requirement` keys. `form_fields_per_document` must contain fields referencing a group defined in `form_field_groups`. | [optional] **FormFieldRules** | [**List<SubFormFieldRule>**](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | [optional] **FormFieldsPerDocument** | [**List<SubFormFieldsPerDocumentBase>**](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | [optional] **HideTextTags** | **bool** | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [optional] [default to false]**IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] **UseTextTags** | **bool** | Send with a value of `true` if you wish to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document. Defaults to disabled, or `false`. | [optional] [default to false]**ExpiresAt** | **int?** | When the signature request will expire. Unsigned signatures will be moved to the expired status, and no longer signable. See [Signature Request Expiration Date](https://developers.hellosign.com/docs/signature-request/expiration/) for details. | [optional] +**Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **Signers** | [**List<SubSignatureRequestSigner>**](SubSignatureRequestSigner.md) | Add Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **GroupedSigners** | [**List<SubSignatureRequestGroupedSigners>**](SubSignatureRequestGroupedSigners.md) | Add Grouped Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**AllowReassign** | **bool** | Allows signers to reassign their signature requests to other signers if set to `true`. Defaults to `false`.

**NOTE:** Only available for Premium plan and higher. | [optional] [default to false]**Attachments** | [**List<SubAttachment>**](SubAttachment.md) | A list describing the attachments | [optional] **CcEmailAddresses** | **List<string>** | The email addresses that should be CCed. | [optional] **ClientId** | **string** | The client id of the API App you want to associate with this request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | When used together with merge fields, `custom_fields` allows users to add pre-filled data to their signature requests.

Pre-filled data can be used with "send-once" signature requests by adding merge fields with `form_fields_per_document` or [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) while passing values back with `custom_fields` together in one API call.

For using pre-filled on repeatable signature requests, merge fields are added to templates in the Dropbox Sign UI or by calling [/template/create_embedded_draft](/api/reference/operation/templateCreateEmbeddedDraft) and then passing `custom_fields` on subsequent signature requests referencing that template. | [optional] **FieldOptions** | [**SubFieldOptions**](SubFieldOptions.md) | | [optional] **FormFieldGroups** | [**List<SubFormFieldGroup>**](SubFormFieldGroup.md) | Group information for fields defined in `form_fields_per_document`. String-indexed JSON array with `group_label` and `requirement` keys. `form_fields_per_document` must contain fields referencing a group defined in `form_field_groups`. | [optional] **FormFieldRules** | [**List<SubFormFieldRule>**](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | [optional] **FormFieldsPerDocument** | [**List<SubFormFieldsPerDocumentBase>**](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | [optional] **HideTextTags** | **bool** | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [optional] [default to false]**IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] **UseTextTags** | **bool** | Send with a value of `true` if you wish to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document. Defaults to disabled, or `false`. | [optional] [default to false]**ExpiresAt** | **int?** | When the signature request will expire. Unsigned signatures will be moved to the expired status, and no longer signable. See [Signature Request Expiration Date](https://developers.hellosign.com/docs/signature-request/expiration/) for details. | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/dotnet/docs/SignatureRequestEditWithTemplateRequest.md b/sdks/dotnet/docs/SignatureRequestEditWithTemplateRequest.md index d9ac882ee..1da1fa150 100644 --- a/sdks/dotnet/docs/SignatureRequestEditWithTemplateRequest.md +++ b/sdks/dotnet/docs/SignatureRequestEditWithTemplateRequest.md @@ -4,7 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**TemplateIds** | **List<string>** | Use `template_ids` to create a SignatureRequest from one or more templates, in the order in which the template will be used. | **Signers** | [**List<SubSignatureRequestTemplateSigner>**](SubSignatureRequestTemplateSigner.md) | Add Signers to your Templated-based Signature Request. | **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**Ccs** | [**List<SubCC>**](SubCC.md) | Add CC email recipients. Required when a CC role exists for the Template. | [optional] **ClientId** | **string** | Client id of the app to associate with the signature request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | [optional] **Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] +**TemplateIds** | **List<string>** | Use `template_ids` to create a SignatureRequest from one or more templates, in the order in which the template will be used. | **Signers** | [**List<SubSignatureRequestTemplateSigner>**](SubSignatureRequestTemplateSigner.md) | Add Signers to your Templated-based Signature Request. | **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**Ccs** | [**List<SubCC>**](SubCC.md) | Add CC email recipients. Required when a CC role exists for the Template. | [optional] **ClientId** | **string** | Client id of the app to associate with the signature request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | [optional] **Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/dotnet/docs/SignatureRequestSendRequest.md b/sdks/dotnet/docs/SignatureRequestSendRequest.md index 000c7adec..5261aeb91 100644 --- a/sdks/dotnet/docs/SignatureRequestSendRequest.md +++ b/sdks/dotnet/docs/SignatureRequestSendRequest.md @@ -4,7 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **Signers** | [**List<SubSignatureRequestSigner>**](SubSignatureRequestSigner.md) | Add Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **GroupedSigners** | [**List<SubSignatureRequestGroupedSigners>**](SubSignatureRequestGroupedSigners.md) | Add Grouped Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**AllowReassign** | **bool** | Allows signers to reassign their signature requests to other signers if set to `true`. Defaults to `false`.

**NOTE:** Only available for Premium plan and higher. | [optional] [default to false]**Attachments** | [**List<SubAttachment>**](SubAttachment.md) | A list describing the attachments | [optional] **CcEmailAddresses** | **List<string>** | The email addresses that should be CCed. | [optional] **ClientId** | **string** | The client id of the API App you want to associate with this request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | When used together with merge fields, `custom_fields` allows users to add pre-filled data to their signature requests.

Pre-filled data can be used with "send-once" signature requests by adding merge fields with `form_fields_per_document` or [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) while passing values back with `custom_fields` together in one API call.

For using pre-filled on repeatable signature requests, merge fields are added to templates in the Dropbox Sign UI or by calling [/template/create_embedded_draft](/api/reference/operation/templateCreateEmbeddedDraft) and then passing `custom_fields` on subsequent signature requests referencing that template. | [optional] **FieldOptions** | [**SubFieldOptions**](SubFieldOptions.md) | | [optional] **FormFieldGroups** | [**List<SubFormFieldGroup>**](SubFormFieldGroup.md) | Group information for fields defined in `form_fields_per_document`. String-indexed JSON array with `group_label` and `requirement` keys. `form_fields_per_document` must contain fields referencing a group defined in `form_field_groups`. | [optional] **FormFieldRules** | [**List<SubFormFieldRule>**](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | [optional] **FormFieldsPerDocument** | [**List<SubFormFieldsPerDocumentBase>**](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | [optional] **HideTextTags** | **bool** | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [optional] [default to false]**IsQualifiedSignature** | **bool** | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] **UseTextTags** | **bool** | Send with a value of `true` if you wish to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document. Defaults to disabled, or `false`. | [optional] [default to false]**ExpiresAt** | **int?** | When the signature request will expire. Unsigned signatures will be moved to the expired status, and no longer signable. See [Signature Request Expiration Date](https://developers.hellosign.com/docs/signature-request/expiration/) for details. | [optional] +**Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **Signers** | [**List<SubSignatureRequestSigner>**](SubSignatureRequestSigner.md) | Add Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **GroupedSigners** | [**List<SubSignatureRequestGroupedSigners>**](SubSignatureRequestGroupedSigners.md) | Add Grouped Signers to your Signature Request.

This endpoint requires either **signers** or **grouped_signers**, but not both. | [optional] **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**AllowReassign** | **bool** | Allows signers to reassign their signature requests to other signers if set to `true`. Defaults to `false`.

**NOTE:** Only available for Premium plan and higher. | [optional] [default to false]**Attachments** | [**List<SubAttachment>**](SubAttachment.md) | A list describing the attachments | [optional] **CcEmailAddresses** | **List<string>** | The email addresses that should be CCed. | [optional] **ClientId** | **string** | The client id of the API App you want to associate with this request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | When used together with merge fields, `custom_fields` allows users to add pre-filled data to their signature requests.

Pre-filled data can be used with "send-once" signature requests by adding merge fields with `form_fields_per_document` or [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) while passing values back with `custom_fields` together in one API call.

For using pre-filled on repeatable signature requests, merge fields are added to templates in the Dropbox Sign UI or by calling [/template/create_embedded_draft](/api/reference/operation/templateCreateEmbeddedDraft) and then passing `custom_fields` on subsequent signature requests referencing that template. | [optional] **FieldOptions** | [**SubFieldOptions**](SubFieldOptions.md) | | [optional] **FormFieldGroups** | [**List<SubFormFieldGroup>**](SubFormFieldGroup.md) | Group information for fields defined in `form_fields_per_document`. String-indexed JSON array with `group_label` and `requirement` keys. `form_fields_per_document` must contain fields referencing a group defined in `form_field_groups`. | [optional] **FormFieldRules** | [**List<SubFormFieldRule>**](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | [optional] **FormFieldsPerDocument** | [**List<SubFormFieldsPerDocumentBase>**](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | [optional] **HideTextTags** | **bool** | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [optional] [default to false]**IsQualifiedSignature** | **bool** | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] **UseTextTags** | **bool** | Send with a value of `true` if you wish to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document. Defaults to disabled, or `false`. | [optional] [default to false]**ExpiresAt** | **int?** | When the signature request will expire. Unsigned signatures will be moved to the expired status, and no longer signable. See [Signature Request Expiration Date](https://developers.hellosign.com/docs/signature-request/expiration/) for details. | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/dotnet/docs/SignatureRequestSendWithTemplateRequest.md b/sdks/dotnet/docs/SignatureRequestSendWithTemplateRequest.md index 12fc09be5..89bbdcc3a 100644 --- a/sdks/dotnet/docs/SignatureRequestSendWithTemplateRequest.md +++ b/sdks/dotnet/docs/SignatureRequestSendWithTemplateRequest.md @@ -4,7 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**TemplateIds** | **List<string>** | Use `template_ids` to create a SignatureRequest from one or more templates, in the order in which the template will be used. | **Signers** | [**List<SubSignatureRequestTemplateSigner>**](SubSignatureRequestTemplateSigner.md) | Add Signers to your Templated-based Signature Request. | **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**Ccs** | [**List<SubCC>**](SubCC.md) | Add CC email recipients. Required when a CC role exists for the Template. | [optional] **ClientId** | **string** | Client id of the app to associate with the signature request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | [optional] **Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **IsQualifiedSignature** | **bool** | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] +**TemplateIds** | **List<string>** | Use `template_ids` to create a SignatureRequest from one or more templates, in the order in which the template will be used. | **Signers** | [**List<SubSignatureRequestTemplateSigner>**](SubSignatureRequestTemplateSigner.md) | Add Signers to your Templated-based Signature Request. | **AllowDecline** | **bool** | Allows signers to decline to sign a document if `true`. Defaults to `false`. | [optional] [default to false]**Ccs** | [**List<SubCC>**](SubCC.md) | Add CC email recipients. Required when a CC role exists for the Template. | [optional] **ClientId** | **string** | Client id of the app to associate with the signature request. Used to apply the branding and callback url defined for the app. | [optional] **CustomFields** | [**List<SubCustomField>**](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | [optional] **Files** | **List<System.IO.Stream>** | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **FileUrls** | **List<string>** | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | [optional] **IsQualifiedSignature** | **bool** | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**IsEid** | **bool** | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [optional] [default to false]**Message** | **string** | The custom message in the email that will be sent to the signers. | [optional] **Metadata** | **Dictionary<string, Object>** | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | [optional] **SigningOptions** | [**SubSigningOptions**](SubSigningOptions.md) | | [optional] **SigningRedirectUrl** | **string** | The URL you want signers redirected to after they successfully sign. | [optional] **Subject** | **string** | The subject in the email that will be sent to the signers. | [optional] **TestMode** | **bool** | Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. | [optional] [default to false]**Title** | **string** | The title you want to assign to the SignatureRequest. | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/dotnet/docs/SubSigningOptions.md b/sdks/dotnet/docs/SubSigningOptions.md index a65674196..7ae5fa9fb 100644 --- a/sdks/dotnet/docs/SubSigningOptions.md +++ b/sdks/dotnet/docs/SubSigningOptions.md @@ -1,11 +1,11 @@ # Dropbox.Sign.Model.SubSigningOptions -This allows the requester to specify the types allowed for creating a signature. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. +This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**DefaultType** | **string** | The default type shown (limited to the listed types) | **Draw** | **bool** | Allows drawing the signature | [optional] [default to false]**Phone** | **bool** | Allows using a smartphone to email the signature | [optional] [default to false]**Type** | **bool** | Allows typing the signature | [optional] [default to false]**Upload** | **bool** | Allows uploading the signature | [optional] [default to false] +**DefaultType** | **string** | The default type shown (limited to the listed types) | **Draw** | **bool** | Allows drawing the signature | [optional] [default to false]**Phone** | **bool** | Allows using a smartphone to email the signature | [optional] [default to false]**Type** | **bool** | Allows typing the signature | [optional] [default to false]**Upload** | **bool** | Allows uploading the signature | [optional] [default to false]**ForceAdvancedSignatureDetails** | **bool** | Turning on advanced signature details for the signature request | [optional] [default to false] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/dotnet/docs/SubUpdateFormField.md b/sdks/dotnet/docs/SubUpdateFormField.md new file mode 100644 index 000000000..2760bfbd9 --- /dev/null +++ b/sdks/dotnet/docs/SubUpdateFormField.md @@ -0,0 +1,10 @@ +# Dropbox.Sign.Model.SubUpdateFormField + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ApiId** | **string** | The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found | **Name** | **string** | The new name of the field. If not passed the name will remain unchanged. | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/sdks/dotnet/docs/TemplateApi.md b/sdks/dotnet/docs/TemplateApi.md index f9c66e11c..133b641e6 100644 --- a/sdks/dotnet/docs/TemplateApi.md +++ b/sdks/dotnet/docs/TemplateApi.md @@ -124,7 +124,7 @@ catch (ApiException e) Create Template -Creates a template that can then be used. +Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. ### Example ```csharp diff --git a/sdks/dotnet/docs/TemplateEditResponse.md b/sdks/dotnet/docs/TemplateEditResponse.md deleted file mode 100644 index 830c7a9ed..000000000 --- a/sdks/dotnet/docs/TemplateEditResponse.md +++ /dev/null @@ -1,10 +0,0 @@ -# Dropbox.Sign.Model.TemplateEditResponse - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**TemplateId** | **string** | The id of the Template. | - -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - diff --git a/sdks/dotnet/src/Dropbox.Sign.Test/Model/SubFormFieldRuleActionTests.cs b/sdks/dotnet/src/Dropbox.Sign.Test/Model/SubFormFieldRuleActionTests.cs new file mode 100644 index 000000000..6e5a65cd6 --- /dev/null +++ b/sdks/dotnet/src/Dropbox.Sign.Test/Model/SubFormFieldRuleActionTests.cs @@ -0,0 +1,84 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Xunit; +using Dropbox.Sign.Model; + +namespace Dropbox.Sign.Test.Model +{ + public class SubFormFieldRuleActionTests + { + // SubFormFieldRuleAction.TypeEnum must serialize to the exact + // wire values accepted by the Dropbox Sign API + // (change-field-visibility, change-group-visibility). The enum + // intentionally carries legacy alias members (FieldVisibility, + // GroupVisibility) that share a numeric value with the canonical + // members, so at runtime they are indistinguishable (xUnit also + // dedups the alias rows because [InlineData] compares enums by + // their underlying int). The dedicated TypeEnumJsonConverter + // maps by underlying value so both names produce the same wire + // string; pinning the canonical members is therefore sufficient. + [Theory] + [InlineData(SubFormFieldRuleAction.TypeEnum.ChangeFieldVisibility, "change-field-visibility")] + [InlineData(SubFormFieldRuleAction.TypeEnum.ChangeGroupVisibility, "change-group-visibility")] + public void TypeEnum_Serializes_To_EnumMember_Value( + SubFormFieldRuleAction.TypeEnum value, + string expected) + { + var json = JsonConvert.SerializeObject(value); + + Assert.Equal($"\"{expected}\"", json); + } + + [Theory] + [InlineData(SubFormFieldRuleAction.TypeEnum.ChangeFieldVisibility, "change-field-visibility")] + [InlineData(SubFormFieldRuleAction.TypeEnum.ChangeGroupVisibility, "change-group-visibility")] + public void Action_Payload_Uses_EnumMember_Value_For_Type( + SubFormFieldRuleAction.TypeEnum value, + string expected) + { + var action = new SubFormFieldRuleAction( + fieldId: "api_id_2", + hidden: true, + type: value + ); + + var json = JObject.Parse(action.ToJson()); + + Assert.Equal(expected, (string)json["type"]); + } + + [Theory] + [InlineData("change-field-visibility", SubFormFieldRuleAction.TypeEnum.ChangeFieldVisibility)] + [InlineData("change-group-visibility", SubFormFieldRuleAction.TypeEnum.ChangeGroupVisibility)] + public void Action_Payload_Deserializes_EnumMember_Value_For_Type( + string wireValue, + SubFormFieldRuleAction.TypeEnum expected) + { + var payload = new JObject( + new JProperty("field_id", "api_id_2"), + new JProperty("hidden", true), + new JProperty("type", wireValue) + ).ToString(); + + var action = SubFormFieldRuleAction.Init(payload); + + Assert.Equal(expected, action.Type); + } + + [Theory] + [InlineData("FieldVisibility")] + [InlineData("GroupVisibility")] + [InlineData("change-unknown-thing")] + [InlineData("")] + public void Action_Payload_Rejects_Unknown_Type_Values(string wireValue) + { + var payload = new JObject( + new JProperty("field_id", "api_id_2"), + new JProperty("hidden", true), + new JProperty("type", wireValue) + ).ToString(); + + Assert.ThrowsAny(() => SubFormFieldRuleAction.Init(payload)); + } + } +} diff --git a/sdks/dotnet/src/Dropbox.Sign/Api/TemplateApi.cs b/sdks/dotnet/src/Dropbox.Sign/Api/TemplateApi.cs index f98f0671c..80da8262a 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Api/TemplateApi.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Api/TemplateApi.cs @@ -56,7 +56,7 @@ public interface ITemplateApiSync : IApiAccessor /// Create Template /// /// - /// Creates a template that can then be used. + /// Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// @@ -68,7 +68,7 @@ public interface ITemplateApiSync : IApiAccessor /// Create Template /// /// - /// Creates a template that can then be used. + /// Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// @@ -336,7 +336,7 @@ public interface ITemplateApiAsync : IApiAccessor /// Create Template /// /// - /// Creates a template that can then be used. + /// Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// @@ -349,7 +349,7 @@ public interface ITemplateApiAsync : IApiAccessor /// Create Template /// /// - /// Creates a template that can then be used. + /// Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// @@ -919,7 +919,7 @@ public Dropbox.Sign.Client.ApiResponse TemplateAddUserWithH } /// - /// Create Template Creates a template that can then be used. + /// Create Template Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// @@ -932,7 +932,7 @@ public TemplateCreateResponse TemplateCreate(TemplateCreateRequest templateCreat } /// - /// Create Template Creates a template that can then be used. + /// Create Template Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// @@ -1009,7 +1009,7 @@ public Dropbox.Sign.Client.ApiResponse TemplateCreateWit } /// - /// Create Template Creates a template that can then be used. + /// Create Template Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// @@ -1023,7 +1023,7 @@ public Dropbox.Sign.Client.ApiResponse TemplateCreateWit } /// - /// Create Template Creates a template that can then be used. + /// Create Template Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. /// /// Thrown when fails to make API call /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/AccountResponse.cs b/sdks/dotnet/src/Dropbox.Sign/Model/AccountResponse.cs index 6d65726d7..e4af82916 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/AccountResponse.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/AccountResponse.cs @@ -52,7 +52,8 @@ protected AccountResponse() { } /// The id of the team account belongs to.. /// The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values.. /// usage. - public AccountResponse(string accountId = default(string), string emailAddress = default(string), bool isLocked = default(bool), bool isPaidHs = default(bool), bool isPaidHf = default(bool), AccountResponseQuotas quotas = default(AccountResponseQuotas), string callbackUrl = default(string), string roleCode = default(string), string teamId = default(string), string locale = default(string), AccountResponseUsage usage = default(AccountResponseUsage)) + /// settings. + public AccountResponse(string accountId = default(string), string emailAddress = default(string), bool isLocked = default(bool), bool isPaidHs = default(bool), bool isPaidHf = default(bool), AccountResponseQuotas quotas = default(AccountResponseQuotas), string callbackUrl = default(string), string roleCode = default(string), string teamId = default(string), string locale = default(string), AccountResponseUsage usage = default(AccountResponseUsage), AccountResponseSettings settings = default(AccountResponseSettings)) { this.AccountId = accountId; @@ -66,6 +67,7 @@ protected AccountResponse() { } this.TeamId = teamId; this.Locale = locale; this.Usage = usage; + this.Settings = settings; } /// @@ -159,6 +161,12 @@ public static AccountResponse Init(string jsonData) [DataMember(Name = "usage", EmitDefaultValue = true)] public AccountResponseUsage Usage { get; set; } + /// + /// Gets or Sets Settings + /// + [DataMember(Name = "settings", EmitDefaultValue = true)] + public AccountResponseSettings Settings { get; set; } + /// /// Returns the string presentation of the object /// @@ -178,6 +186,7 @@ public override string ToString() sb.Append(" TeamId: ").Append(TeamId).Append("\n"); sb.Append(" Locale: ").Append(Locale).Append("\n"); sb.Append(" Usage: ").Append(Usage).Append("\n"); + sb.Append(" Settings: ").Append(Settings).Append("\n"); sb.Append("}\n"); return sb.ToString(); } @@ -264,6 +273,11 @@ public bool Equals(AccountResponse input) this.Usage == input.Usage || (this.Usage != null && this.Usage.Equals(input.Usage)) + ) && + ( + this.Settings == input.Settings || + (this.Settings != null && + this.Settings.Equals(input.Settings)) ); } @@ -311,6 +325,10 @@ public override int GetHashCode() { hashCode = (hashCode * 59) + this.Usage.GetHashCode(); } + if (this.Settings != null) + { + hashCode = (hashCode * 59) + this.Settings.GetHashCode(); + } return hashCode; } } @@ -404,6 +422,13 @@ public List GetOpenApiTypes() Type = "AccountResponseUsage", Value = Usage, }); + types.Add(new OpenApiType() + { + Name = "settings", + Property = "Settings", + Type = "AccountResponseSettings", + Value = Settings, + }); return types; } diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/AccountResponseSettings.cs b/sdks/dotnet/src/Dropbox.Sign/Model/AccountResponseSettings.cs new file mode 100644 index 000000000..0359d7317 --- /dev/null +++ b/sdks/dotnet/src/Dropbox.Sign/Model/AccountResponseSettings.cs @@ -0,0 +1,206 @@ +/* + * Dropbox Sign API + * + * Dropbox Sign v3 API + * + * The version of the OpenAPI document: 3.0.0 + * Contact: apisupport@hellosign.com + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using System.ComponentModel.DataAnnotations; +using OpenAPIDateConverter = Dropbox.Sign.Client.OpenAPIDateConverter; + +namespace Dropbox.Sign.Model +{ + /// + /// Subset of configured settings + /// + [DataContract(Name = "AccountResponseSettings")] + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + public partial class AccountResponseSettings : IEquatable, IValidatableObject + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected AccountResponseSettings() { } + /// + /// Initializes a new instance of the class. + /// + /// Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).. + /// Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).. + /// Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).. + public AccountResponseSettings(bool signerAccessCodes = default(bool), bool smsDelivery = default(bool), bool smsAuthentication = default(bool)) + { + + this.SignerAccessCodes = signerAccessCodes; + this.SmsDelivery = smsDelivery; + this.SmsAuthentication = smsAuthentication; + } + + /// + /// Attempt to instantiate and hydrate a new instance of this class + /// + /// String of JSON data representing target object + public static AccountResponseSettings Init(string jsonData) + { + var obj = JsonConvert.DeserializeObject(jsonData); + + if (obj == null) + { + throw new Exception("Unable to deserialize JSON to instance of AccountResponseSettings"); + } + + return obj; + } + + /// + /// Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + /// + /// Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + [DataMember(Name = "signer_access_codes", EmitDefaultValue = true)] + public bool SignerAccessCodes { get; set; } + + /// + /// Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + /// + /// Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + [DataMember(Name = "sms_delivery", EmitDefaultValue = true)] + public bool SmsDelivery { get; set; } + + /// + /// Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + /// + /// Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + [DataMember(Name = "sms_authentication", EmitDefaultValue = true)] + public bool SmsAuthentication { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class AccountResponseSettings {\n"); + sb.Append(" SignerAccessCodes: ").Append(SignerAccessCodes).Append("\n"); + sb.Append(" SmsDelivery: ").Append(SmsDelivery).Append("\n"); + sb.Append(" SmsAuthentication: ").Append(SmsAuthentication).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as AccountResponseSettings); + } + + /// + /// Returns true if AccountResponseSettings instances are equal + /// + /// Instance of AccountResponseSettings to be compared + /// Boolean + public bool Equals(AccountResponseSettings input) + { + if (input == null) + { + return false; + } + return + ( + this.SignerAccessCodes == input.SignerAccessCodes || + this.SignerAccessCodes.Equals(input.SignerAccessCodes) + ) && + ( + this.SmsDelivery == input.SmsDelivery || + this.SmsDelivery.Equals(input.SmsDelivery) + ) && + ( + this.SmsAuthentication == input.SmsAuthentication || + this.SmsAuthentication.Equals(input.SmsAuthentication) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + hashCode = (hashCode * 59) + this.SignerAccessCodes.GetHashCode(); + hashCode = (hashCode * 59) + this.SmsDelivery.GetHashCode(); + hashCode = (hashCode * 59) + this.SmsAuthentication.GetHashCode(); + return hashCode; + } + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + public List GetOpenApiTypes() + { + var types = new List(); + types.Add(new OpenApiType() + { + Name = "signer_access_codes", + Property = "SignerAccessCodes", + Type = "bool", + Value = SignerAccessCodes, + }); + types.Add(new OpenApiType() + { + Name = "sms_delivery", + Property = "SmsDelivery", + Type = "bool", + Value = SmsDelivery, + }); + types.Add(new OpenApiType() + { + Name = "sms_authentication", + Property = "SmsAuthentication", + Type = "bool", + Value = SmsAuthentication, + }); + + return types; + } + } + +} diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/ReportCreateRequest.cs b/sdks/dotnet/src/Dropbox.Sign/Model/ReportCreateRequest.cs index 8ae648930..010db6e9b 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/ReportCreateRequest.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/ReportCreateRequest.cs @@ -55,7 +55,13 @@ public enum ReportTypeEnum /// Enum SmsActivity for value: sms_activity /// [EnumMember(Value = "sms_activity")] - SmsActivity = 3 + SmsActivity = 3, + + /// + /// Enum FaxUsage for value: fax_usage + /// + [EnumMember(Value = "fax_usage")] + FaxUsage = 4 } /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/ReportResponse.cs b/sdks/dotnet/src/Dropbox.Sign/Model/ReportResponse.cs index bd63ab7fa..5ec9d9690 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/ReportResponse.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/ReportResponse.cs @@ -55,7 +55,13 @@ public enum ReportTypeEnum /// Enum SmsActivity for value: sms_activity /// [EnumMember(Value = "sms_activity")] - SmsActivity = 3 + SmsActivity = 3, + + /// + /// Enum FaxUsage for value: fax_usage + /// + [EnumMember(Value = "fax_usage")] + FaxUsage = 4 } /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditRequest.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditRequest.cs index f239fcf60..585c78c47 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditRequest.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditRequest.cs @@ -56,7 +56,7 @@ protected SignatureRequestEditRequest() { } /// Conditional Logic rules for fields defined in `form_fields_per_document`.. /// The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).) **NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types. * Text Field use `SubFormFieldsPerDocumentText` * Dropdown Field use `SubFormFieldsPerDocumentDropdown` * Hyperlink Field use `SubFormFieldsPerDocumentHyperlink` * Checkbox Field use `SubFormFieldsPerDocumentCheckbox` * Radio Field use `SubFormFieldsPerDocumentRadio` * Signature Field use `SubFormFieldsPerDocumentSignature` * Date Signed Field use `SubFormFieldsPerDocumentDateSigned` * Initials Field use `SubFormFieldsPerDocumentInitials` * Text Merge Field use `SubFormFieldsPerDocumentTextMerge` * Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge`. /// Enables automatic Text Tag removal when set to true. **NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. (default to false). - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). /// The custom message in the email that will be sent to the signers.. /// Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request. Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long.. /// signingOptions. @@ -217,9 +217,9 @@ public static SignatureRequestEditRequest Init(string jsonData) public bool HideTextTags { get; set; } /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. [DataMember(Name = "is_eid", EmitDefaultValue = true)] public bool IsEid { get; set; } diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditWithTemplateRequest.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditWithTemplateRequest.cs index 84990b8ff..ca8887939 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditWithTemplateRequest.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestEditWithTemplateRequest.cs @@ -48,7 +48,7 @@ protected SignatureRequestEditWithTemplateRequest() { } /// An array defining values and options for custom fields. Required when a custom field exists in the Template.. /// Use `files[]` to indicate the uploaded file(s) to send for signature. This endpoint requires either **files** or **file_urls[]**, but not both.. /// Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature. This endpoint requires either **files** or **file_urls[]**, but not both.. - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). /// The custom message in the email that will be sent to the signers.. /// Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request. Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long.. /// Add Signers to your Templated-based Signature Request. (required). @@ -161,9 +161,9 @@ public static SignatureRequestEditWithTemplateRequest Init(string jsonData) public List FileUrls { get; set; } /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. [DataMember(Name = "is_eid", EmitDefaultValue = true)] public bool IsEid { get; set; } diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendRequest.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendRequest.cs index 51c0d97a0..9719a297a 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendRequest.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendRequest.cs @@ -57,7 +57,7 @@ protected SignatureRequestSendRequest() { } /// The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).) **NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types. * Text Field use `SubFormFieldsPerDocumentText` * Dropdown Field use `SubFormFieldsPerDocumentDropdown` * Hyperlink Field use `SubFormFieldsPerDocumentHyperlink` * Checkbox Field use `SubFormFieldsPerDocumentCheckbox` * Radio Field use `SubFormFieldsPerDocumentRadio` * Signature Field use `SubFormFieldsPerDocumentSignature` * Date Signed Field use `SubFormFieldsPerDocumentDateSigned` * Initials Field use `SubFormFieldsPerDocumentInitials` * Text Merge Field use `SubFormFieldsPerDocumentTextMerge` * Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge`. /// Enables automatic Text Tag removal when set to true. **NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. (default to false). /// Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br> **NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). /// The custom message in the email that will be sent to the signers.. /// Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request. Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long.. /// signingOptions. @@ -227,9 +227,9 @@ public static SignatureRequestSendRequest Init(string jsonData) public bool IsQualifiedSignature { get; set; } /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. [DataMember(Name = "is_eid", EmitDefaultValue = true)] public bool IsEid { get; set; } diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendWithTemplateRequest.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendWithTemplateRequest.cs index 071627daa..681de91fb 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendWithTemplateRequest.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SignatureRequestSendWithTemplateRequest.cs @@ -49,7 +49,7 @@ protected SignatureRequestSendWithTemplateRequest() { } /// Use `files[]` to indicate the uploaded file(s) to send for signature. This endpoint requires either **files** or **file_urls[]**, but not both.. /// Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature. This endpoint requires either **files** or **file_urls[]**, but not both.. /// Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br> **NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. (default to false). /// The custom message in the email that will be sent to the signers.. /// Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request. Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long.. /// Add Signers to your Templated-based Signature Request. (required). @@ -171,9 +171,9 @@ public static SignatureRequestSendWithTemplateRequest Init(string jsonData) public bool IsQualifiedSignature { get; set; } /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. /// - /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + /// Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. [DataMember(Name = "is_eid", EmitDefaultValue = true)] public bool IsEid { get; set; } diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldRuleAction.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldRuleAction.cs index b6af36b3d..34634d199 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldRuleAction.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldRuleAction.cs @@ -36,7 +36,16 @@ public partial class SubFormFieldRuleAction : IEquatable /// /// Defines Type /// - [JsonConverter(typeof(StringEnumConverter))] + // A dedicated converter is used instead of StringEnumConverter + // because this enum intentionally carries alias members + // (FieldVisibility, GroupVisibility) that share a numeric value + // with their canonical counterparts. StringEnumConverter goes + // through Enum.GetName, which is not guaranteed to pick the + // canonical name when multiple members share a value, and + // Newtonsoft rejects duplicate [EnumMember] values on the same + // enum. Mapping by numeric value here is unambiguous: both the + // canonical name and its alias produce the same wire string. + [JsonConverter(typeof(TypeEnumJsonConverter))] public enum TypeEnum { /// @@ -54,6 +63,54 @@ public enum TypeEnum GroupVisibility = ChangeGroupVisibility } + /// + /// Serializes SubFormFieldRuleAction.TypeEnum to and from the + /// OpenAPI wire values (change-field-visibility, + /// change-group-visibility). The switch is driven by the + /// underlying numeric value so that legacy alias members + /// (FieldVisibility, GroupVisibility) serialize identically to + /// their canonical counterparts. + /// + public class TypeEnumJsonConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, TypeEnum value, JsonSerializer serializer) + { + switch (value) + { + case TypeEnum.ChangeFieldVisibility: + writer.WriteValue("change-field-visibility"); + return; + case TypeEnum.ChangeGroupVisibility: + writer.WriteValue("change-group-visibility"); + return; + default: + throw new JsonSerializationException( + $"Unknown value for SubFormFieldRuleAction.TypeEnum: {(int)value}"); + } + } + + public override TypeEnum ReadJson(JsonReader reader, Type objectType, TypeEnum existingValue, bool hasExistingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) + { + throw new JsonSerializationException( + "Cannot deserialize null into SubFormFieldRuleAction.TypeEnum"); + } + + var raw = reader.Value?.ToString(); + switch (raw) + { + case "change-field-visibility": + return TypeEnum.ChangeFieldVisibility; + case "change-group-visibility": + return TypeEnum.ChangeGroupVisibility; + default: + throw new JsonSerializationException( + $"Unknown wire value for SubFormFieldRuleAction.TypeEnum: {raw}"); + } + } + } + /// /// Gets or Sets Type diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDateSigned.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDateSigned.cs index 485c02d9a..83cfccf2e 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDateSigned.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDateSigned.cs @@ -215,7 +215,7 @@ public static SubFormFieldsPerDocumentDateSigned Init(string jsonData) /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. /// /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. - [DataMember(Name = "font_size", EmitDefaultValue = true)] + [DataMember(Name = "font_size", EmitDefaultValue = false)] public int FontSize { get; set; } /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDropdown.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDropdown.cs index 467103717..91869c0dc 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDropdown.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentDropdown.cs @@ -238,7 +238,7 @@ public static SubFormFieldsPerDocumentDropdown Init(string jsonData) /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. /// /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. - [DataMember(Name = "font_size", EmitDefaultValue = true)] + [DataMember(Name = "font_size", EmitDefaultValue = false)] public int FontSize { get; set; } /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentHyperlink.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentHyperlink.cs index d766865ca..7ab930ec9 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentHyperlink.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentHyperlink.cs @@ -243,7 +243,7 @@ public static SubFormFieldsPerDocumentHyperlink Init(string jsonData) /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. /// /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. - [DataMember(Name = "font_size", EmitDefaultValue = true)] + [DataMember(Name = "font_size", EmitDefaultValue = false)] public int FontSize { get; set; } /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentText.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentText.cs index c514d0f50..429b9c711 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentText.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentText.cs @@ -353,7 +353,7 @@ public static SubFormFieldsPerDocumentText Init(string jsonData) /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. /// /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. - [DataMember(Name = "font_size", EmitDefaultValue = true)] + [DataMember(Name = "font_size", EmitDefaultValue = false)] public int FontSize { get; set; } /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentTextMerge.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentTextMerge.cs index d2d0c6412..ac96ff2cc 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentTextMerge.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubFormFieldsPerDocumentTextMerge.cs @@ -215,7 +215,7 @@ public static SubFormFieldsPerDocumentTextMerge Init(string jsonData) /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. /// /// The initial px font size for the field contents. Can be any integer value between `7` and `49`. **NOTE:** Font size may be reduced during processing in order to fit the contents within the dimensions of the field. - [DataMember(Name = "font_size", EmitDefaultValue = true)] + [DataMember(Name = "font_size", EmitDefaultValue = false)] public int FontSize { get; set; } /// diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/SubSigningOptions.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubSigningOptions.cs index 03e60af0b..da27f470b 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/SubSigningOptions.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubSigningOptions.cs @@ -27,7 +27,7 @@ namespace Dropbox.Sign.Model { /// - /// This allows the requester to specify the types allowed for creating a signature. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + /// This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. /// [DataContract(Name = "SubSigningOptions")] [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] @@ -85,7 +85,8 @@ protected SubSigningOptions() { } /// Allows using a smartphone to email the signature (default to false). /// Allows typing the signature (default to false). /// Allows uploading the signature (default to false). - public SubSigningOptions(DefaultTypeEnum defaultType = default(DefaultTypeEnum), bool draw = false, bool phone = false, bool type = false, bool upload = false) + /// Turning on advanced signature details for the signature request (default to false). + public SubSigningOptions(DefaultTypeEnum defaultType = default(DefaultTypeEnum), bool draw = false, bool phone = false, bool type = false, bool upload = false, bool forceAdvancedSignatureDetails = false) { this.DefaultType = defaultType; @@ -93,6 +94,7 @@ protected SubSigningOptions() { } this.Phone = phone; this.Type = type; this.Upload = upload; + this.ForceAdvancedSignatureDetails = forceAdvancedSignatureDetails; } /// @@ -139,6 +141,13 @@ public static SubSigningOptions Init(string jsonData) [DataMember(Name = "upload", EmitDefaultValue = true)] public bool Upload { get; set; } + /// + /// Turning on advanced signature details for the signature request + /// + /// Turning on advanced signature details for the signature request + [DataMember(Name = "force_advanced_signature_details", EmitDefaultValue = true)] + public bool ForceAdvancedSignatureDetails { get; set; } + /// /// Returns the string presentation of the object /// @@ -152,6 +161,7 @@ public override string ToString() sb.Append(" Phone: ").Append(Phone).Append("\n"); sb.Append(" Type: ").Append(Type).Append("\n"); sb.Append(" Upload: ").Append(Upload).Append("\n"); + sb.Append(" ForceAdvancedSignatureDetails: ").Append(ForceAdvancedSignatureDetails).Append("\n"); sb.Append("}\n"); return sb.ToString(); } @@ -206,6 +216,10 @@ public bool Equals(SubSigningOptions input) ( this.Upload == input.Upload || this.Upload.Equals(input.Upload) + ) && + ( + this.ForceAdvancedSignatureDetails == input.ForceAdvancedSignatureDetails || + this.ForceAdvancedSignatureDetails.Equals(input.ForceAdvancedSignatureDetails) ); } @@ -223,6 +237,7 @@ public override int GetHashCode() hashCode = (hashCode * 59) + this.Phone.GetHashCode(); hashCode = (hashCode * 59) + this.Type.GetHashCode(); hashCode = (hashCode * 59) + this.Upload.GetHashCode(); + hashCode = (hashCode * 59) + this.ForceAdvancedSignatureDetails.GetHashCode(); return hashCode; } } @@ -274,6 +289,13 @@ public List GetOpenApiTypes() Type = "bool", Value = Upload, }); + types.Add(new OpenApiType() + { + Name = "force_advanced_signature_details", + Property = "ForceAdvancedSignatureDetails", + Type = "bool", + Value = ForceAdvancedSignatureDetails, + }); return types; } diff --git a/sdks/dotnet/src/Dropbox.Sign/Model/TemplateEditResponse.cs b/sdks/dotnet/src/Dropbox.Sign/Model/SubUpdateFormField.cs similarity index 51% rename from sdks/dotnet/src/Dropbox.Sign/Model/TemplateEditResponse.cs rename to sdks/dotnet/src/Dropbox.Sign/Model/SubUpdateFormField.cs index f76b5eb4f..18dde7b0f 100644 --- a/sdks/dotnet/src/Dropbox.Sign/Model/TemplateEditResponse.cs +++ b/sdks/dotnet/src/Dropbox.Sign/Model/SubUpdateFormField.cs @@ -27,54 +27,63 @@ namespace Dropbox.Sign.Model { /// - /// TemplateEditResponse + /// SubUpdateFormField /// - [DataContract(Name = "TemplateEditResponse")] + [DataContract(Name = "SubUpdateFormField")] [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] - public partial class TemplateEditResponse : IEquatable, IValidatableObject + public partial class SubUpdateFormField : IEquatable, IValidatableObject { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// [JsonConstructorAttribute] - protected TemplateEditResponse() { } + protected SubUpdateFormField() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The id of the Template. (required). - public TemplateEditResponse(string templateId = default(string)) + /// The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found (required). + /// The new name of the field. If not passed the name will remain unchanged.. + public SubUpdateFormField(string apiId = default(string), string name = default(string)) { - // to ensure "templateId" is required (not null) - if (templateId == null) + // to ensure "apiId" is required (not null) + if (apiId == null) { - throw new ArgumentNullException("templateId is a required property for TemplateEditResponse and cannot be null"); + throw new ArgumentNullException("apiId is a required property for SubUpdateFormField and cannot be null"); } - this.TemplateId = templateId; + this.ApiId = apiId; + this.Name = name; } /// /// Attempt to instantiate and hydrate a new instance of this class /// /// String of JSON data representing target object - public static TemplateEditResponse Init(string jsonData) + public static SubUpdateFormField Init(string jsonData) { - var obj = JsonConvert.DeserializeObject(jsonData); + var obj = JsonConvert.DeserializeObject(jsonData); if (obj == null) { - throw new Exception("Unable to deserialize JSON to instance of TemplateEditResponse"); + throw new Exception("Unable to deserialize JSON to instance of SubUpdateFormField"); } return obj; } /// - /// The id of the Template. + /// The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found /// - /// The id of the Template. - [DataMember(Name = "template_id", IsRequired = true, EmitDefaultValue = true)] - public string TemplateId { get; set; } + /// The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found + [DataMember(Name = "api_id", IsRequired = true, EmitDefaultValue = true)] + public string ApiId { get; set; } + + /// + /// The new name of the field. If not passed the name will remain unchanged. + /// + /// The new name of the field. If not passed the name will remain unchanged. + [DataMember(Name = "name", EmitDefaultValue = true)] + public string Name { get; set; } /// /// Returns the string presentation of the object @@ -83,8 +92,9 @@ public static TemplateEditResponse Init(string jsonData) public override string ToString() { StringBuilder sb = new StringBuilder(); - sb.Append("class TemplateEditResponse {\n"); - sb.Append(" TemplateId: ").Append(TemplateId).Append("\n"); + sb.Append("class SubUpdateFormField {\n"); + sb.Append(" ApiId: ").Append(ApiId).Append("\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); sb.Append("}\n"); return sb.ToString(); } @@ -105,15 +115,15 @@ public virtual string ToJson() /// Boolean public override bool Equals(object input) { - return this.Equals(input as TemplateEditResponse); + return this.Equals(input as SubUpdateFormField); } /// - /// Returns true if TemplateEditResponse instances are equal + /// Returns true if SubUpdateFormField instances are equal /// - /// Instance of TemplateEditResponse to be compared + /// Instance of SubUpdateFormField to be compared /// Boolean - public bool Equals(TemplateEditResponse input) + public bool Equals(SubUpdateFormField input) { if (input == null) { @@ -121,9 +131,14 @@ public bool Equals(TemplateEditResponse input) } return ( - this.TemplateId == input.TemplateId || - (this.TemplateId != null && - this.TemplateId.Equals(input.TemplateId)) + this.ApiId == input.ApiId || + (this.ApiId != null && + this.ApiId.Equals(input.ApiId)) + ) && + ( + this.Name == input.Name || + (this.Name != null && + this.Name.Equals(input.Name)) ); } @@ -136,9 +151,13 @@ public override int GetHashCode() unchecked // Overflow is fine, just wrap { int hashCode = 41; - if (this.TemplateId != null) + if (this.ApiId != null) + { + hashCode = (hashCode * 59) + this.ApiId.GetHashCode(); + } + if (this.Name != null) { - hashCode = (hashCode * 59) + this.TemplateId.GetHashCode(); + hashCode = (hashCode * 59) + this.Name.GetHashCode(); } return hashCode; } @@ -158,10 +177,17 @@ public List GetOpenApiTypes() var types = new List(); types.Add(new OpenApiType() { - Name = "template_id", - Property = "TemplateId", + Name = "api_id", + Property = "ApiId", + Type = "string", + Value = ApiId, + }); + types.Add(new OpenApiType() + { + Name = "name", + Property = "Name", Type = "string", - Value = TemplateId, + Value = Name, }); return types; diff --git a/sdks/java-v1/README.md b/sdks/java-v1/README.md index 50dab15bb..bd8decae3 100644 --- a/sdks/java-v1/README.md +++ b/sdks/java-v1/README.md @@ -256,6 +256,7 @@ Class | Method | HTTP request | Description - [AccountGetResponse](docs/AccountGetResponse.md) - [AccountResponse](docs/AccountResponse.md) - [AccountResponseQuotas](docs/AccountResponseQuotas.md) + - [AccountResponseSettings](docs/AccountResponseSettings.md) - [AccountResponseUsage](docs/AccountResponseUsage.md) - [AccountUpdateRequest](docs/AccountUpdateRequest.md) - [AccountVerifyRequest](docs/AccountVerifyRequest.md) @@ -377,6 +378,7 @@ Class | Method | HTTP request | Description - [SubTemplateRole](docs/SubTemplateRole.md) - [SubUnclaimedDraftSigner](docs/SubUnclaimedDraftSigner.md) - [SubUnclaimedDraftTemplateSigner](docs/SubUnclaimedDraftTemplateSigner.md) + - [SubUpdateFormField](docs/SubUpdateFormField.md) - [SubWhiteLabelingOptions](docs/SubWhiteLabelingOptions.md) - [TeamAddMemberRequest](docs/TeamAddMemberRequest.md) - [TeamCreateRequest](docs/TeamCreateRequest.md) @@ -399,7 +401,6 @@ Class | Method | HTTP request | Description - [TemplateCreateRequest](docs/TemplateCreateRequest.md) - [TemplateCreateResponse](docs/TemplateCreateResponse.md) - [TemplateCreateResponseTemplate](docs/TemplateCreateResponseTemplate.md) - - [TemplateEditResponse](docs/TemplateEditResponse.md) - [TemplateGetResponse](docs/TemplateGetResponse.md) - [TemplateListResponse](docs/TemplateListResponse.md) - [TemplateRemoveUserRequest](docs/TemplateRemoveUserRequest.md) diff --git a/sdks/java-v1/docs/AccountResponse.md b/sdks/java-v1/docs/AccountResponse.md index 5b73aa02d..18ab59fc1 100644 --- a/sdks/java-v1/docs/AccountResponse.md +++ b/sdks/java-v1/docs/AccountResponse.md @@ -19,6 +19,7 @@ | `teamId` | ```String``` | The id of the team account belongs to. | | | `locale` | ```String``` | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | | | `usage` | [```AccountResponseUsage```](AccountResponseUsage.md) | | | +| `settings` | [```AccountResponseSettings```](AccountResponseSettings.md) | | | diff --git a/sdks/java-v1/docs/AccountResponseSettings.md b/sdks/java-v1/docs/AccountResponseSettings.md new file mode 100644 index 000000000..cd139079d --- /dev/null +++ b/sdks/java-v1/docs/AccountResponseSettings.md @@ -0,0 +1,16 @@ + + +# AccountResponseSettings + +Subset of configured settings + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +| `signerAccessCodes` | ```Boolean``` | Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `smsDelivery` | ```Boolean``` | Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `smsAuthentication` | ```Boolean``` | Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | + + + diff --git a/sdks/java-v1/docs/ReportCreateRequest.md b/sdks/java-v1/docs/ReportCreateRequest.md index 78390304c..2d4b11610 100644 --- a/sdks/java-v1/docs/ReportCreateRequest.md +++ b/sdks/java-v1/docs/ReportCreateRequest.md @@ -21,6 +21,7 @@ | USER_ACTIVITY | "user_activity" | | DOCUMENT_STATUS | "document_status" | | SMS_ACTIVITY | "sms_activity" | +| FAX_USAGE | "fax_usage" | diff --git a/sdks/java-v1/docs/ReportResponse.md b/sdks/java-v1/docs/ReportResponse.md index aa74d68e0..bfd56aec6 100644 --- a/sdks/java-v1/docs/ReportResponse.md +++ b/sdks/java-v1/docs/ReportResponse.md @@ -22,6 +22,7 @@ Contains information about the report request. | USER_ACTIVITY | "user_activity" | | DOCUMENT_STATUS | "document_status" | | SMS_ACTIVITY | "sms_activity" | +| FAX_USAGE | "fax_usage" | diff --git a/sdks/java-v1/docs/SignatureRequestApi.md b/sdks/java-v1/docs/SignatureRequestApi.md index 939b10ef3..bf16f02c0 100644 --- a/sdks/java-v1/docs/SignatureRequestApi.md +++ b/sdks/java-v1/docs/SignatureRequestApi.md @@ -459,6 +459,7 @@ public class SignatureRequestCreateEmbeddedExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); @@ -579,6 +580,7 @@ public class SignatureRequestCreateEmbeddedWithTemplateExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); @@ -1874,6 +1876,7 @@ public class SignatureRequestSendExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); @@ -2000,6 +2003,7 @@ public class SignatureRequestSendWithTemplateExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); diff --git a/sdks/java-v1/docs/SignatureRequestEditRequest.md b/sdks/java-v1/docs/SignatureRequestEditRequest.md index 7fa3aca65..b4705fe97 100644 --- a/sdks/java-v1/docs/SignatureRequestEditRequest.md +++ b/sdks/java-v1/docs/SignatureRequestEditRequest.md @@ -23,7 +23,7 @@ | `formFieldRules` | [```List```](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | | | `formFieldsPerDocument` | [```List```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hideTextTags` | ```Boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v1/docs/SignatureRequestEditWithTemplateRequest.md b/sdks/java-v1/docs/SignatureRequestEditWithTemplateRequest.md index d079524b1..42095fa8b 100644 --- a/sdks/java-v1/docs/SignatureRequestEditWithTemplateRequest.md +++ b/sdks/java-v1/docs/SignatureRequestEditWithTemplateRequest.md @@ -16,7 +16,7 @@ | `customFields` | [```List```](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | | | `files` | ```List``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `fileUrls` | ```List``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v1/docs/SignatureRequestSendRequest.md b/sdks/java-v1/docs/SignatureRequestSendRequest.md index 914303935..a34284aa2 100644 --- a/sdks/java-v1/docs/SignatureRequestSendRequest.md +++ b/sdks/java-v1/docs/SignatureRequestSendRequest.md @@ -24,7 +24,7 @@ | `formFieldsPerDocument` | [```List```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hideTextTags` | ```Boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | | | `isQualifiedSignature` | ```Boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v1/docs/SignatureRequestSendWithTemplateRequest.md b/sdks/java-v1/docs/SignatureRequestSendWithTemplateRequest.md index 7a8d8c88a..425ccff28 100644 --- a/sdks/java-v1/docs/SignatureRequestSendWithTemplateRequest.md +++ b/sdks/java-v1/docs/SignatureRequestSendWithTemplateRequest.md @@ -17,7 +17,7 @@ | `files` | ```List``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `fileUrls` | ```List``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `isQualifiedSignature` | ```Boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v1/docs/SubSigningOptions.md b/sdks/java-v1/docs/SubSigningOptions.md index bca116053..6f419c3a2 100644 --- a/sdks/java-v1/docs/SubSigningOptions.md +++ b/sdks/java-v1/docs/SubSigningOptions.md @@ -2,10 +2,12 @@ # SubSigningOptions -This allows the requester to specify the types allowed for creating a signature. +This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. +**NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. + ## Properties | Name | Type | Description | Notes | @@ -15,6 +17,7 @@ This allows the requester to specify the types allowed for creating a signature. | `phone` | ```Boolean``` | Allows using a smartphone to email the signature | | | `type` | ```Boolean``` | Allows typing the signature | | | `upload` | ```Boolean``` | Allows uploading the signature | | +| `forceAdvancedSignatureDetails` | ```Boolean``` | Turning on advanced signature details for the signature request | | diff --git a/sdks/java-v1/docs/SubUpdateFormField.md b/sdks/java-v1/docs/SubUpdateFormField.md new file mode 100644 index 000000000..0f09c17e9 --- /dev/null +++ b/sdks/java-v1/docs/SubUpdateFormField.md @@ -0,0 +1,15 @@ + + +# SubUpdateFormField + + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +| `apiId`*_required_ | ```String``` | The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found | | +| `name` | ```String``` | The new name of the field. If not passed the name will remain unchanged. | | + + + diff --git a/sdks/java-v1/docs/TemplateApi.md b/sdks/java-v1/docs/TemplateApi.md index dd470487b..e9233865f 100644 --- a/sdks/java-v1/docs/TemplateApi.md +++ b/sdks/java-v1/docs/TemplateApi.md @@ -111,7 +111,11 @@ public class TemplateAddUserExample Create Template -Creates a template that can then be used. +Creates a template that can be used in future signature requests. + +If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). + +Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. ### Example diff --git a/sdks/java-v1/docs/TemplateEditResponse.md b/sdks/java-v1/docs/TemplateEditResponse.md deleted file mode 100644 index 88d225e68..000000000 --- a/sdks/java-v1/docs/TemplateEditResponse.md +++ /dev/null @@ -1,14 +0,0 @@ - - -# TemplateEditResponse - - - -## Properties - -| Name | Type | Description | Notes | -|------------ | ------------- | ------------- | -------------| -| `templateId`*_required_ | ```String``` | The id of the Template. | | - - - diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/api/TemplateApi.java b/sdks/java-v1/src/main/java/com/dropbox/sign/api/TemplateApi.java index 14eeae070..f70c0134b 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/api/TemplateApi.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/api/TemplateApi.java @@ -144,7 +144,18 @@ public ApiResponse templateAddUserWithHttpInfo( } /** - * Create Template Creates a template that can then be used. + * Create Template Creates a template that can be used in future signature requests. If + * `client_id` is provided, the template will be created as an embedded template. + * Embedded templates can be used for embedded signature requests and can be edited later by + * generating a new `edit_url` with + * [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template + * creation may complete asynchronously after the initial request is accepted. It is recommended + * that a callback be implemented to listen for the callback event. A + * `template_created` event indicates the template is ready to use, while a + * `template_error` event indicates there was a problem while creating the template. + * If a callback handler has been configured and the event has not been received within 60 + * minutes of making the call, check the status of the request in the API dashboard and retry + * the request if necessary. * * @param templateCreateRequest (required) * @return TemplateCreateResponse @@ -163,7 +174,18 @@ public TemplateCreateResponse templateCreate(TemplateCreateRequest templateCreat } /** - * Create Template Creates a template that can then be used. + * Create Template Creates a template that can be used in future signature requests. If + * `client_id` is provided, the template will be created as an embedded template. + * Embedded templates can be used for embedded signature requests and can be edited later by + * generating a new `edit_url` with + * [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template + * creation may complete asynchronously after the initial request is accepted. It is recommended + * that a callback be implemented to listen for the callback event. A + * `template_created` event indicates the template is ready to use, while a + * `template_error` event indicates there was a problem while creating the template. + * If a callback handler has been configured and the event has not been received within 60 + * minutes of making the call, check the status of the request in the API dashboard and retry + * the request if necessary. * * @param templateCreateRequest (required) * @return ApiResponse<TemplateCreateResponse> diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/AccountResponse.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/AccountResponse.java index 02ee9cf83..7d694847b 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/AccountResponse.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/AccountResponse.java @@ -35,7 +35,8 @@ AccountResponse.JSON_PROPERTY_ROLE_CODE, AccountResponse.JSON_PROPERTY_TEAM_ID, AccountResponse.JSON_PROPERTY_LOCALE, - AccountResponse.JSON_PROPERTY_USAGE + AccountResponse.JSON_PROPERTY_USAGE, + AccountResponse.JSON_PROPERTY_SETTINGS }) @javax.annotation.Generated( value = "org.openapitools.codegen.languages.JavaClientCodegen", @@ -75,6 +76,9 @@ public class AccountResponse { public static final String JSON_PROPERTY_USAGE = "usage"; @javax.annotation.Nullable private AccountResponseUsage usage; + public static final String JSON_PROPERTY_SETTINGS = "settings"; + @javax.annotation.Nullable private AccountResponseSettings settings; + public AccountResponse() {} /** @@ -335,6 +339,28 @@ public void setUsage(@javax.annotation.Nullable AccountResponseUsage usage) { this.usage = usage; } + public AccountResponse settings(@javax.annotation.Nullable AccountResponseSettings settings) { + this.settings = settings; + return this; + } + + /** + * Get settings + * + * @return settings + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_SETTINGS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public AccountResponseSettings getSettings() { + return settings; + } + + @JsonProperty(JSON_PROPERTY_SETTINGS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSettings(@javax.annotation.Nullable AccountResponseSettings settings) { + this.settings = settings; + } + /** Return true if this AccountResponse object is equal to o. */ @Override public boolean equals(Object o) { @@ -355,7 +381,8 @@ public boolean equals(Object o) { && Objects.equals(this.roleCode, accountResponse.roleCode) && Objects.equals(this.teamId, accountResponse.teamId) && Objects.equals(this.locale, accountResponse.locale) - && Objects.equals(this.usage, accountResponse.usage); + && Objects.equals(this.usage, accountResponse.usage) + && Objects.equals(this.settings, accountResponse.settings); } @Override @@ -371,7 +398,8 @@ public int hashCode() { roleCode, teamId, locale, - usage); + usage, + settings); } @Override @@ -389,6 +417,7 @@ public String toString() { sb.append(" teamId: ").append(toIndentedString(teamId)).append("\n"); sb.append(" locale: ").append(toIndentedString(locale)).append("\n"); sb.append(" usage: ").append(toIndentedString(usage)).append("\n"); + sb.append(" settings: ").append(toIndentedString(settings)).append("\n"); sb.append("}"); return sb.toString(); } @@ -609,6 +638,24 @@ public Map createFormData() throws ApiException { map.put("usage", JSON.getDefault().getMapper().writeValueAsString(usage)); } } + if (settings != null) { + if (isFileTypeOrListOfFiles(settings)) { + fileTypeFound = true; + } + + if (settings.getClass().equals(java.io.File.class) + || settings.getClass().equals(Integer.class) + || settings.getClass().equals(String.class) + || settings.getClass().isEnum()) { + map.put("settings", settings); + } else if (isListOfFile(settings)) { + for (int i = 0; i < getListSize(settings); i++) { + map.put("settings[" + i + "]", getFromList(settings, i)); + } + } else { + map.put("settings", JSON.getDefault().getMapper().writeValueAsString(settings)); + } + } } catch (Exception e) { throw new ApiException(e); } diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/AccountResponseSettings.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/AccountResponseSettings.java new file mode 100644 index 000000000..1f43c1d3a --- /dev/null +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/AccountResponseSettings.java @@ -0,0 +1,278 @@ +/* + * Dropbox Sign API + * Dropbox Sign v3 API + * + * The version of the OpenAPI document: 3.0.0 + * Contact: apisupport@hellosign.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package com.dropbox.sign.model; + +import com.dropbox.sign.ApiException; +import com.dropbox.sign.JSON; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** Subset of configured settings */ +@JsonPropertyOrder({ + AccountResponseSettings.JSON_PROPERTY_SIGNER_ACCESS_CODES, + AccountResponseSettings.JSON_PROPERTY_SMS_DELIVERY, + AccountResponseSettings.JSON_PROPERTY_SMS_AUTHENTICATION +}) +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + comments = "Generator version: 7.12.0") +@JsonIgnoreProperties(ignoreUnknown = true) +public class AccountResponseSettings { + public static final String JSON_PROPERTY_SIGNER_ACCESS_CODES = "signer_access_codes"; + @javax.annotation.Nullable private Boolean signerAccessCodes; + + public static final String JSON_PROPERTY_SMS_DELIVERY = "sms_delivery"; + @javax.annotation.Nullable private Boolean smsDelivery; + + public static final String JSON_PROPERTY_SMS_AUTHENTICATION = "sms_authentication"; + @javax.annotation.Nullable private Boolean smsAuthentication; + + public AccountResponseSettings() {} + + /** + * Attempt to instantiate and hydrate a new instance of this class + * + * @param jsonData String of JSON data representing target object + */ + public static AccountResponseSettings init(String jsonData) throws Exception { + return new ObjectMapper().readValue(jsonData, AccountResponseSettings.class); + } + + public static AccountResponseSettings init(HashMap data) throws Exception { + return new ObjectMapper() + .readValue( + new ObjectMapper().writeValueAsString(data), AccountResponseSettings.class); + } + + public AccountResponseSettings signerAccessCodes( + @javax.annotation.Nullable Boolean signerAccessCodes) { + this.signerAccessCodes = signerAccessCodes; + return this; + } + + /** + * Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read + * more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * + * @return signerAccessCodes + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_SIGNER_ACCESS_CODES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Boolean getSignerAccessCodes() { + return signerAccessCodes; + } + + @JsonProperty(JSON_PROPERTY_SIGNER_ACCESS_CODES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSignerAccessCodes(@javax.annotation.Nullable Boolean signerAccessCodes) { + this.signerAccessCodes = signerAccessCodes; + } + + public AccountResponseSettings smsDelivery(@javax.annotation.Nullable Boolean smsDelivery) { + this.smsDelivery = smsDelivery; + return this; + } + + /** + * Returns `true` if _Text message_ is enabled in Admin Console. [Read + * more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * + * @return smsDelivery + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_SMS_DELIVERY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Boolean getSmsDelivery() { + return smsDelivery; + } + + @JsonProperty(JSON_PROPERTY_SMS_DELIVERY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSmsDelivery(@javax.annotation.Nullable Boolean smsDelivery) { + this.smsDelivery = smsDelivery; + } + + public AccountResponseSettings smsAuthentication( + @javax.annotation.Nullable Boolean smsAuthentication) { + this.smsAuthentication = smsAuthentication; + return this; + } + + /** + * Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read + * more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * + * @return smsAuthentication + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_SMS_AUTHENTICATION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Boolean getSmsAuthentication() { + return smsAuthentication; + } + + @JsonProperty(JSON_PROPERTY_SMS_AUTHENTICATION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSmsAuthentication(@javax.annotation.Nullable Boolean smsAuthentication) { + this.smsAuthentication = smsAuthentication; + } + + /** Return true if this AccountResponseSettings object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AccountResponseSettings accountResponseSettings = (AccountResponseSettings) o; + return Objects.equals(this.signerAccessCodes, accountResponseSettings.signerAccessCodes) + && Objects.equals(this.smsDelivery, accountResponseSettings.smsDelivery) + && Objects.equals( + this.smsAuthentication, accountResponseSettings.smsAuthentication); + } + + @Override + public int hashCode() { + return Objects.hash(signerAccessCodes, smsDelivery, smsAuthentication); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AccountResponseSettings {\n"); + sb.append(" signerAccessCodes: ") + .append(toIndentedString(signerAccessCodes)) + .append("\n"); + sb.append(" smsDelivery: ").append(toIndentedString(smsDelivery)).append("\n"); + sb.append(" smsAuthentication: ") + .append(toIndentedString(smsAuthentication)) + .append("\n"); + sb.append("}"); + return sb.toString(); + } + + public Map createFormData() throws ApiException { + Map map = new HashMap<>(); + boolean fileTypeFound = false; + try { + if (signerAccessCodes != null) { + if (isFileTypeOrListOfFiles(signerAccessCodes)) { + fileTypeFound = true; + } + + if (signerAccessCodes.getClass().equals(java.io.File.class) + || signerAccessCodes.getClass().equals(Integer.class) + || signerAccessCodes.getClass().equals(String.class) + || signerAccessCodes.getClass().isEnum()) { + map.put("signer_access_codes", signerAccessCodes); + } else if (isListOfFile(signerAccessCodes)) { + for (int i = 0; i < getListSize(signerAccessCodes); i++) { + map.put( + "signer_access_codes[" + i + "]", + getFromList(signerAccessCodes, i)); + } + } else { + map.put( + "signer_access_codes", + JSON.getDefault().getMapper().writeValueAsString(signerAccessCodes)); + } + } + if (smsDelivery != null) { + if (isFileTypeOrListOfFiles(smsDelivery)) { + fileTypeFound = true; + } + + if (smsDelivery.getClass().equals(java.io.File.class) + || smsDelivery.getClass().equals(Integer.class) + || smsDelivery.getClass().equals(String.class) + || smsDelivery.getClass().isEnum()) { + map.put("sms_delivery", smsDelivery); + } else if (isListOfFile(smsDelivery)) { + for (int i = 0; i < getListSize(smsDelivery); i++) { + map.put("sms_delivery[" + i + "]", getFromList(smsDelivery, i)); + } + } else { + map.put( + "sms_delivery", + JSON.getDefault().getMapper().writeValueAsString(smsDelivery)); + } + } + if (smsAuthentication != null) { + if (isFileTypeOrListOfFiles(smsAuthentication)) { + fileTypeFound = true; + } + + if (smsAuthentication.getClass().equals(java.io.File.class) + || smsAuthentication.getClass().equals(Integer.class) + || smsAuthentication.getClass().equals(String.class) + || smsAuthentication.getClass().isEnum()) { + map.put("sms_authentication", smsAuthentication); + } else if (isListOfFile(smsAuthentication)) { + for (int i = 0; i < getListSize(smsAuthentication); i++) { + map.put("sms_authentication[" + i + "]", getFromList(smsAuthentication, i)); + } + } else { + map.put( + "sms_authentication", + JSON.getDefault().getMapper().writeValueAsString(smsAuthentication)); + } + } + } catch (Exception e) { + throw new ApiException(e); + } + + return fileTypeFound ? map : new HashMap<>(); + } + + private boolean isFileTypeOrListOfFiles(Object obj) throws Exception { + return obj.getClass().equals(java.io.File.class) || isListOfFile(obj); + } + + private boolean isListOfFile(Object obj) throws Exception { + return obj instanceof java.util.List + && !isListEmpty(obj) + && getFromList(obj, 0) instanceof java.io.File; + } + + private boolean isListEmpty(Object obj) throws Exception { + return (boolean) + Class.forName(java.util.List.class.getName()).getMethod("isEmpty").invoke(obj); + } + + private Object getFromList(Object obj, int index) throws Exception { + return Class.forName(java.util.List.class.getName()) + .getMethod("get", int.class) + .invoke(obj, index); + } + + private int getListSize(Object obj) throws Exception { + return (int) Class.forName(java.util.List.class.getName()).getMethod("size").invoke(obj); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java index 38e625dc3..3efd6b860 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java @@ -47,7 +47,9 @@ public enum ReportTypeEnum { DOCUMENT_STATUS(String.valueOf("document_status")), - SMS_ACTIVITY(String.valueOf("sms_activity")); + SMS_ACTIVITY(String.valueOf("sms_activity")), + + FAX_USAGE(String.valueOf("fax_usage")); private String value; diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportResponse.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportResponse.java index 6d5079f54..b919980cf 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportResponse.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/ReportResponse.java @@ -54,7 +54,9 @@ public enum ReportTypeEnum { DOCUMENT_STATUS(String.valueOf("document_status")), - SMS_ACTIVITY(String.valueOf("sms_activity")); + SMS_ACTIVITY(String.valueOf("sms_activity")), + + FAX_USAGE(String.valueOf("fax_usage")); private String value; diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java index 0173d32e5..85a485a07 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java @@ -631,9 +631,10 @@ public SignatureRequestEditRequest isEid(@javax.annotation.Nullable Boolean isEi /** * Send with a value of `true` if you wish to enable [electronic identification * (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify - * their identity with an eID provider to sign a document.<br> **NOTE:** eID is only - * available on the Premium API plan. Cannot be used in `test_mode`. Only works on - * requests with one signer. + * their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID + * add-on to use this feature. Please [contact + * sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in + * `test_mode`. Only works on requests with one signer. * * @return isEid */ diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java index c49c66ff3..21daacc77 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java @@ -369,9 +369,10 @@ public SignatureRequestEditWithTemplateRequest isEid(@javax.annotation.Nullable /** * Send with a value of `true` if you wish to enable [electronic identification * (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify - * their identity with an eID provider to sign a document.<br> **NOTE:** eID is only - * available on the Premium API plan. Cannot be used in `test_mode`. Only works on - * requests with one signer. + * their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID + * add-on to use this feature. Please [contact + * sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in + * `test_mode`. Only works on requests with one signer. * * @return isEid */ diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java index 252b39102..912bf0f17 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java @@ -666,9 +666,10 @@ public SignatureRequestSendRequest isEid(@javax.annotation.Nullable Boolean isEi /** * Send with a value of `true` if you wish to enable [electronic identification * (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify - * their identity with an eID provider to sign a document.<br> **NOTE:** eID is only - * available on the Premium API plan. Cannot be used in `test_mode`. Only works on - * requests with one signer. + * their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID + * add-on to use this feature. Please [contact + * sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in + * `test_mode`. Only works on requests with one signer. * * @return isEid */ diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java index eba4b1488..0c0055e43 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java @@ -404,9 +404,10 @@ public SignatureRequestSendWithTemplateRequest isEid(@javax.annotation.Nullable /** * Send with a value of `true` if you wish to enable [electronic identification * (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify - * their identity with an eID provider to sign a document.<br> **NOTE:** eID is only - * available on the Premium API plan. Cannot be used in `test_mode`. Only works on - * requests with one signer. + * their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID + * add-on to use this feature. Please [contact + * sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in + * `test_mode`. Only works on requests with one signer. * * @return isEid */ diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SubSigningOptions.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SubSigningOptions.java index 0dea6a670..6b9c493da 100644 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SubSigningOptions.java +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SubSigningOptions.java @@ -26,16 +26,18 @@ import java.util.Objects; /** - * This allows the requester to specify the types allowed for creating a signature. **NOTE:** If - * `signing_options` are not defined in the request, the allowed types will default to - * those specified in the account settings. + * This allows the requester to specify the types allowed for creating a signature and specify + * another signing options. **NOTE:** If `signing_options` are not defined in the request, + * the allowed types will default to those specified in the account settings. **NOTE:** If + * `force_advanced_signature_details` is set, allowed types has to be defined too. */ @JsonPropertyOrder({ SubSigningOptions.JSON_PROPERTY_DEFAULT_TYPE, SubSigningOptions.JSON_PROPERTY_DRAW, SubSigningOptions.JSON_PROPERTY_PHONE, SubSigningOptions.JSON_PROPERTY_TYPE, - SubSigningOptions.JSON_PROPERTY_UPLOAD + SubSigningOptions.JSON_PROPERTY_UPLOAD, + SubSigningOptions.JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS }) @javax.annotation.Generated( value = "org.openapitools.codegen.languages.JavaClientCodegen", @@ -94,6 +96,10 @@ public static DefaultTypeEnum fromValue(String value) { public static final String JSON_PROPERTY_UPLOAD = "upload"; @javax.annotation.Nullable private Boolean upload = false; + public static final String JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS = + "force_advanced_signature_details"; + @javax.annotation.Nullable private Boolean forceAdvancedSignatureDetails = false; + public SubSigningOptions() {} /** @@ -221,6 +227,30 @@ public void setUpload(@javax.annotation.Nullable Boolean upload) { this.upload = upload; } + public SubSigningOptions forceAdvancedSignatureDetails( + @javax.annotation.Nullable Boolean forceAdvancedSignatureDetails) { + this.forceAdvancedSignatureDetails = forceAdvancedSignatureDetails; + return this; + } + + /** + * Turning on advanced signature details for the signature request + * + * @return forceAdvancedSignatureDetails + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Boolean getForceAdvancedSignatureDetails() { + return forceAdvancedSignatureDetails; + } + + @JsonProperty(JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setForceAdvancedSignatureDetails( + @javax.annotation.Nullable Boolean forceAdvancedSignatureDetails) { + this.forceAdvancedSignatureDetails = forceAdvancedSignatureDetails; + } + /** Return true if this SubSigningOptions object is equal to o. */ @Override public boolean equals(Object o) { @@ -235,12 +265,15 @@ public boolean equals(Object o) { && Objects.equals(this.draw, subSigningOptions.draw) && Objects.equals(this.phone, subSigningOptions.phone) && Objects.equals(this.type, subSigningOptions.type) - && Objects.equals(this.upload, subSigningOptions.upload); + && Objects.equals(this.upload, subSigningOptions.upload) + && Objects.equals( + this.forceAdvancedSignatureDetails, + subSigningOptions.forceAdvancedSignatureDetails); } @Override public int hashCode() { - return Objects.hash(defaultType, draw, phone, type, upload); + return Objects.hash(defaultType, draw, phone, type, upload, forceAdvancedSignatureDetails); } @Override @@ -252,6 +285,9 @@ public String toString() { sb.append(" phone: ").append(toIndentedString(phone)).append("\n"); sb.append(" type: ").append(toIndentedString(type)).append("\n"); sb.append(" upload: ").append(toIndentedString(upload)).append("\n"); + sb.append(" forceAdvancedSignatureDetails: ") + .append(toIndentedString(forceAdvancedSignatureDetails)) + .append("\n"); sb.append("}"); return sb.toString(); } @@ -352,6 +388,30 @@ public Map createFormData() throws ApiException { map.put("upload", JSON.getDefault().getMapper().writeValueAsString(upload)); } } + if (forceAdvancedSignatureDetails != null) { + if (isFileTypeOrListOfFiles(forceAdvancedSignatureDetails)) { + fileTypeFound = true; + } + + if (forceAdvancedSignatureDetails.getClass().equals(java.io.File.class) + || forceAdvancedSignatureDetails.getClass().equals(Integer.class) + || forceAdvancedSignatureDetails.getClass().equals(String.class) + || forceAdvancedSignatureDetails.getClass().isEnum()) { + map.put("force_advanced_signature_details", forceAdvancedSignatureDetails); + } else if (isListOfFile(forceAdvancedSignatureDetails)) { + for (int i = 0; i < getListSize(forceAdvancedSignatureDetails); i++) { + map.put( + "force_advanced_signature_details[" + i + "]", + getFromList(forceAdvancedSignatureDetails, i)); + } + } else { + map.put( + "force_advanced_signature_details", + JSON.getDefault() + .getMapper() + .writeValueAsString(forceAdvancedSignatureDetails)); + } + } } catch (Exception e) { throw new ApiException(e); } diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/SubUpdateFormField.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SubUpdateFormField.java new file mode 100644 index 000000000..65e0fe1c9 --- /dev/null +++ b/sdks/java-v1/src/main/java/com/dropbox/sign/model/SubUpdateFormField.java @@ -0,0 +1,212 @@ +/* + * Dropbox Sign API + * Dropbox Sign v3 API + * + * The version of the OpenAPI document: 3.0.0 + * Contact: apisupport@hellosign.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package com.dropbox.sign.model; + +import com.dropbox.sign.ApiException; +import com.dropbox.sign.JSON; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** SubUpdateFormField */ +@JsonPropertyOrder({SubUpdateFormField.JSON_PROPERTY_API_ID, SubUpdateFormField.JSON_PROPERTY_NAME}) +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + comments = "Generator version: 7.12.0") +@JsonIgnoreProperties(ignoreUnknown = true) +public class SubUpdateFormField { + public static final String JSON_PROPERTY_API_ID = "api_id"; + @javax.annotation.Nonnull private String apiId; + + public static final String JSON_PROPERTY_NAME = "name"; + @javax.annotation.Nullable private String name; + + public SubUpdateFormField() {} + + /** + * Attempt to instantiate and hydrate a new instance of this class + * + * @param jsonData String of JSON data representing target object + */ + public static SubUpdateFormField init(String jsonData) throws Exception { + return new ObjectMapper().readValue(jsonData, SubUpdateFormField.class); + } + + public static SubUpdateFormField init(HashMap data) throws Exception { + return new ObjectMapper() + .readValue(new ObjectMapper().writeValueAsString(data), SubUpdateFormField.class); + } + + public SubUpdateFormField apiId(@javax.annotation.Nonnull String apiId) { + this.apiId = apiId; + return this; + } + + /** + * The unique ID for this field. The endpoint will update an existing field with matching + * `api_id`, and warn you if no matches are found + * + * @return apiId + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_API_ID) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getApiId() { + return apiId; + } + + @JsonProperty(JSON_PROPERTY_API_ID) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setApiId(@javax.annotation.Nonnull String apiId) { + this.apiId = apiId; + } + + public SubUpdateFormField name(@javax.annotation.Nullable String name) { + this.name = name; + return this; + } + + /** + * The new name of the field. If not passed the name will remain unchanged. + * + * @return name + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getName() { + return name; + } + + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setName(@javax.annotation.Nullable String name) { + this.name = name; + } + + /** Return true if this SubUpdateFormField object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SubUpdateFormField subUpdateFormField = (SubUpdateFormField) o; + return Objects.equals(this.apiId, subUpdateFormField.apiId) + && Objects.equals(this.name, subUpdateFormField.name); + } + + @Override + public int hashCode() { + return Objects.hash(apiId, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SubUpdateFormField {\n"); + sb.append(" apiId: ").append(toIndentedString(apiId)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + public Map createFormData() throws ApiException { + Map map = new HashMap<>(); + boolean fileTypeFound = false; + try { + if (apiId != null) { + if (isFileTypeOrListOfFiles(apiId)) { + fileTypeFound = true; + } + + if (apiId.getClass().equals(java.io.File.class) + || apiId.getClass().equals(Integer.class) + || apiId.getClass().equals(String.class) + || apiId.getClass().isEnum()) { + map.put("api_id", apiId); + } else if (isListOfFile(apiId)) { + for (int i = 0; i < getListSize(apiId); i++) { + map.put("api_id[" + i + "]", getFromList(apiId, i)); + } + } else { + map.put("api_id", JSON.getDefault().getMapper().writeValueAsString(apiId)); + } + } + if (name != null) { + if (isFileTypeOrListOfFiles(name)) { + fileTypeFound = true; + } + + if (name.getClass().equals(java.io.File.class) + || name.getClass().equals(Integer.class) + || name.getClass().equals(String.class) + || name.getClass().isEnum()) { + map.put("name", name); + } else if (isListOfFile(name)) { + for (int i = 0; i < getListSize(name); i++) { + map.put("name[" + i + "]", getFromList(name, i)); + } + } else { + map.put("name", JSON.getDefault().getMapper().writeValueAsString(name)); + } + } + } catch (Exception e) { + throw new ApiException(e); + } + + return fileTypeFound ? map : new HashMap<>(); + } + + private boolean isFileTypeOrListOfFiles(Object obj) throws Exception { + return obj.getClass().equals(java.io.File.class) || isListOfFile(obj); + } + + private boolean isListOfFile(Object obj) throws Exception { + return obj instanceof java.util.List + && !isListEmpty(obj) + && getFromList(obj, 0) instanceof java.io.File; + } + + private boolean isListEmpty(Object obj) throws Exception { + return (boolean) + Class.forName(java.util.List.class.getName()).getMethod("isEmpty").invoke(obj); + } + + private Object getFromList(Object obj, int index) throws Exception { + return Class.forName(java.util.List.class.getName()) + .getMethod("get", int.class) + .invoke(obj, index); + } + + private int getListSize(Object obj) throws Exception { + return (int) Class.forName(java.util.List.class.getName()).getMethod("size").invoke(obj); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/sdks/java-v1/src/main/java/com/dropbox/sign/model/TemplateEditResponse.java b/sdks/java-v1/src/main/java/com/dropbox/sign/model/TemplateEditResponse.java deleted file mode 100644 index 095b796a1..000000000 --- a/sdks/java-v1/src/main/java/com/dropbox/sign/model/TemplateEditResponse.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Dropbox Sign API - * Dropbox Sign v3 API - * - * The version of the OpenAPI document: 3.0.0 - * Contact: apisupport@hellosign.com - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -package com.dropbox.sign.model; - -import com.dropbox.sign.ApiException; -import com.dropbox.sign.JSON; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** TemplateEditResponse */ -@JsonPropertyOrder({TemplateEditResponse.JSON_PROPERTY_TEMPLATE_ID}) -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - comments = "Generator version: 7.12.0") -@JsonIgnoreProperties(ignoreUnknown = true) -public class TemplateEditResponse { - public static final String JSON_PROPERTY_TEMPLATE_ID = "template_id"; - @javax.annotation.Nonnull private String templateId; - - public TemplateEditResponse() {} - - /** - * Attempt to instantiate and hydrate a new instance of this class - * - * @param jsonData String of JSON data representing target object - */ - public static TemplateEditResponse init(String jsonData) throws Exception { - return new ObjectMapper().readValue(jsonData, TemplateEditResponse.class); - } - - public static TemplateEditResponse init(HashMap data) throws Exception { - return new ObjectMapper() - .readValue(new ObjectMapper().writeValueAsString(data), TemplateEditResponse.class); - } - - public TemplateEditResponse templateId(@javax.annotation.Nonnull String templateId) { - this.templateId = templateId; - return this; - } - - /** - * The id of the Template. - * - * @return templateId - */ - @javax.annotation.Nonnull - @JsonProperty(JSON_PROPERTY_TEMPLATE_ID) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - public String getTemplateId() { - return templateId; - } - - @JsonProperty(JSON_PROPERTY_TEMPLATE_ID) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setTemplateId(@javax.annotation.Nonnull String templateId) { - this.templateId = templateId; - } - - /** Return true if this TemplateEditResponse object is equal to o. */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TemplateEditResponse templateEditResponse = (TemplateEditResponse) o; - return Objects.equals(this.templateId, templateEditResponse.templateId); - } - - @Override - public int hashCode() { - return Objects.hash(templateId); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class TemplateEditResponse {\n"); - sb.append(" templateId: ").append(toIndentedString(templateId)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - public Map createFormData() throws ApiException { - Map map = new HashMap<>(); - boolean fileTypeFound = false; - try { - if (templateId != null) { - if (isFileTypeOrListOfFiles(templateId)) { - fileTypeFound = true; - } - - if (templateId.getClass().equals(java.io.File.class) - || templateId.getClass().equals(Integer.class) - || templateId.getClass().equals(String.class) - || templateId.getClass().isEnum()) { - map.put("template_id", templateId); - } else if (isListOfFile(templateId)) { - for (int i = 0; i < getListSize(templateId); i++) { - map.put("template_id[" + i + "]", getFromList(templateId, i)); - } - } else { - map.put( - "template_id", - JSON.getDefault().getMapper().writeValueAsString(templateId)); - } - } - } catch (Exception e) { - throw new ApiException(e); - } - - return fileTypeFound ? map : new HashMap<>(); - } - - private boolean isFileTypeOrListOfFiles(Object obj) throws Exception { - return obj.getClass().equals(java.io.File.class) || isListOfFile(obj); - } - - private boolean isListOfFile(Object obj) throws Exception { - return obj instanceof java.util.List - && !isListEmpty(obj) - && getFromList(obj, 0) instanceof java.io.File; - } - - private boolean isListEmpty(Object obj) throws Exception { - return (boolean) - Class.forName(java.util.List.class.getName()).getMethod("isEmpty").invoke(obj); - } - - private Object getFromList(Object obj, int index) throws Exception { - return Class.forName(java.util.List.class.getName()) - .getMethod("get", int.class) - .invoke(obj, index); - } - - private int getListSize(Object obj) throws Exception { - return (int) Class.forName(java.util.List.class.getName()).getMethod("size").invoke(obj); - } - - /** - * Convert the given object to string with each line indented by 4 spaces (except the first - * line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} diff --git a/sdks/java-v2/README.md b/sdks/java-v2/README.md index bf70604a9..f498e99e7 100644 --- a/sdks/java-v2/README.md +++ b/sdks/java-v2/README.md @@ -232,6 +232,7 @@ Class | Method | HTTP request | Description - [AccountGetResponse](docs/AccountGetResponse.md) - [AccountResponse](docs/AccountResponse.md) - [AccountResponseQuotas](docs/AccountResponseQuotas.md) + - [AccountResponseSettings](docs/AccountResponseSettings.md) - [AccountResponseUsage](docs/AccountResponseUsage.md) - [AccountUpdateRequest](docs/AccountUpdateRequest.md) - [AccountVerifyRequest](docs/AccountVerifyRequest.md) @@ -353,6 +354,7 @@ Class | Method | HTTP request | Description - [SubTemplateRole](docs/SubTemplateRole.md) - [SubUnclaimedDraftSigner](docs/SubUnclaimedDraftSigner.md) - [SubUnclaimedDraftTemplateSigner](docs/SubUnclaimedDraftTemplateSigner.md) + - [SubUpdateFormField](docs/SubUpdateFormField.md) - [SubWhiteLabelingOptions](docs/SubWhiteLabelingOptions.md) - [TeamAddMemberRequest](docs/TeamAddMemberRequest.md) - [TeamCreateRequest](docs/TeamCreateRequest.md) @@ -375,7 +377,6 @@ Class | Method | HTTP request | Description - [TemplateCreateRequest](docs/TemplateCreateRequest.md) - [TemplateCreateResponse](docs/TemplateCreateResponse.md) - [TemplateCreateResponseTemplate](docs/TemplateCreateResponseTemplate.md) - - [TemplateEditResponse](docs/TemplateEditResponse.md) - [TemplateGetResponse](docs/TemplateGetResponse.md) - [TemplateListResponse](docs/TemplateListResponse.md) - [TemplateRemoveUserRequest](docs/TemplateRemoveUserRequest.md) diff --git a/sdks/java-v2/docs/AccountResponse.md b/sdks/java-v2/docs/AccountResponse.md index 5b73aa02d..18ab59fc1 100644 --- a/sdks/java-v2/docs/AccountResponse.md +++ b/sdks/java-v2/docs/AccountResponse.md @@ -19,6 +19,7 @@ | `teamId` | ```String``` | The id of the team account belongs to. | | | `locale` | ```String``` | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | | | `usage` | [```AccountResponseUsage```](AccountResponseUsage.md) | | | +| `settings` | [```AccountResponseSettings```](AccountResponseSettings.md) | | | diff --git a/sdks/java-v2/docs/AccountResponseSettings.md b/sdks/java-v2/docs/AccountResponseSettings.md new file mode 100644 index 000000000..cd139079d --- /dev/null +++ b/sdks/java-v2/docs/AccountResponseSettings.md @@ -0,0 +1,16 @@ + + +# AccountResponseSettings + +Subset of configured settings + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +| `signerAccessCodes` | ```Boolean``` | Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `smsDelivery` | ```Boolean``` | Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `smsAuthentication` | ```Boolean``` | Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | + + + diff --git a/sdks/java-v2/docs/ReportCreateRequest.md b/sdks/java-v2/docs/ReportCreateRequest.md index 78390304c..2d4b11610 100644 --- a/sdks/java-v2/docs/ReportCreateRequest.md +++ b/sdks/java-v2/docs/ReportCreateRequest.md @@ -21,6 +21,7 @@ | USER_ACTIVITY | "user_activity" | | DOCUMENT_STATUS | "document_status" | | SMS_ACTIVITY | "sms_activity" | +| FAX_USAGE | "fax_usage" | diff --git a/sdks/java-v2/docs/ReportResponse.md b/sdks/java-v2/docs/ReportResponse.md index aa74d68e0..bfd56aec6 100644 --- a/sdks/java-v2/docs/ReportResponse.md +++ b/sdks/java-v2/docs/ReportResponse.md @@ -22,6 +22,7 @@ Contains information about the report request. | USER_ACTIVITY | "user_activity" | | DOCUMENT_STATUS | "document_status" | | SMS_ACTIVITY | "sms_activity" | +| FAX_USAGE | "fax_usage" | diff --git a/sdks/java-v2/docs/SignatureRequestApi.md b/sdks/java-v2/docs/SignatureRequestApi.md index 939b10ef3..bf16f02c0 100644 --- a/sdks/java-v2/docs/SignatureRequestApi.md +++ b/sdks/java-v2/docs/SignatureRequestApi.md @@ -459,6 +459,7 @@ public class SignatureRequestCreateEmbeddedExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); @@ -579,6 +580,7 @@ public class SignatureRequestCreateEmbeddedWithTemplateExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); @@ -1874,6 +1876,7 @@ public class SignatureRequestSendExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestSigner(); signers1.name("Jack"); @@ -2000,6 +2003,7 @@ public class SignatureRequestSendWithTemplateExample signingOptions.phone(false); signingOptions.type(true); signingOptions.upload(true); + signingOptions.forceAdvancedSignatureDetails(false); var signers1 = new SubSignatureRequestTemplateSigner(); signers1.role("Client"); diff --git a/sdks/java-v2/docs/SignatureRequestEditRequest.md b/sdks/java-v2/docs/SignatureRequestEditRequest.md index 7fa3aca65..b4705fe97 100644 --- a/sdks/java-v2/docs/SignatureRequestEditRequest.md +++ b/sdks/java-v2/docs/SignatureRequestEditRequest.md @@ -23,7 +23,7 @@ | `formFieldRules` | [```List```](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | | | `formFieldsPerDocument` | [```List```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hideTextTags` | ```Boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v2/docs/SignatureRequestEditWithTemplateRequest.md b/sdks/java-v2/docs/SignatureRequestEditWithTemplateRequest.md index d079524b1..42095fa8b 100644 --- a/sdks/java-v2/docs/SignatureRequestEditWithTemplateRequest.md +++ b/sdks/java-v2/docs/SignatureRequestEditWithTemplateRequest.md @@ -16,7 +16,7 @@ | `customFields` | [```List```](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | | | `files` | ```List``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `fileUrls` | ```List``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v2/docs/SignatureRequestSendRequest.md b/sdks/java-v2/docs/SignatureRequestSendRequest.md index 914303935..a34284aa2 100644 --- a/sdks/java-v2/docs/SignatureRequestSendRequest.md +++ b/sdks/java-v2/docs/SignatureRequestSendRequest.md @@ -24,7 +24,7 @@ | `formFieldsPerDocument` | [```List```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hideTextTags` | ```Boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | | | `isQualifiedSignature` | ```Boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v2/docs/SignatureRequestSendWithTemplateRequest.md b/sdks/java-v2/docs/SignatureRequestSendWithTemplateRequest.md index 7a8d8c88a..425ccff28 100644 --- a/sdks/java-v2/docs/SignatureRequestSendWithTemplateRequest.md +++ b/sdks/java-v2/docs/SignatureRequestSendWithTemplateRequest.md @@ -17,7 +17,7 @@ | `files` | ```List``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `fileUrls` | ```List``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `isQualifiedSignature` | ```Boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | | -| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | | +| `isEid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Map``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/java-v2/docs/SubSigningOptions.md b/sdks/java-v2/docs/SubSigningOptions.md index bca116053..6f419c3a2 100644 --- a/sdks/java-v2/docs/SubSigningOptions.md +++ b/sdks/java-v2/docs/SubSigningOptions.md @@ -2,10 +2,12 @@ # SubSigningOptions -This allows the requester to specify the types allowed for creating a signature. +This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. +**NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. + ## Properties | Name | Type | Description | Notes | @@ -15,6 +17,7 @@ This allows the requester to specify the types allowed for creating a signature. | `phone` | ```Boolean``` | Allows using a smartphone to email the signature | | | `type` | ```Boolean``` | Allows typing the signature | | | `upload` | ```Boolean``` | Allows uploading the signature | | +| `forceAdvancedSignatureDetails` | ```Boolean``` | Turning on advanced signature details for the signature request | | diff --git a/sdks/java-v2/docs/SubUpdateFormField.md b/sdks/java-v2/docs/SubUpdateFormField.md new file mode 100644 index 000000000..0f09c17e9 --- /dev/null +++ b/sdks/java-v2/docs/SubUpdateFormField.md @@ -0,0 +1,15 @@ + + +# SubUpdateFormField + + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +| `apiId`*_required_ | ```String``` | The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found | | +| `name` | ```String``` | The new name of the field. If not passed the name will remain unchanged. | | + + + diff --git a/sdks/java-v2/docs/TemplateApi.md b/sdks/java-v2/docs/TemplateApi.md index dd470487b..e9233865f 100644 --- a/sdks/java-v2/docs/TemplateApi.md +++ b/sdks/java-v2/docs/TemplateApi.md @@ -111,7 +111,11 @@ public class TemplateAddUserExample Create Template -Creates a template that can then be used. +Creates a template that can be used in future signature requests. + +If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). + +Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. ### Example diff --git a/sdks/java-v2/docs/TemplateEditResponse.md b/sdks/java-v2/docs/TemplateEditResponse.md deleted file mode 100644 index 88d225e68..000000000 --- a/sdks/java-v2/docs/TemplateEditResponse.md +++ /dev/null @@ -1,14 +0,0 @@ - - -# TemplateEditResponse - - - -## Properties - -| Name | Type | Description | Notes | -|------------ | ------------- | ------------- | -------------| -| `templateId`*_required_ | ```String``` | The id of the Template. | | - - - diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/api/TemplateApi.java b/sdks/java-v2/src/main/java/com/dropbox/sign/api/TemplateApi.java index 974e61c40..f6f6d255b 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/api/TemplateApi.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/api/TemplateApi.java @@ -133,7 +133,7 @@ public ApiResponse templateAddUserWithHttpInfo(String templ } /** * Create Template - * Creates a template that can then be used. + * Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. * @param templateCreateRequest (required) * @return TemplateCreateResponse * @throws ApiException if fails to make API call @@ -152,7 +152,7 @@ public TemplateCreateResponse templateCreate(TemplateCreateRequest templateCreat /** * Create Template - * Creates a template that can then be used. + * Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. * @param templateCreateRequest (required) * @return ApiResponse<TemplateCreateResponse> * @throws ApiException if fails to make API call diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/AccountResponse.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/AccountResponse.java index e7140787d..d851bed80 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/AccountResponse.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/AccountResponse.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.HashMap; import com.dropbox.sign.model.AccountResponseQuotas; +import com.dropbox.sign.model.AccountResponseSettings; import com.dropbox.sign.model.AccountResponseUsage; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @@ -45,7 +46,8 @@ AccountResponse.JSON_PROPERTY_ROLE_CODE, AccountResponse.JSON_PROPERTY_TEAM_ID, AccountResponse.JSON_PROPERTY_LOCALE, - AccountResponse.JSON_PROPERTY_USAGE + AccountResponse.JSON_PROPERTY_USAGE, + AccountResponse.JSON_PROPERTY_SETTINGS }) @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.12.0") @JsonIgnoreProperties(ignoreUnknown=true) @@ -94,6 +96,10 @@ public class AccountResponse { @jakarta.annotation.Nullable private AccountResponseUsage usage; + public static final String JSON_PROPERTY_SETTINGS = "settings"; + @jakarta.annotation.Nullable + private AccountResponseSettings settings; + public AccountResponse() { } @@ -387,6 +393,31 @@ public void setUsage(@jakarta.annotation.Nullable AccountResponseUsage usage) { } + public AccountResponse settings(@jakarta.annotation.Nullable AccountResponseSettings settings) { + this.settings = settings; + return this; + } + + /** + * Get settings + * @return settings + */ + @jakarta.annotation.Nullable + @JsonProperty(JSON_PROPERTY_SETTINGS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public AccountResponseSettings getSettings() { + return settings; + } + + + @JsonProperty(JSON_PROPERTY_SETTINGS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSettings(@jakarta.annotation.Nullable AccountResponseSettings settings) { + this.settings = settings; + } + + /** * Return true if this AccountResponse object is equal to o. */ @@ -409,12 +440,13 @@ public boolean equals(Object o) { Objects.equals(this.roleCode, accountResponse.roleCode) && Objects.equals(this.teamId, accountResponse.teamId) && Objects.equals(this.locale, accountResponse.locale) && - Objects.equals(this.usage, accountResponse.usage); + Objects.equals(this.usage, accountResponse.usage) && + Objects.equals(this.settings, accountResponse.settings); } @Override public int hashCode() { - return Objects.hash(accountId, emailAddress, isLocked, isPaidHs, isPaidHf, quotas, callbackUrl, roleCode, teamId, locale, usage); + return Objects.hash(accountId, emailAddress, isLocked, isPaidHs, isPaidHf, quotas, callbackUrl, roleCode, teamId, locale, usage, settings); } @Override @@ -432,6 +464,7 @@ public String toString() { sb.append(" teamId: ").append(toIndentedString(teamId)).append("\n"); sb.append(" locale: ").append(toIndentedString(locale)).append("\n"); sb.append(" usage: ").append(toIndentedString(usage)).append("\n"); + sb.append(" settings: ").append(toIndentedString(settings)).append("\n"); sb.append("}"); return sb.toString(); } @@ -649,6 +682,25 @@ public Map createFormData() throws ApiException { map.put("usage", JSON.getDefault().getMapper().writeValueAsString(usage)); } } + if (settings != null) { + if (isFileTypeOrListOfFiles(settings)) { + fileTypeFound = true; + } + + if (settings.getClass().equals(java.io.File.class) || + settings.getClass().equals(Integer.class) || + settings.getClass().equals(String.class) || + settings.getClass().isEnum()) { + map.put("settings", settings); + } else if (isListOfFile(settings)) { + for(int i = 0; i< getListSize(settings); i++) { + map.put("settings[" + i + "]", getFromList(settings, i)); + } + } + else { + map.put("settings", JSON.getDefault().getMapper().writeValueAsString(settings)); + } + } } catch (Exception e) { throw new ApiException(e); } diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/AccountResponseSettings.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/AccountResponseSettings.java new file mode 100644 index 000000000..fa92563d0 --- /dev/null +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/AccountResponseSettings.java @@ -0,0 +1,281 @@ +/* + * Dropbox Sign API + * Dropbox Sign v3 API + * + * The version of the OpenAPI document: 3.0.0 + * Contact: apisupport@hellosign.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package com.dropbox.sign.model; + +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.dropbox.sign.JSON; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.ObjectMapper; + + +import com.dropbox.sign.ApiException; +/** + * Subset of configured settings + */ +@JsonPropertyOrder({ + AccountResponseSettings.JSON_PROPERTY_SIGNER_ACCESS_CODES, + AccountResponseSettings.JSON_PROPERTY_SMS_DELIVERY, + AccountResponseSettings.JSON_PROPERTY_SMS_AUTHENTICATION +}) +@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.12.0") +@JsonIgnoreProperties(ignoreUnknown=true) +public class AccountResponseSettings { + public static final String JSON_PROPERTY_SIGNER_ACCESS_CODES = "signer_access_codes"; + @jakarta.annotation.Nullable + private Boolean signerAccessCodes; + + public static final String JSON_PROPERTY_SMS_DELIVERY = "sms_delivery"; + @jakarta.annotation.Nullable + private Boolean smsDelivery; + + public static final String JSON_PROPERTY_SMS_AUTHENTICATION = "sms_authentication"; + @jakarta.annotation.Nullable + private Boolean smsAuthentication; + + public AccountResponseSettings() { + } + + /** + * Attempt to instantiate and hydrate a new instance of this class + * @param jsonData String of JSON data representing target object + */ + static public AccountResponseSettings init(String jsonData) throws Exception { + return new ObjectMapper().readValue(jsonData, AccountResponseSettings.class); + } + + static public AccountResponseSettings init(HashMap data) throws Exception { + return new ObjectMapper().readValue( + new ObjectMapper().writeValueAsString(data), + AccountResponseSettings.class + ); + } + + public AccountResponseSettings signerAccessCodes(@jakarta.annotation.Nullable Boolean signerAccessCodes) { + this.signerAccessCodes = signerAccessCodes; + return this; + } + + /** + * Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * @return signerAccessCodes + */ + @jakarta.annotation.Nullable + @JsonProperty(JSON_PROPERTY_SIGNER_ACCESS_CODES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Boolean getSignerAccessCodes() { + return signerAccessCodes; + } + + + @JsonProperty(JSON_PROPERTY_SIGNER_ACCESS_CODES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSignerAccessCodes(@jakarta.annotation.Nullable Boolean signerAccessCodes) { + this.signerAccessCodes = signerAccessCodes; + } + + + public AccountResponseSettings smsDelivery(@jakarta.annotation.Nullable Boolean smsDelivery) { + this.smsDelivery = smsDelivery; + return this; + } + + /** + * Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * @return smsDelivery + */ + @jakarta.annotation.Nullable + @JsonProperty(JSON_PROPERTY_SMS_DELIVERY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Boolean getSmsDelivery() { + return smsDelivery; + } + + + @JsonProperty(JSON_PROPERTY_SMS_DELIVERY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSmsDelivery(@jakarta.annotation.Nullable Boolean smsDelivery) { + this.smsDelivery = smsDelivery; + } + + + public AccountResponseSettings smsAuthentication(@jakarta.annotation.Nullable Boolean smsAuthentication) { + this.smsAuthentication = smsAuthentication; + return this; + } + + /** + * Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * @return smsAuthentication + */ + @jakarta.annotation.Nullable + @JsonProperty(JSON_PROPERTY_SMS_AUTHENTICATION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Boolean getSmsAuthentication() { + return smsAuthentication; + } + + + @JsonProperty(JSON_PROPERTY_SMS_AUTHENTICATION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSmsAuthentication(@jakarta.annotation.Nullable Boolean smsAuthentication) { + this.smsAuthentication = smsAuthentication; + } + + + /** + * Return true if this AccountResponseSettings object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AccountResponseSettings accountResponseSettings = (AccountResponseSettings) o; + return Objects.equals(this.signerAccessCodes, accountResponseSettings.signerAccessCodes) && + Objects.equals(this.smsDelivery, accountResponseSettings.smsDelivery) && + Objects.equals(this.smsAuthentication, accountResponseSettings.smsAuthentication); + } + + @Override + public int hashCode() { + return Objects.hash(signerAccessCodes, smsDelivery, smsAuthentication); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AccountResponseSettings {\n"); + sb.append(" signerAccessCodes: ").append(toIndentedString(signerAccessCodes)).append("\n"); + sb.append(" smsDelivery: ").append(toIndentedString(smsDelivery)).append("\n"); + sb.append(" smsAuthentication: ").append(toIndentedString(smsAuthentication)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + public Map createFormData() throws ApiException { + Map map = new HashMap<>(); + boolean fileTypeFound = false; + try { + if (signerAccessCodes != null) { + if (isFileTypeOrListOfFiles(signerAccessCodes)) { + fileTypeFound = true; + } + + if (signerAccessCodes.getClass().equals(java.io.File.class) || + signerAccessCodes.getClass().equals(Integer.class) || + signerAccessCodes.getClass().equals(String.class) || + signerAccessCodes.getClass().isEnum()) { + map.put("signer_access_codes", signerAccessCodes); + } else if (isListOfFile(signerAccessCodes)) { + for(int i = 0; i< getListSize(signerAccessCodes); i++) { + map.put("signer_access_codes[" + i + "]", getFromList(signerAccessCodes, i)); + } + } + else { + map.put("signer_access_codes", JSON.getDefault().getMapper().writeValueAsString(signerAccessCodes)); + } + } + if (smsDelivery != null) { + if (isFileTypeOrListOfFiles(smsDelivery)) { + fileTypeFound = true; + } + + if (smsDelivery.getClass().equals(java.io.File.class) || + smsDelivery.getClass().equals(Integer.class) || + smsDelivery.getClass().equals(String.class) || + smsDelivery.getClass().isEnum()) { + map.put("sms_delivery", smsDelivery); + } else if (isListOfFile(smsDelivery)) { + for(int i = 0; i< getListSize(smsDelivery); i++) { + map.put("sms_delivery[" + i + "]", getFromList(smsDelivery, i)); + } + } + else { + map.put("sms_delivery", JSON.getDefault().getMapper().writeValueAsString(smsDelivery)); + } + } + if (smsAuthentication != null) { + if (isFileTypeOrListOfFiles(smsAuthentication)) { + fileTypeFound = true; + } + + if (smsAuthentication.getClass().equals(java.io.File.class) || + smsAuthentication.getClass().equals(Integer.class) || + smsAuthentication.getClass().equals(String.class) || + smsAuthentication.getClass().isEnum()) { + map.put("sms_authentication", smsAuthentication); + } else if (isListOfFile(smsAuthentication)) { + for(int i = 0; i< getListSize(smsAuthentication); i++) { + map.put("sms_authentication[" + i + "]", getFromList(smsAuthentication, i)); + } + } + else { + map.put("sms_authentication", JSON.getDefault().getMapper().writeValueAsString(smsAuthentication)); + } + } + } catch (Exception e) { + throw new ApiException(e); + } + + return fileTypeFound ? map : new HashMap<>(); + } + + private boolean isFileTypeOrListOfFiles(Object obj) throws Exception { + return obj.getClass().equals(java.io.File.class) || isListOfFile(obj); + } + + private boolean isListOfFile(Object obj) throws Exception { + return obj instanceof java.util.List && !isListEmpty(obj) && getFromList(obj, 0) instanceof java.io.File; + } + + private boolean isListEmpty(Object obj) throws Exception { + return (boolean) Class.forName(java.util.List.class.getName()).getMethod("isEmpty").invoke(obj); + } + + private Object getFromList(Object obj, int index) throws Exception { + return Class.forName(java.util.List.class.getName()).getMethod("get", int.class).invoke(obj, index); + } + + private int getListSize(Object obj) throws Exception { + return (int) Class.forName(java.util.List.class.getName()).getMethod("size").invoke(obj); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java index 020326d82..d2c1dbf76 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportCreateRequest.java @@ -54,7 +54,9 @@ public enum ReportTypeEnum { DOCUMENT_STATUS(String.valueOf("document_status")), - SMS_ACTIVITY(String.valueOf("sms_activity")); + SMS_ACTIVITY(String.valueOf("sms_activity")), + + FAX_USAGE(String.valueOf("fax_usage")); private String value; diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportResponse.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportResponse.java index 18b6f39a1..0299b45d3 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportResponse.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/ReportResponse.java @@ -63,7 +63,9 @@ public enum ReportTypeEnum { DOCUMENT_STATUS(String.valueOf("document_status")), - SMS_ACTIVITY(String.valueOf("sms_activity")); + SMS_ACTIVITY(String.valueOf("sms_activity")), + + FAX_USAGE(String.valueOf("fax_usage")); private String value; diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java index 719a6b457..9ca66e0f5 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditRequest.java @@ -655,7 +655,7 @@ public SignatureRequestEditRequest isEid(@jakarta.annotation.Nullable Boolean is } /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * @return isEid */ @jakarta.annotation.Nullable diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java index 02f2a4d2f..89445f6f8 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestEditWithTemplateRequest.java @@ -398,7 +398,7 @@ public SignatureRequestEditWithTemplateRequest isEid(@jakarta.annotation.Nullabl } /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * @return isEid */ @jakarta.annotation.Nullable diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java index a76ab911f..89792b2b5 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendRequest.java @@ -690,7 +690,7 @@ public SignatureRequestSendRequest isEid(@jakarta.annotation.Nullable Boolean is } /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * @return isEid */ @jakarta.annotation.Nullable diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java index 861f52e96..f007ed7a9 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SignatureRequestSendWithTemplateRequest.java @@ -433,7 +433,7 @@ public SignatureRequestSendWithTemplateRequest isEid(@jakarta.annotation.Nullabl } /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br> **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * @return isEid */ @jakarta.annotation.Nullable diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SubSigningOptions.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SubSigningOptions.java index 8a194e4bf..2fe79900b 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/SubSigningOptions.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SubSigningOptions.java @@ -30,14 +30,15 @@ import com.dropbox.sign.ApiException; /** - * This allows the requester to specify the types allowed for creating a signature. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + * This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. */ @JsonPropertyOrder({ SubSigningOptions.JSON_PROPERTY_DEFAULT_TYPE, SubSigningOptions.JSON_PROPERTY_DRAW, SubSigningOptions.JSON_PROPERTY_PHONE, SubSigningOptions.JSON_PROPERTY_TYPE, - SubSigningOptions.JSON_PROPERTY_UPLOAD + SubSigningOptions.JSON_PROPERTY_UPLOAD, + SubSigningOptions.JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS }) @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.12.0") @JsonIgnoreProperties(ignoreUnknown=true) @@ -101,6 +102,10 @@ public static DefaultTypeEnum fromValue(String value) { @jakarta.annotation.Nullable private Boolean upload = false; + public static final String JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS = "force_advanced_signature_details"; + @jakarta.annotation.Nullable + private Boolean forceAdvancedSignatureDetails = false; + public SubSigningOptions() { } @@ -244,6 +249,31 @@ public void setUpload(@jakarta.annotation.Nullable Boolean upload) { } + public SubSigningOptions forceAdvancedSignatureDetails(@jakarta.annotation.Nullable Boolean forceAdvancedSignatureDetails) { + this.forceAdvancedSignatureDetails = forceAdvancedSignatureDetails; + return this; + } + + /** + * Turning on advanced signature details for the signature request + * @return forceAdvancedSignatureDetails + */ + @jakarta.annotation.Nullable + @JsonProperty(JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Boolean getForceAdvancedSignatureDetails() { + return forceAdvancedSignatureDetails; + } + + + @JsonProperty(JSON_PROPERTY_FORCE_ADVANCED_SIGNATURE_DETAILS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setForceAdvancedSignatureDetails(@jakarta.annotation.Nullable Boolean forceAdvancedSignatureDetails) { + this.forceAdvancedSignatureDetails = forceAdvancedSignatureDetails; + } + + /** * Return true if this SubSigningOptions object is equal to o. */ @@ -260,12 +290,13 @@ public boolean equals(Object o) { Objects.equals(this.draw, subSigningOptions.draw) && Objects.equals(this.phone, subSigningOptions.phone) && Objects.equals(this.type, subSigningOptions.type) && - Objects.equals(this.upload, subSigningOptions.upload); + Objects.equals(this.upload, subSigningOptions.upload) && + Objects.equals(this.forceAdvancedSignatureDetails, subSigningOptions.forceAdvancedSignatureDetails); } @Override public int hashCode() { - return Objects.hash(defaultType, draw, phone, type, upload); + return Objects.hash(defaultType, draw, phone, type, upload, forceAdvancedSignatureDetails); } @Override @@ -277,6 +308,7 @@ public String toString() { sb.append(" phone: ").append(toIndentedString(phone)).append("\n"); sb.append(" type: ").append(toIndentedString(type)).append("\n"); sb.append(" upload: ").append(toIndentedString(upload)).append("\n"); + sb.append(" forceAdvancedSignatureDetails: ").append(toIndentedString(forceAdvancedSignatureDetails)).append("\n"); sb.append("}"); return sb.toString(); } @@ -380,6 +412,25 @@ public Map createFormData() throws ApiException { map.put("upload", JSON.getDefault().getMapper().writeValueAsString(upload)); } } + if (forceAdvancedSignatureDetails != null) { + if (isFileTypeOrListOfFiles(forceAdvancedSignatureDetails)) { + fileTypeFound = true; + } + + if (forceAdvancedSignatureDetails.getClass().equals(java.io.File.class) || + forceAdvancedSignatureDetails.getClass().equals(Integer.class) || + forceAdvancedSignatureDetails.getClass().equals(String.class) || + forceAdvancedSignatureDetails.getClass().isEnum()) { + map.put("force_advanced_signature_details", forceAdvancedSignatureDetails); + } else if (isListOfFile(forceAdvancedSignatureDetails)) { + for(int i = 0; i< getListSize(forceAdvancedSignatureDetails); i++) { + map.put("force_advanced_signature_details[" + i + "]", getFromList(forceAdvancedSignatureDetails, i)); + } + } + else { + map.put("force_advanced_signature_details", JSON.getDefault().getMapper().writeValueAsString(forceAdvancedSignatureDetails)); + } + } } catch (Exception e) { throw new ApiException(e); } diff --git a/sdks/java-v2/src/main/java/com/dropbox/sign/model/TemplateEditResponse.java b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SubUpdateFormField.java similarity index 50% rename from sdks/java-v2/src/main/java/com/dropbox/sign/model/TemplateEditResponse.java rename to sdks/java-v2/src/main/java/com/dropbox/sign/model/SubUpdateFormField.java index 866a87fa3..1c9fe6b84 100644 --- a/sdks/java-v2/src/main/java/com/dropbox/sign/model/TemplateEditResponse.java +++ b/sdks/java-v2/src/main/java/com/dropbox/sign/model/SubUpdateFormField.java @@ -30,63 +30,93 @@ import com.dropbox.sign.ApiException; /** - * TemplateEditResponse + * SubUpdateFormField */ @JsonPropertyOrder({ - TemplateEditResponse.JSON_PROPERTY_TEMPLATE_ID + SubUpdateFormField.JSON_PROPERTY_API_ID, + SubUpdateFormField.JSON_PROPERTY_NAME }) @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.12.0") @JsonIgnoreProperties(ignoreUnknown=true) -public class TemplateEditResponse { - public static final String JSON_PROPERTY_TEMPLATE_ID = "template_id"; +public class SubUpdateFormField { + public static final String JSON_PROPERTY_API_ID = "api_id"; @jakarta.annotation.Nonnull - private String templateId; + private String apiId; - public TemplateEditResponse() { + public static final String JSON_PROPERTY_NAME = "name"; + @jakarta.annotation.Nullable + private String name; + + public SubUpdateFormField() { } /** * Attempt to instantiate and hydrate a new instance of this class * @param jsonData String of JSON data representing target object */ - static public TemplateEditResponse init(String jsonData) throws Exception { - return new ObjectMapper().readValue(jsonData, TemplateEditResponse.class); + static public SubUpdateFormField init(String jsonData) throws Exception { + return new ObjectMapper().readValue(jsonData, SubUpdateFormField.class); } - static public TemplateEditResponse init(HashMap data) throws Exception { + static public SubUpdateFormField init(HashMap data) throws Exception { return new ObjectMapper().readValue( new ObjectMapper().writeValueAsString(data), - TemplateEditResponse.class + SubUpdateFormField.class ); } - public TemplateEditResponse templateId(@jakarta.annotation.Nonnull String templateId) { - this.templateId = templateId; + public SubUpdateFormField apiId(@jakarta.annotation.Nonnull String apiId) { + this.apiId = apiId; return this; } /** - * The id of the Template. - * @return templateId + * The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found + * @return apiId */ @jakarta.annotation.Nonnull - @JsonProperty(JSON_PROPERTY_TEMPLATE_ID) + @JsonProperty(JSON_PROPERTY_API_ID) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public String getTemplateId() { - return templateId; + public String getApiId() { + return apiId; } - @JsonProperty(JSON_PROPERTY_TEMPLATE_ID) + @JsonProperty(JSON_PROPERTY_API_ID) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setTemplateId(@jakarta.annotation.Nonnull String templateId) { - this.templateId = templateId; + public void setApiId(@jakarta.annotation.Nonnull String apiId) { + this.apiId = apiId; } + public SubUpdateFormField name(@jakarta.annotation.Nullable String name) { + this.name = name; + return this; + } + /** - * Return true if this TemplateEditResponse object is equal to o. + * The new name of the field. If not passed the name will remain unchanged. + * @return name + */ + @jakarta.annotation.Nullable + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getName() { + return name; + } + + + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setName(@jakarta.annotation.Nullable String name) { + this.name = name; + } + + + /** + * Return true if this SubUpdateFormField object is equal to o. */ @Override public boolean equals(Object o) { @@ -96,20 +126,22 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - TemplateEditResponse templateEditResponse = (TemplateEditResponse) o; - return Objects.equals(this.templateId, templateEditResponse.templateId); + SubUpdateFormField subUpdateFormField = (SubUpdateFormField) o; + return Objects.equals(this.apiId, subUpdateFormField.apiId) && + Objects.equals(this.name, subUpdateFormField.name); } @Override public int hashCode() { - return Objects.hash(templateId); + return Objects.hash(apiId, name); } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("class TemplateEditResponse {\n"); - sb.append(" templateId: ").append(toIndentedString(templateId)).append("\n"); + sb.append("class SubUpdateFormField {\n"); + sb.append(" apiId: ").append(toIndentedString(apiId)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append("}"); return sb.toString(); } @@ -118,23 +150,42 @@ public Map createFormData() throws ApiException { Map map = new HashMap<>(); boolean fileTypeFound = false; try { - if (templateId != null) { - if (isFileTypeOrListOfFiles(templateId)) { + if (apiId != null) { + if (isFileTypeOrListOfFiles(apiId)) { + fileTypeFound = true; + } + + if (apiId.getClass().equals(java.io.File.class) || + apiId.getClass().equals(Integer.class) || + apiId.getClass().equals(String.class) || + apiId.getClass().isEnum()) { + map.put("api_id", apiId); + } else if (isListOfFile(apiId)) { + for(int i = 0; i< getListSize(apiId); i++) { + map.put("api_id[" + i + "]", getFromList(apiId, i)); + } + } + else { + map.put("api_id", JSON.getDefault().getMapper().writeValueAsString(apiId)); + } + } + if (name != null) { + if (isFileTypeOrListOfFiles(name)) { fileTypeFound = true; } - if (templateId.getClass().equals(java.io.File.class) || - templateId.getClass().equals(Integer.class) || - templateId.getClass().equals(String.class) || - templateId.getClass().isEnum()) { - map.put("template_id", templateId); - } else if (isListOfFile(templateId)) { - for(int i = 0; i< getListSize(templateId); i++) { - map.put("template_id[" + i + "]", getFromList(templateId, i)); + if (name.getClass().equals(java.io.File.class) || + name.getClass().equals(Integer.class) || + name.getClass().equals(String.class) || + name.getClass().isEnum()) { + map.put("name", name); + } else if (isListOfFile(name)) { + for(int i = 0; i< getListSize(name); i++) { + map.put("name[" + i + "]", getFromList(name, i)); } } else { - map.put("template_id", JSON.getDefault().getMapper().writeValueAsString(templateId)); + map.put("name", JSON.getDefault().getMapper().writeValueAsString(name)); } } } catch (Exception e) { diff --git a/sdks/node/README.md b/sdks/node/README.md index 93d2bfdfd..7e2b78e3b 100644 --- a/sdks/node/README.md +++ b/sdks/node/README.md @@ -160,6 +160,7 @@ All URIs are relative to *https://api.hellosign.com/v3* - [AccountGetResponse](./docs/model/AccountGetResponse.md) - [AccountResponse](./docs/model/AccountResponse.md) - [AccountResponseQuotas](./docs/model/AccountResponseQuotas.md) +- [AccountResponseSettings](./docs/model/AccountResponseSettings.md) - [AccountResponseUsage](./docs/model/AccountResponseUsage.md) - [AccountUpdateRequest](./docs/model/AccountUpdateRequest.md) - [AccountVerifyRequest](./docs/model/AccountVerifyRequest.md) @@ -281,6 +282,7 @@ All URIs are relative to *https://api.hellosign.com/v3* - [SubTemplateRole](./docs/model/SubTemplateRole.md) - [SubUnclaimedDraftSigner](./docs/model/SubUnclaimedDraftSigner.md) - [SubUnclaimedDraftTemplateSigner](./docs/model/SubUnclaimedDraftTemplateSigner.md) +- [SubUpdateFormField](./docs/model/SubUpdateFormField.md) - [SubWhiteLabelingOptions](./docs/model/SubWhiteLabelingOptions.md) - [TeamAddMemberRequest](./docs/model/TeamAddMemberRequest.md) - [TeamCreateRequest](./docs/model/TeamCreateRequest.md) @@ -303,7 +305,6 @@ All URIs are relative to *https://api.hellosign.com/v3* - [TemplateCreateRequest](./docs/model/TemplateCreateRequest.md) - [TemplateCreateResponse](./docs/model/TemplateCreateResponse.md) - [TemplateCreateResponseTemplate](./docs/model/TemplateCreateResponseTemplate.md) -- [TemplateEditResponse](./docs/model/TemplateEditResponse.md) - [TemplateGetResponse](./docs/model/TemplateGetResponse.md) - [TemplateListResponse](./docs/model/TemplateListResponse.md) - [TemplateRemoveUserRequest](./docs/model/TemplateRemoveUserRequest.md) diff --git a/sdks/node/api/templateApi.ts b/sdks/node/api/templateApi.ts index 35ac24648..676e33e18 100644 --- a/sdks/node/api/templateApi.ts +++ b/sdks/node/api/templateApi.ts @@ -290,7 +290,7 @@ export class TemplateApi { }); } /** - * Creates a template that can then be used. + * Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. * @summary Create Template * @param templateCreateRequest * @param options diff --git a/sdks/node/dist/api.js b/sdks/node/dist/api.js index 059bd726e..b5e3b1398 100644 --- a/sdks/node/dist/api.js +++ b/sdks/node/dist/api.js @@ -13150,6 +13150,7 @@ __export(api_exports, { AccountGetResponse: () => AccountGetResponse, AccountResponse: () => AccountResponse, AccountResponseQuotas: () => AccountResponseQuotas, + AccountResponseSettings: () => AccountResponseSettings, AccountResponseUsage: () => AccountResponseUsage, AccountUpdateRequest: () => AccountUpdateRequest, AccountVerifyRequest: () => AccountVerifyRequest, @@ -13286,6 +13287,7 @@ __export(api_exports, { SubTemplateRole: () => SubTemplateRole, SubUnclaimedDraftSigner: () => SubUnclaimedDraftSigner, SubUnclaimedDraftTemplateSigner: () => SubUnclaimedDraftTemplateSigner, + SubUpdateFormField: () => SubUpdateFormField, SubWhiteLabelingOptions: () => SubWhiteLabelingOptions, TeamAddMemberRequest: () => TeamAddMemberRequest, TeamApi: () => TeamApi, @@ -13310,7 +13312,6 @@ __export(api_exports, { TemplateCreateRequest: () => TemplateCreateRequest, TemplateCreateResponse: () => TemplateCreateResponse, TemplateCreateResponseTemplate: () => TemplateCreateResponseTemplate, - TemplateEditResponse: () => TemplateEditResponse, TemplateGetResponse: () => TemplateGetResponse, TemplateListResponse: () => TemplateListResponse, TemplateRemoveUserRequest: () => TemplateRemoveUserRequest, @@ -16823,6 +16824,11 @@ var AccountResponse = class _AccountResponse { name: "usage", baseName: "usage", type: "AccountResponseUsage" + }, + { + name: "settings", + baseName: "settings", + type: "AccountResponseSettings" } ]; } @@ -16883,6 +16889,39 @@ var AccountResponseQuotas = class _AccountResponseQuotas { } }; +// model/accountResponseSettings.ts +var AccountResponseSettings = class _AccountResponseSettings { + static { + this.discriminator = void 0; + } + static { + this.attributeTypeMap = [ + { + name: "signerAccessCodes", + baseName: "signer_access_codes", + type: "boolean" + }, + { + name: "smsDelivery", + baseName: "sms_delivery", + type: "boolean" + }, + { + name: "smsAuthentication", + baseName: "sms_authentication", + type: "boolean" + } + ]; + } + static getAttributeTypeMap() { + return _AccountResponseSettings.attributeTypeMap; + } + /** Attempt to instantiate and hydrate a new instance of this class */ + static init(data) { + return ObjectSerializer.deserialize(data, "AccountResponseSettings"); + } +}; + // model/accountResponseUsage.ts var AccountResponseUsage = class _AccountResponseUsage { static { @@ -19240,6 +19279,7 @@ var ReportCreateRequest = class _ReportCreateRequest { ReportTypeEnum2["UserActivity"] = "user_activity"; ReportTypeEnum2["DocumentStatus"] = "document_status"; ReportTypeEnum2["SmsActivity"] = "sms_activity"; + ReportTypeEnum2["FaxUsage"] = "fax_usage"; })(ReportTypeEnum = ReportCreateRequest2.ReportTypeEnum || (ReportCreateRequest2.ReportTypeEnum = {})); })(ReportCreateRequest || (ReportCreateRequest = {})); @@ -19314,6 +19354,7 @@ var ReportResponse = class _ReportResponse { ReportTypeEnum2["UserActivity"] = "user_activity"; ReportTypeEnum2["DocumentStatus"] = "document_status"; ReportTypeEnum2["SmsActivity"] = "sms_activity"; + ReportTypeEnum2["FaxUsage"] = "fax_usage"; })(ReportTypeEnum = ReportResponse2.ReportTypeEnum || (ReportResponse2.ReportTypeEnum = {})); })(ReportResponse || (ReportResponse = {})); @@ -20079,7 +20120,7 @@ var SignatureRequestEditRequest = class _SignatureRequestEditRequest { */ this["hideTextTags"] = false; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ this["isEid"] = false; /** @@ -20240,7 +20281,7 @@ var SignatureRequestEditWithTemplateRequest = class _SignatureRequestEditWithTem */ this["allowDecline"] = false; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ this["isEid"] = false; /** @@ -21346,7 +21387,7 @@ var SignatureRequestSendRequest = class _SignatureRequestSendRequest { */ this["isQualifiedSignature"] = false; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ this["isEid"] = false; /** @@ -21518,7 +21559,7 @@ var SignatureRequestSendWithTemplateRequest = class _SignatureRequestSendWithTem */ this["isQualifiedSignature"] = false; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ this["isEid"] = false; /** @@ -23090,6 +23131,10 @@ var SubSigningOptions = class _SubSigningOptions { * Allows uploading the signature */ this["upload"] = false; + /** + * Turning on advanced signature details for the signature request + */ + this["forceAdvancedSignatureDetails"] = false; } static { this.discriminator = void 0; @@ -23120,6 +23165,11 @@ var SubSigningOptions = class _SubSigningOptions { name: "upload", baseName: "upload", type: "boolean" + }, + { + name: "forceAdvancedSignatureDetails", + baseName: "force_advanced_signature_details", + type: "boolean" } ]; } @@ -23266,6 +23316,34 @@ var SubUnclaimedDraftTemplateSigner = class _SubUnclaimedDraftTemplateSigner { } }; +// model/subUpdateFormField.ts +var SubUpdateFormField = class _SubUpdateFormField { + static { + this.discriminator = void 0; + } + static { + this.attributeTypeMap = [ + { + name: "apiId", + baseName: "api_id", + type: "string" + }, + { + name: "name", + baseName: "name", + type: "string" + } + ]; + } + static getAttributeTypeMap() { + return _SubUpdateFormField.attributeTypeMap; + } + /** Attempt to instantiate and hydrate a new instance of this class */ + static init(data) { + return ObjectSerializer.deserialize(data, "SubUpdateFormField"); + } +}; + // model/subWhiteLabelingOptions.ts var SubWhiteLabelingOptions = class _SubWhiteLabelingOptions { constructor() { @@ -24336,29 +24414,6 @@ var TemplateCreateResponseTemplate = class _TemplateCreateResponseTemplate { } }; -// model/templateEditResponse.ts -var TemplateEditResponse = class _TemplateEditResponse { - static { - this.discriminator = void 0; - } - static { - this.attributeTypeMap = [ - { - name: "templateId", - baseName: "template_id", - type: "string" - } - ]; - } - static getAttributeTypeMap() { - return _TemplateEditResponse.attributeTypeMap; - } - /** Attempt to instantiate and hydrate a new instance of this class */ - static init(data) { - return ObjectSerializer.deserialize(data, "TemplateEditResponse"); - } -}; - // model/templateGetResponse.ts var TemplateGetResponse = class _TemplateGetResponse { static { @@ -26803,6 +26858,7 @@ var typeMap = { AccountGetResponse, AccountResponse, AccountResponseQuotas, + AccountResponseSettings, AccountResponseUsage, AccountUpdateRequest, AccountVerifyRequest, @@ -26917,6 +26973,7 @@ var typeMap = { SubTemplateRole, SubUnclaimedDraftSigner, SubUnclaimedDraftTemplateSigner, + SubUpdateFormField, SubWhiteLabelingOptions, TeamAddMemberRequest, TeamCreateRequest, @@ -26939,7 +26996,6 @@ var typeMap = { TemplateCreateRequest, TemplateCreateResponse, TemplateCreateResponseTemplate, - TemplateEditResponse, TemplateGetResponse, TemplateListResponse, TemplateRemoveUserRequest, @@ -34474,7 +34530,7 @@ var TemplateApi = class { }); } /** - * Creates a template that can then be used. + * Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. * @summary Create Template * @param templateCreateRequest * @param options @@ -36316,6 +36372,7 @@ var APIS = [ AccountGetResponse, AccountResponse, AccountResponseQuotas, + AccountResponseSettings, AccountResponseUsage, AccountUpdateRequest, AccountVerifyRequest, @@ -36452,6 +36509,7 @@ var APIS = [ SubTemplateRole, SubUnclaimedDraftSigner, SubUnclaimedDraftTemplateSigner, + SubUpdateFormField, SubWhiteLabelingOptions, TeamAddMemberRequest, TeamApi, @@ -36476,7 +36534,6 @@ var APIS = [ TemplateCreateRequest, TemplateCreateResponse, TemplateCreateResponseTemplate, - TemplateEditResponse, TemplateGetResponse, TemplateListResponse, TemplateRemoveUserRequest, diff --git a/sdks/node/docs/api/SignatureRequestApi.md b/sdks/node/docs/api/SignatureRequestApi.md index 04b197f7d..47e5e9b86 100644 --- a/sdks/node/docs/api/SignatureRequestApi.md +++ b/sdks/node/docs/api/SignatureRequestApi.md @@ -366,6 +366,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestSigner = { @@ -463,6 +464,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestTemplateSigner = { @@ -1406,6 +1408,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestSigner = { @@ -1507,6 +1510,7 @@ const signingOptions: models.SubSigningOptions = { phone: false, type: true, upload: true, + force_advanced_signature_details: false, }; const signers1: models.SubSignatureRequestTemplateSigner = { diff --git a/sdks/node/docs/api/TemplateApi.md b/sdks/node/docs/api/TemplateApi.md index d86551c72..a9ce2013a 100644 --- a/sdks/node/docs/api/TemplateApi.md +++ b/sdks/node/docs/api/TemplateApi.md @@ -86,7 +86,7 @@ templateCreate(templateCreateRequest: TemplateCreateRequest): TemplateCreateResp Create Template -Creates a template that can then be used. +Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. ### TypeScript Example diff --git a/sdks/node/docs/model/AccountResponse.md b/sdks/node/docs/model/AccountResponse.md index b24e1638f..87f26057e 100644 --- a/sdks/node/docs/model/AccountResponse.md +++ b/sdks/node/docs/model/AccountResponse.md @@ -17,5 +17,6 @@ Name | Type | Description | Notes | `teamId` | ```string``` | The id of the team account belongs to. | | | `locale` | ```string``` | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | | | `usage` | [```AccountResponseUsage```](AccountResponseUsage.md) | | | +| `settings` | [```AccountResponseSettings```](AccountResponseSettings.md) | | | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/node/docs/model/AccountResponseSettings.md b/sdks/node/docs/model/AccountResponseSettings.md new file mode 100644 index 000000000..f9071a590 --- /dev/null +++ b/sdks/node/docs/model/AccountResponseSettings.md @@ -0,0 +1,13 @@ +# # AccountResponseSettings + +Subset of configured settings + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +| `signerAccessCodes` | ```boolean``` | Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `smsDelivery` | ```boolean``` | Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `smsAuthentication` | ```boolean``` | Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | + +[[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/node/docs/model/SignatureRequestEditRequest.md b/sdks/node/docs/model/SignatureRequestEditRequest.md index 309384652..3e29f398f 100644 --- a/sdks/node/docs/model/SignatureRequestEditRequest.md +++ b/sdks/node/docs/model/SignatureRequestEditRequest.md @@ -21,7 +21,7 @@ Name | Type | Description | Notes | `formFieldRules` | [```Array```](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | | | `formFieldsPerDocument` | [```Array```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hideTextTags` | ```boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to false] | -| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```{ [key: string]: any; }``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/node/docs/model/SignatureRequestEditWithTemplateRequest.md b/sdks/node/docs/model/SignatureRequestEditWithTemplateRequest.md index fdec2cfc0..6357e7bc5 100644 --- a/sdks/node/docs/model/SignatureRequestEditWithTemplateRequest.md +++ b/sdks/node/docs/model/SignatureRequestEditWithTemplateRequest.md @@ -14,7 +14,7 @@ Name | Type | Description | Notes | `customFields` | [```Array```](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | | | `files` | ```Array``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `fileUrls` | ```Array``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | -| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```{ [key: string]: any; }``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/node/docs/model/SignatureRequestSendRequest.md b/sdks/node/docs/model/SignatureRequestSendRequest.md index b35df0d86..656e79f9f 100644 --- a/sdks/node/docs/model/SignatureRequestSendRequest.md +++ b/sdks/node/docs/model/SignatureRequestSendRequest.md @@ -22,7 +22,7 @@ Name | Type | Description | Notes | `formFieldsPerDocument` | [```Array```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hideTextTags` | ```boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to false] | | `isQualifiedSignature` | ```boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | -| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```{ [key: string]: any; }``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/node/docs/model/SignatureRequestSendWithTemplateRequest.md b/sdks/node/docs/model/SignatureRequestSendWithTemplateRequest.md index 73d132e0b..04cf0739f 100644 --- a/sdks/node/docs/model/SignatureRequestSendWithTemplateRequest.md +++ b/sdks/node/docs/model/SignatureRequestSendWithTemplateRequest.md @@ -15,7 +15,7 @@ Name | Type | Description | Notes | `files` | ```Array``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `fileUrls` | ```Array``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `isQualifiedSignature` | ```boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | -| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `isEid` | ```boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```{ [key: string]: any; }``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signingOptions` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/node/docs/model/SubSigningOptions.md b/sdks/node/docs/model/SubSigningOptions.md index 1e1c670f6..d795c194b 100644 --- a/sdks/node/docs/model/SubSigningOptions.md +++ b/sdks/node/docs/model/SubSigningOptions.md @@ -1,9 +1,11 @@ # # SubSigningOptions -This allows the requester to specify the types allowed for creating a signature. +This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. +**NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. + ## Properties Name | Type | Description | Notes @@ -13,5 +15,6 @@ Name | Type | Description | Notes | `phone` | ```boolean``` | Allows using a smartphone to email the signature | [default to false] | | `type` | ```boolean``` | Allows typing the signature | [default to false] | | `upload` | ```boolean``` | Allows uploading the signature | [default to false] | +| `forceAdvancedSignatureDetails` | ```boolean``` | Turning on advanced signature details for the signature request | [default to false] | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/node/docs/model/SubUpdateFormField.md b/sdks/node/docs/model/SubUpdateFormField.md new file mode 100644 index 000000000..2228401c2 --- /dev/null +++ b/sdks/node/docs/model/SubUpdateFormField.md @@ -0,0 +1,12 @@ +# # SubUpdateFormField + + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +| `apiId`*_required_ | ```string``` | The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found | | +| `name` | ```string``` | The new name of the field. If not passed the name will remain unchanged. | | + +[[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/node/docs/model/TemplateEditResponse.md b/sdks/node/docs/model/TemplateEditResponse.md deleted file mode 100644 index 2f40ccbad..000000000 --- a/sdks/node/docs/model/TemplateEditResponse.md +++ /dev/null @@ -1,11 +0,0 @@ -# # TemplateEditResponse - - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -| `templateId`*_required_ | ```string``` | The id of the Template. | | - -[[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/node/model/accountResponse.ts b/sdks/node/model/accountResponse.ts index 73394d615..131dedc2a 100644 --- a/sdks/node/model/accountResponse.ts +++ b/sdks/node/model/accountResponse.ts @@ -24,6 +24,7 @@ import { AttributeTypeMap, ObjectSerializer } from "./"; import { AccountResponseQuotas } from "./accountResponseQuotas"; +import { AccountResponseSettings } from "./accountResponseSettings"; import { AccountResponseUsage } from "./accountResponseUsage"; export class AccountResponse { @@ -65,6 +66,7 @@ export class AccountResponse { */ "locale"?: string | null; "usage"?: AccountResponseUsage; + "settings"?: AccountResponseSettings; static discriminator: string | undefined = undefined; @@ -124,6 +126,11 @@ export class AccountResponse { baseName: "usage", type: "AccountResponseUsage", }, + { + name: "settings", + baseName: "settings", + type: "AccountResponseSettings", + }, ]; static getAttributeTypeMap(): AttributeTypeMap { diff --git a/sdks/node/model/accountResponseSettings.ts b/sdks/node/model/accountResponseSettings.ts new file mode 100644 index 000000000..600e041de --- /dev/null +++ b/sdks/node/model/accountResponseSettings.ts @@ -0,0 +1,72 @@ +/** + * The MIT License (MIT) + * + * Copyright (C) 2023 dropbox.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import { AttributeTypeMap, ObjectSerializer } from "./"; + +/** + * Subset of configured settings + */ +export class AccountResponseSettings { + /** + * Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + */ + "signerAccessCodes"?: boolean; + /** + * Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + */ + "smsDelivery"?: boolean; + /** + * Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + */ + "smsAuthentication"?: boolean; + + static discriminator: string | undefined = undefined; + + static attributeTypeMap: AttributeTypeMap = [ + { + name: "signerAccessCodes", + baseName: "signer_access_codes", + type: "boolean", + }, + { + name: "smsDelivery", + baseName: "sms_delivery", + type: "boolean", + }, + { + name: "smsAuthentication", + baseName: "sms_authentication", + type: "boolean", + }, + ]; + + static getAttributeTypeMap(): AttributeTypeMap { + return AccountResponseSettings.attributeTypeMap; + } + + /** Attempt to instantiate and hydrate a new instance of this class */ + static init(data: any): AccountResponseSettings { + return ObjectSerializer.deserialize(data, "AccountResponseSettings"); + } +} diff --git a/sdks/node/model/index.ts b/sdks/node/model/index.ts index 1f2ea9c97..c30e4c127 100644 --- a/sdks/node/model/index.ts +++ b/sdks/node/model/index.ts @@ -3,6 +3,7 @@ import { AccountCreateResponse } from "./accountCreateResponse"; import { AccountGetResponse } from "./accountGetResponse"; import { AccountResponse } from "./accountResponse"; import { AccountResponseQuotas } from "./accountResponseQuotas"; +import { AccountResponseSettings } from "./accountResponseSettings"; import { AccountResponseUsage } from "./accountResponseUsage"; import { AccountUpdateRequest } from "./accountUpdateRequest"; import { AccountVerifyRequest } from "./accountVerifyRequest"; @@ -138,6 +139,7 @@ import { SubTeamResponse } from "./subTeamResponse"; import { SubTemplateRole } from "./subTemplateRole"; import { SubUnclaimedDraftSigner } from "./subUnclaimedDraftSigner"; import { SubUnclaimedDraftTemplateSigner } from "./subUnclaimedDraftTemplateSigner"; +import { SubUpdateFormField } from "./subUpdateFormField"; import { SubWhiteLabelingOptions } from "./subWhiteLabelingOptions"; import { TeamAddMemberRequest } from "./teamAddMemberRequest"; import { TeamCreateRequest } from "./teamCreateRequest"; @@ -160,7 +162,6 @@ import { TemplateCreateEmbeddedDraftResponseTemplate } from "./templateCreateEmb import { TemplateCreateRequest } from "./templateCreateRequest"; import { TemplateCreateResponse } from "./templateCreateResponse"; import { TemplateCreateResponseTemplate } from "./templateCreateResponseTemplate"; -import { TemplateEditResponse } from "./templateEditResponse"; import { TemplateGetResponse } from "./templateGetResponse"; import { TemplateListResponse } from "./templateListResponse"; import { TemplateRemoveUserRequest } from "./templateRemoveUserRequest"; @@ -260,6 +261,7 @@ export let typeMap: { [index: string]: any } = { AccountGetResponse: AccountGetResponse, AccountResponse: AccountResponse, AccountResponseQuotas: AccountResponseQuotas, + AccountResponseSettings: AccountResponseSettings, AccountResponseUsage: AccountResponseUsage, AccountUpdateRequest: AccountUpdateRequest, AccountVerifyRequest: AccountVerifyRequest, @@ -392,6 +394,7 @@ export let typeMap: { [index: string]: any } = { SubTemplateRole: SubTemplateRole, SubUnclaimedDraftSigner: SubUnclaimedDraftSigner, SubUnclaimedDraftTemplateSigner: SubUnclaimedDraftTemplateSigner, + SubUpdateFormField: SubUpdateFormField, SubWhiteLabelingOptions: SubWhiteLabelingOptions, TeamAddMemberRequest: TeamAddMemberRequest, TeamCreateRequest: TeamCreateRequest, @@ -415,7 +418,6 @@ export let typeMap: { [index: string]: any } = { TemplateCreateRequest: TemplateCreateRequest, TemplateCreateResponse: TemplateCreateResponse, TemplateCreateResponseTemplate: TemplateCreateResponseTemplate, - TemplateEditResponse: TemplateEditResponse, TemplateGetResponse: TemplateGetResponse, TemplateListResponse: TemplateListResponse, TemplateRemoveUserRequest: TemplateRemoveUserRequest, @@ -488,6 +490,7 @@ export { AccountGetResponse, AccountResponse, AccountResponseQuotas, + AccountResponseSettings, AccountResponseUsage, AccountUpdateRequest, AccountVerifyRequest, @@ -620,6 +623,7 @@ export { SubTemplateRole, SubUnclaimedDraftSigner, SubUnclaimedDraftTemplateSigner, + SubUpdateFormField, SubWhiteLabelingOptions, TeamAddMemberRequest, TeamCreateRequest, @@ -642,7 +646,6 @@ export { TemplateCreateRequest, TemplateCreateResponse, TemplateCreateResponseTemplate, - TemplateEditResponse, TemplateGetResponse, TemplateListResponse, TemplateRemoveUserRequest, diff --git a/sdks/node/model/reportCreateRequest.ts b/sdks/node/model/reportCreateRequest.ts index de074447a..ee1cb00d9 100644 --- a/sdks/node/model/reportCreateRequest.ts +++ b/sdks/node/model/reportCreateRequest.ts @@ -73,5 +73,6 @@ export namespace ReportCreateRequest { UserActivity = "user_activity", DocumentStatus = "document_status", SmsActivity = "sms_activity", + FaxUsage = "fax_usage", } } diff --git a/sdks/node/model/reportResponse.ts b/sdks/node/model/reportResponse.ts index e47c0248f..555cc8dfd 100644 --- a/sdks/node/model/reportResponse.ts +++ b/sdks/node/model/reportResponse.ts @@ -85,5 +85,6 @@ export namespace ReportResponse { UserActivity = "user_activity", DocumentStatus = "document_status", SmsActivity = "sms_activity", + FaxUsage = "fax_usage", } } diff --git a/sdks/node/model/signatureRequestEditRequest.ts b/sdks/node/model/signatureRequestEditRequest.ts index 432e8fe4f..5f079203c 100644 --- a/sdks/node/model/signatureRequestEditRequest.ts +++ b/sdks/node/model/signatureRequestEditRequest.ts @@ -92,7 +92,7 @@ export class SignatureRequestEditRequest { */ "hideTextTags"?: boolean = false; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ "isEid"?: boolean = false; /** diff --git a/sdks/node/model/signatureRequestEditWithTemplateRequest.ts b/sdks/node/model/signatureRequestEditWithTemplateRequest.ts index f35af5999..2ad306f33 100644 --- a/sdks/node/model/signatureRequestEditWithTemplateRequest.ts +++ b/sdks/node/model/signatureRequestEditWithTemplateRequest.ts @@ -65,7 +65,7 @@ export class SignatureRequestEditWithTemplateRequest { */ "fileUrls"?: Array; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ "isEid"?: boolean = false; /** diff --git a/sdks/node/model/signatureRequestSendRequest.ts b/sdks/node/model/signatureRequestSendRequest.ts index 75720c17b..f18588a35 100644 --- a/sdks/node/model/signatureRequestSendRequest.ts +++ b/sdks/node/model/signatureRequestSendRequest.ts @@ -98,7 +98,7 @@ export class SignatureRequestSendRequest { */ "isQualifiedSignature"?: boolean = false; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ "isEid"?: boolean = false; /** diff --git a/sdks/node/model/signatureRequestSendWithTemplateRequest.ts b/sdks/node/model/signatureRequestSendWithTemplateRequest.ts index 12232a129..2d0d5981a 100644 --- a/sdks/node/model/signatureRequestSendWithTemplateRequest.ts +++ b/sdks/node/model/signatureRequestSendWithTemplateRequest.ts @@ -71,7 +71,7 @@ export class SignatureRequestSendWithTemplateRequest { */ "isQualifiedSignature"?: boolean = false; /** - * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. */ "isEid"?: boolean = false; /** diff --git a/sdks/node/model/subSigningOptions.ts b/sdks/node/model/subSigningOptions.ts index 886d611c7..3e983dd78 100644 --- a/sdks/node/model/subSigningOptions.ts +++ b/sdks/node/model/subSigningOptions.ts @@ -25,7 +25,7 @@ import { AttributeTypeMap, ObjectSerializer } from "./"; /** - * This allows the requester to specify the types allowed for creating a signature. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + * This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. */ export class SubSigningOptions { /** @@ -48,6 +48,10 @@ export class SubSigningOptions { * Allows uploading the signature */ "upload"?: boolean = false; + /** + * Turning on advanced signature details for the signature request + */ + "forceAdvancedSignatureDetails"?: boolean = false; static discriminator: string | undefined = undefined; @@ -77,6 +81,11 @@ export class SubSigningOptions { baseName: "upload", type: "boolean", }, + { + name: "forceAdvancedSignatureDetails", + baseName: "force_advanced_signature_details", + type: "boolean", + }, ]; static getAttributeTypeMap(): AttributeTypeMap { diff --git a/sdks/node/model/templateEditResponse.ts b/sdks/node/model/subUpdateFormField.ts similarity index 71% rename from sdks/node/model/templateEditResponse.ts rename to sdks/node/model/subUpdateFormField.ts index aa51f43d0..50f206cf7 100644 --- a/sdks/node/model/templateEditResponse.ts +++ b/sdks/node/model/subUpdateFormField.ts @@ -24,28 +24,37 @@ import { AttributeTypeMap, ObjectSerializer } from "./"; -export class TemplateEditResponse { +export class SubUpdateFormField { /** - * The id of the Template. + * The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found */ - "templateId": string; + "apiId": string; + /** + * The new name of the field. If not passed the name will remain unchanged. + */ + "name"?: string; static discriminator: string | undefined = undefined; static attributeTypeMap: AttributeTypeMap = [ { - name: "templateId", - baseName: "template_id", + name: "apiId", + baseName: "api_id", + type: "string", + }, + { + name: "name", + baseName: "name", type: "string", }, ]; static getAttributeTypeMap(): AttributeTypeMap { - return TemplateEditResponse.attributeTypeMap; + return SubUpdateFormField.attributeTypeMap; } /** Attempt to instantiate and hydrate a new instance of this class */ - static init(data: any): TemplateEditResponse { - return ObjectSerializer.deserialize(data, "TemplateEditResponse"); + static init(data: any): SubUpdateFormField { + return ObjectSerializer.deserialize(data, "SubUpdateFormField"); } } diff --git a/sdks/node/types/model/accountResponse.d.ts b/sdks/node/types/model/accountResponse.d.ts index c38fde985..767441b96 100644 --- a/sdks/node/types/model/accountResponse.d.ts +++ b/sdks/node/types/model/accountResponse.d.ts @@ -1,5 +1,6 @@ import { AttributeTypeMap } from "./"; import { AccountResponseQuotas } from "./accountResponseQuotas"; +import { AccountResponseSettings } from "./accountResponseSettings"; import { AccountResponseUsage } from "./accountResponseUsage"; export declare class AccountResponse { "accountId"?: string; @@ -13,6 +14,7 @@ export declare class AccountResponse { "teamId"?: string | null; "locale"?: string | null; "usage"?: AccountResponseUsage; + "settings"?: AccountResponseSettings; static discriminator: string | undefined; static attributeTypeMap: AttributeTypeMap; static getAttributeTypeMap(): AttributeTypeMap; diff --git a/sdks/node/types/model/accountResponseSettings.d.ts b/sdks/node/types/model/accountResponseSettings.d.ts new file mode 100644 index 000000000..4d816d64c --- /dev/null +++ b/sdks/node/types/model/accountResponseSettings.d.ts @@ -0,0 +1,10 @@ +import { AttributeTypeMap } from "./"; +export declare class AccountResponseSettings { + "signerAccessCodes"?: boolean; + "smsDelivery"?: boolean; + "smsAuthentication"?: boolean; + static discriminator: string | undefined; + static attributeTypeMap: AttributeTypeMap; + static getAttributeTypeMap(): AttributeTypeMap; + static init(data: any): AccountResponseSettings; +} diff --git a/sdks/node/types/model/index.d.ts b/sdks/node/types/model/index.d.ts index 99010c62f..198242dc3 100644 --- a/sdks/node/types/model/index.d.ts +++ b/sdks/node/types/model/index.d.ts @@ -3,6 +3,7 @@ import { AccountCreateResponse } from "./accountCreateResponse"; import { AccountGetResponse } from "./accountGetResponse"; import { AccountResponse } from "./accountResponse"; import { AccountResponseQuotas } from "./accountResponseQuotas"; +import { AccountResponseSettings } from "./accountResponseSettings"; import { AccountResponseUsage } from "./accountResponseUsage"; import { AccountUpdateRequest } from "./accountUpdateRequest"; import { AccountVerifyRequest } from "./accountVerifyRequest"; @@ -126,6 +127,7 @@ import { SubTeamResponse } from "./subTeamResponse"; import { SubTemplateRole } from "./subTemplateRole"; import { SubUnclaimedDraftSigner } from "./subUnclaimedDraftSigner"; import { SubUnclaimedDraftTemplateSigner } from "./subUnclaimedDraftTemplateSigner"; +import { SubUpdateFormField } from "./subUpdateFormField"; import { SubWhiteLabelingOptions } from "./subWhiteLabelingOptions"; import { TeamAddMemberRequest } from "./teamAddMemberRequest"; import { TeamCreateRequest } from "./teamCreateRequest"; @@ -148,7 +150,6 @@ import { TemplateCreateEmbeddedDraftResponseTemplate } from "./templateCreateEmb import { TemplateCreateRequest } from "./templateCreateRequest"; import { TemplateCreateResponse } from "./templateCreateResponse"; import { TemplateCreateResponseTemplate } from "./templateCreateResponseTemplate"; -import { TemplateEditResponse } from "./templateEditResponse"; import { TemplateGetResponse } from "./templateGetResponse"; import { TemplateListResponse } from "./templateListResponse"; import { TemplateRemoveUserRequest } from "./templateRemoveUserRequest"; @@ -198,4 +199,4 @@ export declare let enumsMap: { export declare let typeMap: { [index: string]: any; }; -export { AccountCreateRequest, AccountCreateResponse, AccountGetResponse, AccountResponse, AccountResponseQuotas, AccountResponseUsage, AccountUpdateRequest, AccountVerifyRequest, AccountVerifyResponse, AccountVerifyResponseAccount, ApiAppCreateRequest, ApiAppGetResponse, ApiAppListResponse, ApiAppResponse, ApiAppResponseOAuth, ApiAppResponseOptions, ApiAppResponseOwnerAccount, ApiAppResponseWhiteLabelingOptions, ApiAppUpdateRequest, ApiKeyAuth, AttributeTypeMap, Authentication, BulkSendJobGetResponse, BulkSendJobGetResponseSignatureRequests, BulkSendJobListResponse, BulkSendJobResponse, BulkSendJobSendResponse, EmbeddedEditUrlRequest, EmbeddedEditUrlResponse, EmbeddedEditUrlResponseEmbedded, EmbeddedSignUrlResponse, EmbeddedSignUrlResponseEmbedded, ErrorResponse, ErrorResponseError, EventCallbackHelper, EventCallbackRequest, EventCallbackRequestEvent, EventCallbackRequestEventMetadata, FaxGetResponse, FaxLineAddUserRequest, FaxLineAreaCodeGetCountryEnum, FaxLineAreaCodeGetProvinceEnum, FaxLineAreaCodeGetResponse, FaxLineAreaCodeGetStateEnum, FaxLineCreateRequest, FaxLineDeleteRequest, FaxLineListResponse, FaxLineRemoveUserRequest, FaxLineResponse, FaxLineResponseFaxLine, FaxListResponse, FaxResponse, FaxResponseTransmission, FaxSendRequest, FileResponse, FileResponseDataUri, HttpBasicAuth, HttpBearerAuth, Interceptor, ListInfoResponse, OAuth, OAuthTokenGenerateRequest, OAuthTokenRefreshRequest, OAuthTokenResponse, ObjectSerializer, ReportCreateRequest, ReportCreateResponse, ReportResponse, RequestDetailedFile, RequestFile, SignatureRequestBulkCreateEmbeddedWithTemplateRequest, SignatureRequestBulkSendWithTemplateRequest, SignatureRequestCreateEmbeddedRequest, SignatureRequestCreateEmbeddedWithTemplateRequest, SignatureRequestEditEmbeddedRequest, SignatureRequestEditEmbeddedWithTemplateRequest, SignatureRequestEditRequest, SignatureRequestEditWithTemplateRequest, SignatureRequestGetResponse, SignatureRequestListResponse, SignatureRequestRemindRequest, SignatureRequestResponse, SignatureRequestResponseAttachment, SignatureRequestResponseCustomFieldBase, SignatureRequestResponseCustomFieldCheckbox, SignatureRequestResponseCustomFieldText, SignatureRequestResponseCustomFieldTypeEnum, SignatureRequestResponseDataBase, SignatureRequestResponseDataTypeEnum, SignatureRequestResponseDataValueCheckbox, SignatureRequestResponseDataValueCheckboxMerge, SignatureRequestResponseDataValueDateSigned, SignatureRequestResponseDataValueDropdown, SignatureRequestResponseDataValueInitials, SignatureRequestResponseDataValueRadio, SignatureRequestResponseDataValueSignature, SignatureRequestResponseDataValueText, SignatureRequestResponseDataValueTextMerge, SignatureRequestResponseSignatures, SignatureRequestSendRequest, SignatureRequestSendWithTemplateRequest, SignatureRequestUpdateRequest, SubAttachment, SubBulkSignerList, SubBulkSignerListCustomField, SubCC, SubCustomField, SubEditorOptions, SubFieldOptions, SubFormFieldGroup, SubFormFieldRule, SubFormFieldRuleAction, SubFormFieldRuleTrigger, SubFormFieldsPerDocumentBase, SubFormFieldsPerDocumentCheckbox, SubFormFieldsPerDocumentCheckboxMerge, SubFormFieldsPerDocumentDateSigned, SubFormFieldsPerDocumentDropdown, SubFormFieldsPerDocumentFontEnum, SubFormFieldsPerDocumentHyperlink, SubFormFieldsPerDocumentInitials, SubFormFieldsPerDocumentRadio, SubFormFieldsPerDocumentSignature, SubFormFieldsPerDocumentText, SubFormFieldsPerDocumentTextMerge, SubFormFieldsPerDocumentTypeEnum, SubMergeField, SubOAuth, SubOptions, SubSignatureRequestGroupedSigners, SubSignatureRequestSigner, SubSignatureRequestTemplateSigner, SubSigningOptions, SubTeamResponse, SubTemplateRole, SubUnclaimedDraftSigner, SubUnclaimedDraftTemplateSigner, SubWhiteLabelingOptions, TeamAddMemberRequest, TeamCreateRequest, TeamGetInfoResponse, TeamGetResponse, TeamInfoResponse, TeamInviteResponse, TeamInvitesResponse, TeamMemberResponse, TeamMembersResponse, TeamParentResponse, TeamRemoveMemberRequest, TeamResponse, TeamSubTeamsResponse, TeamUpdateRequest, TemplateAddUserRequest, TemplateCreateEmbeddedDraftRequest, TemplateCreateEmbeddedDraftResponse, TemplateCreateEmbeddedDraftResponseTemplate, TemplateCreateRequest, TemplateCreateResponse, TemplateCreateResponseTemplate, TemplateEditResponse, TemplateGetResponse, TemplateListResponse, TemplateRemoveUserRequest, TemplateResponse, TemplateResponseAccount, TemplateResponseAccountQuota, TemplateResponseCCRole, TemplateResponseDocument, TemplateResponseDocumentCustomFieldBase, TemplateResponseDocumentCustomFieldCheckbox, TemplateResponseDocumentCustomFieldText, TemplateResponseDocumentFieldGroup, TemplateResponseDocumentFieldGroupRule, TemplateResponseDocumentFormFieldBase, TemplateResponseDocumentFormFieldCheckbox, TemplateResponseDocumentFormFieldDateSigned, TemplateResponseDocumentFormFieldDropdown, TemplateResponseDocumentFormFieldHyperlink, TemplateResponseDocumentFormFieldInitials, TemplateResponseDocumentFormFieldRadio, TemplateResponseDocumentFormFieldSignature, TemplateResponseDocumentFormFieldText, TemplateResponseDocumentStaticFieldBase, TemplateResponseDocumentStaticFieldCheckbox, TemplateResponseDocumentStaticFieldDateSigned, TemplateResponseDocumentStaticFieldDropdown, TemplateResponseDocumentStaticFieldHyperlink, TemplateResponseDocumentStaticFieldInitials, TemplateResponseDocumentStaticFieldRadio, TemplateResponseDocumentStaticFieldSignature, TemplateResponseDocumentStaticFieldText, TemplateResponseFieldAvgTextLength, TemplateResponseSignerRole, TemplateUpdateFilesRequest, TemplateUpdateFilesResponse, TemplateUpdateFilesResponseTemplate, UnclaimedDraftCreateEmbeddedRequest, UnclaimedDraftCreateEmbeddedWithTemplateRequest, UnclaimedDraftCreateRequest, UnclaimedDraftCreateResponse, UnclaimedDraftEditAndResendRequest, UnclaimedDraftResponse, VoidAuth, WarningResponse, }; +export { AccountCreateRequest, AccountCreateResponse, AccountGetResponse, AccountResponse, AccountResponseQuotas, AccountResponseSettings, AccountResponseUsage, AccountUpdateRequest, AccountVerifyRequest, AccountVerifyResponse, AccountVerifyResponseAccount, ApiAppCreateRequest, ApiAppGetResponse, ApiAppListResponse, ApiAppResponse, ApiAppResponseOAuth, ApiAppResponseOptions, ApiAppResponseOwnerAccount, ApiAppResponseWhiteLabelingOptions, ApiAppUpdateRequest, ApiKeyAuth, AttributeTypeMap, Authentication, BulkSendJobGetResponse, BulkSendJobGetResponseSignatureRequests, BulkSendJobListResponse, BulkSendJobResponse, BulkSendJobSendResponse, EmbeddedEditUrlRequest, EmbeddedEditUrlResponse, EmbeddedEditUrlResponseEmbedded, EmbeddedSignUrlResponse, EmbeddedSignUrlResponseEmbedded, ErrorResponse, ErrorResponseError, EventCallbackHelper, EventCallbackRequest, EventCallbackRequestEvent, EventCallbackRequestEventMetadata, FaxGetResponse, FaxLineAddUserRequest, FaxLineAreaCodeGetCountryEnum, FaxLineAreaCodeGetProvinceEnum, FaxLineAreaCodeGetResponse, FaxLineAreaCodeGetStateEnum, FaxLineCreateRequest, FaxLineDeleteRequest, FaxLineListResponse, FaxLineRemoveUserRequest, FaxLineResponse, FaxLineResponseFaxLine, FaxListResponse, FaxResponse, FaxResponseTransmission, FaxSendRequest, FileResponse, FileResponseDataUri, HttpBasicAuth, HttpBearerAuth, Interceptor, ListInfoResponse, OAuth, OAuthTokenGenerateRequest, OAuthTokenRefreshRequest, OAuthTokenResponse, ObjectSerializer, ReportCreateRequest, ReportCreateResponse, ReportResponse, RequestDetailedFile, RequestFile, SignatureRequestBulkCreateEmbeddedWithTemplateRequest, SignatureRequestBulkSendWithTemplateRequest, SignatureRequestCreateEmbeddedRequest, SignatureRequestCreateEmbeddedWithTemplateRequest, SignatureRequestEditEmbeddedRequest, SignatureRequestEditEmbeddedWithTemplateRequest, SignatureRequestEditRequest, SignatureRequestEditWithTemplateRequest, SignatureRequestGetResponse, SignatureRequestListResponse, SignatureRequestRemindRequest, SignatureRequestResponse, SignatureRequestResponseAttachment, SignatureRequestResponseCustomFieldBase, SignatureRequestResponseCustomFieldCheckbox, SignatureRequestResponseCustomFieldText, SignatureRequestResponseCustomFieldTypeEnum, SignatureRequestResponseDataBase, SignatureRequestResponseDataTypeEnum, SignatureRequestResponseDataValueCheckbox, SignatureRequestResponseDataValueCheckboxMerge, SignatureRequestResponseDataValueDateSigned, SignatureRequestResponseDataValueDropdown, SignatureRequestResponseDataValueInitials, SignatureRequestResponseDataValueRadio, SignatureRequestResponseDataValueSignature, SignatureRequestResponseDataValueText, SignatureRequestResponseDataValueTextMerge, SignatureRequestResponseSignatures, SignatureRequestSendRequest, SignatureRequestSendWithTemplateRequest, SignatureRequestUpdateRequest, SubAttachment, SubBulkSignerList, SubBulkSignerListCustomField, SubCC, SubCustomField, SubEditorOptions, SubFieldOptions, SubFormFieldGroup, SubFormFieldRule, SubFormFieldRuleAction, SubFormFieldRuleTrigger, SubFormFieldsPerDocumentBase, SubFormFieldsPerDocumentCheckbox, SubFormFieldsPerDocumentCheckboxMerge, SubFormFieldsPerDocumentDateSigned, SubFormFieldsPerDocumentDropdown, SubFormFieldsPerDocumentFontEnum, SubFormFieldsPerDocumentHyperlink, SubFormFieldsPerDocumentInitials, SubFormFieldsPerDocumentRadio, SubFormFieldsPerDocumentSignature, SubFormFieldsPerDocumentText, SubFormFieldsPerDocumentTextMerge, SubFormFieldsPerDocumentTypeEnum, SubMergeField, SubOAuth, SubOptions, SubSignatureRequestGroupedSigners, SubSignatureRequestSigner, SubSignatureRequestTemplateSigner, SubSigningOptions, SubTeamResponse, SubTemplateRole, SubUnclaimedDraftSigner, SubUnclaimedDraftTemplateSigner, SubUpdateFormField, SubWhiteLabelingOptions, TeamAddMemberRequest, TeamCreateRequest, TeamGetInfoResponse, TeamGetResponse, TeamInfoResponse, TeamInviteResponse, TeamInvitesResponse, TeamMemberResponse, TeamMembersResponse, TeamParentResponse, TeamRemoveMemberRequest, TeamResponse, TeamSubTeamsResponse, TeamUpdateRequest, TemplateAddUserRequest, TemplateCreateEmbeddedDraftRequest, TemplateCreateEmbeddedDraftResponse, TemplateCreateEmbeddedDraftResponseTemplate, TemplateCreateRequest, TemplateCreateResponse, TemplateCreateResponseTemplate, TemplateGetResponse, TemplateListResponse, TemplateRemoveUserRequest, TemplateResponse, TemplateResponseAccount, TemplateResponseAccountQuota, TemplateResponseCCRole, TemplateResponseDocument, TemplateResponseDocumentCustomFieldBase, TemplateResponseDocumentCustomFieldCheckbox, TemplateResponseDocumentCustomFieldText, TemplateResponseDocumentFieldGroup, TemplateResponseDocumentFieldGroupRule, TemplateResponseDocumentFormFieldBase, TemplateResponseDocumentFormFieldCheckbox, TemplateResponseDocumentFormFieldDateSigned, TemplateResponseDocumentFormFieldDropdown, TemplateResponseDocumentFormFieldHyperlink, TemplateResponseDocumentFormFieldInitials, TemplateResponseDocumentFormFieldRadio, TemplateResponseDocumentFormFieldSignature, TemplateResponseDocumentFormFieldText, TemplateResponseDocumentStaticFieldBase, TemplateResponseDocumentStaticFieldCheckbox, TemplateResponseDocumentStaticFieldDateSigned, TemplateResponseDocumentStaticFieldDropdown, TemplateResponseDocumentStaticFieldHyperlink, TemplateResponseDocumentStaticFieldInitials, TemplateResponseDocumentStaticFieldRadio, TemplateResponseDocumentStaticFieldSignature, TemplateResponseDocumentStaticFieldText, TemplateResponseFieldAvgTextLength, TemplateResponseSignerRole, TemplateUpdateFilesRequest, TemplateUpdateFilesResponse, TemplateUpdateFilesResponseTemplate, UnclaimedDraftCreateEmbeddedRequest, UnclaimedDraftCreateEmbeddedWithTemplateRequest, UnclaimedDraftCreateRequest, UnclaimedDraftCreateResponse, UnclaimedDraftEditAndResendRequest, UnclaimedDraftResponse, VoidAuth, WarningResponse, }; diff --git a/sdks/node/types/model/reportCreateRequest.d.ts b/sdks/node/types/model/reportCreateRequest.d.ts index 4bdd1f595..457ad8890 100644 --- a/sdks/node/types/model/reportCreateRequest.d.ts +++ b/sdks/node/types/model/reportCreateRequest.d.ts @@ -12,6 +12,7 @@ export declare namespace ReportCreateRequest { enum ReportTypeEnum { UserActivity = "user_activity", DocumentStatus = "document_status", - SmsActivity = "sms_activity" + SmsActivity = "sms_activity", + FaxUsage = "fax_usage" } } diff --git a/sdks/node/types/model/reportResponse.d.ts b/sdks/node/types/model/reportResponse.d.ts index 1490e79e9..79556c74e 100644 --- a/sdks/node/types/model/reportResponse.d.ts +++ b/sdks/node/types/model/reportResponse.d.ts @@ -13,6 +13,7 @@ export declare namespace ReportResponse { enum ReportTypeEnum { UserActivity = "user_activity", DocumentStatus = "document_status", - SmsActivity = "sms_activity" + SmsActivity = "sms_activity", + FaxUsage = "fax_usage" } } diff --git a/sdks/node/types/model/subSigningOptions.d.ts b/sdks/node/types/model/subSigningOptions.d.ts index c81b643d3..865ccf317 100644 --- a/sdks/node/types/model/subSigningOptions.d.ts +++ b/sdks/node/types/model/subSigningOptions.d.ts @@ -5,6 +5,7 @@ export declare class SubSigningOptions { "phone"?: boolean; "type"?: boolean; "upload"?: boolean; + "forceAdvancedSignatureDetails"?: boolean; static discriminator: string | undefined; static attributeTypeMap: AttributeTypeMap; static getAttributeTypeMap(): AttributeTypeMap; diff --git a/sdks/node/types/model/templateEditResponse.d.ts b/sdks/node/types/model/subUpdateFormField.d.ts similarity index 58% rename from sdks/node/types/model/templateEditResponse.d.ts rename to sdks/node/types/model/subUpdateFormField.d.ts index dba3ddce6..545043ecd 100644 --- a/sdks/node/types/model/templateEditResponse.d.ts +++ b/sdks/node/types/model/subUpdateFormField.d.ts @@ -1,8 +1,9 @@ import { AttributeTypeMap } from "./"; -export declare class TemplateEditResponse { - "templateId": string; +export declare class SubUpdateFormField { + "apiId": string; + "name"?: string; static discriminator: string | undefined; static attributeTypeMap: AttributeTypeMap; static getAttributeTypeMap(): AttributeTypeMap; - static init(data: any): TemplateEditResponse; + static init(data: any): SubUpdateFormField; } diff --git a/sdks/php/README.md b/sdks/php/README.md index ddc1ded08..3a709a912 100644 --- a/sdks/php/README.md +++ b/sdks/php/README.md @@ -229,6 +229,7 @@ All URIs are relative to *https://api.hellosign.com/v3* - [AccountGetResponse](docs/Model/AccountGetResponse.md) - [AccountResponse](docs/Model/AccountResponse.md) - [AccountResponseQuotas](docs/Model/AccountResponseQuotas.md) +- [AccountResponseSettings](docs/Model/AccountResponseSettings.md) - [AccountResponseUsage](docs/Model/AccountResponseUsage.md) - [AccountUpdateRequest](docs/Model/AccountUpdateRequest.md) - [AccountVerifyRequest](docs/Model/AccountVerifyRequest.md) @@ -350,6 +351,7 @@ All URIs are relative to *https://api.hellosign.com/v3* - [SubTemplateRole](docs/Model/SubTemplateRole.md) - [SubUnclaimedDraftSigner](docs/Model/SubUnclaimedDraftSigner.md) - [SubUnclaimedDraftTemplateSigner](docs/Model/SubUnclaimedDraftTemplateSigner.md) +- [SubUpdateFormField](docs/Model/SubUpdateFormField.md) - [SubWhiteLabelingOptions](docs/Model/SubWhiteLabelingOptions.md) - [TeamAddMemberRequest](docs/Model/TeamAddMemberRequest.md) - [TeamCreateRequest](docs/Model/TeamCreateRequest.md) @@ -372,7 +374,6 @@ All URIs are relative to *https://api.hellosign.com/v3* - [TemplateCreateRequest](docs/Model/TemplateCreateRequest.md) - [TemplateCreateResponse](docs/Model/TemplateCreateResponse.md) - [TemplateCreateResponseTemplate](docs/Model/TemplateCreateResponseTemplate.md) -- [TemplateEditResponse](docs/Model/TemplateEditResponse.md) - [TemplateGetResponse](docs/Model/TemplateGetResponse.md) - [TemplateListResponse](docs/Model/TemplateListResponse.md) - [TemplateRemoveUserRequest](docs/Model/TemplateRemoveUserRequest.md) diff --git a/sdks/php/composer.json b/sdks/php/composer.json index 347c72797..8347a023b 100644 --- a/sdks/php/composer.json +++ b/sdks/php/composer.json @@ -31,7 +31,7 @@ }, "require-dev": { "phpunit/phpunit": "^8.0 || ^9.0", - "friendsofphp/php-cs-fixer": "^3.5", + "friendsofphp/php-cs-fixer": "v3.84.0", "symfony/yaml": "^5.4" }, "autoload": { diff --git a/sdks/php/docs/Api/SignatureRequestApi.md b/sdks/php/docs/Api/SignatureRequestApi.md index 3e2c764a1..5e395b147 100644 --- a/sdks/php/docs/Api/SignatureRequestApi.md +++ b/sdks/php/docs/Api/SignatureRequestApi.md @@ -368,7 +368,8 @@ $signing_options = (new Dropbox\Sign\Model\SubSigningOptions()) ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestSigner()) ->setName("Jack") @@ -465,7 +466,8 @@ $signing_options = (new Dropbox\Sign\Model\SubSigningOptions()) ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestTemplateSigner()) ->setRole("Client") @@ -1449,7 +1451,8 @@ $signing_options = (new Dropbox\Sign\Model\SubSigningOptions()) ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestSigner()) ->setName("Jack") @@ -1552,7 +1555,8 @@ $signing_options = (new Dropbox\Sign\Model\SubSigningOptions()) ->setDraw(true) ->setPhone(false) ->setType(true) - ->setUpload(true); + ->setUpload(true) + ->setForceAdvancedSignatureDetails(false); $signers_1 = (new Dropbox\Sign\Model\SubSignatureRequestTemplateSigner()) ->setRole("Client") diff --git a/sdks/php/docs/Api/TemplateApi.md b/sdks/php/docs/Api/TemplateApi.md index 23d1d5a98..2215c078c 100644 --- a/sdks/php/docs/Api/TemplateApi.md +++ b/sdks/php/docs/Api/TemplateApi.md @@ -89,7 +89,7 @@ templateCreate($template_create_request): \Dropbox\Sign\Model\TemplateCreateResp ``` Create Template -Creates a template that can then be used. +Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. ### Example diff --git a/sdks/php/docs/Model/AccountResponse.md b/sdks/php/docs/Model/AccountResponse.md index 3121826ba..8cabded2a 100644 --- a/sdks/php/docs/Model/AccountResponse.md +++ b/sdks/php/docs/Model/AccountResponse.md @@ -17,5 +17,6 @@ Name | Type | Description | Notes | `team_id` | ```string``` | The id of the team account belongs to. | | | `locale` | ```string``` | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | | | `usage` | [```\Dropbox\Sign\Model\AccountResponseUsage```](AccountResponseUsage.md) | | | +| `settings` | [```\Dropbox\Sign\Model\AccountResponseSettings```](AccountResponseSettings.md) | | | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/php/docs/Model/AccountResponseSettings.md b/sdks/php/docs/Model/AccountResponseSettings.md new file mode 100644 index 000000000..913c6584a --- /dev/null +++ b/sdks/php/docs/Model/AccountResponseSettings.md @@ -0,0 +1,13 @@ +# # AccountResponseSettings + +Subset of configured settings + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +| `signer_access_codes` | ```bool``` | Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `sms_delivery` | ```bool``` | Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `sms_authentication` | ```bool``` | Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | + +[[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/php/docs/Model/SignatureRequestEditRequest.md b/sdks/php/docs/Model/SignatureRequestEditRequest.md index 0d3ca23ce..bd308cf42 100644 --- a/sdks/php/docs/Model/SignatureRequestEditRequest.md +++ b/sdks/php/docs/Model/SignatureRequestEditRequest.md @@ -21,7 +21,7 @@ Name | Type | Description | Notes | `form_field_rules` | [```\Dropbox\Sign\Model\SubFormFieldRule[]```](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | | | `form_fields_per_document` | [```\Dropbox\Sign\Model\SubFormFieldsPerDocumentBase[]```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hide_text_tags` | ```bool``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to false] | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```array``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```\Dropbox\Sign\Model\SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/php/docs/Model/SignatureRequestEditWithTemplateRequest.md b/sdks/php/docs/Model/SignatureRequestEditWithTemplateRequest.md index 072fdc080..835ab98ea 100644 --- a/sdks/php/docs/Model/SignatureRequestEditWithTemplateRequest.md +++ b/sdks/php/docs/Model/SignatureRequestEditWithTemplateRequest.md @@ -14,7 +14,7 @@ Name | Type | Description | Notes | `custom_fields` | [```\Dropbox\Sign\Model\SubCustomField[]```](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | | | `files` | ```\SplFileObject[]``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `file_urls` | ```string[]``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```array``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```\Dropbox\Sign\Model\SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/php/docs/Model/SignatureRequestSendRequest.md b/sdks/php/docs/Model/SignatureRequestSendRequest.md index 65d3a7d91..bad47fcfc 100644 --- a/sdks/php/docs/Model/SignatureRequestSendRequest.md +++ b/sdks/php/docs/Model/SignatureRequestSendRequest.md @@ -22,7 +22,7 @@ Name | Type | Description | Notes | `form_fields_per_document` | [```\Dropbox\Sign\Model\SubFormFieldsPerDocumentBase[]```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hide_text_tags` | ```bool``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to false] | | `is_qualified_signature` | ```bool``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```array``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```\Dropbox\Sign\Model\SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/php/docs/Model/SignatureRequestSendWithTemplateRequest.md b/sdks/php/docs/Model/SignatureRequestSendWithTemplateRequest.md index cbfaeb338..4942a5c71 100644 --- a/sdks/php/docs/Model/SignatureRequestSendWithTemplateRequest.md +++ b/sdks/php/docs/Model/SignatureRequestSendWithTemplateRequest.md @@ -15,7 +15,7 @@ Name | Type | Description | Notes | `files` | ```\SplFileObject[]``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `file_urls` | ```string[]``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `is_qualified_signature` | ```bool``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```string``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```array``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```\Dropbox\Sign\Model\SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/php/docs/Model/SubSigningOptions.md b/sdks/php/docs/Model/SubSigningOptions.md index e2a1b1660..0a3d3a40e 100644 --- a/sdks/php/docs/Model/SubSigningOptions.md +++ b/sdks/php/docs/Model/SubSigningOptions.md @@ -1,9 +1,11 @@ # # SubSigningOptions -This allows the requester to specify the types allowed for creating a signature. +This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. +**NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. + ## Properties Name | Type | Description | Notes @@ -13,5 +15,6 @@ Name | Type | Description | Notes | `phone` | ```bool``` | Allows using a smartphone to email the signature | [default to false] | | `type` | ```bool``` | Allows typing the signature | [default to false] | | `upload` | ```bool``` | Allows uploading the signature | [default to false] | +| `force_advanced_signature_details` | ```bool``` | Turning on advanced signature details for the signature request | [default to false] | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/php/docs/Model/SubUpdateFormField.md b/sdks/php/docs/Model/SubUpdateFormField.md new file mode 100644 index 000000000..1398a7960 --- /dev/null +++ b/sdks/php/docs/Model/SubUpdateFormField.md @@ -0,0 +1,12 @@ +# # SubUpdateFormField + + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +| `api_id`*_required_ | ```string``` | The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found | | +| `name` | ```string``` | The new name of the field. If not passed the name will remain unchanged. | | + +[[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/php/docs/Model/TemplateEditResponse.md b/sdks/php/docs/Model/TemplateEditResponse.md deleted file mode 100644 index b343db573..000000000 --- a/sdks/php/docs/Model/TemplateEditResponse.md +++ /dev/null @@ -1,11 +0,0 @@ -# # TemplateEditResponse - - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -| `template_id`*_required_ | ```string``` | The id of the Template. | | - -[[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) diff --git a/sdks/php/src/Model/AccountResponse.php b/sdks/php/src/Model/AccountResponse.php index 251546bab..25a88c24f 100644 --- a/sdks/php/src/Model/AccountResponse.php +++ b/sdks/php/src/Model/AccountResponse.php @@ -68,6 +68,7 @@ class AccountResponse implements ModelInterface, ArrayAccess, JsonSerializable 'team_id' => 'string', 'locale' => 'string', 'usage' => '\Dropbox\Sign\Model\AccountResponseUsage', + 'settings' => '\Dropbox\Sign\Model\AccountResponseSettings', ]; /** @@ -89,6 +90,7 @@ class AccountResponse implements ModelInterface, ArrayAccess, JsonSerializable 'team_id' => null, 'locale' => null, 'usage' => null, + 'settings' => null, ]; /** @@ -108,6 +110,7 @@ class AccountResponse implements ModelInterface, ArrayAccess, JsonSerializable 'team_id' => true, 'locale' => true, 'usage' => false, + 'settings' => false, ]; /** @@ -199,6 +202,7 @@ public function isNullableSetToNull(string $property): bool 'team_id' => 'team_id', 'locale' => 'locale', 'usage' => 'usage', + 'settings' => 'settings', ]; /** @@ -218,6 +222,7 @@ public function isNullableSetToNull(string $property): bool 'team_id' => 'setTeamId', 'locale' => 'setLocale', 'usage' => 'setUsage', + 'settings' => 'setSettings', ]; /** @@ -237,6 +242,7 @@ public function isNullableSetToNull(string $property): bool 'team_id' => 'getTeamId', 'locale' => 'getLocale', 'usage' => 'getUsage', + 'settings' => 'getSettings', ]; /** @@ -306,6 +312,7 @@ public function __construct(?array $data = null) $this->setIfExists('team_id', $data ?? [], null); $this->setIfExists('locale', $data ?? [], null); $this->setIfExists('usage', $data ?? [], null); + $this->setIfExists('settings', $data ?? [], null); } /** @@ -690,6 +697,33 @@ public function setUsage(?AccountResponseUsage $usage) return $this; } + /** + * Gets settings + * + * @return AccountResponseSettings|null + */ + public function getSettings() + { + return $this->container['settings']; + } + + /** + * Sets settings + * + * @param AccountResponseSettings|null $settings settings + * + * @return self + */ + public function setSettings(?AccountResponseSettings $settings) + { + if (is_null($settings)) { + throw new InvalidArgumentException('non-nullable settings cannot be null'); + } + $this->container['settings'] = $settings; + + return $this; + } + /** * Returns true if offset exists. False otherwise. * diff --git a/sdks/php/src/Model/AccountResponseSettings.php b/sdks/php/src/Model/AccountResponseSettings.php new file mode 100644 index 000000000..b150e8088 --- /dev/null +++ b/sdks/php/src/Model/AccountResponseSettings.php @@ -0,0 +1,480 @@ + + */ +class AccountResponseSettings implements ModelInterface, ArrayAccess, JsonSerializable +{ + public const DISCRIMINATOR = null; + + /** + * The original name of the model. + * + * @var string + */ + protected static $openAPIModelName = 'AccountResponseSettings'; + + /** + * Array of property to type mappings. Used for (de)serialization + * + * @var string[] + */ + protected static $openAPITypes = [ + 'signer_access_codes' => 'bool', + 'sms_delivery' => 'bool', + 'sms_authentication' => 'bool', + ]; + + /** + * Array of property to format mappings. Used for (de)serialization + * + * @var string[] + * @phpstan-var array + * @psalm-var array + */ + protected static $openAPIFormats = [ + 'signer_access_codes' => null, + 'sms_delivery' => null, + 'sms_authentication' => null, + ]; + + /** + * Array of nullable properties. Used for (de)serialization + * + * @var bool[] + */ + protected static array $openAPINullables = [ + 'signer_access_codes' => false, + 'sms_delivery' => false, + 'sms_authentication' => false, + ]; + + /** + * If a nullable field gets set to null, insert it here + * + * @var bool[] + */ + protected array $openAPINullablesSetToNull = []; + + /** + * Array of property to type mappings. Used for (de)serialization + * + * @return array + */ + public static function openAPITypes() + { + return self::$openAPITypes; + } + + /** + * Array of property to format mappings. Used for (de)serialization + * + * @return array + */ + public static function openAPIFormats() + { + return self::$openAPIFormats; + } + + /** + * Array of nullable properties + */ + protected static function openAPINullables(): array + { + return self::$openAPINullables; + } + + /** + * Array of nullable field names deliberately set to null + * + * @return bool[] + */ + private function getOpenAPINullablesSetToNull(): array + { + return $this->openAPINullablesSetToNull; + } + + /** + * Setter - Array of nullable field names deliberately set to null + * + * @param bool[] $openAPINullablesSetToNull + */ + private function setOpenAPINullablesSetToNull(array $openAPINullablesSetToNull): void + { + $this->openAPINullablesSetToNull = $openAPINullablesSetToNull; + } + + /** + * Checks if a property is nullable + */ + public static function isNullable(string $property): bool + { + return self::openAPINullables()[$property] ?? false; + } + + /** + * Checks if a nullable property is set to null. + */ + public function isNullableSetToNull(string $property): bool + { + return in_array($property, $this->getOpenAPINullablesSetToNull(), true); + } + + /** + * Array of attributes where the key is the local name, + * and the value is the original name + * + * @var string[] + */ + protected static $attributeMap = [ + 'signer_access_codes' => 'signer_access_codes', + 'sms_delivery' => 'sms_delivery', + 'sms_authentication' => 'sms_authentication', + ]; + + /** + * Array of attributes to setter functions (for deserialization of responses) + * + * @var string[] + */ + protected static $setters = [ + 'signer_access_codes' => 'setSignerAccessCodes', + 'sms_delivery' => 'setSmsDelivery', + 'sms_authentication' => 'setSmsAuthentication', + ]; + + /** + * Array of attributes to getter functions (for serialization of requests) + * + * @var string[] + */ + protected static $getters = [ + 'signer_access_codes' => 'getSignerAccessCodes', + 'sms_delivery' => 'getSmsDelivery', + 'sms_authentication' => 'getSmsAuthentication', + ]; + + /** + * Array of attributes where the key is the local name, + * and the value is the original name + * + * @return array + */ + public static function attributeMap() + { + return self::$attributeMap; + } + + /** + * Array of attributes to setter functions (for deserialization of responses) + * + * @return array + */ + public static function setters() + { + return self::$setters; + } + + /** + * Array of attributes to getter functions (for serialization of requests) + * + * @return array + */ + public static function getters() + { + return self::$getters; + } + + /** + * The original name of the model. + * + * @return string + */ + public function getModelName() + { + return self::$openAPIModelName; + } + + /** + * Associative array for storing property values + * + * @var mixed[] + */ + protected $container = []; + + /** + * Constructor + * + * @param mixed[]|null $data Associated array of property values + * initializing the model + */ + public function __construct(?array $data = null) + { + $this->setIfExists('signer_access_codes', $data ?? [], null); + $this->setIfExists('sms_delivery', $data ?? [], null); + $this->setIfExists('sms_authentication', $data ?? [], null); + } + + /** + * @deprecated use ::init() + */ + public static function fromArray(array $data): AccountResponseSettings + { + return self::init($data); + } + + /** + * Attempt to instantiate and hydrate a new instance of this class + */ + public static function init(array $data): AccountResponseSettings + { + /** @var AccountResponseSettings */ + return ObjectSerializer::deserialize( + $data, + AccountResponseSettings::class, + ); + } + + /** + * Sets $this->container[$variableName] to the given data or to the given default Value; if $variableName + * is nullable and its value is set to null in the $fields array, then mark it as "set to null" in the + * $this->openAPINullablesSetToNull array + * + * @param string|int|object|array|mixed $defaultValue + */ + private function setIfExists(string $variableName, array $fields, $defaultValue): void + { + if (self::isNullable($variableName) && array_key_exists($variableName, $fields) && is_null($fields[$variableName])) { + $this->openAPINullablesSetToNull[] = $variableName; + } + + $this->container[$variableName] = $fields[$variableName] ?? $defaultValue; + } + + /** + * Show all the invalid properties with reasons. + * + * @return array invalid properties with reasons + */ + public function listInvalidProperties() + { + return []; + } + + /** + * Validate all the properties in the model + * return true if all passed + * + * @return bool True if all properties are valid + */ + public function valid() + { + return count($this->listInvalidProperties()) === 0; + } + + /** + * Gets signer_access_codes + * + * @return bool|null + */ + public function getSignerAccessCodes() + { + return $this->container['signer_access_codes']; + } + + /** + * Sets signer_access_codes + * + * @param bool|null $signer_access_codes Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * + * @return self + */ + public function setSignerAccessCodes(?bool $signer_access_codes) + { + if (is_null($signer_access_codes)) { + throw new InvalidArgumentException('non-nullable signer_access_codes cannot be null'); + } + $this->container['signer_access_codes'] = $signer_access_codes; + + return $this; + } + + /** + * Gets sms_delivery + * + * @return bool|null + */ + public function getSmsDelivery() + { + return $this->container['sms_delivery']; + } + + /** + * Sets sms_delivery + * + * @param bool|null $sms_delivery Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * + * @return self + */ + public function setSmsDelivery(?bool $sms_delivery) + { + if (is_null($sms_delivery)) { + throw new InvalidArgumentException('non-nullable sms_delivery cannot be null'); + } + $this->container['sms_delivery'] = $sms_delivery; + + return $this; + } + + /** + * Gets sms_authentication + * + * @return bool|null + */ + public function getSmsAuthentication() + { + return $this->container['sms_authentication']; + } + + /** + * Sets sms_authentication + * + * @param bool|null $sms_authentication Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + * + * @return self + */ + public function setSmsAuthentication(?bool $sms_authentication) + { + if (is_null($sms_authentication)) { + throw new InvalidArgumentException('non-nullable sms_authentication cannot be null'); + } + $this->container['sms_authentication'] = $sms_authentication; + + return $this; + } + + /** + * Returns true if offset exists. False otherwise. + * + * @param int $offset Offset + */ + #[ReturnTypeWillChange] + public function offsetExists($offset): bool + { + return isset($this->container[$offset]); + } + + /** + * Gets offset. + * + * @param int $offset Offset + * + * @return mixed|null + */ + #[ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->container[$offset] ?? null; + } + + /** + * Sets value based on offset. + * + * @param int|null $offset Offset + * @param mixed $value Value to be set + */ + #[ReturnTypeWillChange] + public function offsetSet($offset, $value): void + { + if (is_null($offset)) { + $this->container[] = $value; + } else { + $this->container[$offset] = $value; + } + } + + /** + * Unsets offset. + * + * @param int $offset Offset + */ + #[ReturnTypeWillChange] + public function offsetUnset($offset): void + { + unset($this->container[$offset]); + } + + /** + * Serializes the object to a value that can be serialized natively by json_encode(). + * @see https://www.php.net/manual/en/jsonserializable.jsonserialize.php + * + * @return mixed returns data which can be serialized by json_encode(), which is a value + * of any type other than a resource + */ + #[ReturnTypeWillChange] + public function jsonSerialize() + { + return ObjectSerializer::sanitizeForSerialization($this); + } + + /** + * Gets the string presentation of the object + * + * @return string + */ + public function __toString() + { + return json_encode( + ObjectSerializer::sanitizeForSerialization($this), + JSON_UNESCAPED_SLASHES + ); + } + + /** + * Gets a header-safe presentation of the object + * + * @return string + */ + public function toHeaderValue() + { + return json_encode(ObjectSerializer::sanitizeForSerialization($this)); + } +} diff --git a/sdks/php/src/Model/ReportCreateRequest.php b/sdks/php/src/Model/ReportCreateRequest.php index a52ef7b01..6b693ecb2 100644 --- a/sdks/php/src/Model/ReportCreateRequest.php +++ b/sdks/php/src/Model/ReportCreateRequest.php @@ -235,6 +235,7 @@ public function getModelName() public const REPORT_TYPE_USER_ACTIVITY = 'user_activity'; public const REPORT_TYPE_DOCUMENT_STATUS = 'document_status'; public const REPORT_TYPE_SMS_ACTIVITY = 'sms_activity'; + public const REPORT_TYPE_FAX_USAGE = 'fax_usage'; /** * Gets allowable values of the enum @@ -247,6 +248,7 @@ public function getReportTypeAllowableValues() self::REPORT_TYPE_USER_ACTIVITY, self::REPORT_TYPE_DOCUMENT_STATUS, self::REPORT_TYPE_SMS_ACTIVITY, + self::REPORT_TYPE_FAX_USAGE, ]; } diff --git a/sdks/php/src/Model/ReportResponse.php b/sdks/php/src/Model/ReportResponse.php index 29122ed4e..4354b4f39 100644 --- a/sdks/php/src/Model/ReportResponse.php +++ b/sdks/php/src/Model/ReportResponse.php @@ -242,6 +242,7 @@ public function getModelName() public const REPORT_TYPE_USER_ACTIVITY = 'user_activity'; public const REPORT_TYPE_DOCUMENT_STATUS = 'document_status'; public const REPORT_TYPE_SMS_ACTIVITY = 'sms_activity'; + public const REPORT_TYPE_FAX_USAGE = 'fax_usage'; /** * Gets allowable values of the enum @@ -254,6 +255,7 @@ public function getReportTypeAllowableValues() self::REPORT_TYPE_USER_ACTIVITY, self::REPORT_TYPE_DOCUMENT_STATUS, self::REPORT_TYPE_SMS_ACTIVITY, + self::REPORT_TYPE_FAX_USAGE, ]; } diff --git a/sdks/php/src/Model/SignatureRequestEditRequest.php b/sdks/php/src/Model/SignatureRequestEditRequest.php index 8763f7dc6..1e16db897 100644 --- a/sdks/php/src/Model/SignatureRequestEditRequest.php +++ b/sdks/php/src/Model/SignatureRequestEditRequest.php @@ -896,7 +896,7 @@ public function getIsEid() /** * Sets is_eid * - * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * * @return self */ diff --git a/sdks/php/src/Model/SignatureRequestEditWithTemplateRequest.php b/sdks/php/src/Model/SignatureRequestEditWithTemplateRequest.php index b27cec8ee..990405643 100644 --- a/sdks/php/src/Model/SignatureRequestEditWithTemplateRequest.php +++ b/sdks/php/src/Model/SignatureRequestEditWithTemplateRequest.php @@ -651,7 +651,7 @@ public function getIsEid() /** * Sets is_eid * - * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * * @return self */ diff --git a/sdks/php/src/Model/SignatureRequestSendRequest.php b/sdks/php/src/Model/SignatureRequestSendRequest.php index 1d4379e53..a0f74237e 100644 --- a/sdks/php/src/Model/SignatureRequestSendRequest.php +++ b/sdks/php/src/Model/SignatureRequestSendRequest.php @@ -932,7 +932,7 @@ public function getIsEid() /** * Sets is_eid * - * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * * @return self */ diff --git a/sdks/php/src/Model/SignatureRequestSendWithTemplateRequest.php b/sdks/php/src/Model/SignatureRequestSendWithTemplateRequest.php index a353109aa..b7487179c 100644 --- a/sdks/php/src/Model/SignatureRequestSendWithTemplateRequest.php +++ b/sdks/php/src/Model/SignatureRequestSendWithTemplateRequest.php @@ -687,7 +687,7 @@ public function getIsEid() /** * Sets is_eid * - * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + * @param bool|null $is_eid Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. * * @return self */ diff --git a/sdks/php/src/Model/SubSigningOptions.php b/sdks/php/src/Model/SubSigningOptions.php index 51185a7ac..445065b20 100644 --- a/sdks/php/src/Model/SubSigningOptions.php +++ b/sdks/php/src/Model/SubSigningOptions.php @@ -37,7 +37,7 @@ * SubSigningOptions Class Doc Comment * * @category Class - * @description This allows the requester to specify the types allowed for creating a signature. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + * @description This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. * @see https://openapi-generator.tech * @implements ArrayAccess */ @@ -63,6 +63,7 @@ class SubSigningOptions implements ModelInterface, ArrayAccess, JsonSerializable 'phone' => 'bool', 'type' => 'bool', 'upload' => 'bool', + 'force_advanced_signature_details' => 'bool', ]; /** @@ -78,6 +79,7 @@ class SubSigningOptions implements ModelInterface, ArrayAccess, JsonSerializable 'phone' => null, 'type' => null, 'upload' => null, + 'force_advanced_signature_details' => null, ]; /** @@ -91,6 +93,7 @@ class SubSigningOptions implements ModelInterface, ArrayAccess, JsonSerializable 'phone' => false, 'type' => false, 'upload' => false, + 'force_advanced_signature_details' => false, ]; /** @@ -176,6 +179,7 @@ public function isNullableSetToNull(string $property): bool 'phone' => 'phone', 'type' => 'type', 'upload' => 'upload', + 'force_advanced_signature_details' => 'force_advanced_signature_details', ]; /** @@ -189,6 +193,7 @@ public function isNullableSetToNull(string $property): bool 'phone' => 'setPhone', 'type' => 'setType', 'upload' => 'setUpload', + 'force_advanced_signature_details' => 'setForceAdvancedSignatureDetails', ]; /** @@ -202,6 +207,7 @@ public function isNullableSetToNull(string $property): bool 'phone' => 'getPhone', 'type' => 'getType', 'upload' => 'getUpload', + 'force_advanced_signature_details' => 'getForceAdvancedSignatureDetails', ]; /** @@ -285,6 +291,7 @@ public function __construct(?array $data = null) $this->setIfExists('phone', $data ?? [], false); $this->setIfExists('type', $data ?? [], false); $this->setIfExists('upload', $data ?? [], false); + $this->setIfExists('force_advanced_signature_details', $data ?? [], false); } /** @@ -503,6 +510,33 @@ public function setUpload(?bool $upload) return $this; } + /** + * Gets force_advanced_signature_details + * + * @return bool|null + */ + public function getForceAdvancedSignatureDetails() + { + return $this->container['force_advanced_signature_details']; + } + + /** + * Sets force_advanced_signature_details + * + * @param bool|null $force_advanced_signature_details Turning on advanced signature details for the signature request + * + * @return self + */ + public function setForceAdvancedSignatureDetails(?bool $force_advanced_signature_details) + { + if (is_null($force_advanced_signature_details)) { + throw new InvalidArgumentException('non-nullable force_advanced_signature_details cannot be null'); + } + $this->container['force_advanced_signature_details'] = $force_advanced_signature_details; + + return $this; + } + /** * Returns true if offset exists. False otherwise. * diff --git a/sdks/php/src/Model/TemplateEditResponse.php b/sdks/php/src/Model/SubUpdateFormField.php similarity index 80% rename from sdks/php/src/Model/TemplateEditResponse.php rename to sdks/php/src/Model/SubUpdateFormField.php index 625024594..9dcbeee00 100644 --- a/sdks/php/src/Model/TemplateEditResponse.php +++ b/sdks/php/src/Model/SubUpdateFormField.php @@ -1,6 +1,6 @@ */ -class TemplateEditResponse implements ModelInterface, ArrayAccess, JsonSerializable +class SubUpdateFormField implements ModelInterface, ArrayAccess, JsonSerializable { public const DISCRIMINATOR = null; @@ -49,7 +49,7 @@ class TemplateEditResponse implements ModelInterface, ArrayAccess, JsonSerializa * * @var string */ - protected static $openAPIModelName = 'TemplateEditResponse'; + protected static $openAPIModelName = 'SubUpdateFormField'; /** * Array of property to type mappings. Used for (de)serialization @@ -57,7 +57,8 @@ class TemplateEditResponse implements ModelInterface, ArrayAccess, JsonSerializa * @var string[] */ protected static $openAPITypes = [ - 'template_id' => 'string', + 'api_id' => 'string', + 'name' => 'string', ]; /** @@ -68,7 +69,8 @@ class TemplateEditResponse implements ModelInterface, ArrayAccess, JsonSerializa * @psalm-var array */ protected static $openAPIFormats = [ - 'template_id' => null, + 'api_id' => null, + 'name' => null, ]; /** @@ -77,7 +79,8 @@ class TemplateEditResponse implements ModelInterface, ArrayAccess, JsonSerializa * @var bool[] */ protected static array $openAPINullables = [ - 'template_id' => false, + 'api_id' => false, + 'name' => false, ]; /** @@ -158,7 +161,8 @@ public function isNullableSetToNull(string $property): bool * @var string[] */ protected static $attributeMap = [ - 'template_id' => 'template_id', + 'api_id' => 'api_id', + 'name' => 'name', ]; /** @@ -167,7 +171,8 @@ public function isNullableSetToNull(string $property): bool * @var string[] */ protected static $setters = [ - 'template_id' => 'setTemplateId', + 'api_id' => 'setApiId', + 'name' => 'setName', ]; /** @@ -176,7 +181,8 @@ public function isNullableSetToNull(string $property): bool * @var string[] */ protected static $getters = [ - 'template_id' => 'getTemplateId', + 'api_id' => 'getApiId', + 'name' => 'getName', ]; /** @@ -235,13 +241,14 @@ public function getModelName() */ public function __construct(?array $data = null) { - $this->setIfExists('template_id', $data ?? [], null); + $this->setIfExists('api_id', $data ?? [], null); + $this->setIfExists('name', $data ?? [], null); } /** * @deprecated use ::init() */ - public static function fromArray(array $data): TemplateEditResponse + public static function fromArray(array $data): SubUpdateFormField { return self::init($data); } @@ -249,12 +256,12 @@ public static function fromArray(array $data): TemplateEditResponse /** * Attempt to instantiate and hydrate a new instance of this class */ - public static function init(array $data): TemplateEditResponse + public static function init(array $data): SubUpdateFormField { - /** @var TemplateEditResponse */ + /** @var SubUpdateFormField */ return ObjectSerializer::deserialize( $data, - TemplateEditResponse::class, + SubUpdateFormField::class, ); } @@ -283,8 +290,8 @@ public function listInvalidProperties() { $invalidProperties = []; - if ($this->container['template_id'] === null) { - $invalidProperties[] = "'template_id' can't be null"; + if ($this->container['api_id'] === null) { + $invalidProperties[] = "'api_id' can't be null"; } return $invalidProperties; } @@ -301,28 +308,55 @@ public function valid() } /** - * Gets template_id + * Gets api_id * * @return string */ - public function getTemplateId() + public function getApiId() { - return $this->container['template_id']; + return $this->container['api_id']; } /** - * Sets template_id + * Sets api_id * - * @param string $template_id the id of the Template + * @param string $api_id The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found * * @return self */ - public function setTemplateId(string $template_id) + public function setApiId(string $api_id) { - if (is_null($template_id)) { - throw new InvalidArgumentException('non-nullable template_id cannot be null'); + if (is_null($api_id)) { + throw new InvalidArgumentException('non-nullable api_id cannot be null'); } - $this->container['template_id'] = $template_id; + $this->container['api_id'] = $api_id; + + return $this; + } + + /** + * Gets name + * + * @return string|null + */ + public function getName() + { + return $this->container['name']; + } + + /** + * Sets name + * + * @param string|null $name The new name of the field. If not passed the name will remain unchanged. + * + * @return self + */ + public function setName(?string $name) + { + if (is_null($name)) { + throw new InvalidArgumentException('non-nullable name cannot be null'); + } + $this->container['name'] = $name; return $this; } diff --git a/sdks/php/templates/composer.mustache b/sdks/php/templates/composer.mustache index 85807e08c..2efd505ed 100644 --- a/sdks/php/templates/composer.mustache +++ b/sdks/php/templates/composer.mustache @@ -52,7 +52,7 @@ "friendsofphp/php-cs-fixer": "^3.5" {{/useCustomTemplateCode}} {{#useCustomTemplateCode}} - "friendsofphp/php-cs-fixer": "^3.5", + "friendsofphp/php-cs-fixer": "v3.84.0", "symfony/yaml": "^5.4" {{/useCustomTemplateCode}} }, diff --git a/sdks/python/README.md b/sdks/python/README.md index 5c2d67154..40055084a 100644 --- a/sdks/python/README.md +++ b/sdks/python/README.md @@ -185,6 +185,7 @@ Class | Method | HTTP request | Description - [AccountGetResponse](docs/AccountGetResponse.md) - [AccountResponse](docs/AccountResponse.md) - [AccountResponseQuotas](docs/AccountResponseQuotas.md) + - [AccountResponseSettings](docs/AccountResponseSettings.md) - [AccountResponseUsage](docs/AccountResponseUsage.md) - [AccountUpdateRequest](docs/AccountUpdateRequest.md) - [AccountVerifyRequest](docs/AccountVerifyRequest.md) @@ -306,6 +307,7 @@ Class | Method | HTTP request | Description - [SubTemplateRole](docs/SubTemplateRole.md) - [SubUnclaimedDraftSigner](docs/SubUnclaimedDraftSigner.md) - [SubUnclaimedDraftTemplateSigner](docs/SubUnclaimedDraftTemplateSigner.md) + - [SubUpdateFormField](docs/SubUpdateFormField.md) - [SubWhiteLabelingOptions](docs/SubWhiteLabelingOptions.md) - [TeamAddMemberRequest](docs/TeamAddMemberRequest.md) - [TeamCreateRequest](docs/TeamCreateRequest.md) @@ -328,7 +330,6 @@ Class | Method | HTTP request | Description - [TemplateCreateRequest](docs/TemplateCreateRequest.md) - [TemplateCreateResponse](docs/TemplateCreateResponse.md) - [TemplateCreateResponseTemplate](docs/TemplateCreateResponseTemplate.md) - - [TemplateEditResponse](docs/TemplateEditResponse.md) - [TemplateGetResponse](docs/TemplateGetResponse.md) - [TemplateListResponse](docs/TemplateListResponse.md) - [TemplateRemoveUserRequest](docs/TemplateRemoveUserRequest.md) diff --git a/sdks/python/docs/AccountResponse.md b/sdks/python/docs/AccountResponse.md index fe7f8da48..169026b85 100644 --- a/sdks/python/docs/AccountResponse.md +++ b/sdks/python/docs/AccountResponse.md @@ -16,6 +16,7 @@ Name | Type | Description | Notes | `team_id` | ```str``` | The id of the team account belongs to. | | | `locale` | ```str``` | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | | | `usage` | [```AccountResponseUsage```](AccountResponseUsage.md) | | | +| `settings` | [```AccountResponseSettings```](AccountResponseSettings.md) | | | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/python/docs/AccountResponseSettings.md b/sdks/python/docs/AccountResponseSettings.md new file mode 100644 index 000000000..2817e7268 --- /dev/null +++ b/sdks/python/docs/AccountResponseSettings.md @@ -0,0 +1,14 @@ +# AccountResponseSettings + +Subset of configured settings + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +| `signer_access_codes` | ```bool``` | Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `sms_delivery` | ```bool``` | Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `sms_authentication` | ```bool``` | Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/sdks/python/docs/SignatureRequestApi.md b/sdks/python/docs/SignatureRequestApi.md index aa17c91f3..039735160 100644 --- a/sdks/python/docs/SignatureRequestApi.md +++ b/sdks/python/docs/SignatureRequestApi.md @@ -425,6 +425,7 @@ with ApiClient(configuration) as api_client: phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestSigner( @@ -536,6 +537,7 @@ with ApiClient(configuration) as api_client: phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestTemplateSigner( @@ -674,14 +676,12 @@ with ApiClient(configuration) as api_client: files=[ open("./example_signature_request.pdf", "rb").read(), ], - metadata=json.loads( - """ + metadata=json.loads(""" { "custom_id": 1234, "custom_text": "NDA #9" } - """ - ), + """), field_options=field_options, signing_options=signing_options, signers=signers, @@ -1673,6 +1673,7 @@ with ApiClient(configuration) as api_client: phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestSigner( @@ -1704,14 +1705,12 @@ with ApiClient(configuration) as api_client: files=[ open("./example_signature_request.pdf", "rb").read(), ], - metadata=json.loads( - """ + metadata=json.loads(""" { "custom_id": 1234, "custom_text": "NDA #9" } - """ - ), + """), field_options=field_options, signing_options=signing_options, signers=signers, @@ -1790,6 +1789,7 @@ with ApiClient(configuration) as api_client: phone=False, type=True, upload=True, + force_advanced_signature_details=False, ) signers_1 = models.SubSignatureRequestTemplateSigner( diff --git a/sdks/python/docs/SignatureRequestEditRequest.md b/sdks/python/docs/SignatureRequestEditRequest.md index b4d9783d6..a6731f71a 100644 --- a/sdks/python/docs/SignatureRequestEditRequest.md +++ b/sdks/python/docs/SignatureRequestEditRequest.md @@ -20,7 +20,7 @@ Name | Type | Description | Notes | `form_field_rules` | [```List[SubFormFieldRule]```](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | | | `form_fields_per_document` | [```List[SubFormFieldsPerDocumentBase]```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hide_text_tags` | ```bool``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to False] | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | | `message` | ```str``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Dict[str, object]``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/python/docs/SignatureRequestEditWithTemplateRequest.md b/sdks/python/docs/SignatureRequestEditWithTemplateRequest.md index 47b6af51b..978a0b38a 100644 --- a/sdks/python/docs/SignatureRequestEditWithTemplateRequest.md +++ b/sdks/python/docs/SignatureRequestEditWithTemplateRequest.md @@ -13,7 +13,7 @@ Name | Type | Description | Notes | `custom_fields` | [```List[SubCustomField]```](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | | | `files` | ```List[io.IOBase]``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `file_urls` | ```List[str]``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | | `message` | ```str``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Dict[str, object]``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/python/docs/SignatureRequestSendRequest.md b/sdks/python/docs/SignatureRequestSendRequest.md index 54e5d9d4c..20db17ad6 100644 --- a/sdks/python/docs/SignatureRequestSendRequest.md +++ b/sdks/python/docs/SignatureRequestSendRequest.md @@ -21,7 +21,7 @@ Name | Type | Description | Notes | `form_fields_per_document` | [```List[SubFormFieldsPerDocumentBase]```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hide_text_tags` | ```bool``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to False] | | `is_qualified_signature` | ```bool``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | | `message` | ```str``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Dict[str, object]``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/python/docs/SignatureRequestSendWithTemplateRequest.md b/sdks/python/docs/SignatureRequestSendWithTemplateRequest.md index 0278d63a8..6cdff0346 100644 --- a/sdks/python/docs/SignatureRequestSendWithTemplateRequest.md +++ b/sdks/python/docs/SignatureRequestSendWithTemplateRequest.md @@ -14,7 +14,7 @@ Name | Type | Description | Notes | `files` | ```List[io.IOBase]``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `file_urls` | ```List[str]``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `is_qualified_signature` | ```bool``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | -| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | +| `is_eid` | ```bool``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to False] | | `message` | ```str``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Dict[str, object]``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/python/docs/SubSigningOptions.md b/sdks/python/docs/SubSigningOptions.md index 9584478ec..23ddf9135 100644 --- a/sdks/python/docs/SubSigningOptions.md +++ b/sdks/python/docs/SubSigningOptions.md @@ -1,9 +1,11 @@ # SubSigningOptions -This allows the requester to specify the types allowed for creating a signature. +This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. +**NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- @@ -12,6 +14,7 @@ Name | Type | Description | Notes | `phone` | ```bool``` | Allows using a smartphone to email the signature | [default to False] | | `type` | ```bool``` | Allows typing the signature | [default to False] | | `upload` | ```bool``` | Allows uploading the signature | [default to False] | +| `force_advanced_signature_details` | ```bool``` | Turning on advanced signature details for the signature request | [default to False] | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/python/docs/SubUpdateFormField.md b/sdks/python/docs/SubUpdateFormField.md new file mode 100644 index 000000000..f227abfda --- /dev/null +++ b/sdks/python/docs/SubUpdateFormField.md @@ -0,0 +1,13 @@ +# SubUpdateFormField + + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +| `api_id`*_required_ | ```str``` | The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found | | +| `name` | ```str``` | The new name of the field. If not passed the name will remain unchanged. | | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/sdks/python/docs/TemplateApi.md b/sdks/python/docs/TemplateApi.md index 5ff5a44c8..23d16d10b 100644 --- a/sdks/python/docs/TemplateApi.md +++ b/sdks/python/docs/TemplateApi.md @@ -92,7 +92,11 @@ with ApiClient(configuration) as api_client: Create Template -Creates a template that can then be used. +Creates a template that can be used in future signature requests. + +If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). + +Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. ### Example diff --git a/sdks/python/docs/TemplateEditResponse.md b/sdks/python/docs/TemplateEditResponse.md deleted file mode 100644 index 2384cb094..000000000 --- a/sdks/python/docs/TemplateEditResponse.md +++ /dev/null @@ -1,12 +0,0 @@ -# TemplateEditResponse - - - -## Properties -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -| `template_id`*_required_ | ```str``` | The id of the Template. | | - -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/sdks/python/dropbox_sign/__init__.py b/sdks/python/dropbox_sign/__init__.py index 82a36a10d..8d35721ba 100644 --- a/sdks/python/dropbox_sign/__init__.py +++ b/sdks/python/dropbox_sign/__init__.py @@ -14,7 +14,6 @@ Do not edit the class manually. """ # noqa: E501 - __version__ = "1.10-dev" # import apis into sdk package @@ -37,6 +36,7 @@ from dropbox_sign.models.account_get_response import AccountGetResponse from dropbox_sign.models.account_response import AccountResponse from dropbox_sign.models.account_response_quotas import AccountResponseQuotas +from dropbox_sign.models.account_response_settings import AccountResponseSettings from dropbox_sign.models.account_response_usage import AccountResponseUsage from dropbox_sign.models.account_update_request import AccountUpdateRequest from dropbox_sign.models.account_verify_request import AccountVerifyRequest @@ -276,6 +276,7 @@ from dropbox_sign.models.sub_unclaimed_draft_template_signer import ( SubUnclaimedDraftTemplateSigner, ) +from dropbox_sign.models.sub_update_form_field import SubUpdateFormField from dropbox_sign.models.sub_white_labeling_options import SubWhiteLabelingOptions from dropbox_sign.models.team_add_member_request import TeamAddMemberRequest from dropbox_sign.models.team_create_request import TeamCreateRequest @@ -306,7 +307,6 @@ from dropbox_sign.models.template_create_response_template import ( TemplateCreateResponseTemplate, ) -from dropbox_sign.models.template_edit_response import TemplateEditResponse from dropbox_sign.models.template_get_response import TemplateGetResponse from dropbox_sign.models.template_list_response import TemplateListResponse from dropbox_sign.models.template_remove_user_request import TemplateRemoveUserRequest diff --git a/sdks/python/dropbox_sign/api/template_api.py b/sdks/python/dropbox_sign/api/template_api.py index 3205675ea..723488921 100644 --- a/sdks/python/dropbox_sign/api/template_api.py +++ b/sdks/python/dropbox_sign/api/template_api.py @@ -376,7 +376,7 @@ def template_create( ) -> TemplateCreateResponse: """Create Template - Creates a template that can then be used. + Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. :param template_create_request: (required) :type template_create_request: TemplateCreateRequest @@ -441,7 +441,7 @@ def template_create_with_http_info( ) -> ApiResponse[TemplateCreateResponse]: """Create Template - Creates a template that can then be used. + Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. :param template_create_request: (required) :type template_create_request: TemplateCreateRequest @@ -506,7 +506,7 @@ def template_create_without_preload_content( ) -> RESTResponseType: """Create Template - Creates a template that can then be used. + Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. :param template_create_request: (required) :type template_create_request: TemplateCreateRequest diff --git a/sdks/python/dropbox_sign/api_client.py b/sdks/python/dropbox_sign/api_client.py index b90e8029a..091508190 100644 --- a/sdks/python/dropbox_sign/api_client.py +++ b/sdks/python/dropbox_sign/api_client.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - import datetime from dateutil.parser import parse from enum import Enum diff --git a/sdks/python/dropbox_sign/configuration.py b/sdks/python/dropbox_sign/configuration.py index 7247bd547..fd139f0f1 100644 --- a/sdks/python/dropbox_sign/configuration.py +++ b/sdks/python/dropbox_sign/configuration.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - import copy import http.client as httplib import logging @@ -24,7 +23,6 @@ import urllib3 - JSON_SCHEMA_VALIDATION_KEYWORDS = { "multipleOf", "maximum", diff --git a/sdks/python/dropbox_sign/models/__init__.py b/sdks/python/dropbox_sign/models/__init__.py index fd5331ae1..58571d591 100644 --- a/sdks/python/dropbox_sign/models/__init__.py +++ b/sdks/python/dropbox_sign/models/__init__.py @@ -13,13 +13,13 @@ Do not edit the class manually. """ # noqa: E501 - # import models into model package from dropbox_sign.models.account_create_request import AccountCreateRequest from dropbox_sign.models.account_create_response import AccountCreateResponse from dropbox_sign.models.account_get_response import AccountGetResponse from dropbox_sign.models.account_response import AccountResponse from dropbox_sign.models.account_response_quotas import AccountResponseQuotas +from dropbox_sign.models.account_response_settings import AccountResponseSettings from dropbox_sign.models.account_response_usage import AccountResponseUsage from dropbox_sign.models.account_update_request import AccountUpdateRequest from dropbox_sign.models.account_verify_request import AccountVerifyRequest @@ -259,6 +259,7 @@ from dropbox_sign.models.sub_unclaimed_draft_template_signer import ( SubUnclaimedDraftTemplateSigner, ) +from dropbox_sign.models.sub_update_form_field import SubUpdateFormField from dropbox_sign.models.sub_white_labeling_options import SubWhiteLabelingOptions from dropbox_sign.models.team_add_member_request import TeamAddMemberRequest from dropbox_sign.models.team_create_request import TeamCreateRequest @@ -289,7 +290,6 @@ from dropbox_sign.models.template_create_response_template import ( TemplateCreateResponseTemplate, ) -from dropbox_sign.models.template_edit_response import TemplateEditResponse from dropbox_sign.models.template_get_response import TemplateGetResponse from dropbox_sign.models.template_list_response import TemplateListResponse from dropbox_sign.models.template_remove_user_request import TemplateRemoveUserRequest diff --git a/sdks/python/dropbox_sign/models/account_create_request.py b/sdks/python/dropbox_sign/models/account_create_request.py index 06eb22484..c460b5556 100644 --- a/sdks/python/dropbox_sign/models/account_create_request.py +++ b/sdks/python/dropbox_sign/models/account_create_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_create_response.py b/sdks/python/dropbox_sign/models/account_create_response.py index 3bcabfd76..f1a8dc67b 100644 --- a/sdks/python/dropbox_sign/models/account_create_response.py +++ b/sdks/python/dropbox_sign/models/account_create_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_get_response.py b/sdks/python/dropbox_sign/models/account_get_response.py index 9a12adb80..4ff285781 100644 --- a/sdks/python/dropbox_sign/models/account_get_response.py +++ b/sdks/python/dropbox_sign/models/account_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_response.py b/sdks/python/dropbox_sign/models/account_response.py index 527377330..94f32163b 100644 --- a/sdks/python/dropbox_sign/models/account_response.py +++ b/sdks/python/dropbox_sign/models/account_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -21,6 +20,7 @@ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr from typing import Any, ClassVar, Dict, List, Optional from dropbox_sign.models.account_response_quotas import AccountResponseQuotas +from dropbox_sign.models.account_response_settings import AccountResponseSettings from dropbox_sign.models.account_response_usage import AccountResponseUsage from typing import Optional, Set from typing_extensions import Self @@ -67,6 +67,7 @@ class AccountResponse(BaseModel): description="The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values.", ) usage: Optional[AccountResponseUsage] = None + settings: Optional[AccountResponseSettings] = None __properties: ClassVar[List[str]] = [ "account_id", "email_address", @@ -79,6 +80,7 @@ class AccountResponse(BaseModel): "team_id", "locale", "usage", + "settings", ] model_config = ConfigDict( @@ -137,6 +139,9 @@ def to_dict(self, excluded_fields: Set[str] = None) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of usage if self.usage: _dict["usage"] = self.usage.to_dict() + # override the default output from pydantic by calling `to_dict()` of settings + if self.settings: + _dict["settings"] = self.settings.to_dict() return _dict @classmethod @@ -169,6 +174,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("usage") is not None else None ), + "settings": ( + AccountResponseSettings.from_dict(obj["settings"]) + if obj.get("settings") is not None + else None + ), } ) return _obj @@ -197,6 +207,7 @@ def openapi_types(cls) -> Dict[str, str]: "team_id": "(str,)", "locale": "(str,)", "usage": "(AccountResponseUsage,)", + "settings": "(AccountResponseSettings,)", } @classmethod diff --git a/sdks/python/dropbox_sign/models/account_response_quotas.py b/sdks/python/dropbox_sign/models/account_response_quotas.py index d2b2ffbb0..995d323c7 100644 --- a/sdks/python/dropbox_sign/models/account_response_quotas.py +++ b/sdks/python/dropbox_sign/models/account_response_quotas.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_response_settings.py b/sdks/python/dropbox_sign/models/account_response_settings.py new file mode 100644 index 000000000..b35cdc6f4 --- /dev/null +++ b/sdks/python/dropbox_sign/models/account_response_settings.py @@ -0,0 +1,142 @@ +# coding: utf-8 + +""" +Dropbox Sign API + +Dropbox Sign v3 API + +The version of the OpenAPI document: 3.0.0 +Contact: apisupport@hellosign.com +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from typing import Tuple, Union +import io +from pydantic import StrictBool + + +class AccountResponseSettings(BaseModel): + """ + Subset of configured settings + """ # noqa: E501 + + signer_access_codes: Optional[StrictBool] = Field( + default=None, + description="Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).", + ) + sms_delivery: Optional[StrictBool] = Field( + default=None, + description="Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).", + ) + sms_authentication: Optional[StrictBool] = Field( + default=None, + description="Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough).", + ) + __properties: ClassVar[List[str]] = [ + "signer_access_codes", + "sms_delivery", + "sms_authentication", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + arbitrary_types_allowed=True, + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + def to_json_form_params( + self, excluded_fields: Set[str] = None + ) -> List[Tuple[str, str]]: + data: List[Tuple[str, str]] = [] + + for key, value in self.to_dict(excluded_fields).items(): + if isinstance(value, (int, str, bool)): + data.append((key, value)) + else: + data.append((key, json.dumps(value, ensure_ascii=False))) + + return data + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AccountResponseSettings from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self, excluded_fields: Set[str] = None) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AccountResponseSettings from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "signer_access_codes": obj.get("signer_access_codes"), + "sms_delivery": obj.get("sms_delivery"), + "sms_authentication": obj.get("sms_authentication"), + } + ) + return _obj + + @classmethod + def init(cls, data: Any) -> Self: + """ + Attempt to instantiate and hydrate a new instance of this class + """ + if isinstance(data, str): + data = json.loads(data) + + return cls.from_dict(data) + + @classmethod + def openapi_types(cls) -> Dict[str, str]: + return { + "signer_access_codes": "(bool,)", + "sms_delivery": "(bool,)", + "sms_authentication": "(bool,)", + } + + @classmethod + def openapi_type_is_array(cls, property_name: str) -> bool: + return property_name in [] diff --git a/sdks/python/dropbox_sign/models/account_response_usage.py b/sdks/python/dropbox_sign/models/account_response_usage.py index 6fc759346..abf963fcd 100644 --- a/sdks/python/dropbox_sign/models/account_response_usage.py +++ b/sdks/python/dropbox_sign/models/account_response_usage.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_update_request.py b/sdks/python/dropbox_sign/models/account_update_request.py index a0cafd7c4..a502292f3 100644 --- a/sdks/python/dropbox_sign/models/account_update_request.py +++ b/sdks/python/dropbox_sign/models/account_update_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_verify_request.py b/sdks/python/dropbox_sign/models/account_verify_request.py index 39804b0bc..794ceb845 100644 --- a/sdks/python/dropbox_sign/models/account_verify_request.py +++ b/sdks/python/dropbox_sign/models/account_verify_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_verify_response.py b/sdks/python/dropbox_sign/models/account_verify_response.py index 3b0ee8ddf..bf8198c56 100644 --- a/sdks/python/dropbox_sign/models/account_verify_response.py +++ b/sdks/python/dropbox_sign/models/account_verify_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/account_verify_response_account.py b/sdks/python/dropbox_sign/models/account_verify_response_account.py index 98f5fb302..ccd1d403e 100644 --- a/sdks/python/dropbox_sign/models/account_verify_response_account.py +++ b/sdks/python/dropbox_sign/models/account_verify_response_account.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_create_request.py b/sdks/python/dropbox_sign/models/api_app_create_request.py index 788c74a23..cec5bfaa1 100644 --- a/sdks/python/dropbox_sign/models/api_app_create_request.py +++ b/sdks/python/dropbox_sign/models/api_app_create_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_get_response.py b/sdks/python/dropbox_sign/models/api_app_get_response.py index 4337be1ee..2933696ba 100644 --- a/sdks/python/dropbox_sign/models/api_app_get_response.py +++ b/sdks/python/dropbox_sign/models/api_app_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_list_response.py b/sdks/python/dropbox_sign/models/api_app_list_response.py index 98a950e09..6d9b8afc0 100644 --- a/sdks/python/dropbox_sign/models/api_app_list_response.py +++ b/sdks/python/dropbox_sign/models/api_app_list_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_response.py b/sdks/python/dropbox_sign/models/api_app_response.py index ad4e87207..cdca9dca8 100644 --- a/sdks/python/dropbox_sign/models/api_app_response.py +++ b/sdks/python/dropbox_sign/models/api_app_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_response_o_auth.py b/sdks/python/dropbox_sign/models/api_app_response_o_auth.py index b078c1a71..388f840ac 100644 --- a/sdks/python/dropbox_sign/models/api_app_response_o_auth.py +++ b/sdks/python/dropbox_sign/models/api_app_response_o_auth.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_response_options.py b/sdks/python/dropbox_sign/models/api_app_response_options.py index ec34ed913..80315b901 100644 --- a/sdks/python/dropbox_sign/models/api_app_response_options.py +++ b/sdks/python/dropbox_sign/models/api_app_response_options.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_response_owner_account.py b/sdks/python/dropbox_sign/models/api_app_response_owner_account.py index d57994800..95ca83253 100644 --- a/sdks/python/dropbox_sign/models/api_app_response_owner_account.py +++ b/sdks/python/dropbox_sign/models/api_app_response_owner_account.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_response_white_labeling_options.py b/sdks/python/dropbox_sign/models/api_app_response_white_labeling_options.py index b5747219c..a1317662c 100644 --- a/sdks/python/dropbox_sign/models/api_app_response_white_labeling_options.py +++ b/sdks/python/dropbox_sign/models/api_app_response_white_labeling_options.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/api_app_update_request.py b/sdks/python/dropbox_sign/models/api_app_update_request.py index 7370a7e96..393954c1d 100644 --- a/sdks/python/dropbox_sign/models/api_app_update_request.py +++ b/sdks/python/dropbox_sign/models/api_app_update_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/bulk_send_job_get_response.py b/sdks/python/dropbox_sign/models/bulk_send_job_get_response.py index 9461ccfa6..94b90cfa1 100644 --- a/sdks/python/dropbox_sign/models/bulk_send_job_get_response.py +++ b/sdks/python/dropbox_sign/models/bulk_send_job_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/bulk_send_job_get_response_signature_requests.py b/sdks/python/dropbox_sign/models/bulk_send_job_get_response_signature_requests.py index 704089bef..ded85043d 100644 --- a/sdks/python/dropbox_sign/models/bulk_send_job_get_response_signature_requests.py +++ b/sdks/python/dropbox_sign/models/bulk_send_job_get_response_signature_requests.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/bulk_send_job_list_response.py b/sdks/python/dropbox_sign/models/bulk_send_job_list_response.py index 8f9791880..83c4551c6 100644 --- a/sdks/python/dropbox_sign/models/bulk_send_job_list_response.py +++ b/sdks/python/dropbox_sign/models/bulk_send_job_list_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/bulk_send_job_response.py b/sdks/python/dropbox_sign/models/bulk_send_job_response.py index 8d6eeeee0..fb95404f8 100644 --- a/sdks/python/dropbox_sign/models/bulk_send_job_response.py +++ b/sdks/python/dropbox_sign/models/bulk_send_job_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/bulk_send_job_send_response.py b/sdks/python/dropbox_sign/models/bulk_send_job_send_response.py index a2eca9737..288b87cbd 100644 --- a/sdks/python/dropbox_sign/models/bulk_send_job_send_response.py +++ b/sdks/python/dropbox_sign/models/bulk_send_job_send_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/embedded_edit_url_request.py b/sdks/python/dropbox_sign/models/embedded_edit_url_request.py index 849ebf426..104164cb5 100644 --- a/sdks/python/dropbox_sign/models/embedded_edit_url_request.py +++ b/sdks/python/dropbox_sign/models/embedded_edit_url_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/embedded_edit_url_response.py b/sdks/python/dropbox_sign/models/embedded_edit_url_response.py index 653ca7c2c..cf5908634 100644 --- a/sdks/python/dropbox_sign/models/embedded_edit_url_response.py +++ b/sdks/python/dropbox_sign/models/embedded_edit_url_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/embedded_edit_url_response_embedded.py b/sdks/python/dropbox_sign/models/embedded_edit_url_response_embedded.py index 67413cb9a..64c804dbc 100644 --- a/sdks/python/dropbox_sign/models/embedded_edit_url_response_embedded.py +++ b/sdks/python/dropbox_sign/models/embedded_edit_url_response_embedded.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/embedded_sign_url_response.py b/sdks/python/dropbox_sign/models/embedded_sign_url_response.py index f0e03a177..cd89bea61 100644 --- a/sdks/python/dropbox_sign/models/embedded_sign_url_response.py +++ b/sdks/python/dropbox_sign/models/embedded_sign_url_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/embedded_sign_url_response_embedded.py b/sdks/python/dropbox_sign/models/embedded_sign_url_response_embedded.py index dc7145702..fb2f95acb 100644 --- a/sdks/python/dropbox_sign/models/embedded_sign_url_response_embedded.py +++ b/sdks/python/dropbox_sign/models/embedded_sign_url_response_embedded.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/error_response.py b/sdks/python/dropbox_sign/models/error_response.py index 98c6e5a90..d71038457 100644 --- a/sdks/python/dropbox_sign/models/error_response.py +++ b/sdks/python/dropbox_sign/models/error_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/error_response_error.py b/sdks/python/dropbox_sign/models/error_response_error.py index 6991a0a27..4f17bb6ee 100644 --- a/sdks/python/dropbox_sign/models/error_response_error.py +++ b/sdks/python/dropbox_sign/models/error_response_error.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/event_callback_request.py b/sdks/python/dropbox_sign/models/event_callback_request.py index f8ac8473d..a5cad664d 100644 --- a/sdks/python/dropbox_sign/models/event_callback_request.py +++ b/sdks/python/dropbox_sign/models/event_callback_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/event_callback_request_event.py b/sdks/python/dropbox_sign/models/event_callback_request_event.py index 7f263da42..67def101d 100644 --- a/sdks/python/dropbox_sign/models/event_callback_request_event.py +++ b/sdks/python/dropbox_sign/models/event_callback_request_event.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/event_callback_request_event_metadata.py b/sdks/python/dropbox_sign/models/event_callback_request_event_metadata.py index fee5309d9..39903767b 100644 --- a/sdks/python/dropbox_sign/models/event_callback_request_event_metadata.py +++ b/sdks/python/dropbox_sign/models/event_callback_request_event_metadata.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_get_response.py b/sdks/python/dropbox_sign/models/fax_get_response.py index 25bf9d2fd..0c139a61a 100644 --- a/sdks/python/dropbox_sign/models/fax_get_response.py +++ b/sdks/python/dropbox_sign/models/fax_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_add_user_request.py b/sdks/python/dropbox_sign/models/fax_line_add_user_request.py index 7a7a92b60..4951c87bd 100644 --- a/sdks/python/dropbox_sign/models/fax_line_add_user_request.py +++ b/sdks/python/dropbox_sign/models/fax_line_add_user_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_area_code_get_country_enum.py b/sdks/python/dropbox_sign/models/fax_line_area_code_get_country_enum.py index 94df88562..6249d1459 100644 --- a/sdks/python/dropbox_sign/models/fax_line_area_code_get_country_enum.py +++ b/sdks/python/dropbox_sign/models/fax_line_area_code_get_country_enum.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import json from enum import Enum diff --git a/sdks/python/dropbox_sign/models/fax_line_area_code_get_province_enum.py b/sdks/python/dropbox_sign/models/fax_line_area_code_get_province_enum.py index e7994f3f5..e111091cc 100644 --- a/sdks/python/dropbox_sign/models/fax_line_area_code_get_province_enum.py +++ b/sdks/python/dropbox_sign/models/fax_line_area_code_get_province_enum.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import json from enum import Enum diff --git a/sdks/python/dropbox_sign/models/fax_line_area_code_get_response.py b/sdks/python/dropbox_sign/models/fax_line_area_code_get_response.py index 4d41c9b56..55bbd5703 100644 --- a/sdks/python/dropbox_sign/models/fax_line_area_code_get_response.py +++ b/sdks/python/dropbox_sign/models/fax_line_area_code_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_area_code_get_state_enum.py b/sdks/python/dropbox_sign/models/fax_line_area_code_get_state_enum.py index 8cfe5ad2e..5f302809e 100644 --- a/sdks/python/dropbox_sign/models/fax_line_area_code_get_state_enum.py +++ b/sdks/python/dropbox_sign/models/fax_line_area_code_get_state_enum.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import json from enum import Enum diff --git a/sdks/python/dropbox_sign/models/fax_line_create_request.py b/sdks/python/dropbox_sign/models/fax_line_create_request.py index 7a8d88c34..722ecd04c 100644 --- a/sdks/python/dropbox_sign/models/fax_line_create_request.py +++ b/sdks/python/dropbox_sign/models/fax_line_create_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_delete_request.py b/sdks/python/dropbox_sign/models/fax_line_delete_request.py index 9e966098b..2ba409b29 100644 --- a/sdks/python/dropbox_sign/models/fax_line_delete_request.py +++ b/sdks/python/dropbox_sign/models/fax_line_delete_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_list_response.py b/sdks/python/dropbox_sign/models/fax_line_list_response.py index 07581a37e..354b03d5e 100644 --- a/sdks/python/dropbox_sign/models/fax_line_list_response.py +++ b/sdks/python/dropbox_sign/models/fax_line_list_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_remove_user_request.py b/sdks/python/dropbox_sign/models/fax_line_remove_user_request.py index 6021a0c84..08e9cb5e3 100644 --- a/sdks/python/dropbox_sign/models/fax_line_remove_user_request.py +++ b/sdks/python/dropbox_sign/models/fax_line_remove_user_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_response.py b/sdks/python/dropbox_sign/models/fax_line_response.py index bb733f4da..d85e0c2ac 100644 --- a/sdks/python/dropbox_sign/models/fax_line_response.py +++ b/sdks/python/dropbox_sign/models/fax_line_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_line_response_fax_line.py b/sdks/python/dropbox_sign/models/fax_line_response_fax_line.py index 8a0676cbe..d55a0cd7d 100644 --- a/sdks/python/dropbox_sign/models/fax_line_response_fax_line.py +++ b/sdks/python/dropbox_sign/models/fax_line_response_fax_line.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_list_response.py b/sdks/python/dropbox_sign/models/fax_list_response.py index 99140e3c0..4afc53b6c 100644 --- a/sdks/python/dropbox_sign/models/fax_list_response.py +++ b/sdks/python/dropbox_sign/models/fax_list_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_response.py b/sdks/python/dropbox_sign/models/fax_response.py index 1648df8e2..9f336111d 100644 --- a/sdks/python/dropbox_sign/models/fax_response.py +++ b/sdks/python/dropbox_sign/models/fax_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_response_transmission.py b/sdks/python/dropbox_sign/models/fax_response_transmission.py index 66c613dd2..3d54f4e57 100644 --- a/sdks/python/dropbox_sign/models/fax_response_transmission.py +++ b/sdks/python/dropbox_sign/models/fax_response_transmission.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/fax_send_request.py b/sdks/python/dropbox_sign/models/fax_send_request.py index c4f0af8c1..71bdb7b61 100644 --- a/sdks/python/dropbox_sign/models/fax_send_request.py +++ b/sdks/python/dropbox_sign/models/fax_send_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/file_response.py b/sdks/python/dropbox_sign/models/file_response.py index 434a4f1be..6e70e7805 100644 --- a/sdks/python/dropbox_sign/models/file_response.py +++ b/sdks/python/dropbox_sign/models/file_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/file_response_data_uri.py b/sdks/python/dropbox_sign/models/file_response_data_uri.py index da1384d66..2a535f798 100644 --- a/sdks/python/dropbox_sign/models/file_response_data_uri.py +++ b/sdks/python/dropbox_sign/models/file_response_data_uri.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/list_info_response.py b/sdks/python/dropbox_sign/models/list_info_response.py index cdca4fa28..23583a020 100644 --- a/sdks/python/dropbox_sign/models/list_info_response.py +++ b/sdks/python/dropbox_sign/models/list_info_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/o_auth_token_generate_request.py b/sdks/python/dropbox_sign/models/o_auth_token_generate_request.py index 06359f488..915adcd27 100644 --- a/sdks/python/dropbox_sign/models/o_auth_token_generate_request.py +++ b/sdks/python/dropbox_sign/models/o_auth_token_generate_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/o_auth_token_refresh_request.py b/sdks/python/dropbox_sign/models/o_auth_token_refresh_request.py index 7a1aa9ae1..bd2b11ed2 100644 --- a/sdks/python/dropbox_sign/models/o_auth_token_refresh_request.py +++ b/sdks/python/dropbox_sign/models/o_auth_token_refresh_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/o_auth_token_response.py b/sdks/python/dropbox_sign/models/o_auth_token_response.py index 4b91161f4..b56f36a14 100644 --- a/sdks/python/dropbox_sign/models/o_auth_token_response.py +++ b/sdks/python/dropbox_sign/models/o_auth_token_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/report_create_request.py b/sdks/python/dropbox_sign/models/report_create_request.py index 9c4e3e1ff..3d94d8fd6 100644 --- a/sdks/python/dropbox_sign/models/report_create_request.py +++ b/sdks/python/dropbox_sign/models/report_create_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -48,9 +47,11 @@ class ReportCreateRequest(BaseModel): def report_type_validate_enum(cls, value): """Validates the enum""" for i in value: - if i not in set(["user_activity", "document_status", "sms_activity"]): + if i not in set( + ["user_activity", "document_status", "sms_activity", "fax_usage"] + ): raise ValueError( - "each list item must be one of ('user_activity', 'document_status', 'sms_activity')" + "each list item must be one of ('user_activity', 'document_status', 'sms_activity', 'fax_usage')" ) return value diff --git a/sdks/python/dropbox_sign/models/report_create_response.py b/sdks/python/dropbox_sign/models/report_create_response.py index 3d781b9bd..fb309c154 100644 --- a/sdks/python/dropbox_sign/models/report_create_response.py +++ b/sdks/python/dropbox_sign/models/report_create_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/report_response.py b/sdks/python/dropbox_sign/models/report_response.py index 176195da1..40ca150cd 100644 --- a/sdks/python/dropbox_sign/models/report_response.py +++ b/sdks/python/dropbox_sign/models/report_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -62,9 +61,11 @@ def report_type_validate_enum(cls, value): return value for i in value: - if i not in set(["user_activity", "document_status", "sms_activity"]): + if i not in set( + ["user_activity", "document_status", "sms_activity", "fax_usage"] + ): raise ValueError( - "each list item must be one of ('user_activity', 'document_status', 'sms_activity')" + "each list item must be one of ('user_activity', 'document_status', 'sms_activity', 'fax_usage')" ) return value diff --git a/sdks/python/dropbox_sign/models/signature_request_bulk_create_embedded_with_template_request.py b/sdks/python/dropbox_sign/models/signature_request_bulk_create_embedded_with_template_request.py index 54fd997c1..eb69f3375 100644 --- a/sdks/python/dropbox_sign/models/signature_request_bulk_create_embedded_with_template_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_bulk_create_embedded_with_template_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_bulk_send_with_template_request.py b/sdks/python/dropbox_sign/models/signature_request_bulk_send_with_template_request.py index 54cb9808f..c52618e77 100644 --- a/sdks/python/dropbox_sign/models/signature_request_bulk_send_with_template_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_bulk_send_with_template_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_create_embedded_request.py b/sdks/python/dropbox_sign/models/signature_request_create_embedded_request.py index 72ef4be80..2d855ef50 100644 --- a/sdks/python/dropbox_sign/models/signature_request_create_embedded_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_create_embedded_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_create_embedded_with_template_request.py b/sdks/python/dropbox_sign/models/signature_request_create_embedded_with_template_request.py index 07c2d0cfe..cb4362e6d 100644 --- a/sdks/python/dropbox_sign/models/signature_request_create_embedded_with_template_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_create_embedded_with_template_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_edit_embedded_request.py b/sdks/python/dropbox_sign/models/signature_request_edit_embedded_request.py index 6e952ad78..b5579dbf5 100644 --- a/sdks/python/dropbox_sign/models/signature_request_edit_embedded_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_edit_embedded_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_edit_embedded_with_template_request.py b/sdks/python/dropbox_sign/models/signature_request_edit_embedded_with_template_request.py index 0061169bb..1c0480924 100644 --- a/sdks/python/dropbox_sign/models/signature_request_edit_embedded_with_template_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_edit_embedded_with_template_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_edit_request.py b/sdks/python/dropbox_sign/models/signature_request_edit_request.py index 4bd18cf01..3f622f8d5 100644 --- a/sdks/python/dropbox_sign/models/signature_request_edit_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_edit_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -113,7 +112,7 @@ class SignatureRequestEditRequest(BaseModel): ) is_eid: Optional[StrictBool] = Field( default=False, - description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer.", + description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer.", ) message: Optional[Annotated[str, Field(strict=True, max_length=5000)]] = Field( default=None, diff --git a/sdks/python/dropbox_sign/models/signature_request_edit_with_template_request.py b/sdks/python/dropbox_sign/models/signature_request_edit_with_template_request.py index fedc9afd5..b7215ec46 100644 --- a/sdks/python/dropbox_sign/models/signature_request_edit_with_template_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_edit_with_template_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -71,7 +70,7 @@ class SignatureRequestEditWithTemplateRequest(BaseModel): ) is_eid: Optional[StrictBool] = Field( default=False, - description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer.", + description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer.", ) message: Optional[Annotated[str, Field(strict=True, max_length=5000)]] = Field( default=None, diff --git a/sdks/python/dropbox_sign/models/signature_request_get_response.py b/sdks/python/dropbox_sign/models/signature_request_get_response.py index 546c12ce3..10d2b1229 100644 --- a/sdks/python/dropbox_sign/models/signature_request_get_response.py +++ b/sdks/python/dropbox_sign/models/signature_request_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_list_response.py b/sdks/python/dropbox_sign/models/signature_request_list_response.py index 2df4cbfe3..4c46fbeef 100644 --- a/sdks/python/dropbox_sign/models/signature_request_list_response.py +++ b/sdks/python/dropbox_sign/models/signature_request_list_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_remind_request.py b/sdks/python/dropbox_sign/models/signature_request_remind_request.py index df37e043e..3454e86b4 100644 --- a/sdks/python/dropbox_sign/models/signature_request_remind_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_remind_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response.py b/sdks/python/dropbox_sign/models/signature_request_response.py index 7720256b8..4be2db472 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response.py +++ b/sdks/python/dropbox_sign/models/signature_request_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_attachment.py b/sdks/python/dropbox_sign/models/signature_request_response_attachment.py index 30af75823..10bb333b1 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_attachment.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_attachment.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_base.py b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_base.py index 61ecdd69c..a9ab8ddf5 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_base.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_base.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_checkbox.py b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_checkbox.py index de55b64e5..e10fe7e3a 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_checkbox.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_checkbox.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_text.py b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_text.py index 48fa24f29..8f9e4eb1a 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_text.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_text.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_type_enum.py b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_type_enum.py index 8f715aea2..a8e880e2e 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_custom_field_type_enum.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_custom_field_type_enum.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import json from enum import Enum diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_base.py b/sdks/python/dropbox_sign/models/signature_request_response_data_base.py index 374d2cc50..9353ca349 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_base.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_base.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_type_enum.py b/sdks/python/dropbox_sign/models/signature_request_response_data_type_enum.py index 8c4d01dac..eaae18cfe 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_type_enum.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_type_enum.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import json from enum import Enum diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox.py index 4e258335d..8d3604e42 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox_merge.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox_merge.py index 0a25a7ca7..ba5fd382b 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox_merge.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_checkbox_merge.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_date_signed.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_date_signed.py index ac09c2600..4644f1b36 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_date_signed.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_date_signed.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_dropdown.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_dropdown.py index 9eb735261..f4423cb1b 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_dropdown.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_dropdown.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_initials.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_initials.py index 9a5f19055..d470cd74b 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_initials.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_initials.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_radio.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_radio.py index 38b3cc04a..db6f2bd50 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_radio.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_radio.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_signature.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_signature.py index a928d102b..af7eade77 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_signature.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_signature.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_text.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_text.py index 7b5b782e5..8c9ad56e5 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_text.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_text.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_data_value_text_merge.py b/sdks/python/dropbox_sign/models/signature_request_response_data_value_text_merge.py index 13b9591e9..176c4b0cb 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_data_value_text_merge.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_data_value_text_merge.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_response_signatures.py b/sdks/python/dropbox_sign/models/signature_request_response_signatures.py index 9b36e81f6..ae4f2d9be 100644 --- a/sdks/python/dropbox_sign/models/signature_request_response_signatures.py +++ b/sdks/python/dropbox_sign/models/signature_request_response_signatures.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/signature_request_send_request.py b/sdks/python/dropbox_sign/models/signature_request_send_request.py index d1f7b7280..4d781039d 100644 --- a/sdks/python/dropbox_sign/models/signature_request_send_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_send_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -117,7 +116,7 @@ class SignatureRequestSendRequest(BaseModel): ) is_eid: Optional[StrictBool] = Field( default=False, - description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer.", + description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer.", ) message: Optional[Annotated[str, Field(strict=True, max_length=5000)]] = Field( default=None, diff --git a/sdks/python/dropbox_sign/models/signature_request_send_with_template_request.py b/sdks/python/dropbox_sign/models/signature_request_send_with_template_request.py index f09727801..f4f4230d1 100644 --- a/sdks/python/dropbox_sign/models/signature_request_send_with_template_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_send_with_template_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -75,7 +74,7 @@ class SignatureRequestSendWithTemplateRequest(BaseModel): ) is_eid: Optional[StrictBool] = Field( default=False, - description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer.", + description="Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer.", ) message: Optional[Annotated[str, Field(strict=True, max_length=5000)]] = Field( default=None, diff --git a/sdks/python/dropbox_sign/models/signature_request_update_request.py b/sdks/python/dropbox_sign/models/signature_request_update_request.py index a5ec1ddc1..dcb2de5b9 100644 --- a/sdks/python/dropbox_sign/models/signature_request_update_request.py +++ b/sdks/python/dropbox_sign/models/signature_request_update_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_attachment.py b/sdks/python/dropbox_sign/models/sub_attachment.py index 82daeb1f5..b2203b2ff 100644 --- a/sdks/python/dropbox_sign/models/sub_attachment.py +++ b/sdks/python/dropbox_sign/models/sub_attachment.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_bulk_signer_list.py b/sdks/python/dropbox_sign/models/sub_bulk_signer_list.py index 899f57701..e1eb782df 100644 --- a/sdks/python/dropbox_sign/models/sub_bulk_signer_list.py +++ b/sdks/python/dropbox_sign/models/sub_bulk_signer_list.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_bulk_signer_list_custom_field.py b/sdks/python/dropbox_sign/models/sub_bulk_signer_list_custom_field.py index 0efdff283..396406867 100644 --- a/sdks/python/dropbox_sign/models/sub_bulk_signer_list_custom_field.py +++ b/sdks/python/dropbox_sign/models/sub_bulk_signer_list_custom_field.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_cc.py b/sdks/python/dropbox_sign/models/sub_cc.py index fb14ef0c0..02b6b98a4 100644 --- a/sdks/python/dropbox_sign/models/sub_cc.py +++ b/sdks/python/dropbox_sign/models/sub_cc.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_custom_field.py b/sdks/python/dropbox_sign/models/sub_custom_field.py index ec74927d1..952debcec 100644 --- a/sdks/python/dropbox_sign/models/sub_custom_field.py +++ b/sdks/python/dropbox_sign/models/sub_custom_field.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_editor_options.py b/sdks/python/dropbox_sign/models/sub_editor_options.py index 8693cfa02..230af545b 100644 --- a/sdks/python/dropbox_sign/models/sub_editor_options.py +++ b/sdks/python/dropbox_sign/models/sub_editor_options.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_field_options.py b/sdks/python/dropbox_sign/models/sub_field_options.py index 12336e67e..3a09fad08 100644 --- a/sdks/python/dropbox_sign/models/sub_field_options.py +++ b/sdks/python/dropbox_sign/models/sub_field_options.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_field_group.py b/sdks/python/dropbox_sign/models/sub_form_field_group.py index a892d2147..833b04461 100644 --- a/sdks/python/dropbox_sign/models/sub_form_field_group.py +++ b/sdks/python/dropbox_sign/models/sub_form_field_group.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_field_rule.py b/sdks/python/dropbox_sign/models/sub_form_field_rule.py index f09ac200c..f61f9984f 100644 --- a/sdks/python/dropbox_sign/models/sub_form_field_rule.py +++ b/sdks/python/dropbox_sign/models/sub_form_field_rule.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_field_rule_action.py b/sdks/python/dropbox_sign/models/sub_form_field_rule_action.py index 59be4336a..033009908 100644 --- a/sdks/python/dropbox_sign/models/sub_form_field_rule_action.py +++ b/sdks/python/dropbox_sign/models/sub_form_field_rule_action.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_field_rule_trigger.py b/sdks/python/dropbox_sign/models/sub_form_field_rule_trigger.py index ff6c5beca..a045125d6 100644 --- a/sdks/python/dropbox_sign/models/sub_form_field_rule_trigger.py +++ b/sdks/python/dropbox_sign/models/sub_form_field_rule_trigger.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_base.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_base.py index 615f1089e..95c07378e 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_base.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_base.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox.py index 90538984b..4fe8308bf 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox_merge.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox_merge.py index aa947338f..67d7aa4e5 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox_merge.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_checkbox_merge.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_date_signed.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_date_signed.py index 583a3a8e6..5adeffd8e 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_date_signed.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_date_signed.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_dropdown.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_dropdown.py index c668c354e..b5b13e537 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_dropdown.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_dropdown.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_font_enum.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_font_enum.py index 8865fdc9e..c01ac7c5c 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_font_enum.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_font_enum.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import json from enum import Enum diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_hyperlink.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_hyperlink.py index 650d76679..887a0987d 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_hyperlink.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_hyperlink.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_initials.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_initials.py index 3383d7151..faefc0b12 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_initials.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_initials.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_radio.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_radio.py index a91bd8688..20aca1855 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_radio.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_radio.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_signature.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_signature.py index 11a056cb0..60c40c746 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_signature.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_signature.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text.py index c2e2c3ae4..0e41d4278 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text_merge.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text_merge.py index 990c2374a..152b54856 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text_merge.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_text_merge.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_type_enum.py b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_type_enum.py index e1d61ca05..005c16db2 100644 --- a/sdks/python/dropbox_sign/models/sub_form_fields_per_document_type_enum.py +++ b/sdks/python/dropbox_sign/models/sub_form_fields_per_document_type_enum.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import json from enum import Enum diff --git a/sdks/python/dropbox_sign/models/sub_merge_field.py b/sdks/python/dropbox_sign/models/sub_merge_field.py index e83058e97..9ced5d512 100644 --- a/sdks/python/dropbox_sign/models/sub_merge_field.py +++ b/sdks/python/dropbox_sign/models/sub_merge_field.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_o_auth.py b/sdks/python/dropbox_sign/models/sub_o_auth.py index 2c11784aa..6d1014143 100644 --- a/sdks/python/dropbox_sign/models/sub_o_auth.py +++ b/sdks/python/dropbox_sign/models/sub_o_auth.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_options.py b/sdks/python/dropbox_sign/models/sub_options.py index e7965f446..75a57ffca 100644 --- a/sdks/python/dropbox_sign/models/sub_options.py +++ b/sdks/python/dropbox_sign/models/sub_options.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_signature_request_grouped_signers.py b/sdks/python/dropbox_sign/models/sub_signature_request_grouped_signers.py index a14f315f0..9246b829c 100644 --- a/sdks/python/dropbox_sign/models/sub_signature_request_grouped_signers.py +++ b/sdks/python/dropbox_sign/models/sub_signature_request_grouped_signers.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_signature_request_signer.py b/sdks/python/dropbox_sign/models/sub_signature_request_signer.py index 3337098c4..486d819be 100644 --- a/sdks/python/dropbox_sign/models/sub_signature_request_signer.py +++ b/sdks/python/dropbox_sign/models/sub_signature_request_signer.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_signature_request_template_signer.py b/sdks/python/dropbox_sign/models/sub_signature_request_template_signer.py index 4d1e239ec..1d41cd463 100644 --- a/sdks/python/dropbox_sign/models/sub_signature_request_template_signer.py +++ b/sdks/python/dropbox_sign/models/sub_signature_request_template_signer.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_signing_options.py b/sdks/python/dropbox_sign/models/sub_signing_options.py index 717d3a8d7..e1416ed82 100644 --- a/sdks/python/dropbox_sign/models/sub_signing_options.py +++ b/sdks/python/dropbox_sign/models/sub_signing_options.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 @@ -36,7 +35,7 @@ class SubSigningOptions(BaseModel): """ - This allows the requester to specify the types allowed for creating a signature. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. """ # noqa: E501 default_type: StrictStr = Field( @@ -54,12 +53,17 @@ class SubSigningOptions(BaseModel): upload: Optional[StrictBool] = Field( default=False, description="Allows uploading the signature" ) + force_advanced_signature_details: Optional[StrictBool] = Field( + default=False, + description="Turning on advanced signature details for the signature request", + ) __properties: ClassVar[List[str]] = [ "default_type", "draw", "phone", "type", "upload", + "force_advanced_signature_details", ] @field_validator("default_type") @@ -139,6 +143,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "phone": obj.get("phone") if obj.get("phone") is not None else False, "type": obj.get("type") if obj.get("type") is not None else False, "upload": obj.get("upload") if obj.get("upload") is not None else False, + "force_advanced_signature_details": ( + obj.get("force_advanced_signature_details") + if obj.get("force_advanced_signature_details") is not None + else False + ), } ) return _obj @@ -161,6 +170,7 @@ def openapi_types(cls) -> Dict[str, str]: "phone": "(bool,)", "type": "(bool,)", "upload": "(bool,)", + "force_advanced_signature_details": "(bool,)", } @classmethod diff --git a/sdks/python/dropbox_sign/models/sub_team_response.py b/sdks/python/dropbox_sign/models/sub_team_response.py index 5a3b7f74f..7eb8822ff 100644 --- a/sdks/python/dropbox_sign/models/sub_team_response.py +++ b/sdks/python/dropbox_sign/models/sub_team_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_template_role.py b/sdks/python/dropbox_sign/models/sub_template_role.py index fd407632c..2024d5c7d 100644 --- a/sdks/python/dropbox_sign/models/sub_template_role.py +++ b/sdks/python/dropbox_sign/models/sub_template_role.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_unclaimed_draft_signer.py b/sdks/python/dropbox_sign/models/sub_unclaimed_draft_signer.py index 318fd8056..aa13619af 100644 --- a/sdks/python/dropbox_sign/models/sub_unclaimed_draft_signer.py +++ b/sdks/python/dropbox_sign/models/sub_unclaimed_draft_signer.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/sub_unclaimed_draft_template_signer.py b/sdks/python/dropbox_sign/models/sub_unclaimed_draft_template_signer.py index a668e9fdc..98ef0fa2b 100644 --- a/sdks/python/dropbox_sign/models/sub_unclaimed_draft_template_signer.py +++ b/sdks/python/dropbox_sign/models/sub_unclaimed_draft_template_signer.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_edit_response.py b/sdks/python/dropbox_sign/models/sub_update_form_field.py similarity index 78% rename from sdks/python/dropbox_sign/models/template_edit_response.py rename to sdks/python/dropbox_sign/models/sub_update_form_field.py index 198813848..e06e3ef06 100644 --- a/sdks/python/dropbox_sign/models/template_edit_response.py +++ b/sdks/python/dropbox_sign/models/sub_update_form_field.py @@ -12,14 +12,13 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 import json from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List +from typing import Any, ClassVar, Dict, List, Optional from typing import Optional, Set from typing_extensions import Self from typing import Tuple, Union @@ -27,13 +26,19 @@ from pydantic import StrictBool -class TemplateEditResponse(BaseModel): +class SubUpdateFormField(BaseModel): """ - TemplateEditResponse + SubUpdateFormField """ # noqa: E501 - template_id: StrictStr = Field(description="The id of the Template.") - __properties: ClassVar[List[str]] = ["template_id"] + api_id: StrictStr = Field( + description="The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found" + ) + name: Optional[StrictStr] = Field( + default=None, + description="The new name of the field. If not passed the name will remain unchanged.", + ) + __properties: ClassVar[List[str]] = ["api_id", "name"] model_config = ConfigDict( populate_by_name=True, @@ -66,7 +71,7 @@ def to_json_form_params( @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of TemplateEditResponse from a JSON string""" + """Create an instance of SubUpdateFormField from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self, excluded_fields: Set[str] = None) -> Dict[str, Any]: @@ -89,14 +94,16 @@ def to_dict(self, excluded_fields: Set[str] = None) -> Dict[str, Any]: @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of TemplateEditResponse from a dict""" + """Create an instance of SubUpdateFormField from a dict""" if obj is None: return None if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({"template_id": obj.get("template_id")}) + _obj = cls.model_validate( + {"api_id": obj.get("api_id"), "name": obj.get("name")} + ) return _obj @classmethod @@ -112,7 +119,8 @@ def init(cls, data: Any) -> Self: @classmethod def openapi_types(cls) -> Dict[str, str]: return { - "template_id": "(str,)", + "api_id": "(str,)", + "name": "(str,)", } @classmethod diff --git a/sdks/python/dropbox_sign/models/sub_white_labeling_options.py b/sdks/python/dropbox_sign/models/sub_white_labeling_options.py index 9fe6f145c..44acf440e 100644 --- a/sdks/python/dropbox_sign/models/sub_white_labeling_options.py +++ b/sdks/python/dropbox_sign/models/sub_white_labeling_options.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_add_member_request.py b/sdks/python/dropbox_sign/models/team_add_member_request.py index 9fa1fbc88..afa2232e6 100644 --- a/sdks/python/dropbox_sign/models/team_add_member_request.py +++ b/sdks/python/dropbox_sign/models/team_add_member_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_create_request.py b/sdks/python/dropbox_sign/models/team_create_request.py index 94d38e66b..3cec269be 100644 --- a/sdks/python/dropbox_sign/models/team_create_request.py +++ b/sdks/python/dropbox_sign/models/team_create_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_get_info_response.py b/sdks/python/dropbox_sign/models/team_get_info_response.py index e716e4daa..8a26bdb91 100644 --- a/sdks/python/dropbox_sign/models/team_get_info_response.py +++ b/sdks/python/dropbox_sign/models/team_get_info_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_get_response.py b/sdks/python/dropbox_sign/models/team_get_response.py index 3c137e35a..6740d48f0 100644 --- a/sdks/python/dropbox_sign/models/team_get_response.py +++ b/sdks/python/dropbox_sign/models/team_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_info_response.py b/sdks/python/dropbox_sign/models/team_info_response.py index b10d7cb82..9002a81c6 100644 --- a/sdks/python/dropbox_sign/models/team_info_response.py +++ b/sdks/python/dropbox_sign/models/team_info_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_invite_response.py b/sdks/python/dropbox_sign/models/team_invite_response.py index 0f377202b..88a4072f8 100644 --- a/sdks/python/dropbox_sign/models/team_invite_response.py +++ b/sdks/python/dropbox_sign/models/team_invite_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_invites_response.py b/sdks/python/dropbox_sign/models/team_invites_response.py index e6171e8fe..1a107ec58 100644 --- a/sdks/python/dropbox_sign/models/team_invites_response.py +++ b/sdks/python/dropbox_sign/models/team_invites_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_member_response.py b/sdks/python/dropbox_sign/models/team_member_response.py index d59fc5d64..0f6006e32 100644 --- a/sdks/python/dropbox_sign/models/team_member_response.py +++ b/sdks/python/dropbox_sign/models/team_member_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_members_response.py b/sdks/python/dropbox_sign/models/team_members_response.py index 73ed1c490..0a55ac24d 100644 --- a/sdks/python/dropbox_sign/models/team_members_response.py +++ b/sdks/python/dropbox_sign/models/team_members_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_parent_response.py b/sdks/python/dropbox_sign/models/team_parent_response.py index 2478765be..579f0ede7 100644 --- a/sdks/python/dropbox_sign/models/team_parent_response.py +++ b/sdks/python/dropbox_sign/models/team_parent_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_remove_member_request.py b/sdks/python/dropbox_sign/models/team_remove_member_request.py index 0df67abe9..52c373255 100644 --- a/sdks/python/dropbox_sign/models/team_remove_member_request.py +++ b/sdks/python/dropbox_sign/models/team_remove_member_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_response.py b/sdks/python/dropbox_sign/models/team_response.py index 9f72e11fe..3ea2e3524 100644 --- a/sdks/python/dropbox_sign/models/team_response.py +++ b/sdks/python/dropbox_sign/models/team_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_sub_teams_response.py b/sdks/python/dropbox_sign/models/team_sub_teams_response.py index 15e0a30c6..a705e74c3 100644 --- a/sdks/python/dropbox_sign/models/team_sub_teams_response.py +++ b/sdks/python/dropbox_sign/models/team_sub_teams_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/team_update_request.py b/sdks/python/dropbox_sign/models/team_update_request.py index 9c4b17e55..360391441 100644 --- a/sdks/python/dropbox_sign/models/team_update_request.py +++ b/sdks/python/dropbox_sign/models/team_update_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_add_user_request.py b/sdks/python/dropbox_sign/models/template_add_user_request.py index 2e4447115..06d488773 100644 --- a/sdks/python/dropbox_sign/models/template_add_user_request.py +++ b/sdks/python/dropbox_sign/models/template_add_user_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_create_embedded_draft_request.py b/sdks/python/dropbox_sign/models/template_create_embedded_draft_request.py index 808ba1ce8..2c4e52152 100644 --- a/sdks/python/dropbox_sign/models/template_create_embedded_draft_request.py +++ b/sdks/python/dropbox_sign/models/template_create_embedded_draft_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_create_embedded_draft_response.py b/sdks/python/dropbox_sign/models/template_create_embedded_draft_response.py index fb9a0eb9a..1bdaf8d4b 100644 --- a/sdks/python/dropbox_sign/models/template_create_embedded_draft_response.py +++ b/sdks/python/dropbox_sign/models/template_create_embedded_draft_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_create_embedded_draft_response_template.py b/sdks/python/dropbox_sign/models/template_create_embedded_draft_response_template.py index 3016dce2e..01c86dde6 100644 --- a/sdks/python/dropbox_sign/models/template_create_embedded_draft_response_template.py +++ b/sdks/python/dropbox_sign/models/template_create_embedded_draft_response_template.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_create_request.py b/sdks/python/dropbox_sign/models/template_create_request.py index 532027646..8505936cd 100644 --- a/sdks/python/dropbox_sign/models/template_create_request.py +++ b/sdks/python/dropbox_sign/models/template_create_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_create_response.py b/sdks/python/dropbox_sign/models/template_create_response.py index bc5f6c6a2..9654fb9e3 100644 --- a/sdks/python/dropbox_sign/models/template_create_response.py +++ b/sdks/python/dropbox_sign/models/template_create_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_create_response_template.py b/sdks/python/dropbox_sign/models/template_create_response_template.py index 25d9bd7bd..64051f724 100644 --- a/sdks/python/dropbox_sign/models/template_create_response_template.py +++ b/sdks/python/dropbox_sign/models/template_create_response_template.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_get_response.py b/sdks/python/dropbox_sign/models/template_get_response.py index 10d714c52..3f581a17a 100644 --- a/sdks/python/dropbox_sign/models/template_get_response.py +++ b/sdks/python/dropbox_sign/models/template_get_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_list_response.py b/sdks/python/dropbox_sign/models/template_list_response.py index 5ccaba716..c1b1036c9 100644 --- a/sdks/python/dropbox_sign/models/template_list_response.py +++ b/sdks/python/dropbox_sign/models/template_list_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_remove_user_request.py b/sdks/python/dropbox_sign/models/template_remove_user_request.py index 44ddbf42e..27ac14435 100644 --- a/sdks/python/dropbox_sign/models/template_remove_user_request.py +++ b/sdks/python/dropbox_sign/models/template_remove_user_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response.py b/sdks/python/dropbox_sign/models/template_response.py index 667465fff..66d732ef5 100644 --- a/sdks/python/dropbox_sign/models/template_response.py +++ b/sdks/python/dropbox_sign/models/template_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_account.py b/sdks/python/dropbox_sign/models/template_response_account.py index d29db33d0..88c9766c5 100644 --- a/sdks/python/dropbox_sign/models/template_response_account.py +++ b/sdks/python/dropbox_sign/models/template_response_account.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_account_quota.py b/sdks/python/dropbox_sign/models/template_response_account_quota.py index e4fa3668b..89f54c88a 100644 --- a/sdks/python/dropbox_sign/models/template_response_account_quota.py +++ b/sdks/python/dropbox_sign/models/template_response_account_quota.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_cc_role.py b/sdks/python/dropbox_sign/models/template_response_cc_role.py index 89a3b4c88..1f17d0cc1 100644 --- a/sdks/python/dropbox_sign/models/template_response_cc_role.py +++ b/sdks/python/dropbox_sign/models/template_response_cc_role.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document.py b/sdks/python/dropbox_sign/models/template_response_document.py index d2f0cafb6..a7177287c 100644 --- a/sdks/python/dropbox_sign/models/template_response_document.py +++ b/sdks/python/dropbox_sign/models/template_response_document.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_custom_field_base.py b/sdks/python/dropbox_sign/models/template_response_document_custom_field_base.py index 6c6a35b7e..278b83aaa 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_custom_field_base.py +++ b/sdks/python/dropbox_sign/models/template_response_document_custom_field_base.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_custom_field_checkbox.py b/sdks/python/dropbox_sign/models/template_response_document_custom_field_checkbox.py index 35e391517..60acd170d 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_custom_field_checkbox.py +++ b/sdks/python/dropbox_sign/models/template_response_document_custom_field_checkbox.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_custom_field_text.py b/sdks/python/dropbox_sign/models/template_response_document_custom_field_text.py index 09a85e20f..8d71ca65a 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_custom_field_text.py +++ b/sdks/python/dropbox_sign/models/template_response_document_custom_field_text.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_field_group.py b/sdks/python/dropbox_sign/models/template_response_document_field_group.py index 8f3bc1a16..b9774c263 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_field_group.py +++ b/sdks/python/dropbox_sign/models/template_response_document_field_group.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_field_group_rule.py b/sdks/python/dropbox_sign/models/template_response_document_field_group_rule.py index 17d81cbd9..df4e5b827 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_field_group_rule.py +++ b/sdks/python/dropbox_sign/models/template_response_document_field_group_rule.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_base.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_base.py index 6f8777a3b..ff2269fa8 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_base.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_base.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_checkbox.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_checkbox.py index d81d6572a..a24921b12 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_checkbox.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_checkbox.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_date_signed.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_date_signed.py index 8ee5fe31b..8b7f3d13f 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_date_signed.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_date_signed.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_dropdown.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_dropdown.py index 2b30ae4c5..76b035657 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_dropdown.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_dropdown.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_hyperlink.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_hyperlink.py index 0102248d3..9e9798369 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_hyperlink.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_hyperlink.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_initials.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_initials.py index 64321add8..1f4eb7392 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_initials.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_initials.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_radio.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_radio.py index 0f0c3443a..f0855859c 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_radio.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_radio.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_signature.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_signature.py index c509f92ce..844558f21 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_signature.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_signature.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_form_field_text.py b/sdks/python/dropbox_sign/models/template_response_document_form_field_text.py index 6280970f4..3fcd28712 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_form_field_text.py +++ b/sdks/python/dropbox_sign/models/template_response_document_form_field_text.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_base.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_base.py index d9735c703..927c2c026 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_base.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_base.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_checkbox.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_checkbox.py index 0afba0d9f..d8d1f135f 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_checkbox.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_checkbox.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_date_signed.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_date_signed.py index 0b232a6c9..bfc9f2e33 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_date_signed.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_date_signed.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_dropdown.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_dropdown.py index 7ac71ec4e..fb7cde0fb 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_dropdown.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_dropdown.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_hyperlink.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_hyperlink.py index bdd27c9d2..dd322e0e6 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_hyperlink.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_hyperlink.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_initials.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_initials.py index bd755ee8e..22da86102 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_initials.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_initials.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_radio.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_radio.py index a78d5b803..cb58af258 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_radio.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_radio.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_signature.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_signature.py index c0ff8eee6..664b3d7d2 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_signature.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_signature.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_document_static_field_text.py b/sdks/python/dropbox_sign/models/template_response_document_static_field_text.py index 03a3a4831..a70afa340 100644 --- a/sdks/python/dropbox_sign/models/template_response_document_static_field_text.py +++ b/sdks/python/dropbox_sign/models/template_response_document_static_field_text.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_field_avg_text_length.py b/sdks/python/dropbox_sign/models/template_response_field_avg_text_length.py index 1936e75ee..34dc71172 100644 --- a/sdks/python/dropbox_sign/models/template_response_field_avg_text_length.py +++ b/sdks/python/dropbox_sign/models/template_response_field_avg_text_length.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_response_signer_role.py b/sdks/python/dropbox_sign/models/template_response_signer_role.py index 2cada158d..571469e90 100644 --- a/sdks/python/dropbox_sign/models/template_response_signer_role.py +++ b/sdks/python/dropbox_sign/models/template_response_signer_role.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_update_files_request.py b/sdks/python/dropbox_sign/models/template_update_files_request.py index 18612ddbf..424a254b0 100644 --- a/sdks/python/dropbox_sign/models/template_update_files_request.py +++ b/sdks/python/dropbox_sign/models/template_update_files_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_update_files_response.py b/sdks/python/dropbox_sign/models/template_update_files_response.py index 67b1d3b68..94b562027 100644 --- a/sdks/python/dropbox_sign/models/template_update_files_response.py +++ b/sdks/python/dropbox_sign/models/template_update_files_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/template_update_files_response_template.py b/sdks/python/dropbox_sign/models/template_update_files_response_template.py index 2a8cd11ad..0825101cb 100644 --- a/sdks/python/dropbox_sign/models/template_update_files_response_template.py +++ b/sdks/python/dropbox_sign/models/template_update_files_response_template.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_request.py b/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_request.py index 53527e34c..2ca5e9c5b 100644 --- a/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_request.py +++ b/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_with_template_request.py b/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_with_template_request.py index 3ab702393..7ce070ff1 100644 --- a/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_with_template_request.py +++ b/sdks/python/dropbox_sign/models/unclaimed_draft_create_embedded_with_template_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/unclaimed_draft_create_request.py b/sdks/python/dropbox_sign/models/unclaimed_draft_create_request.py index 49a7aeec3..88ae6835e 100644 --- a/sdks/python/dropbox_sign/models/unclaimed_draft_create_request.py +++ b/sdks/python/dropbox_sign/models/unclaimed_draft_create_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/unclaimed_draft_create_response.py b/sdks/python/dropbox_sign/models/unclaimed_draft_create_response.py index 085e5b907..dab0513a1 100644 --- a/sdks/python/dropbox_sign/models/unclaimed_draft_create_response.py +++ b/sdks/python/dropbox_sign/models/unclaimed_draft_create_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/unclaimed_draft_edit_and_resend_request.py b/sdks/python/dropbox_sign/models/unclaimed_draft_edit_and_resend_request.py index 38903beef..29e4afe3a 100644 --- a/sdks/python/dropbox_sign/models/unclaimed_draft_edit_and_resend_request.py +++ b/sdks/python/dropbox_sign/models/unclaimed_draft_edit_and_resend_request.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/unclaimed_draft_response.py b/sdks/python/dropbox_sign/models/unclaimed_draft_response.py index 51fdcfa9b..5f8849d69 100644 --- a/sdks/python/dropbox_sign/models/unclaimed_draft_response.py +++ b/sdks/python/dropbox_sign/models/unclaimed_draft_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/models/warning_response.py b/sdks/python/dropbox_sign/models/warning_response.py index d2a26d5c3..5e0b464ce 100644 --- a/sdks/python/dropbox_sign/models/warning_response.py +++ b/sdks/python/dropbox_sign/models/warning_response.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations import pprint import re # noqa: F401 diff --git a/sdks/python/dropbox_sign/rest.py b/sdks/python/dropbox_sign/rest.py index 4aaa80dbe..dcabe9c34 100644 --- a/sdks/python/dropbox_sign/rest.py +++ b/sdks/python/dropbox_sign/rest.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - import io import json import re diff --git a/sdks/ruby/README.md b/sdks/ruby/README.md index 2e973be17..4c46f0bd0 100644 --- a/sdks/ruby/README.md +++ b/sdks/ruby/README.md @@ -189,6 +189,7 @@ All URIs are relative to *https://api.hellosign.com/v3* - [Dropbox::Sign::AccountGetResponse](docs/AccountGetResponse.md) - [Dropbox::Sign::AccountResponse](docs/AccountResponse.md) - [Dropbox::Sign::AccountResponseQuotas](docs/AccountResponseQuotas.md) + - [Dropbox::Sign::AccountResponseSettings](docs/AccountResponseSettings.md) - [Dropbox::Sign::AccountResponseUsage](docs/AccountResponseUsage.md) - [Dropbox::Sign::AccountUpdateRequest](docs/AccountUpdateRequest.md) - [Dropbox::Sign::AccountVerifyRequest](docs/AccountVerifyRequest.md) @@ -310,6 +311,7 @@ All URIs are relative to *https://api.hellosign.com/v3* - [Dropbox::Sign::SubTemplateRole](docs/SubTemplateRole.md) - [Dropbox::Sign::SubUnclaimedDraftSigner](docs/SubUnclaimedDraftSigner.md) - [Dropbox::Sign::SubUnclaimedDraftTemplateSigner](docs/SubUnclaimedDraftTemplateSigner.md) + - [Dropbox::Sign::SubUpdateFormField](docs/SubUpdateFormField.md) - [Dropbox::Sign::SubWhiteLabelingOptions](docs/SubWhiteLabelingOptions.md) - [Dropbox::Sign::TeamAddMemberRequest](docs/TeamAddMemberRequest.md) - [Dropbox::Sign::TeamCreateRequest](docs/TeamCreateRequest.md) @@ -332,7 +334,6 @@ All URIs are relative to *https://api.hellosign.com/v3* - [Dropbox::Sign::TemplateCreateRequest](docs/TemplateCreateRequest.md) - [Dropbox::Sign::TemplateCreateResponse](docs/TemplateCreateResponse.md) - [Dropbox::Sign::TemplateCreateResponseTemplate](docs/TemplateCreateResponseTemplate.md) - - [Dropbox::Sign::TemplateEditResponse](docs/TemplateEditResponse.md) - [Dropbox::Sign::TemplateGetResponse](docs/TemplateGetResponse.md) - [Dropbox::Sign::TemplateListResponse](docs/TemplateListResponse.md) - [Dropbox::Sign::TemplateRemoveUserRequest](docs/TemplateRemoveUserRequest.md) diff --git a/sdks/ruby/docs/AccountResponse.md b/sdks/ruby/docs/AccountResponse.md index 294f29431..aeb1b38ae 100644 --- a/sdks/ruby/docs/AccountResponse.md +++ b/sdks/ruby/docs/AccountResponse.md @@ -17,4 +17,5 @@ | `team_id` | ```String``` | The id of the team account belongs to. | | | `locale` | ```String``` | The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. | | | `usage` | [```AccountResponseUsage```](AccountResponseUsage.md) | | | +| `settings` | [```AccountResponseSettings```](AccountResponseSettings.md) | | | diff --git a/sdks/ruby/docs/AccountResponseSettings.md b/sdks/ruby/docs/AccountResponseSettings.md new file mode 100644 index 000000000..642280e83 --- /dev/null +++ b/sdks/ruby/docs/AccountResponseSettings.md @@ -0,0 +1,12 @@ +# Dropbox::Sign::AccountResponseSettings + +Subset of configured settings + +## Properties + +| Name | Type | Description | Notes | +| ---- | ---- | ----------- | ----- | +| `signer_access_codes` | ```Boolean``` | Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `sms_delivery` | ```Boolean``` | Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | +| `sms_authentication` | ```Boolean``` | Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). | | + diff --git a/sdks/ruby/docs/SignatureRequestApi.md b/sdks/ruby/docs/SignatureRequestApi.md index 964273c5f..e3f4b361e 100644 --- a/sdks/ruby/docs/SignatureRequestApi.md +++ b/sdks/ruby/docs/SignatureRequestApi.md @@ -390,6 +390,7 @@ signing_options.draw = true signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestSigner.new signers_1.name = "Jack" @@ -497,6 +498,7 @@ signing_options.draw = true signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestTemplateSigner.new signers_1.role = "Client" @@ -1609,6 +1611,7 @@ signing_options.draw = true signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestSigner.new signers_1.name = "Jack" @@ -1723,6 +1726,7 @@ signing_options.draw = true signing_options.phone = false signing_options.type = true signing_options.upload = true +signing_options.force_advanced_signature_details = false signers_1 = Dropbox::Sign::SubSignatureRequestTemplateSigner.new signers_1.role = "Client" diff --git a/sdks/ruby/docs/SignatureRequestEditRequest.md b/sdks/ruby/docs/SignatureRequestEditRequest.md index 39d575aa3..ce5325052 100644 --- a/sdks/ruby/docs/SignatureRequestEditRequest.md +++ b/sdks/ruby/docs/SignatureRequestEditRequest.md @@ -21,7 +21,7 @@ | `form_field_rules` | [```Array```](SubFormFieldRule.md) | Conditional Logic rules for fields defined in `form_fields_per_document`. | | | `form_fields_per_document` | [```Array```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hide_text_tags` | ```Boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to false] | -| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Hash``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/ruby/docs/SignatureRequestEditWithTemplateRequest.md b/sdks/ruby/docs/SignatureRequestEditWithTemplateRequest.md index 12b4bee82..f4391eba9 100644 --- a/sdks/ruby/docs/SignatureRequestEditWithTemplateRequest.md +++ b/sdks/ruby/docs/SignatureRequestEditWithTemplateRequest.md @@ -14,7 +14,7 @@ | `custom_fields` | [```Array```](SubCustomField.md) | An array defining values and options for custom fields. Required when a custom field exists in the Template. | | | `files` | ```Array``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `file_urls` | ```Array``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | -| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Hash``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/ruby/docs/SignatureRequestSendRequest.md b/sdks/ruby/docs/SignatureRequestSendRequest.md index 683075e13..ca6f16746 100644 --- a/sdks/ruby/docs/SignatureRequestSendRequest.md +++ b/sdks/ruby/docs/SignatureRequestSendRequest.md @@ -22,7 +22,7 @@ | `form_fields_per_document` | [```Array```](SubFormFieldsPerDocumentBase.md) | The fields that should appear on the document, expressed as an array of objects. (For more details you can read about it here: [Using Form Fields per Document](/docs/openapi/form-fields-per-document).)

**NOTE:** Fields like **text**, **dropdown**, **checkbox**, **radio**, and **hyperlink** have additional required and optional parameters. Check out the list of [additional parameters](/api/reference/constants/#form-fields-per-document) for these field types.

* Text Field use `SubFormFieldsPerDocumentText`
* Dropdown Field use `SubFormFieldsPerDocumentDropdown`
* Hyperlink Field use `SubFormFieldsPerDocumentHyperlink`
* Checkbox Field use `SubFormFieldsPerDocumentCheckbox`
* Radio Field use `SubFormFieldsPerDocumentRadio`
* Signature Field use `SubFormFieldsPerDocumentSignature`
* Date Signed Field use `SubFormFieldsPerDocumentDateSigned`
* Initials Field use `SubFormFieldsPerDocumentInitials`
* Text Merge Field use `SubFormFieldsPerDocumentTextMerge`
* Checkbox Merge Field use `SubFormFieldsPerDocumentCheckboxMerge` | | | `hide_text_tags` | ```Boolean``` | Enables automatic Text Tag removal when set to true.

**NOTE:** Removing text tags this way can cause unwanted clipping. We recommend leaving this setting on `false` and instead hiding your text tags using white text or a similar approach. See the [Text Tags Walkthrough](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) for more information. | [default to false] | | `is_qualified_signature` | ```Boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | -| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Hash``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/ruby/docs/SignatureRequestSendWithTemplateRequest.md b/sdks/ruby/docs/SignatureRequestSendWithTemplateRequest.md index 94e17b8bf..39b16522b 100644 --- a/sdks/ruby/docs/SignatureRequestSendWithTemplateRequest.md +++ b/sdks/ruby/docs/SignatureRequestSendWithTemplateRequest.md @@ -15,7 +15,7 @@ | `files` | ```Array``` | Use `files[]` to indicate the uploaded file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `file_urls` | ```Array``` | Use `file_urls[]` to have Dropbox Sign download the file(s) to send for signature.

This endpoint requires either **files** or **file_urls[]**, but not both. | | | `is_qualified_signature` | ```Boolean``` | Send with a value of `true` if you wish to enable [Qualified Electronic Signatures](https://www.hellosign.com/features/qualified-electronic-signatures) (QES), which requires a face-to-face call to verify the signer's identity.<br>
**NOTE:** QES is only available on the Premium API plan as an add-on purchase. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | -| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | +| `is_eid` | ```Boolean``` | Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.<br>
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. | [default to false] | | `message` | ```String``` | The custom message in the email that will be sent to the signers. | | | `metadata` | ```Hash``` | Key-value data that should be attached to the signature request. This metadata is included in all API responses and events involving the signature request. For example, use the metadata field to store a signer's order number for look up when receiving events for the signature request.

Each request can include up to 10 metadata keys (or 50 nested metadata keys), with key names up to 40 characters long and values up to 1000 characters long. | | | `signing_options` | [```SubSigningOptions```](SubSigningOptions.md) | | | diff --git a/sdks/ruby/docs/SubSigningOptions.md b/sdks/ruby/docs/SubSigningOptions.md index d2eb449f7..026659a88 100644 --- a/sdks/ruby/docs/SubSigningOptions.md +++ b/sdks/ruby/docs/SubSigningOptions.md @@ -1,9 +1,11 @@ # Dropbox::Sign::SubSigningOptions -This allows the requester to specify the types allowed for creating a signature. +This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. +**NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. + ## Properties | Name | Type | Description | Notes | @@ -13,4 +15,5 @@ This allows the requester to specify the types allowed for creating a signature. | `phone` | ```Boolean``` | Allows using a smartphone to email the signature | [default to false] | | `type` | ```Boolean``` | Allows typing the signature | [default to false] | | `upload` | ```Boolean``` | Allows uploading the signature | [default to false] | +| `force_advanced_signature_details` | ```Boolean``` | Turning on advanced signature details for the signature request | [default to false] | diff --git a/sdks/ruby/docs/SubUpdateFormField.md b/sdks/ruby/docs/SubUpdateFormField.md new file mode 100644 index 000000000..f65ea0c51 --- /dev/null +++ b/sdks/ruby/docs/SubUpdateFormField.md @@ -0,0 +1,11 @@ +# Dropbox::Sign::SubUpdateFormField + + + +## Properties + +| Name | Type | Description | Notes | +| ---- | ---- | ----------- | ----- | +| `api_id`*_required_ | ```String``` | The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found | | +| `name` | ```String``` | The new name of the field. If not passed the name will remain unchanged. | | + diff --git a/sdks/ruby/docs/TemplateApi.md b/sdks/ruby/docs/TemplateApi.md index 315ced97c..ffd6ec0ea 100644 --- a/sdks/ruby/docs/TemplateApi.md +++ b/sdks/ruby/docs/TemplateApi.md @@ -97,7 +97,7 @@ end Create Template -Creates a template that can then be used. +Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. ### Examples diff --git a/sdks/ruby/docs/TemplateEditResponse.md b/sdks/ruby/docs/TemplateEditResponse.md deleted file mode 100644 index 5b46080d2..000000000 --- a/sdks/ruby/docs/TemplateEditResponse.md +++ /dev/null @@ -1,10 +0,0 @@ -# Dropbox::Sign::TemplateEditResponse - - - -## Properties - -| Name | Type | Description | Notes | -| ---- | ---- | ----------- | ----- | -| `template_id`*_required_ | ```String``` | The id of the Template. | | - diff --git a/sdks/ruby/lib/dropbox-sign.rb b/sdks/ruby/lib/dropbox-sign.rb index 413c293c8..fb45147a0 100644 --- a/sdks/ruby/lib/dropbox-sign.rb +++ b/sdks/ruby/lib/dropbox-sign.rb @@ -22,6 +22,7 @@ require 'dropbox-sign/models/account_get_response' require 'dropbox-sign/models/account_response' require 'dropbox-sign/models/account_response_quotas' +require 'dropbox-sign/models/account_response_settings' require 'dropbox-sign/models/account_response_usage' require 'dropbox-sign/models/account_update_request' require 'dropbox-sign/models/account_verify_request' @@ -122,6 +123,7 @@ require 'dropbox-sign/models/sub_template_role' require 'dropbox-sign/models/sub_unclaimed_draft_signer' require 'dropbox-sign/models/sub_unclaimed_draft_template_signer' +require 'dropbox-sign/models/sub_update_form_field' require 'dropbox-sign/models/sub_white_labeling_options' require 'dropbox-sign/models/team_add_member_request' require 'dropbox-sign/models/team_create_request' @@ -144,7 +146,6 @@ require 'dropbox-sign/models/template_create_request' require 'dropbox-sign/models/template_create_response' require 'dropbox-sign/models/template_create_response_template' -require 'dropbox-sign/models/template_edit_response' require 'dropbox-sign/models/template_get_response' require 'dropbox-sign/models/template_list_response' require 'dropbox-sign/models/template_remove_user_request' diff --git a/sdks/ruby/lib/dropbox-sign/api/template_api.rb b/sdks/ruby/lib/dropbox-sign/api/template_api.rb index 4620ab332..c43bf9e06 100644 --- a/sdks/ruby/lib/dropbox-sign/api/template_api.rb +++ b/sdks/ruby/lib/dropbox-sign/api/template_api.rb @@ -138,7 +138,7 @@ def template_add_user_with_http_info(template_id, template_add_user_request, opt end # Create Template - # Creates a template that can then be used. + # Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. # @param template_create_request [TemplateCreateRequest] # @param [Hash] opts the optional parameters # @return [TemplateCreateResponse] @@ -148,7 +148,7 @@ def template_create(template_create_request, opts = {}) end # Create Template - # Creates a template that can then be used. + # Creates a template that can be used in future signature requests. If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. # @param template_create_request [TemplateCreateRequest] # @param [Hash] opts the optional parameters # @return [Array<(TemplateCreateResponse, Integer, Hash)>] TemplateCreateResponse data, response status code and response headers diff --git a/sdks/ruby/lib/dropbox-sign/api_client.rb b/sdks/ruby/lib/dropbox-sign/api_client.rb index ad1d84275..bd7e7367e 100644 --- a/sdks/ruby/lib/dropbox-sign/api_client.rb +++ b/sdks/ruby/lib/dropbox-sign/api_client.rb @@ -132,6 +132,22 @@ def build_request(http_method, path, opts = {}) end end + # Workaround for the Typhoeus/libcurl multipart PUT bug. + # libcurl only builds a multipart body via CURLOPT_HTTPPOST/CURLOPT_MIMEPOST, + # which is engaged for POST requests. For PUT it falls back to CURLOPT_UPLOAD + # and silently drops form fields, so the request is sent without a + # `Content-Type: multipart/form-data; boundary=...` header or body. + # We send the request as POST so the multipart body is encoded correctly, + # then use CURLOPT_CUSTOMREQUEST (exposed by Ethon as :customrequest) to + # restore PUT as the on-the-wire HTTP verb. + # See: https://github.com/typhoeus/typhoeus/issues/389 + content_type_header = header_params['Content-Type'] || header_params['content-type'] + if http_method == :put && content_type_header.is_a?(String) && + content_type_header.start_with?('multipart/form-data') + req_opts[:method] = :post + req_opts[:customrequest] = 'PUT' + end + Typhoeus::Request.new(url, req_opts) end diff --git a/sdks/ruby/lib/dropbox-sign/models/account_response.rb b/sdks/ruby/lib/dropbox-sign/models/account_response.rb index 4e96e470d..d9ccec82e 100644 --- a/sdks/ruby/lib/dropbox-sign/models/account_response.rb +++ b/sdks/ruby/lib/dropbox-sign/models/account_response.rb @@ -60,6 +60,9 @@ class AccountResponse # @return [AccountResponseUsage] attr_accessor :usage + # @return [AccountResponseSettings] + attr_accessor :settings + # Attribute mapping from ruby-style variable name to JSON key. def self.attribute_map { @@ -73,7 +76,8 @@ def self.attribute_map :'role_code' => :'role_code', :'team_id' => :'team_id', :'locale' => :'locale', - :'usage' => :'usage' + :'usage' => :'usage', + :'settings' => :'settings' } end @@ -100,7 +104,8 @@ def self.openapi_types :'role_code' => :'String', :'team_id' => :'String', :'locale' => :'String', - :'usage' => :'AccountResponseUsage' + :'usage' => :'AccountResponseUsage', + :'settings' => :'AccountResponseSettings' } end @@ -198,6 +203,10 @@ def initialize(attributes = {}) if attributes.key?(:'usage') self.usage = attributes[:'usage'] end + + if attributes.key?(:'settings') + self.settings = attributes[:'settings'] + end end # Show invalid properties with the reasons. Usually used together with valid? @@ -228,7 +237,8 @@ def ==(o) role_code == o.role_code && team_id == o.team_id && locale == o.locale && - usage == o.usage + usage == o.usage && + settings == o.settings end # @see the `==` method @@ -240,7 +250,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [account_id, email_address, is_locked, is_paid_hs, is_paid_hf, quotas, callback_url, role_code, team_id, locale, usage].hash + [account_id, email_address, is_locked, is_paid_hs, is_paid_hf, quotas, callback_url, role_code, team_id, locale, usage, settings].hash end # Builds the object from hash diff --git a/sdks/ruby/lib/dropbox-sign/models/account_response_settings.rb b/sdks/ruby/lib/dropbox-sign/models/account_response_settings.rb new file mode 100644 index 000000000..5710c3ac8 --- /dev/null +++ b/sdks/ruby/lib/dropbox-sign/models/account_response_settings.rb @@ -0,0 +1,275 @@ +=begin +#Dropbox Sign API + +#Dropbox Sign v3 API + +The version of the OpenAPI document: 3.0.0 +Contact: apisupport@hellosign.com +Generated by: https://openapi-generator.tech +Generator version: 7.12.0 + +=end + +require 'date' +require 'time' + +module Dropbox +end + +module Dropbox::Sign + # Subset of configured settings + class AccountResponseSettings + # Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + # @return [Boolean] + attr_accessor :signer_access_codes + + # Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + # @return [Boolean] + attr_accessor :sms_delivery + + # Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). + # @return [Boolean] + attr_accessor :sms_authentication + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'signer_access_codes' => :'signer_access_codes', + :'sms_delivery' => :'sms_delivery', + :'sms_authentication' => :'sms_authentication' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'signer_access_codes' => :'Boolean', + :'sms_delivery' => :'Boolean', + :'sms_authentication' => :'Boolean' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Returns attribute map of this model + parent + def self.merged_attributes + self.attribute_map + end + + # Attribute type mapping of this model + parent + def self.merged_types + self.openapi_types + end + + # Returns list of attributes with nullable: true of this model + parent + def self.merged_nullable + self.openapi_nullable + end + + # Attempt to instantiate and hydrate a new instance of this class + # @param [Object] data Data to be converted + # @return [AccountResponseSettings] + def self.init(data) + ApiClient.default.convert_to_type( + data, + "AccountResponseSettings" + ) || AccountResponseSettings.new + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Dropbox::Sign::AccountResponseSettings` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!self.class.merged_attributes.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Dropbox::Sign::AccountResponseSettings`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'signer_access_codes') + self.signer_access_codes = attributes[:'signer_access_codes'] + end + + if attributes.key?(:'sms_delivery') + self.sms_delivery = attributes[:'sms_delivery'] + end + + if attributes.key?(:'sms_authentication') + self.sms_authentication = attributes[:'sms_authentication'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + invalid_properties = Array.new + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + true + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + signer_access_codes == o.signer_access_codes && + sms_delivery == o.sms_delivery && + sms_authentication == o.sms_authentication + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [signer_access_codes, sms_delivery, sms_authentication].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + new.build_from_hash(attributes) + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attribute_map = self.class.merged_attributes + + self.class.merged_types.each_pair do |key, type| + if type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + self.send("#{key}=", attributes[attribute_map[key]].map { |v| _deserialize($1, v) }) + end + elsif !attributes[attribute_map[key]].nil? + self.send("#{key}=", _deserialize(type, attributes[attribute_map[key]])) + end + end + + self + end + + # Deserializes the data based on type + # @param string type Data type + # @param string value Value to be deserialized + # @return [Object] Deserialized data + def _deserialize(type, value) + case type.to_sym + when :Time + Time.parse(value) + when :Date + Date.parse(value) + when :String + value.to_s + when :Integer + value.to_i + when :Float + value.to_f + when :Boolean + if value.to_s =~ /\A(true|t|yes|y|1)\z/i + true + else + false + end + when :Object + # generic object (usually a Hash), return directly + value + when /\AArray<(?.+)>\z/ + inner_type = Regexp.last_match[:inner_type] + value.map { |v| _deserialize(inner_type, v) } + when /\AHash<(?.+?), (?.+)>\z/ + k_type = Regexp.last_match[:k_type] + v_type = Regexp.last_match[:v_type] + {}.tap do |hash| + value.each do |k, v| + hash[_deserialize(k_type, k)] = _deserialize(v_type, v) + end + end + else # model + klass = Dropbox::Sign.const_get(type) + klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value) + end + end + + # Returns the string representation of the object + # @return [String] String presentation of the object + def to_s + to_hash.to_s + end + + # to_body is an alias to to_hash (backward compatibility) + # @return [Hash] Returns the object in the form of hash + def to_body + to_hash + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash(include_nil = true) + hash = {} + self.class.merged_attributes.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + next unless include_nil + is_nullable = self.class.merged_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value, include_nil) + end + hash + end + + # Outputs non-array value in the form of hash + # For object, use to_hash. Otherwise, just return the value + # @param [Object] value Any valid value + # @return [Hash] Returns the value in the form of hash + def _to_hash(value, include_nil = true) + if value.is_a?(Array) + value.compact.map { |v| _to_hash(v, include_nil) } + elsif value.is_a?(Hash) + {}.tap do |hash| + value.each { |k, v| hash[k] = _to_hash(v, include_nil) } + end + elsif value.respond_to? :to_hash + value.to_hash(include_nil) + else + value + end + end + end +end diff --git a/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_request.rb b/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_request.rb index 299dc7033..68e7c2f6c 100644 --- a/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_request.rb +++ b/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_request.rb @@ -77,7 +77,7 @@ class SignatureRequestEditRequest # @return [Boolean] attr_accessor :hide_text_tags - # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. # @return [Boolean] attr_accessor :is_eid diff --git a/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_with_template_request.rb b/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_with_template_request.rb index ea8f2a943..d20fef4a0 100644 --- a/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_with_template_request.rb +++ b/sdks/ruby/lib/dropbox-sign/models/signature_request_edit_with_template_request.rb @@ -51,7 +51,7 @@ class SignatureRequestEditWithTemplateRequest # @return [Array] attr_accessor :file_urls - # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. # @return [Boolean] attr_accessor :is_eid diff --git a/sdks/ruby/lib/dropbox-sign/models/signature_request_send_request.rb b/sdks/ruby/lib/dropbox-sign/models/signature_request_send_request.rb index 1bfe729ab..8dec7e411 100644 --- a/sdks/ruby/lib/dropbox-sign/models/signature_request_send_request.rb +++ b/sdks/ruby/lib/dropbox-sign/models/signature_request_send_request.rb @@ -81,7 +81,7 @@ class SignatureRequestSendRequest # @return [Boolean] attr_accessor :is_qualified_signature - # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. # @return [Boolean] attr_accessor :is_eid diff --git a/sdks/ruby/lib/dropbox-sign/models/signature_request_send_with_template_request.rb b/sdks/ruby/lib/dropbox-sign/models/signature_request_send_with_template_request.rb index ac2647256..cf024ca6f 100644 --- a/sdks/ruby/lib/dropbox-sign/models/signature_request_send_with_template_request.rb +++ b/sdks/ruby/lib/dropbox-sign/models/signature_request_send_with_template_request.rb @@ -55,7 +55,7 @@ class SignatureRequestSendWithTemplateRequest # @return [Boolean] attr_accessor :is_qualified_signature - # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + # Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
**NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. # @return [Boolean] attr_accessor :is_eid diff --git a/sdks/ruby/lib/dropbox-sign/models/sub_signing_options.rb b/sdks/ruby/lib/dropbox-sign/models/sub_signing_options.rb index 26a6406f7..7d0969ded 100644 --- a/sdks/ruby/lib/dropbox-sign/models/sub_signing_options.rb +++ b/sdks/ruby/lib/dropbox-sign/models/sub_signing_options.rb @@ -17,7 +17,7 @@ module Dropbox end module Dropbox::Sign - # This allows the requester to specify the types allowed for creating a signature. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + # This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. class SubSigningOptions # The default type shown (limited to the listed types) # @return [String] @@ -39,6 +39,10 @@ class SubSigningOptions # @return [Boolean] attr_accessor :upload + # Turning on advanced signature details for the signature request + # @return [Boolean] + attr_accessor :force_advanced_signature_details + class EnumAttributeValidator attr_reader :datatype attr_reader :allowable_values @@ -68,7 +72,8 @@ def self.attribute_map :'draw' => :'draw', :'phone' => :'phone', :'type' => :'type', - :'upload' => :'upload' + :'upload' => :'upload', + :'force_advanced_signature_details' => :'force_advanced_signature_details' } end @@ -89,7 +94,8 @@ def self.openapi_types :'draw' => :'Boolean', :'phone' => :'Boolean', :'type' => :'Boolean', - :'upload' => :'Boolean' + :'upload' => :'Boolean', + :'force_advanced_signature_details' => :'Boolean' } end @@ -167,6 +173,12 @@ def initialize(attributes = {}) else self.upload = false end + + if attributes.key?(:'force_advanced_signature_details') + self.force_advanced_signature_details = attributes[:'force_advanced_signature_details'] + else + self.force_advanced_signature_details = false + end end # Show invalid properties with the reasons. Usually used together with valid? @@ -208,7 +220,8 @@ def ==(o) draw == o.draw && phone == o.phone && type == o.type && - upload == o.upload + upload == o.upload && + force_advanced_signature_details == o.force_advanced_signature_details end # @see the `==` method @@ -220,7 +233,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [default_type, draw, phone, type, upload].hash + [default_type, draw, phone, type, upload, force_advanced_signature_details].hash end # Builds the object from hash diff --git a/sdks/ruby/lib/dropbox-sign/models/template_edit_response.rb b/sdks/ruby/lib/dropbox-sign/models/sub_update_form_field.rb similarity index 83% rename from sdks/ruby/lib/dropbox-sign/models/template_edit_response.rb rename to sdks/ruby/lib/dropbox-sign/models/sub_update_form_field.rb index 9a4996745..0e9d10732 100644 --- a/sdks/ruby/lib/dropbox-sign/models/template_edit_response.rb +++ b/sdks/ruby/lib/dropbox-sign/models/sub_update_form_field.rb @@ -17,15 +17,20 @@ module Dropbox end module Dropbox::Sign - class TemplateEditResponse - # The id of the Template. + class SubUpdateFormField + # The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found # @return [String] - attr_accessor :template_id + attr_accessor :api_id + + # The new name of the field. If not passed the name will remain unchanged. + # @return [String] + attr_accessor :name # Attribute mapping from ruby-style variable name to JSON key. def self.attribute_map { - :'template_id' => :'template_id' + :'api_id' => :'api_id', + :'name' => :'name' } end @@ -42,7 +47,8 @@ def self.acceptable_attributes # Attribute type mapping. def self.openapi_types { - :'template_id' => :'String' + :'api_id' => :'String', + :'name' => :'String' } end @@ -69,32 +75,36 @@ def self.merged_nullable # Attempt to instantiate and hydrate a new instance of this class # @param [Object] data Data to be converted - # @return [TemplateEditResponse] + # @return [SubUpdateFormField] def self.init(data) ApiClient.default.convert_to_type( data, - "TemplateEditResponse" - ) || TemplateEditResponse.new + "SubUpdateFormField" + ) || SubUpdateFormField.new end # Initializes the object # @param [Hash] attributes Model attributes in the form of hash def initialize(attributes = {}) if (!attributes.is_a?(Hash)) - fail ArgumentError, "The input argument (attributes) must be a hash in `Dropbox::Sign::TemplateEditResponse` initialize method" + fail ArgumentError, "The input argument (attributes) must be a hash in `Dropbox::Sign::SubUpdateFormField` initialize method" end # check to see if the attribute exists and convert string to symbol for hash key acceptable_attribute_map = self.class.acceptable_attribute_map attributes = attributes.each_with_object({}) { |(k, v), h| if (!self.class.merged_attributes.key?(k.to_sym)) - fail ArgumentError, "`#{k}` is not a valid attribute in `Dropbox::Sign::TemplateEditResponse`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + fail ArgumentError, "`#{k}` is not a valid attribute in `Dropbox::Sign::SubUpdateFormField`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect end h[k.to_sym] = v } - if attributes.key?(:'template_id') - self.template_id = attributes[:'template_id'] + if attributes.key?(:'api_id') + self.api_id = attributes[:'api_id'] + end + + if attributes.key?(:'name') + self.name = attributes[:'name'] end end @@ -102,8 +112,8 @@ def initialize(attributes = {}) # @return Array for valid properties with the reasons def list_invalid_properties invalid_properties = Array.new - if @template_id.nil? - invalid_properties.push('invalid value for "template_id", template_id cannot be nil.') + if @api_id.nil? + invalid_properties.push('invalid value for "api_id", api_id cannot be nil.') end invalid_properties @@ -112,18 +122,18 @@ def list_invalid_properties # Check to see if the all the properties in the model are valid # @return true if the model is valid def valid? - return false if @template_id.nil? + return false if @api_id.nil? true end # Custom attribute writer method with validation - # @param [Object] template_id Value to be assigned - def template_id=(template_id) - if template_id.nil? - fail ArgumentError, 'template_id cannot be nil' + # @param [Object] api_id Value to be assigned + def api_id=(api_id) + if api_id.nil? + fail ArgumentError, 'api_id cannot be nil' end - @template_id = template_id + @api_id = api_id end # Checks equality by comparing each attribute. @@ -131,7 +141,8 @@ def template_id=(template_id) def ==(o) return true if self.equal?(o) self.class == o.class && - template_id == o.template_id + api_id == o.api_id && + name == o.name end # @see the `==` method @@ -143,7 +154,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [template_id].hash + [api_id, name].hash end # Builds the object from hash diff --git a/sdks/ruby/templates/api_client_typhoeus_partial.mustache b/sdks/ruby/templates/api_client_typhoeus_partial.mustache index f55f98043..116fd36d7 100644 --- a/sdks/ruby/templates/api_client_typhoeus_partial.mustache +++ b/sdks/ruby/templates/api_client_typhoeus_partial.mustache @@ -87,6 +87,22 @@ end end + # Workaround for the Typhoeus/libcurl multipart PUT bug. + # libcurl only builds a multipart body via CURLOPT_HTTPPOST/CURLOPT_MIMEPOST, + # which is engaged for POST requests. For PUT it falls back to CURLOPT_UPLOAD + # and silently drops form fields, so the request is sent without a + # `Content-Type: multipart/form-data; boundary=...` header or body. + # We send the request as POST so the multipart body is encoded correctly, + # then use CURLOPT_CUSTOMREQUEST (exposed by Ethon as :customrequest) to + # restore PUT as the on-the-wire HTTP verb. + # See: https://github.com/typhoeus/typhoeus/issues/389 + content_type_header = header_params['Content-Type'] || header_params['content-type'] + if http_method == :put && content_type_header.is_a?(String) && + content_type_header.start_with?('multipart/form-data') + req_opts[:method] = :post + req_opts[:customrequest] = 'PUT' + end + Typhoeus::Request.new(url, req_opts) end diff --git a/src/Hello/OpenApi/RawFile.php b/src/Hello/OpenApi/RawFile.php index 0ecfe46a2..fcfa42cc3 100644 --- a/src/Hello/OpenApi/RawFile.php +++ b/src/Hello/OpenApi/RawFile.php @@ -26,8 +26,11 @@ class RawFile * is to be shown. * * e.g. - * x-hideOn: 'SDK' - * x-hideOn: 'DOC' + * x-hideOn: 'sdk' + * x-hideOn: 'doc' + * x-hideOn: + * - sdk + * - doc */ private const HIDE_ON = 'x-hideOn'; @@ -163,10 +166,11 @@ private function recurse(array $data, string $surface_id): TranslationResult foreach ($data as $k => $v) { if (is_iterable($v)) { - if (isset($v[self::HIDE_ON]) && $v[self::HIDE_ON] === $surface_id) { + if (isset($v[self::HIDE_ON]) && $this->shouldHide($v[self::HIDE_ON], $surface_id)) { unset($data[$k]); $empty_by_hiding = empty($data); } else { + unset($v[self::HIDE_ON]); $result = $this->recurse($v, $surface_id); if ($result->isAllHidden()) { unset($data[$k]); @@ -216,6 +220,15 @@ private function recurse(array $data, string $surface_id): TranslationResult return new TranslationResult($data, $empty_by_hiding); } + private function shouldHide($hideOn, string $surface_id): bool + { + if (is_array($hideOn)) { + return in_array($surface_id, $hideOn, true); + } + + return $hideOn === $surface_id; + } + /** * @return array|mixed|void */ diff --git a/test_fixtures/SignatureRequestCreateEmbeddedRequest.json b/test_fixtures/SignatureRequestCreateEmbeddedRequest.json index 16e803706..097446a77 100644 --- a/test_fixtures/SignatureRequestCreateEmbeddedRequest.json +++ b/test_fixtures/SignatureRequestCreateEmbeddedRequest.json @@ -116,7 +116,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "subject": "The NDA we talked about", "test_mode": true, @@ -252,7 +253,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "subject": "The NDA we talked about", "test_mode": true, diff --git a/test_fixtures/SignatureRequestCreateEmbeddedWithTemplateRequest.json b/test_fixtures/SignatureRequestCreateEmbeddedWithTemplateRequest.json index a9597ea64..f997b281e 100644 --- a/test_fixtures/SignatureRequestCreateEmbeddedWithTemplateRequest.json +++ b/test_fixtures/SignatureRequestCreateEmbeddedWithTemplateRequest.json @@ -54,7 +54,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "subject": "Purchase Order", "template_ids": [ diff --git a/test_fixtures/SignatureRequestSendRequest.json b/test_fixtures/SignatureRequestSendRequest.json index 98d12db3b..1f56eb7cc 100644 --- a/test_fixtures/SignatureRequestSendRequest.json +++ b/test_fixtures/SignatureRequestSendRequest.json @@ -229,7 +229,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "signing_redirect_url": "https://example.com/redirect", "subject": "The NDA we talked about", @@ -468,7 +469,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "signing_redirect_url": "https://example.com/redirect", "subject": "The NDA we talked about", diff --git a/test_fixtures/SignatureRequestSendWithTemplateRequest.json b/test_fixtures/SignatureRequestSendWithTemplateRequest.json index 4d1cc8665..df8e207c7 100644 --- a/test_fixtures/SignatureRequestSendWithTemplateRequest.json +++ b/test_fixtures/SignatureRequestSendWithTemplateRequest.json @@ -42,7 +42,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "signing_redirect_url": "https://example.com/redirect", "subject": "Purchase Order", diff --git a/test_fixtures/TemplateUpdateRequest.json b/test_fixtures/TemplateUpdateRequest.json new file mode 100644 index 000000000..9c9afbf33 --- /dev/null +++ b/test_fixtures/TemplateUpdateRequest.json @@ -0,0 +1,18 @@ +{ + "default": { + "title": "Test Title", + "subject": "Test Subject", + "message": "Test Message", + "cc_roles": ["one", "two"], + "form_fields": [ + { + "api_id": "uniqueIdHere_1", + "name": "New name 1" + }, + { + "api_id": "uniqueIdHere_2", + "name": "New name 2" + } + ] + } +} \ No newline at end of file diff --git a/test_fixtures/UnclaimedDraftCreateEmbeddedRequest.json b/test_fixtures/UnclaimedDraftCreateEmbeddedRequest.json index e18890b74..addbe6ac5 100644 --- a/test_fixtures/UnclaimedDraftCreateEmbeddedRequest.json +++ b/test_fixtures/UnclaimedDraftCreateEmbeddedRequest.json @@ -127,7 +127,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "signing_redirect_url": "https://example.com/redirect", "show_progress_stepper": true, diff --git a/test_fixtures/UnclaimedDraftCreateEmbeddedWithTemplateRequest.json b/test_fixtures/UnclaimedDraftCreateEmbeddedWithTemplateRequest.json index 7c7264948..d4f26cd76 100644 --- a/test_fixtures/UnclaimedDraftCreateEmbeddedWithTemplateRequest.json +++ b/test_fixtures/UnclaimedDraftCreateEmbeddedWithTemplateRequest.json @@ -58,7 +58,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "show_progress_stepper": true, "skip_me_now": true, diff --git a/test_fixtures/UnclaimedDraftCreateRequest.json b/test_fixtures/UnclaimedDraftCreateRequest.json index b74d37713..a9ab5b5f4 100644 --- a/test_fixtures/UnclaimedDraftCreateRequest.json +++ b/test_fixtures/UnclaimedDraftCreateRequest.json @@ -114,7 +114,8 @@ "type": true, "upload": true, "phone": false, - "default_type": "draw" + "default_type": "draw", + "force_advanced_signature_details": false }, "signing_redirect_url": "https://example.com/redirect", "subject": "The NDA we talked about", diff --git a/translations/en.yaml b/translations/en.yaml index 77bc3abfa..f32507e4f 100644 --- a/translations/en.yaml +++ b/translations/en.yaml @@ -125,6 +125,8 @@ "EmbeddedEditUrl::SHOW_PROGRESS_STEPPER": When only one step remains in the signature request process and this parameter is set to `false` then the progress stepper will be hidden. "EmbeddedEditUrl::TEMPLATE_ID": The id of the template to edit. "EmbeddedEditUrl::TEST_MODE": Whether this is a test, locked templates will only be available for editing if this is set to `true`. Defaults to `false`. +"EmbeddedEditUrl::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. +"EmbeddedEditUrl::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "EmbeddedSignUrl::SUMMARY": Get Embedded Sign URL "EmbeddedSignUrl::DESCRIPTION": Retrieves an embedded object containing a signature url that can be opened in an iFrame. Note that templates created via the embedded template process will only be accessible through the API. @@ -360,6 +362,8 @@ "SignatureRequestCreateEmbedded::TEST_MODE": Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. "SignatureRequestCreateEmbedded::TITLE": The title you want to assign to the SignatureRequest. "SignatureRequestCreateEmbedded::USE_TEXT_TAGS": Send with a value of `true` if you wish to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document. Defaults to disabled, or `false`. +"SignatureRequestCreateEmbedded::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. +"SignatureRequestCreateEmbedded::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "SignatureRequestEditEmbedded::SUMMARY": Edit Embedded Signature Request "SignatureRequestEditEmbedded::DESCRIPTION": |- @@ -367,6 +371,7 @@ **NOTE:** Edit and resend *will* deduct your signature request quota. "SignatureRequestEditEmbedded::SIGNATURE_REQUEST_ID": The id of the SignatureRequest to edit. +"SignatureRequestEditEmbedded::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. "SignatureRequestCreateEmbeddedWithTemplate::SUMMARY": Create Embedded Signature Request with Template "SignatureRequestCreateEmbeddedWithTemplate::DESCRIPTION": Creates a new SignatureRequest based on the given Template(s) to be signed in an embedded iFrame. Note that embedded signature requests can only be signed in embedded iFrames whereas normal signature requests can only be signed on Dropbox Sign. @@ -385,6 +390,7 @@ "SignatureRequestCreateEmbeddedWithTemplate::TEMPLATE_IDS": Use `template_ids` to create a SignatureRequest from one or more templates, in the order in which the template will be used. "SignatureRequestCreateEmbeddedWithTemplate::TEST_MODE": Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. "SignatureRequestCreateEmbeddedWithTemplate::TITLE": The title you want to assign to the SignatureRequest. +"SignatureRequestCreateEmbeddedWithTemplate::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "SignatureRequestCreateEmbeddedWithTemplate::POPULATE_AUTO_FILL_FIELDS": |- Controls whether [auto fill fields](https://faq.hellosign.com/hc/en-us/articles/360051467511-Auto-Fill-Fields) can automatically populate a signer's information during signing. @@ -487,7 +493,7 @@ Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. "SignatureRequestSend::MESSAGE": The custom message in the email that will be sent to the signers. "SignatureRequestSend::SIGNING_REDIRECT_URL": The URL you want signers redirected to after they successfully sign. "SignatureRequestSend::SUBJECT": The subject in the email that will be sent to the signers. @@ -495,6 +501,8 @@ "SignatureRequestSend::TITLE": The title you want to assign to the SignatureRequest. "SignatureRequestSend::EXPIRES_AT": When the signature request will expire. Unsigned signatures will be moved to the expired status, and no longer signable. See [Signature Request Expiration Date](https://developers.hellosign.com/docs/signature-request/expiration/) for details. "SignatureRequestSend::USE_PREEXISTING_FIELDS": Send with a value of `true` if you wish to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document. Defaults to disabled, or `false`. +"SignatureRequestSend::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. +"SignatureRequestSend::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "SignatureRequestEdit::SUMMARY": Edit Signature Request "SignatureRequestEdit::DESCRIPTION": |- @@ -502,6 +510,7 @@ **NOTE:** Edit and resend *will* deduct your signature request quota. "SignatureRequestEdit::SIGNATURE_REQUEST_ID": The id of the SignatureRequest to edit. +"SignatureRequestEdit::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. "SignatureRequestSendWithTemplate::SUMMARY": Send with Template "SignatureRequestSendWithTemplate::DESCRIPTION": Creates and sends a new SignatureRequest based off of the Template(s) specified with the `template_ids` parameter. @@ -525,13 +534,14 @@ Send with a value of `true` if you wish to enable [electronic identification (eID)](https://www.hellosign.com/features/electronic-id), which requires the signer to verify their identity with an eID provider to sign a document.
- **NOTE:** eID is only available on the Premium API plan. Cannot be used in `test_mode`. Only works on requests with one signer. + **NOTE:** You need the eID add-on to use this feature. Please [contact sales](https://sign.dropbox.com/form/contact-sales) for more information. Cannot be used in `test_mode`. Only works on requests with one signer. "SignatureRequestSendWithTemplate::MESSAGE": The custom message in the email that will be sent to the signers. "SignatureRequestSendWithTemplate::SIGNING_REDIRECT_URL": The URL you want signers redirected to after they successfully sign. "SignatureRequestSendWithTemplate::SUBJECT": The subject in the email that will be sent to the signers. "SignatureRequestSendWithTemplate::TEMPLATE_IDS": Use `template_ids` to create a SignatureRequest from one or more templates, in the order in which the template will be used. "SignatureRequestSendWithTemplate::TEST_MODE": Whether this is a test, the signature request will not be legally binding if set to `true`. Defaults to `false`. "SignatureRequestSendWithTemplate::TITLE": The title you want to assign to the SignatureRequest. +"SignatureRequestSendWithTemplate::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "SignatureRequestEditWithTemplate::SUMMARY": Edit Signature Request With Template "SignatureRequestEditWithTemplate::DESCRIPTION": |- @@ -695,10 +705,16 @@ "TemplateCreateEmbeddedDraft::TEST_MODE": Whether this is a test, the signature request created from this draft will not be legally binding if set to `true`. Defaults to `false`. "TemplateCreateEmbeddedDraft::TITLE": The title you want to assign to the SignatureRequest. "TemplateCreateEmbeddedDraft::USE_PREEXISTING_FIELDS": Enable the detection of predefined PDF fields by setting the `use_preexisting_fields` to `true` (defaults to disabled, or `false`). - +"TemplateCreateEmbeddedDraft::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. +"TemplateCreateEmbeddedDraft::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "TemplateCreate::SUMMARY": Create Template -"TemplateCreate::DESCRIPTION": Creates a template that can then be used. +"TemplateCreate::DESCRIPTION": |- + Creates a template that can be used in future signature requests. + + If `client_id` is provided, the template will be created as an embedded template. Embedded templates can be used for embedded signature requests and can be edited later by generating a new `edit_url` with [/embedded/edit_url/{template_id}](/api/reference/operation/embeddedEditUrl/). + + Template creation may complete asynchronously after the initial request is accepted. It is recommended that a callback be implemented to listen for the callback event. A `template_created` event indicates the template is ready to use, while a `template_error` event indicates there was a problem while creating the template. If a callback handler has been configured and the event has not been received within 60 minutes of making the call, check the status of the request in the API dashboard and retry the request if necessary. "TemplateCreate::ALLOW_CCS": This allows the requester to specify whether the user is allowed to provide email addresses to CC when creating a template. "TemplateCreate::ALLOW_REASSIGN": |- @@ -724,6 +740,8 @@ "TemplateCreate::TEST_MODE": Whether this is a test, the signature request created from this draft will not be legally binding if set to `true`. Defaults to `false`. "TemplateCreate::TITLE": The title you want to assign to the SignatureRequest. "TemplateCreate::USE_PREEXISTING_FIELDS": Enable the detection of predefined PDF fields by setting the `use_preexisting_fields` to `true` (defaults to disabled, or `false`). +"TemplateCreate::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. +"TemplateCreate::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "TemplateDelete::SUMMARY": Delete Template "TemplateDelete::DESCRIPTION": Completely deletes the template specified from the account. @@ -771,6 +789,16 @@ "TemplateRemoveUser::EMAIL_ADDRESS": The id or email address of the Account to remove access to the Template. The account id prevails if both are provided. "TemplateRemoveUser::TEMPLATE_ID": The id of the Template to remove the Account's access to. +"TemplateUpdate::SUMMARY": Update Template +"TemplateUpdate::DESCRIPTION": Update template fields. Every field is optional and the endpoint will only change whatever is provided. The fields not included in the request payload will remain unchanged. +"TemplateUpdate::TEMPLATE_ID": The ID of the template to update. +"TemplateUpdate::CC_ROLES": The CC roles that must be assigned when using the template to send a signature request. +"TemplateUpdate::ALLOW_FORM_VIEW": "The CC roles that must be assigned when using the template to send a signature request. If set to `true` all the form fields on template document must have non-empty names." +"TemplateUpdate::FORM_FIELDS": A list of document form fields to update. The endpoint will not create or remove any fields. Every field must be identified by `api_id`, and the only supported change is renaming the field. +"TemplateUpdate::TITLE": The title you want to assign to the SignatureRequest. +"TemplateUpdate::SUBJECT": The new default template email subject. +"TemplateUpdate::MESSAGE": The new default template email message. + "TemplateUpdateFiles::SUMMARY": Update Template Files "TemplateUpdateFiles::DESCRIPTION": |- Overlays a new file with the overlay of an existing template. The new file(s) must: @@ -821,10 +849,13 @@ "UnclaimedDraftCreate::TYPE": The type of unclaimed draft to create. Use `send_document` to create a claimable file, and `request_signature` for a claimable signature request. If the type is `request_signature` then signers name and email_address are not optional. "UnclaimedDraftCreate::USE_PREEXISTING_FIELDS": Set `use_text_tags` to `true` to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document (defaults to disabled, or `false`). Alternatively, if your PDF contains pre-defined fields, enable the detection of these fields by setting the `use_preexisting_fields` to `true` (defaults to disabled, or `false`). Currently we only support use of either `use_text_tags` or `use_preexisting_fields` parameter, not both. "UnclaimedDraftCreate::USE_TEXT_TAGS": Set `use_text_tags` to `true` to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document (defaults to disabled, or `false`). Alternatively, if your PDF contains pre-defined fields, enable the detection of these fields by setting the `use_preexisting_fields` to `true` (defaults to disabled, or `false`). Currently we only support use of either `use_text_tags` or `use_preexisting_fields` parameter, not both. +"UnclaimedDraftCreate::SIGNER_EXPERIENCE": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "UnclaimedDraftCreate::EXPIRES_AT": |- When the signature request will expire. Unsigned signatures will be moved to the expired status, and no longer signable. See [Signature Request Expiration Date](https://developers.hellosign.com/docs/signature-request/expiration/) for details. **NOTE:** This does not correspond to the **expires_at** returned in the response. +"UnclaimedDraftCreate::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. + "UnclaimedDraftCreateEmbedded::SUMMARY": Create Embedded Unclaimed Draft "UnclaimedDraftCreateEmbedded::DESCRIPTION": |- Creates a new Draft that can be claimed and used in an embedded iFrame. The first authenticated user to access the URL will claim the Draft and will be shown the "Request signature" page with the Draft loaded. Subsequent access to the claim URL will result in a `404`. For this embedded endpoint the `requester_email_address` parameter is required. @@ -875,6 +906,8 @@ When the signature request will expire. Unsigned signatures will be moved to the expired status, and no longer signable. See [Signature Request Expiration Date](https://developers.hellosign.com/docs/signature-request/expiration/) for details. **NOTE:** This does not correspond to the **expires_at** returned in the response. +"UnclaimedDraftCreateEmbedded::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. + "UnclaimedDraftCreateEmbeddedWithTemplate::SUMMARY": Create Embedded Unclaimed Draft with Template "UnclaimedDraftCreateEmbeddedWithTemplate::DESCRIPTION": |- Creates a new Draft with a previously saved template(s) that can be claimed and used in an embedded iFrame. The first authenticated user to access the URL will claim the Draft and will be shown the "Request signature" page with the Draft loaded. Subsequent access to the claim URL will result in a `404`. For this embedded endpoint the `requester_email_address` parameter is required. @@ -1179,6 +1212,7 @@ If `delivery`, a link to complete the signature request is delivered via SMS (_and_ email). +"SignatureRequestSignerExperience::DESCRIPTION": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. "Sub::SignatureRequestTemplateSigner::DESCRIPTION": Add Signers to your Templated-based Signature Request. "Sub::SignatureRequestTemplateSigner::EMAIL_ADDRESS": The email address of the signer. "Sub::SignatureRequestTemplateSigner::NAME": The name of the signer. @@ -1198,18 +1232,32 @@ If `delivery`, a link to complete the signature request is delivered via SMS (_and_ email). +"Sub::SignerExperience::DESCRIPTION": Configuration options for modifying the settings of the signer application. Supports changing the form view behavior. +"Sub::SignerExperience::DEFAULT": |- + Changes the form view setting experienced by the signer. Supported versions are: + - `disabled` - Form view is disabled, and the signer cannot change it + - `enabled` - Form view is disabled initially, the signer can turn it on using a toggle + - `enabled_by_default` - Form view is enabled initially. The signer car turn it off using a toggle + - `forced` - Form view is enabled initially. The signer cannot change it, the toggle is hidden. + "Sub::SignerRole::NAME": The role name of the signer that will be displayed when the template is used to create a signature request. "Sub::SignerRole::ORDER": The order in which this signer role is required to sign. "Sub::SigningOptions::DESCRIPTION": |- - This allows the requester to specify the types allowed for creating a signature. + This allows the requester to specify the types allowed for creating a signature and specify another signing options. **NOTE:** If `signing_options` are not defined in the request, the allowed types will default to those specified in the account settings. + + **NOTE:** If `force_advanced_signature_details` is set, allowed types has to be defined too. "Sub::SigningOptions::DEFAULT": The default type shown (limited to the listed types) "Sub::SigningOptions::DRAW": Allows drawing the signature "Sub::SigningOptions::PHONE": Allows using a smartphone to email the signature "Sub::SigningOptions::TYPE": Allows typing the signature "Sub::SigningOptions::UPLOAD": Allows uploading the signature +"Sub::SigningOptions::FORCE_ADVANCED_SIGNATURE_DETAILS": Turning on advanced signature details for the signature request + +"Sub::UpdateFormField::API_ID": The unique ID for this field. The endpoint will update an existing field with matching `api_id`, and warn you if no matches are found +"Sub::UpdateFormField::NAME": The new name of the field. If not passed the name will remain unchanged. "Sub::UnclaimedDraftSigner::DESCRIPTION": Add Signers to your Unclaimed Draft Signature Request. "Sub::UnclaimedDraftSigner::EMAIL_ADDRESS": The email address of the signer. @@ -1250,6 +1298,7 @@ "Account::LOCALE": The locale used in this Account. Check out the list of [supported locales](/api/reference/constants/#supported-locales) to learn more about the possible values. "Account::QUOTA": Details concerning remaining monthly quotas. "Account::USAGE": Details concerning monthly usage +"Account::SETTINGS": Subset of configured settings "AccountQuota::TEMPLATES_LEFT": API templates remaining. "AccountQuota::TEMPLATES_TOTAL": Total API templates allowed. "AccountQuota::API_SIGNATURE_REQUESTS_LEFT": API signature requests remaining. @@ -1257,6 +1306,9 @@ "AccountQuota::SMS_VERIFICATIONS_LEFT": SMS verifications remaining. "AccountQuota::NUM_FAX_PAGES_LEFT": Number of fax pages left "AccountUsage::FAX_PAGES_SENT": Number of fax pages sent +"AccountSettings::SIGNER_ACCESS_CODES": Returns `true` if _Custom access codes_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). +"AccountSettings::SMS_DELIVERY": Returns `true` if _Text message_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). +"AccountSettings::SMS_AUTHENTICATION": Returns `true` if _Signer authentication_ is enabled in Admin Console. [Read more](https://developers.hellosign.com/docs/sms-tools/walkthrough). "ApiAppCreateResponseExample::SUMMARY": API App "ApiAppGetResponseExample::SUMMARY": API App @@ -1516,6 +1568,7 @@ "TemplateResponse::ACCOUNTS": An array of the Accounts that can use this Template. "TemplateResponse::TITLE": The title of the Template. This will also be the default subject of the message sent to signers when using this Template to send a SignatureRequest. This can be overridden when sending the SignatureRequest. "TemplateResponse::UPDATED_AT": Time the template was last updated. +"TemplateResponse::ALLOW_FORM_VIEW": Allows signers to view the form fields before signing if set to `true`. Defaults to `false`. "TemplateListResponse::DESCRIPTION": List of templates that the API caller has access to. @@ -1818,6 +1871,8 @@ "TemplateList::SEO::DESCRIPTION": "The Dropbox Sign API easily allows you to build custom integrations. To find out how to return a list of the Templates that can be accessed by you, click here." "TemplateRemoveUser::SEO::TITLE": "Remove User from Template | REST API | Dropbox Sign for Developers" "TemplateRemoveUser::SEO::DESCRIPTION": "The Dropbox Sign API easily allows you to build custom integrations. To find out how to remove a specified Account's access to a Template, click here." +"TemplateUpdate::SEO::TITLE": "Update Template | REST API | Dropbox Sign for Developers" +"TemplateUpdate::SEO::DESCRIPTION": "The Dropbox Sign API easily allows you to build custom integrations. To find out how to update properties of an existing template, click here." "TemplateUpdateFiles::SEO::TITLE": "Update Template Files | REST API | Dropbox Sign for Developers" "TemplateUpdateFiles::SEO::DESCRIPTION": "Overlays a new file with the overlay of an existing template" "UnclaimedDraftCreate::SEO::TITLE": "Create Unclaimed Draft | REST API | Dropbox Sign for Developers"