diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml
new file mode 100644
index 00000000..c2940bc4
--- /dev/null
+++ b/.github/workflows/python.yml
@@ -0,0 +1,47 @@
+# This workflow will install Python dependencies, run tests and lint with a single version of Python
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
+
+name: Python CI
+
+on:
+ push:
+ branches: [ "master" ]
+ pull_request:
+ branches: [ "master" ]
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Python 3.10
+ uses: actions/setup-python@v3
+ with:
+ python-version: "3.10"
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install flake8 pytest
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+
+ - name: Lint with flake8
+ run: flake8
+
+ - name: Write private key
+ run: |
+ echo '${{ secrets.PRIVATE_KEY }}' >> app/private.key
+ cp app/ds_config_sample.py app/ds_config.py
+
+ - name: Test with pytest
+ run: pytest
+ env:
+ CLIENT_ID: '${{ secrets.CLIENT_ID }}'
+ USER_ID: '${{ secrets.USER_ID }}'
+ SIGNER_EMAIL: '${{ secrets.SIGNER_EMAIL }}'
+ SIGNER_NAME: '${{ secrets.SIGNER_NAME }}'
diff --git a/.gitignore b/.gitignore
index f9991199..101b3e4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-app/ds_config*
+app/ds_config.py
*/.DS_Store
.DS_Store
@@ -119,3 +119,10 @@ fabric.properties
# Security key files
private.key
+
+# Current flask session
+
+flask_session/
+
+# Workflow ID file
+WORKFLOW_ID.txt
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..0f292b31
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,19 @@
+# start by pulling the python image
+FROM python:3.11.9-slim-bullseye
+
+# copy the requirements file into the image
+COPY ./requirements.txt /app/requirements.txt
+
+# switch working directory
+WORKDIR /app
+
+# install the dependencies and packages in the requirements file
+RUN pip install -r requirements.txt
+
+# copy every content from the local file to the image
+COPY . /app
+
+# configure the container to run in an executed manner
+ENTRYPOINT [ "python" ]
+
+CMD ["run.py", "--docker"]
diff --git a/PAYMENTS_INSTALLATION.md b/PAYMENTS_INSTALLATION.md
index bfd85dcb..de789f93 100644
--- a/PAYMENTS_INSTALLATION.md
+++ b/PAYMENTS_INSTALLATION.md
@@ -1,24 +1,21 @@
-# Configuring a DocuSign payments gateway
+# Configure a payment gateway
-DocuSign offers built-in connections to multiple payment
-gateways. The payments example uses a demo account via the Stripe
-gateway service.
+DocuSign offers built-in connections to multiple payment gateways. The payments code example uses a developer account via the Stripe gateway service.
-## Creating the payments gateway account
-1. Login to demo.docusign.net and go to the Admin Tool.
-1. On the Integrations / Payments screen, click Stripe.
-1. For development, you can skip the Stripe account application
- by using the `Skip this account form` link:
+## Create a Stripe payment gateway
+
+1. Select the Stripe button on the [**Payments**](https://admindemo.docusign.com/authenticate?goTo=payments) page in your developer account.
+
+1. For development, you can skip the Stripe account application by using the **Skip this account form** link at the top of the page.
+
+ 
+
+ An enabled Stripe payment gateway is now associated with your Docusign developer account and is shown under **Payment Gateway**.
+
+1. Save the **Gateway Account ID** GUID to the code example launcher configuration file.
- 
-1. Next, the Admin Tool will show that an enabled Stripe
- payment gateway account has been associated with your
- DocuSign Developer account.
-1. Configure the example launcher with the gateway account id shown in the Admin tool.
## Additional documentation
-See the
-[Managing Payment Gateways](https://support.docusign.com/en/guides/managing-payment-gateways)
-documentation.
-
+* [Managing Payment Gateways](https://support.docusign.com/en/guides/managing-payment-gateways)
+* [How to send a request for payment](https://developers.docusign.com/docs/esign-rest-api/how-to/request-a-payment)
diff --git a/Pipfile.lock b/Pipfile.lock
index 1fc79f49..983cd83b 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -18,10 +18,11 @@
"default": {
"certifi": {
"hashes": [
- "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
- "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
+ "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
+ "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
],
- "version": "==2019.3.9"
+ "index": "pypi",
+ "version": "==2022.12.7"
},
"chardet": {
"hashes": [
@@ -47,10 +48,11 @@
},
"urllib3": {
"hashes": [
- "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
- "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
+ "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4",
+ "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"
],
- "version": "==1.24.2"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'",
+ "version": "==1.24.3"
}
},
"develop": {}
diff --git a/README.md b/README.md
index fa4497da..dfe22f92 100644
--- a/README.md
+++ b/README.md
@@ -1,290 +1,203 @@
# Python Launcher Code Examples
-### Github repo: [code-examples-python](./)
+>
+>### PLEASE! Share your feedback in a [two-question survey](https://docs.google.com/forms/d/e/1FAIpQLScPa74hwhJwi7XWDDj4-XZVOQTF9jJWgbIFEpulXokCqYWT4A/viewform?usp=pp_url&entry.680551577=Python).
+>
+>
+### GitHub repo: [code-examples-python](./README.md)
-This GitHub repo includes code examples for DocuSign APIs.
+If you downloaded this project using the [Quickstart](https://developers.docusign.com/docs/esign-rest-api/quickstart/) tool, it may be configured in one of three ways:
-To switch between API code examples, modify the EXAMPLES_API_TYPE setting at the end of the configuration file. Set only one API type to true and set the remaining to false.
+* **[JWT Grant remote signing example](#jwt-grant-remote-signing-example)**–demonstrates how to implement JSON Web Token authentication. It includes a single remote signing workflow.
+* **[Authorization Code Grant embedded signing example](#authorization-code-grant-embedded-signing-example)**–demonstrates how to implement Authorization Code Grant authentication. It includes a single embedded signing workflow.
+* **[Multiple code examples, Authorization Code Grant and JWT Grant](#installation-steps)**–includes the full range of examples and authentication types.
+
+***Installation and running instructions vary depending on the configuration. Follow the link that matches your project type to get started.***
+
+This GitHub repo includes code examples for the [Web Forms API](https://developers.docusign.com/docs/web-forms-api/), [Docusign Admin API](https://developers.docusign.com/docs/admin-api/), [Click API](https://developers.docusign.com/docs/click-api/), [eSignature REST API](https://developers.docusign.com/docs/esign-rest-api/), [Monitor API](https://developers.docusign.com/docs/monitor-api/), and [Rooms API](https://developers.docusign.com/docs/rooms-api/).
-If none of the API types are set to true, the DocuSign eSignature REST API code examples will be shown. If multiple API types are set to true, only the first will be shown.
-**Note:** to use the Rooms API you must also [create your DocuSign Developer Account for Rooms](https://developers.docusign.com/docs/rooms-api/rooms101/create-account).
## Introduction
-This repo is a Python 3 application that demonstrates:
+
+This repo is a Python 3 application that supports the following authentication workflows:
+
+* Authentication with Docusign via [Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode).
+When the token expires, the user is asked to re-authenticate. The refresh token is not used.
+
+* Authentication with Docusign via [JSON Web Token (JWT) Grant](https://developers.docusign.com/platform/auth/jwt/).
+When the token expires, it updates automatically.
## eSignature API
-1. **Use embedded signing.**
- [Source.](./app/eg001_embedded_signing/controller.py)
- This example sends an envelope, and then uses embedded signing for the first signer.
- With embedded signing, the DocuSign signing is initiated from your website.
-1. **Request a signature by email (Remote Signing).**
- [Source.](./app/eSignature/examples/eg002_signing_via_email/controller.py)
- The envelope includes a pdf, Word, and HTML document.
- Anchor text ([AutoPlace](https://support.docusign.com/en/guides/AutoPlace-New-DocuSign-Experience)) is used to position the signing fields in the documents.
-1. **List envelopes in the user's account.**
- [Source.](./app/eSignature/examples/eg003_list_envelopes/controller.py)
- The envelopes' current status is included.
-1. **Get an envelope's basic information.**
- [Source.](./app/eSignature/examples/eg004_envelope_info/controller.py)
- The example lists the basic information about an envelope, including its overall status.
-1. **List an envelope's recipients**
- [Source.](./app/eSignature/examples/eg005_envelope_recipients/controller.py)
- Includes current recipient status.
-1. **List an envelope's documents.**
- [Source.](./app/eSignature/examples/eg006_envelope_docs/controller.py)
-1. **Download an envelope's documents.**
- [Source.](./app/eSignature/examples/eg007_envelope_get_doc/controller.py)
- The example can download individual
- documents, the documents concatenated together, or a zip file of the documents.
-1. **Programmatically create a template.**
- [Source.](./app/eSignature/examples/eg008_create_template/controller.py)
-1. **Request a signature by email using a template.**
- [Source.](./app/eSignature/examples/eg009_use_template/controller.py)
-1. **Send an envelope and upload its documents with multipart binary transfer.**
- [Source.](./app/eSignature/examples/eg010_send_binary_docs/controller.py)
- Binary transfer is 33% more efficient than using Base64 encoding.
-1. **Use embedded sending.**
- [Source.](./app/eSignature/examples/eg011_embedded_sending/controller.py)
- Embeds the DocuSign web tool (NDSE) in your web app to finalize or update
- the envelope and documents before they are sent.
-1. **Embedded DocuSign web tool (NDSE).**
- [Source.](./app/eSignature/examples/eg012_embedded_console/controller.py)
-1. **Use embedded signing from a template with an added document.**
- [Source.](./app/eSignature/examples/eg013_add_doc_to_template/controller.py)
- This example sends an envelope based on a template.
- In addition to the template's document(s), the example adds an
- additional document to the envelope by using the
- [Composite Templates](https://developers.docusign.com/esign-rest-api/guides/features/templates#composite-templates)
- feature.
-1. **Payments example: an order form, with online payment by credit card.**
- [Source.](./app/eSignature/examples/eg014_collect_payment/controller.py)
-1. **Get the envelope tab data.**
- Retrieve the tab (field) values for all of the envelope's recipients.
- [Source.](./app/eSignature/examples/eg015_envelope_tab_data/controller.py)
-1. **Set envelope tab values.**
- The example creates an envelope and sets the initial values for its tabs (fields). Some of the tabs
- are set to be read-only, others can be updated by the recipient. The example also stores
- metadata with the envelope.
- [Source.](./app/eSignature/examples/eg016_set_tab_values/controller.py)
-1. **Set template tab values.**
- The example creates an envelope using a template and sets the initial values for its tabs (fields).
- The example also stores metadata with the envelope.
- [Source.](./app/eSignature/examples/eg017_set_template_tab_values/controller.py)
-1. **Get the envelope custom field data (metadata).**
- The example retrieves the custom metadata (custom data fields) stored with the envelope.
- [Source.](./app/eSignature/examples/eg018_envelope_custom_field_data/controller.py)
-1. **Requiring an Access Code for a Recipient**
- [Source.](./app/eSignature/examples/eg019_access_code_authentication/controller.py)
- This example sends an envelope that requires an access-code for the purpose of multi-factor authentication.
-1. **Requiring SMS authentication for a recipient**
- [Source.](./app/eSignature/examples/eg020_sms_authentication/controller.py)
- This example sends an envelope that requires entering in a six digit code from an text message for the purpose of multi-factor authentication.
-1. **Requiring Phone authentication for a recipient**
- [Source.](./app/eSignature/examples/eg021_phone_authentication/controller.py)
- This example sends an envelope that requires entering in a voice-based response code for the purpose of multi-factor authentication.
-1. **Requiring Knowledge-Based Authentication (KBA) for a Recipient**
- [Source.](./app/eSignature/examples/eg022_kba_authentication/controller.py)
- This example sends an envelope that requires passing a Public records check to validate identity for the purpose of multi-factor authentication.
-1. **Requiring ID Verification (IDV) for a recipient**
- [Source.](./app/eSignature/examples/eg023_idv_authentication/controller.py)
- This example sends an envelope that requires submitting a photo of a government issued id for the purpose of multi-factor authentication.
-1. **Creating a permission profile**
- [Source.](./app/eSignature/examples/eg024_permissions_creating/controller.py)
- This code example demonstrates how to create a permission profile using the [Create Permission Profile](https://developers.docusign.com/esign-rest-api/reference/Accounts/AccountPermissionProfiles/create) method.
-1. **Setting a permission profile**
- [Source.](./app/eSignature/examples/eg025_permissions_set_user_group/controller.py)
- This code example demonstrates how to set a user group’s permission profile using the [Update Group](https://developers.docusign.com/esign-rest-api/reference/UserGroups/Groups/update) method.
- You must have already created the permissions profile and the group of users.
-1. **Updating individual permission settings**
- [Source.](./app/eSignature/examples/eg026_permissions_change_single_setting/controller.py)
- This code example demonstrates how to edit individual permission settings on a permissions profile using the [Update Permission Profile](https://developers.docusign.com/esign-rest-api/reference/Accounts/AccountPermissionProfiles/update) method.
-1. **Deleting a permission profile**
- [Source.](./app/eSignature/examples/eg027_permissions_delete/controller.py)
- This code example demonstrates how to delete a permission profile using the [Delete Permission Profile](https://developers.docusign.com/esign-rest-api/reference/Accounts/AccountPermissionProfiles/create) method.
-1. **Creating a brand**
- [Source.](./app/eSignature/examples/eg028_brand_creating/controller.py)
- This example creates brand profile for an account using the [Create Brand](https://developers.docusign.com/esign-rest-api/reference/Accounts/AccountBrands/create) method.
-1. **Applying a brand to an envelope**
- [Source.](./app/eSignature/examples/eg029_brands_apply_to_envelope/controller.py)
- This code example demonstrates how to apply a brand you've created to an envelope using the [Create Envelope](https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/create) method.
- First, creates the envelope and then applies the brand to it.
- Anchor text ([AutoPlace](https://support.docusign.com/en/guides/AutoPlace-New-DocuSign-Experience)) is used to position the signing fields in the documents.
-1. **Applying a brand to a template**
- [Source.](./app/eSignature/examples/eg030_brands_apply_to_template/controller.py)
- This code example demonstrates how to apply a brand you've created to a template using the [Create Envelope](https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/create) method.
- You must have already created the template and the brand.
- Anchor text ([AutoPlace](https://support.docusign.com/en/guides/AutoPlace-New-DocuSign-Experience)) is used to position the signing fields in the documents.
-1. **Bulk sending envelopes to multiple recipients**
- [Source.](./app/eSignature/examples/eg031_bulk_send/controller.py)
- This code example demonstrates how to send envelopes in bulk to multiple recipients using these methods:
- [Create Bulk Send List](https://developers.docusign.com/esign-rest-api/reference/BulkEnvelopes/BulkSend/createBulkSendList),
- [Create Bulk Send Request](https://developers.docusign.com/esign-rest-api/reference/BulkEnvelopes/BulkSend/createBulkSendRequest).
- Firstly, creates a bulk send recipients list, and then creates an envelope.
- After that, initiates bulk envelope sending.
-1. **Pausing a signature workflow**
- [Source.](./app/eSignature/examples/eg032_pause_signature_workflow/controller.py)
- This code example demonstrates how to create an envelope where the workflow is paused before the envelope is sent to a second recipient using the [Create Envelope](https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/create) method.
-1. **Unpausing a signature workflow**
- [Source.](./app/eSignature/examples/eg033_unpause_signature_workflow/controller.py)
- This code example demonstrates how to update an envelope to resume the workflow that has been paused using the [Update Envelope](https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/update) method.
- You must have created at least one envelope with a paused signature workflow to run this example.
-1. **Using conditional recipients**
- [Source.](./app/eSignature/examples/eg034_use_conditional_recipients/controller.py)
- This code example demonstrates how to create an envelope where the workflow is routed to different recipients based on the value of a transaction using the [Create Envelope](https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/create) method.
-1. **Request a signature by SMS delivery**
- [Source.](./app/eSignature/examples/eg035_sms_delivery/controller.py)
- This code example demonstrates how to send a signature request via an SMS message using the [Envelopes: create](https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/create) method.
-
-
-## Rooms API
-**Note:** to use the Rooms API you must also [create your DocuSign Developer Account for Rooms](https://developers.docusign.com/docs/rooms-api/rooms101/create-account). Examples 4 and 6 require that you have the [DocuSign Forms feature](https://developers.docusign.com/docs/rooms-api/rooms101/using-forms-in-a-room) enabled in your Rooms for Real Estate account.
-
-1. **Create a room with data.**
-[Source.](./app/rooms/examples/eg001_create_room_with_data/controller.py)
-This example creates a new room in your DocuSign Rooms account to be used for a transaction.
-1. **Create a room from a template.**
-[Source.](./app/rooms/examples/eg002_create_room_with_template/controller.py)
-This example creates a new room using a template.
-1. **Create a room with Data.**
-[Source.](./app/rooms/examples/eg003_export_data_from_room/controller.py)
-This example exports all the available data from a specific room in your DocuSign Rooms account.
-1. **Add forms to a room.**
-[Source.](./app/rooms/examples/eg004_add_forms_to_room/controller.py)
-This example adds a standard real estate related form to a specific room in your DocuSign Rooms account.
-1. **How to search for rooms with filters.**
-[Source.](./app/rooms/examples/eg005_get_rooms_with_filters/controller.py)
-This example demonstrates how to return rooms that have had their field data,
-updated within the time period between Start date and End date.
-1. **Create an external form fillable session.**
-[Source.](./app/rooms/examples/eg006_create_external_form_fill_session/controller.py)
-This example demonstrates how to create an
-external form fill session
-using the Rooms API:
-the result of this code example is the URL for the form fill session, which you can embed
-in your integration or send to the user.
-1. **Create a form group**
-[Source.](./app/rooms/examples/eg007_create_form_group/controller.py)
-This example demonstrates creating a DocuSign Form Group.
-1. **Grant office access to a form group**
-[Source.](./app/rooms/examples/eg008_grant_office_access_to_form_group/controller.py)
-This example demonstrates how to grant Office access to a Form Group.
-1. **Assign a form to a form group**
-[Source.](./app/rooms/examples/eg009_assign_form_to_form_group/controller.py)
-This example demonstrates how to assign a form to a form group.
-
-## Click API
-
-1. **Create a clickwrap.**
-[Source.](./app/click/examples/eg001_create_clickwrap/controller.py)
-This example demonstrates how to use DocuSign Click to create a clickwrap that you can embed in your website or app.
-1. **Activate a clickwrap.**
-[Source.](./app/click/examples/eg002_activate_clickwrap/controller.py)
-This example demonstrates how to use DocuSign Click to activate a new clickwrap that you have already created.
-1. **Create a new clickwrap version.**
-[Source.](./app/click/examples/eg005_create_new_clickwrap_version/controller.py)
-This example demonstrates how to use DocuSign Click to create a new version of a clickwrap.
-1. **Get a list of clickwraps.**
-This example demonstrates how to use DocuSign Click to get a list of clickwraps associated with a specific DocuSign user.
-[Source.](./app/click/examples/eg006_list_clickwraps/controller.py)
-1. **Get clickwrap responses.**
-This example demonstrates how to use DocuSign Click to get user responses to your clickwrap agreements.
-[Source.](./app/click/examples/eg007_clickwrap_responses/controller.py)
+For more information about the scopes used for obtaining authorization to use the eSignature API, see [Required scopes](https://developers.docusign.com/docs/esign-rest-api/esign101/auth#required-scopes).
+
+For a list of code examples that use the eSignature API, see the [How-to guides overview](https://developers.docusign.com/docs/esign-rest-api/how-to/) on the Docusign Developer Center.
+
+
+## Rooms API
+
+**Note:** To use the Rooms API, you must also [create your Rooms developer account](https://developers.docusign.com/docs/rooms-api/rooms101/create-account). Examples 4 and 6 require that you have the Docusign Forms feature enabled in your Rooms for Real Estate account.
+For more information about the scopes used for obtaining authorization to use the Rooms API, see [Required scopes](https://developers.docusign.com/docs/rooms-api/rooms101/auth/).
+
+For a list of code examples that use the Rooms API, see the [How-to guides overview](https://developers.docusign.com/docs/rooms-api/how-to/) on the Docusign Developer Center.
+
+
+## Click API
+For more information about the scopes used for obtaining authorization to use the Click API, see [Required scopes](https://developers.docusign.com/docs/click-api/click101/auth/#required-scopes)
+
+For a list of code examples that use the Click API, see the [How-to guides overview](https://developers.docusign.com/docs/click-api/how-to/) on the Docusign Developer Center.
+
## Monitor API
-1. **Get monitor data.**
-[Source.](./app/monitor/examples/eg001_get_monitoring_data/controller.py)
-This example demonstrates how to get and display all of your organization’s monitoring data.
-## Included OAuth grant types:
+**Note:** To use the Monitor API, you must also [enable Docusign Monitor for your organization](https://developers.docusign.com/docs/monitor-api/how-to/enable-monitor/).
-* Authentication with Docusign via [Authorization Code Grant flow](https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-code-grant) .
-When the token expires, the user is asked to re-authenticate.
-The **refresh token** is not used in this example.
+For information about the scopes used for obtaining authorization to use the Monitor API, see the [scopes section](https://developers.docusign.com/docs/monitor-api/monitor101/auth/).
-* Authentication with DocuSign via the [JSON Web Token (JWT) Grant](https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-jsonwebtoken).
-When the token expires, it updates automatically.
+For a list of code examples that use the Monitor API, see the [How-to guides overview](https://developers.docusign.com/docs/monitor-api/how-to/) on the Docusign Developer Center.
+
+
+## Admin API
+
+**Note:** To use the Admin API, you must [create an organization](https://support.docusign.com/en/guides/org-admin-guide-create-org) in your Docusign developer account. Also, to run the Docusign CLM code example, [CLM must be enabled for your organization](https://support.docusign.com/en/articles/DocuSign-and-SpringCM).
+
+For information about the scopes used for obtaining authorization to use the Admin API, see the [scopes section](https://developers.docusign.com/docs/admin-api/admin101/auth/).
+For a list of code examples that use the Admin API, see the [How-to guides overview](https://developers.docusign.com/docs/admin-api/how-to/) on the Docusign Developer Center.
+
+
+## Web Forms API
+
+The Web Forms API is available in all developer accounts, but only in certain production account plans. Contact [Docusign Support](https://support.docusign.com/) or your account manager to find out whether the Web Forms API is available for your production account plan.
+
+For more information about the scopes used for obtaining authorization to use the Rooms API, see [Required scopes](https://developers.docusign.com/docs/web-forms-api/plan-integration/authentication/).
+
+For a list of code examples that use the Web Forms API, see the [How-to guides overview](https://developers.docusign.com/docs/web-forms-api/how-to/) on the Docusign Developer Center.
## Installation
### Prerequisites
-**Note: If you downloaded this code using Quickstart from the DocuSign Developer Center, skip steps 1 and 2 below as they're automatically performed for you.**
+**Note:** If you downloaded this code using [Quickstart](https://developers.docusign.com/docs/esign-rest-api/quickstart/) from the Docusign Developer Center, skip items 1 and 2 as they were automatically performed for you.
-1. A DocuSign Developer account (email and password) on [demo.docusign.net](https://demo.docusign.net).
- Create a [free account](https://go.docusign.com/sandbox/productshot/?elqCampaignId=16535).
-1. A DocuSign Integration Key (a client ID). To use Authorization code grant, you will need the **Integration Key** itself, and its **secret**. To use JSON Web token, you will need the **Integration Key** itself, the **RSA Secret Key** and an API user ID for the user you are impersonating.
+1. A free [Docusign developer account](https://go.docusign.com/o/sandbox/); create one if you don't already have one.
+1. A Docusign app and integration key that is configured to use either [Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode/) or [JWT Grant](https://developers.docusign.com/platform/auth/jwt/) authentication.
- If you use this example on your own workstation,
- the Integration key must include a **Redirect URI** of `http://localhost:5000/ds/callback`
+ This [video](https://www.youtube.com/watch?v=eiRI4fe5HgM) demonstrates how to obtain an integration key.
+
+ To use [Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode/), you will need an integration key and a secret key. See [Installation steps](#installation-steps) for details.
+
+ To use [JWT Grant](https://developers.docusign.com/platform/auth/jwt/), you will need an integration key, an RSA key pair, and the User ID GUID of the impersonated user. See [Installation steps for JWT Grant authentication](#installation-steps-for-jwt-grant-authentication) for details.
- If you will not be running the example on your own workstation,
- use the appropriate DNS name and port instead of `localhost`
+ For both authentication flows:
+
+ If you use this launcher on your own workstation, the integration key must include a redirect URI of http://localhost:3000/ds/callback
+
+ If you host this launcher on a remote web server, set your redirect URI as
+
+ {base_url}/ds/callback
- This [**video**](https://www.youtube.com/watch?v=eiRI4fe5HgM)
- demonstrates how to create an Integration Key (client id) for a
- user application like this example. Note that the redirect url for your
- Integration Key will be `http://localhost:5000/ds/callback` if you
- use the default Python settings.
+ where {base_url} is the URL for the web app.
1. Python 3.
-1. A name and email for a signer, and a name and email for a cc recipient.
+1. If you are working on a Windows with a Python version after 3.10 you will also need to install [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022). After installing that run `pip install --upgrade setuptools`.
### Installation steps
-**Note: If you downloaded this code using Quickstart from the DocuSign Developer Center, skip steps 4 and 5 below as they're automatically performed for you.**
-1. Extract the Quickstart ZIP file or download or clone the **code-examples-python** repo.
-1. Switch to the folder: **cd ** or **cd code-examples-python**
-1. **pip3 install -r requirements.txt** (or pipenv can be used)
-1. Make a copy of the **app/ds_config_sample.py** and name it **ds_config.py**
-1. Update this new file **app/ds_config.py**
- with your Integration Key and other settings.
+**Note:** If you downloaded this code using [Quickstart](https://developers.docusign.com/docs/esign-rest-api/quickstart/) from the Docusign Developer Center, skip step 4 as it was automatically performed for you.
- **Note:** Protect your Integration Key and secret--you
- should ensure that ds_config.py file will not be stored in your source code
- repository.
+1. Extract the Quickstart ZIP file or download or clone the code-examples-python repository.
+1. In your command-line environment, switch to the folder:
+ `cd ` or `cd code-examples-python`
+1. To install dependencies, run: `pip3 install -r requirements.txt` (or pipenv can be used)
+1. To configure the launcher for [Authorization Code Grant](https://developers.docusign.com/platform/auth/authcode/) authentication, create a copy of the file app/ds_config_sample.py and save the copy as app/ds_config.py.
+ 1. Add your integration key. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **Apps and Integration Keys**, choose the app to use, then select **Actions > Edit**. Under **General Info**, copy the **Integration Key** GUID and save it in ds_config.py as your `ds_client_id`.
+ 1. Generate a secret key, if you don’t already have one. Under **Authentication**, select **+ ADD SECRET KEY**. Copy the secret key and save it in ds_config.py as your `ds_client_secret`.
+ 1. Add the launcher’s redirect URI. Under **Additional settings**, select **+ ADD URI**, and set a redirect URI of http://localhost:3000/ds/callback. Select **SAVE**.
+ 1. Set a name and email address for the signer. In ds_config.py, save an email address as `signer_email` and a name as `signer_name`.
+**Note:** Protect your personal information. Please make sure that ds_config.py will not be stored in your source code repository.
+1. Run the launcher:`python run.py`
+ **Note:** You will need to alias the python command to run Python 3 or use `python3 run.py`
+1. Open a browser to http://localhost:3000
-1. **python run.py**
+### Installation steps with docker
- **Note:** You will need to alias the python command to run Python 3 or use **python3 run.py**
-
-1. Open a browser to **http://localhost:5000**
+**Note**: Running the launcher with docker will use Python 3.11
+
+1. Open the Docker application
+1. `docker image build -t docusign .`
+1. `docker run --name docusign_python -p 3000:3000 -d docusign`
+1. Open a browser to http://localhost:3000
+
+### Installation steps for JWT Grant authentication
+
+**Note:** If you downloaded this code using [Quickstart](https://developers.docusign.com/docs/esign-rest-api/quickstart/) from the Docusign Developer Center, skip step 4 as it was automatically performed for you.
+Also, in order to select JSON Web Token authentication in the launcher, in app/ds_config.py, change the `quickstart` setting to `"false"`.
+
+1. Extract the Quickstart ZIP file or download or clone the code-examples-python repository.
+1. In your command-line environment, switch to the folder: `cd ` or `cd code-examples-python`
+1. To install dependencies, run: `pip3 install -r requirements.txt` (or pipenv can be used)
+1. To configure the launcher for [JWT Grant](https://developers.docusign.com/platform/auth/jwt/) authentication, create a copy of the file app/ds_config_sample.py and save the copy as app/ds_config.py.
+ 1. Add your User ID. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **My Account Information**, copy the **User ID** GUID and save it in ds_config.py as your `ds_impersonated_user_id`.
+ 1. Add your integration key. On the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=apiIntegratorKey) page, under **Apps and Integration Keys**, choose the app to use, then select **Actions > Edit**. Under **General Info**, copy the **Integration Key** GUID and save it in ds_config.py as your `ds_client_id`.
+ 1. Generate an RSA key pair, if you don’t already have one. Under **Authentication**, select **+ GENERATE RSA**. Copy the private key, and save it in a new file named app/private.key.
+ 1. Add the launcher’s redirect URI. Under **Additional settings**, select **+ ADD URI**, and set a redirect URI of http://localhost:3000/ds/callback. Select **SAVE**.
+ 1. Set a name and email address for the signer. In ds_config.py, save an email address as `signer_email` and a name as `signer_name`.
+**Note:** Protect your personal information. Please make sure that your ds_config.py and private.key files will not be stored in your source code repository.
+1. Run the launcher:`python run.py`
+ **Note:** You will need to alias the python command to run Python 3 or use `python3 run.py`
+1. Open a browser to http://localhost:3000
+1. On the black navigation bar, select **Login**.
+1. From the picklist, select **JSON Web Token** > **Authenticate with Docusign**.
+1. When prompted, log in to your Docusign developer account. If this is your first time using the app, select **ACCEPT** at the consent window.
+1. Select your desired code example.
+
+
+## JWT grant remote signing and Authorization Code Grant embedded signing projects
+
+See [Docusign Quickstart overview](https://developers.docusign.com/docs/esign-rest-api/quickstart/overview/) on the Docusign Developer Center for more information on how to run the JWT grant remote signing project and the Authorization Code Grant embedded signing project.
+
+### Authorization Code Grant embedded signing example:
+Run in Git Bash:
+```
+$ cd
+$ pip install -r requirements.txt
+$ python3 -m app.quick_acg.run
+```
-### Configuring JWT
+Open a browser to http://localhost:3000
-1. Create a developer account on developers.docusign.com if you don't already have one.
-2. Create a new API key in the Admin panel: https://admindemo.docusign.com/api-integrator-key, take note of the public key.
-3. Set a redirect URI of `http://localhost:5000/ds/callback` as mentioned in the installation steps above for the API key you make in step 2.
-4. Generate an RSA keypair in the administrator console on the DocuSign developer account and copy the private key to a secure location.
-5. Create a new file in your repo source folder named **private.key**, and paste in that copied RSA private key, then save it.
-6. Update the file **app/ds_config.py** and include the newly created API key from step 2 as well as your account user id GUID which is also found on the Admin panel: `https://admindemo.docusign.com/api-integrator-key`.
+### JWT grant remote signing example:
+Run in Windows Command Prompt (CMD):
+```
+$ cd
+$ python3 jwt_console.py
+```
-From there you should be able to run the launcher using **python run.py** then selecting **JSON Web Token** when authenticaing your account.
+### Installation steps for JWT grant remote signing example
-#### Payments code example
-To use the payments example, create a
-test payments gateway for your developer account.
+Follow the instructions below if you downloaded the JWT grant remote signing example.
-See the
-[PAYMENTS_INSTALLATION.md](https://github.com/docusign/code-examples-python/blob/master/PAYMENTS_INSTALLATION.md)
-file for instructions.
+1. Extract the Quickstart ZIP file or download or clone the code-examples-python repository.
+1. Run the JWT console project: `python jwt_console.py`. If you do not already have the docusign-esign package, it will be
+ installed for you when you start the project.
+ **Note:** You will need to alias the python command to run Python 3 or use `python3 run.py`
+1. Follow the prompts from the command line to grant consent in your browser.
+1. Return to the command line and follow the prompts to enter the names and email addresses of your recipients.
+1. Check your email to sign the example document.
-Then add the payment gateway account id to the **app/ds_config.py** file.
+## Payments code example
+To use the payments code example, create a test payment gateway on the [Payments](https://admindemo.docusign.com/authenticate?goTo=payments) page in your developer account. See [Configure a payment gateway](./PAYMENTS_INSTALLATION.md) for details.
-## License and additional information
+Once you've created a payment gateway, save the **Gateway Account ID** GUID to ds_config.py.
-### Implicit Grant
-The examples in this repository can also be used with the
-Implicit Grant OAuth flow.
-See the [Authentication guide](https://developers.docusign.com/esign-rest-api/guides/authentication)
-for information on choosing the right authentication flow for your application.
+## License and additional information
-### License
-This repository uses the MIT License. See the LICENSE file for more information.
+### License
+This repository uses the MIT License. See [LICENSE](./LICENSE) for details.
### Pull Requests
Pull requests are welcomed. Pull requests will only be considered if their content
diff --git a/app/__init__.py b/app/__init__.py
index fbb195a6..2f38180a 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -1,106 +1,135 @@
-import os
-
-from flask import Flask
-from flask_wtf.csrf import CSRFProtect
-
-from .ds_config import DS_CONFIG
-from .eSignature import examples
-from .docusign.views import ds
-from .ds_config import EXAMPLES_API_TYPE
-from .rooms import examples as rooms_examples
-from .click import examples as click_examples
-from .monitor import examples as monitor_examples
-from .views import core
-
-session_path = "/tmp/python_recipe_sessions"
-
-if EXAMPLES_API_TYPE["Rooms"]:
- app = Flask(__name__, template_folder="rooms/templates")
-elif EXAMPLES_API_TYPE["Click"]:
- app = Flask(__name__, template_folder="click/templates")
-elif EXAMPLES_API_TYPE["Monitor"]:
- app = Flask(__name__, template_folder="monitor/templates")
-else:
- app = Flask(__name__)
-app.config.from_pyfile("config.py")
-
-# See https://flask-wtf.readthedocs.io/en/stable/csrf.html
-csrf = CSRFProtect(app)
-
-# Set whether this is a quickstart in config
-#app.config["quickstart"] = DS_CONFIG["quickstart"]
-
-# Set whether user has logged in
-#app.config["isLoggedIn"] = False
-
-# Register home page
-app.register_blueprint(core)
-
-# Register OAuth
-app.register_blueprint(ds)
-# Register examples
-if EXAMPLES_API_TYPE["Rooms"]:
- app.register_blueprint(rooms_examples.eg001Rooms)
- app.register_blueprint(rooms_examples.eg002)
- app.register_blueprint(rooms_examples.eg003)
- app.register_blueprint(rooms_examples.eg004)
- app.register_blueprint(rooms_examples.eg005)
- app.register_blueprint(rooms_examples.eg006)
- app.register_blueprint(rooms_examples.eg007)
- app.register_blueprint(rooms_examples.eg008)
- app.register_blueprint(rooms_examples.eg009)
-
-elif EXAMPLES_API_TYPE["Monitor"]:
- app.register_blueprint(monitor_examples.eg001)
-
-elif EXAMPLES_API_TYPE["Click"]:
- app.register_blueprint(click_examples.eg001)
- app.register_blueprint(click_examples.eg002)
- app.register_blueprint(click_examples.eg003)
- app.register_blueprint(click_examples.eg004)
- app.register_blueprint(click_examples.eg005)
-else:
- app.register_blueprint(examples.eg001)
- app.register_blueprint(examples.eg002)
- app.register_blueprint(examples.eg003)
- app.register_blueprint(examples.eg004)
- app.register_blueprint(examples.eg005)
- app.register_blueprint(examples.eg006)
- app.register_blueprint(examples.eg007)
- app.register_blueprint(examples.eg008)
- app.register_blueprint(examples.eg009)
- app.register_blueprint(examples.eg010)
- app.register_blueprint(examples.eg011)
- app.register_blueprint(examples.eg012)
- app.register_blueprint(examples.eg013)
- app.register_blueprint(examples.eg014)
- app.register_blueprint(examples.eg015)
- app.register_blueprint(examples.eg016)
- app.register_blueprint(examples.eg017)
- app.register_blueprint(examples.eg018)
- app.register_blueprint(examples.eg019)
- app.register_blueprint(examples.eg020)
- app.register_blueprint(examples.eg021)
- app.register_blueprint(examples.eg022)
- app.register_blueprint(examples.eg023)
- app.register_blueprint(examples.eg024)
- app.register_blueprint(examples.eg025)
- app.register_blueprint(examples.eg026)
- app.register_blueprint(examples.eg027)
- app.register_blueprint(examples.eg028)
- app.register_blueprint(examples.eg029)
- app.register_blueprint(examples.eg030)
- app.register_blueprint(examples.eg031)
- app.register_blueprint(examples.eg032)
- app.register_blueprint(examples.eg033)
- app.register_blueprint(examples.eg034)
- app.register_blueprint(examples.eg035)
-
-if "DYNO" in os.environ: # On Heroku?
- import logging
-
- stream_handler = logging.StreamHandler()
- app.logger.addHandler(stream_handler)
- app.logger.setLevel(logging.INFO)
- app.logger.info("Recipe example startup")
- app.config.update(dict(PREFERRED_URL_SCHEME="https"))
+import os
+
+from flask import Flask, session, current_app
+from flask_wtf.csrf import CSRFProtect
+
+from .ds_config import DS_CONFIG
+from .eSignature import views as esignature_views
+from .docusign.views import ds
+from .api_type import EXAMPLES_API_TYPE
+from .rooms import views as rooms_views
+from .click import views as click_views
+from .monitor import views as monitor_views
+from .admin import views as admin_views
+from .connect import views as connect_views
+from .webforms import views as webforms_views
+from .notary import views as notary_views
+from .connected_fields import views as connected_fields_views
+from .views import core
+
+session_path = "/tmp/python_recipe_sessions"
+app = Flask(__name__)
+
+app.config.from_pyfile("config.py")
+
+# See https://flask-wtf.readthedocs.io/en/stable/csrf.html
+csrf = CSRFProtect(app)
+
+# Set whether this is a quickstart in config
+#app.config["quickstart"] = DS_CONFIG["quickstart"]
+
+# Set whether user has logged in
+#app.config["isLoggedIn"] = False
+
+# Register home page
+app.register_blueprint(core)
+
+# Register OAuth
+app.register_blueprint(ds)
+# Register examples
+
+app.register_blueprint(rooms_views.reg001)
+app.register_blueprint(rooms_views.reg002)
+app.register_blueprint(rooms_views.reg003)
+app.register_blueprint(rooms_views.reg004)
+app.register_blueprint(rooms_views.reg005)
+app.register_blueprint(rooms_views.reg006)
+app.register_blueprint(rooms_views.reg007)
+app.register_blueprint(rooms_views.reg008)
+app.register_blueprint(rooms_views.reg009)
+
+app.register_blueprint(monitor_views.meg001)
+
+app.register_blueprint(admin_views.aeg001)
+app.register_blueprint(admin_views.aeg002)
+app.register_blueprint(admin_views.aeg003)
+app.register_blueprint(admin_views.aeg004)
+app.register_blueprint(admin_views.aeg005)
+app.register_blueprint(admin_views.aeg006)
+app.register_blueprint(admin_views.aeg007)
+app.register_blueprint(admin_views.aeg008)
+app.register_blueprint(admin_views.aeg009)
+app.register_blueprint(admin_views.aeg010)
+app.register_blueprint(admin_views.aeg011)
+app.register_blueprint(admin_views.aeg012)
+app.register_blueprint(admin_views.aeg013)
+
+app.register_blueprint(click_views.ceg001)
+app.register_blueprint(click_views.ceg002)
+app.register_blueprint(click_views.ceg003)
+app.register_blueprint(click_views.ceg004)
+app.register_blueprint(click_views.ceg005)
+app.register_blueprint(click_views.ceg006)
+
+app.register_blueprint(esignature_views.eg001)
+app.register_blueprint(esignature_views.eg002)
+app.register_blueprint(esignature_views.eg003)
+app.register_blueprint(esignature_views.eg004)
+app.register_blueprint(esignature_views.eg005)
+app.register_blueprint(esignature_views.eg006)
+app.register_blueprint(esignature_views.eg007)
+app.register_blueprint(esignature_views.eg008)
+app.register_blueprint(esignature_views.eg009)
+app.register_blueprint(esignature_views.eg010)
+app.register_blueprint(esignature_views.eg011)
+app.register_blueprint(esignature_views.eg012)
+app.register_blueprint(esignature_views.eg013)
+app.register_blueprint(esignature_views.eg014)
+app.register_blueprint(esignature_views.eg015)
+app.register_blueprint(esignature_views.eg016)
+app.register_blueprint(esignature_views.eg017)
+app.register_blueprint(esignature_views.eg018)
+app.register_blueprint(esignature_views.eg019)
+app.register_blueprint(esignature_views.eg020)
+app.register_blueprint(esignature_views.eg022)
+app.register_blueprint(esignature_views.eg023)
+app.register_blueprint(esignature_views.eg024)
+app.register_blueprint(esignature_views.eg025)
+app.register_blueprint(esignature_views.eg026)
+app.register_blueprint(esignature_views.eg027)
+app.register_blueprint(esignature_views.eg028)
+app.register_blueprint(esignature_views.eg029)
+app.register_blueprint(esignature_views.eg030)
+app.register_blueprint(esignature_views.eg031)
+app.register_blueprint(esignature_views.eg032)
+app.register_blueprint(esignature_views.eg033)
+app.register_blueprint(esignature_views.eg034)
+app.register_blueprint(esignature_views.eg035)
+app.register_blueprint(esignature_views.eg036)
+app.register_blueprint(esignature_views.eg037)
+app.register_blueprint(esignature_views.eg038)
+app.register_blueprint(esignature_views.eg039)
+app.register_blueprint(esignature_views.eg040)
+app.register_blueprint(esignature_views.eg041)
+app.register_blueprint(esignature_views.eg042)
+app.register_blueprint(esignature_views.eg043)
+app.register_blueprint(esignature_views.eg044)
+app.register_blueprint(esignature_views.eg045)
+
+app.register_blueprint(connect_views.cneg001)
+
+app.register_blueprint(webforms_views.weg001)
+app.register_blueprint(webforms_views.weg002)
+
+app.register_blueprint(notary_views.neg004)
+
+app.register_blueprint(connected_fields_views.feg001)
+
+if "DYNO" in os.environ: # On Heroku?
+ import logging
+
+ stream_handler = logging.StreamHandler()
+ app.logger.addHandler(stream_handler)
+ app.logger.setLevel(logging.INFO)
+ app.logger.info("Recipe example startup")
+ app.config.update(dict(PREFERRED_URL_SCHEME="https"))
diff --git a/app/admin/__init__.py b/app/admin/__init__.py
new file mode 100644
index 00000000..2b335eb4
--- /dev/null
+++ b/app/admin/__init__.py
@@ -0,0 +1 @@
+from .utils import create_admin_api_client
diff --git a/app/admin/examples/csv/uploaded_file.csv b/app/admin/examples/csv/uploaded_file.csv
new file mode 100644
index 00000000..ea2c5ad1
--- /dev/null
+++ b/app/admin/examples/csv/uploaded_file.csv
@@ -0,0 +1,3 @@
+AccountID,UserName,UserEmail,PermissionSet
+xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,John Dow1,exampleuser1@example.com,DS Viewer
+xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,John Dow2,exampleuser2@example.com,DS Viewer
diff --git a/app/admin/examples/eg001_create_a_new_user.py b/app/admin/examples/eg001_create_a_new_user.py
new file mode 100644
index 00000000..8f2cf1c4
--- /dev/null
+++ b/app/admin/examples/eg001_create_a_new_user.py
@@ -0,0 +1,135 @@
+from docusign_admin import UsersApi, NewUserRequest, NewUserRequestAccountProperties, PermissionProfileRequest, GroupRequest
+from docusign_esign import AccountsApi, ApiClient, GroupsApi
+from flask import session
+
+from app.admin.utils import create_admin_api_client, get_organization_id
+from app.consts import pattern
+from app.ds_config import DS_CONFIG
+
+
+class Eg001CreateNewUserController:
+
+ @staticmethod
+ def get_args(request):
+ """
+ Get request and session arguments
+ """
+
+ organization_id = get_organization_id()
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "user_name": request.form.get("user_name"),
+ "first_name": request.form.get("first_name"),
+ "last_name": request.form.get("last_name"),
+ "user_email": request.form.get("user_email"),
+ "permission_profile": request.form.get("profile_id"),
+ "group": request.form.get("group_id"),
+ "organization_id": organization_id
+ }
+
+ @staticmethod
+ def get_permission_profiles(args):
+ """Get permission profiles"""
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+
+ api_client = ApiClient(host=session["ds_base_path"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+
+ #ds-snippet-start:Admin1Step3
+ accounts_api = AccountsApi(api_client=api_client)
+ profiles = accounts_api.list_permissions(account_id=account_id)
+ profiles_list = profiles.to_dict()["permission_profiles"]
+ #ds-snippet-end:Admin1Step3
+ return profiles_list
+
+ @staticmethod
+ def get_groups(args):
+ """Get ds groups"""
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+
+ # Create an API client with headers
+ api_client = ApiClient(host=session["ds_base_path"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+
+ #ds-snippet-start:Admin1Step4
+ groups_api = GroupsApi(api_client)
+ groups = groups_api.list_groups(account_id=account_id)
+ groups_dict = groups.to_dict()
+ groups_list = groups_dict["groups"]
+ #ds-snippet-end:Admin1Step4
+ return groups_list
+
+ @staticmethod
+ def worker(self, args):
+ """
+ 1. Create the API client object
+ 2. Create the user API request object
+ 3. Create a request body for the create_user method
+ 4. Creates a user using a method from the user API
+ """
+
+ # Get group information
+ groups = self.get_groups(args)
+ for group in groups:
+ if group["group_id"] == args["group"]:
+ group_name = group["group_name"]
+ group_type = group["group_type"]
+
+ # Get permission profile information
+ permission_profiles = self.get_permission_profiles(args)
+ for profile in permission_profiles:
+ if profile["permission_profile_id"] == args["permission_profile"]:
+ profile_name = profile["permission_profile_name"]
+
+ # Create the API client object
+ #ds-snippet-start:Admin1Step2
+ api_client = create_admin_api_client(
+ access_token=session["ds_access_token"]
+ )
+ # Create the user API request object
+ user_api = UsersApi(api_client=api_client)
+ #ds-snippet-end:Admin1Step2
+
+ # Create a request body for the create_user method
+ #ds-snippet-start:Admin1Step5
+ request_body = {
+ "user_name": args["user_name"],
+ "first_name": args['first_name'],
+ "last_name": args['last_name'],
+ "email": args['user_email'],
+ "auto_activate_memberships": True,
+ "accounts": [
+ {
+ "id": session["ds_account_id"],
+ "permission_profile": {
+ "id": args['permission_profile'],
+ },
+ "groups": [
+ {
+ "id": args["group"],
+ }
+ ]
+ }
+ ]
+ }
+ #ds-snippet-end:Admin1Step5
+
+ # Creates a user using a method from the user API
+ #ds-snippet-start:Admin1Step6
+ response = user_api.create_user(
+ args["organization_id"],
+ request_body
+ )
+ #ds-snippet-end:Admin1Step6
+ return response
diff --git a/app/admin/examples/eg002_create_active_clm_esign_user.py b/app/admin/examples/eg002_create_active_clm_esign_user.py
new file mode 100644
index 00000000..c984b46d
--- /dev/null
+++ b/app/admin/examples/eg002_create_active_clm_esign_user.py
@@ -0,0 +1,114 @@
+from docusign_admin import ApiClient, ProductPermissionProfilesApi, DSGroupsApi, UsersApi, NewMultiProductUserAddRequest, ProductPermissionProfileRequest, DSGroupRequest
+from flask import session, json, request
+
+from ...ds_config import DS_CONFIG
+from app.admin.utils import get_organization_id
+
+class Eg002CreateActiveClmEsignUserController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id, # Represents your {ORGANIZATION_ID}
+ "clm_permission_profile_name": request.form.get("clm_permission_profile"),
+ "esign_permission_profile_name": request.form.get("esign_permission_profile"),
+ "user_name": request.form.get("user_name"),
+ "first_name": request.form.get("first_name"),
+ "last_name": request.form.get("last_name"),
+ "email": request.form.get("email"),
+ "group_id": request.form.get("ds_group"),
+ }
+
+ @staticmethod
+ def get_permission_profiles(args):
+ """Get permission profiles"""
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+ org_id = args["organization_id"]
+
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-start:Admin2Step3
+ product_permission_profiles_api = ProductPermissionProfilesApi(api_client=api_client)
+ profiles = product_permission_profiles_api.get_product_permission_profiles(organization_id=org_id, account_id=session["ds_account_id"])
+ profiles_list = profiles.to_dict()["product_permission_profiles"]
+ #ds-snippet-end:Admin2Step3
+ return profiles_list
+
+ @staticmethod
+ def get_groups(args):
+ """Get ds groups"""
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+ org_id = args["organization_id"]
+
+ # Create an API client with headers
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+
+ #ds-snippet-start:Admin2Step4
+ ds_groups_api = DSGroupsApi(api_client)
+ ds_groups = ds_groups_api.get_ds_groups(organization_id=org_id, account_id=session["ds_account_id"])
+ #ds-snippet-end:Admin2Step4
+ return ds_groups
+
+ @staticmethod
+ def worker(self, args):
+ """
+ 1. Create an API client with headers
+ 2. Get your monitor data via SDK
+ """
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+ org_id = args["organization_id"]
+ clm_permission_profile_name = args["clm_permission_profile_name"]
+ esign_permission_profile_name = args["esign_permission_profile_name"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin2Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin2Step2
+
+ profiles_list = self.get_permission_profiles(args)
+
+ for profile in profiles_list:
+ if profile["product_name"] == "CLM":
+ clm_product_id = profile["product_id"]
+ for permission_profile in profile["permission_profiles"]:
+ if permission_profile["permission_profile_name"] == clm_permission_profile_name:
+ clm_permission_profile_id = permission_profile["permission_profile_id"]
+ else:
+ esign_product_id = profile["product_id"]
+ for permission_profile in profile["permission_profiles"]:
+ if permission_profile["permission_profile_name"] == esign_permission_profile_name:
+ esign_permission_profile_id = permission_profile["permission_profile_id"]
+
+ #ds-snippet-start:Admin2Step5
+ clm_product_permission_profile = ProductPermissionProfileRequest(product_id=clm_product_id, permission_profile_id=clm_permission_profile_id)
+ esign_product_permission_profile = ProductPermissionProfileRequest(product_id=esign_product_id, permission_profile_id=esign_permission_profile_id)
+ ds_group_request = DSGroupRequest(ds_group_id=args["group_id"])
+ new_user = NewMultiProductUserAddRequest(product_permission_profiles=[esign_product_permission_profile, clm_product_permission_profile], ds_groups=[ds_group_request], user_name=args["user_name"], first_name=args["first_name"], last_name=args["last_name"], email=args["email"], auto_activate_memberships=True)
+ #ds-snippet-end:Admin2Step5
+
+ #ds-snippet-start:Admin2Step6
+ users_api = UsersApi(api_client)
+ response = users_api.add_or_update_user(organization_id=org_id, account_id=session["ds_account_id"], request=new_user)
+ #ds-snippet-end:Admin2Step6
+
+ return response.to_dict()
diff --git a/app/admin/examples/eg003_bulk_export_user_data.py b/app/admin/examples/eg003_bulk_export_user_data.py
new file mode 100644
index 00000000..713c1d14
--- /dev/null
+++ b/app/admin/examples/eg003_bulk_export_user_data.py
@@ -0,0 +1,99 @@
+from docusign_admin import ApiClient
+from docusign_admin.apis import BulkExportsApi
+from flask import session
+
+from app.admin.utils import create_admin_api_client, get_organization_id
+from app.ds_config import DS_CONFIG
+
+
+class Eg003BulkExportUserDataController:
+
+ @classmethod
+ def worker(cls):
+ """
+ 1. Create the export API object
+ 2. Create a user list export request
+ 3. Save user_list_export_id in a client session
+ 4. Returns a list of pending and completed export requests
+ """
+
+ organization_id = get_organization_id()
+
+ api_client = create_admin_api_client(
+ access_token=session["ds_access_token"]
+ )
+
+ # Create the export API object
+ export_api = BulkExportsApi(api_client=api_client)
+
+ # Create a user list export request
+ #ds-snippet-start:Admin3Step3
+ response = export_api.create_user_list_export(
+ organization_id,
+ {
+ "type": "organization_memberships_export"
+ }
+ )
+ #ds-snippet-end:Admin3Step3
+
+ # Save user_list_export_id in a client session
+ session['user_list_export_id'] = response.id
+
+ # Returns a list of pending and completed export requests
+ return response
+
+ @classmethod
+ def get_csv_user_list(cls):
+ """
+ Getting the csv file of the current list of users:
+ 1. Create the export API object
+ 2. Getting the user list export response
+ 3. Trying to get the user list export id
+ 4. Create the API client object
+ 5. Add headers to the API client object and the desired URL
+ 6. Getting a response containing a csv file
+ 7. Returns the csv file
+ """
+
+ organization_id = get_organization_id()
+
+ #ds-snippet-start:Admin3Step2
+ api_client = create_admin_api_client(
+ access_token=session["ds_access_token"]
+ )
+
+ # Create the export API object
+ export_api = BulkExportsApi(api_client=api_client)
+ #ds-snippet-end:Admin3Step2
+
+ # Getting the user list export response
+ #ds-snippet-start:Admin3Step4
+ response = export_api.get_user_list_export(
+ organization_id,
+ session['user_list_export_id']
+ )
+ #ds-snippet-end:Admin3Step4
+
+ # Trying to get the user list export id
+ try:
+ obj_id = response.results[0].id
+ except TypeError:
+ return None
+
+ # Create the API client object
+ #ds-snippet-start:Admin3Step5
+ api_client = ApiClient()
+
+ # Add headers to the API client object and the desired URL
+ headers = {"Authorization": "Bearer " + session["ds_access_token"]}
+ url = (
+ "https://demo.docusign.net/restapi/v2/organization_exports/"
+ f"{organization_id}/user_list/{obj_id}"
+ )
+
+ # Getting a response containing a csv file
+ response = api_client.request("GET", url, headers=headers)
+ #ds-snippet-end:Admin3Step5
+
+ # Returns the csv file
+ return response.data.decode("UTF8")
diff --git a/app/admin/examples/eg004_add_users_via_bulk_import.py b/app/admin/examples/eg004_add_users_via_bulk_import.py
new file mode 100644
index 00000000..a1240696
--- /dev/null
+++ b/app/admin/examples/eg004_add_users_via_bulk_import.py
@@ -0,0 +1,101 @@
+from os import path
+from docusign_admin.apis import BulkImportsApi
+from flask import session, Response
+import time
+
+from app.admin.utils import create_admin_api_client, get_organization_id
+from app.ds_config import DS_CONFIG
+
+
+class Eg004AddUsersViaBulkImportController:
+ @staticmethod
+ def get_example_csv():
+ """
+ Creates an example of a CSV file, such as that needs to be sent to the Docusign server
+ """
+
+ # Returns an example of a CSV file
+ return (
+ "AccountID,UserName,UserEmail,PermissionSet\n"
+ f"{session['ds_account_id']},Example User1,exampleuser1@example.com,DS Admin\n"
+ f"{session['ds_account_id']},Example User2,exampleuser2@example.com,DS Admin\n"
+ )
+
+ @staticmethod
+ def worker(self, request):
+ """
+ Create a user list import request and
+ returns a list of pending and completed import requests:
+ 1. Create the import API object
+ 2. Getting a CSV file from a form and converting it to a string
+ 3. Creating an import API object
+ 4. Setting headers for creating bulk import request
+ 5. Returns the response from the create_bulk_import_add_users_request method
+ """
+
+ # Get organization ID
+ organization_id = get_organization_id()
+
+ # Create the export API object
+ #ds-snippet-start:Admin4Step2
+ api_client = create_admin_api_client(
+ access_token=session["ds_access_token"]
+ )
+ #ds-snippet-end:Admin4Step2
+
+ # Getting a CSV file from a form and saving it
+ uploaded_file = request.files['csv_file']
+ csv_folder_path = path.abspath(path.join(path.dirname(path.realpath(__file__)), "csv"))
+ csv_file_path = path.join(csv_folder_path, "uploaded_file.csv")
+
+ if uploaded_file and not uploaded_file.filename == '':
+ uploaded_file.save(csv_file_path)
+ else:
+ content = Eg004AddUsersViaBulkImportController.get_example_csv()
+
+ modified_content = content.replace("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", session["ds_account_id"])
+
+ with open(csv_file_path, "w") as file:
+ file.write(modified_content)
+
+ # Creating an import API object
+ #ds-snippet-start:Admin4Step3
+ import_api = BulkImportsApi(api_client=api_client)
+
+ # Setting headers for creating bulk import request
+ header_name, header_value = "Content-Disposition", "filename=myfile.csv"
+ api_client.set_default_header(header_name, header_value)
+
+ # Returns the response from the create_bulk_import_add_users_request method
+ response = import_api.create_bulk_import_add_users_request(
+ organization_id,
+ csv_file_path
+ )
+ #ds-snippet-end:Admin4Step3
+
+ # Save user list import id in a client session
+ session['import_data_id'] = response.id
+
+ return response
+
+ @staticmethod
+ def check_status():
+ """Check request status"""
+
+ organization_id = get_organization_id()
+
+ api_client = create_admin_api_client(
+ access_token=session["ds_access_token"]
+ )
+
+ # Creating an import API object
+ import_api = BulkImportsApi(api_client=api_client)
+
+ #ds-snippet-start:Admin4Step4
+ import_results = import_api.get_bulk_user_import_request(organization_id, session['import_data_id'])
+ #ds-snippet-end:Admin4Step4
+
+ if import_results.status == "completed":
+ return import_results
+ else:
+ return None
diff --git a/app/admin/examples/eg005_audit_users.py b/app/admin/examples/eg005_audit_users.py
new file mode 100644
index 00000000..002edcd7
--- /dev/null
+++ b/app/admin/examples/eg005_audit_users.py
@@ -0,0 +1,68 @@
+from docusign_admin import ApiClient, UsersApi
+from flask import session, json
+
+from ...ds_config import DS_CONFIG
+from app.admin.utils import get_organization_id
+import datetime
+
+class Eg005AuditUsersController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id, # Represents your {ORGANIZATION_ID}
+ }
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Get your monitor data via SDK
+ """
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+ org_id = args["organization_id"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin5Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin5Step2
+
+ #ds-snippet-start:Admin5Step3
+ today = datetime.datetime.now()
+ ten_days_ago = today - (datetime.timedelta(days = 10))
+ last_modified_since = ten_days_ago.strftime('%Y-%m-%d')
+
+ users_api = UsersApi(api_client=api_client)
+ users = users_api.get_users(
+ organization_id=org_id,
+ account_id=account_id,
+ last_modified_since=last_modified_since)
+ #ds-snippet-end:Admin5Step3
+
+ #ds-snippet-start:Admin5Step4
+ modified_users = users.users
+ emails = []
+ for user in modified_users:
+ dict_user = user.to_dict()
+ emails.append(dict_user["email"])
+ #ds-snippet-end:Admin5Step4
+
+ #ds-snippet-start:Admin5Step5
+ profile_list = []
+ for email in emails:
+ profile = users_api.get_user_profiles(organization_id=org_id, email=email)
+ profile_list.append(profile.to_dict())
+
+ results = {"Modified users": profile_list}
+ #ds-snippet-end:Admin5Step5
+
+ return results
diff --git a/app/admin/examples/eg006_get_user_profile_by_email.py b/app/admin/examples/eg006_get_user_profile_by_email.py
new file mode 100644
index 00000000..8a882992
--- /dev/null
+++ b/app/admin/examples/eg006_get_user_profile_by_email.py
@@ -0,0 +1,47 @@
+from docusign_admin import ApiClient, UsersApi
+from flask import session, request
+
+from ...ds_config import DS_CONFIG
+from app.admin.utils import get_organization_id
+
+class Eg006GetUserProfileByEmailController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id, # Represents your {ORGANIZATION_ID},
+ "email": request.form.get("email"),
+ }
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Get user profile data
+ """
+
+ access_token = args["access_token"]
+ org_id = args["organization_id"]
+ email = args["email"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin6Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin6Step2
+
+ #ds-snippet-start:Admin6Step3
+ users_api = UsersApi(api_client=api_client)
+
+ results = users_api.get_user_ds_profiles_by_email(
+ organization_id=org_id,
+ email=email)
+ #ds-snippet-end:Admin6Step3
+
+ return results
diff --git a/app/admin/examples/eg007_get_user_profile_by_user_id.py b/app/admin/examples/eg007_get_user_profile_by_user_id.py
new file mode 100644
index 00000000..380bd069
--- /dev/null
+++ b/app/admin/examples/eg007_get_user_profile_by_user_id.py
@@ -0,0 +1,47 @@
+from docusign_admin import ApiClient, UsersApi
+from flask import session, request
+
+from ...ds_config import DS_CONFIG
+from app.admin.utils import get_organization_id
+
+class Eg007GetUserProfileByUserIdController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id, # Represents your {ORGANIZATION_ID},
+ "user_id": request.form.get("user_id"),
+ }
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Get user profile data
+ """
+
+ access_token = args["access_token"]
+ org_id = args["organization_id"]
+ user_id = args["user_id"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin7Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin7Step2
+
+ #ds-snippet-start:Admin7Step3
+ users_api = UsersApi(api_client=api_client)
+
+ results = users_api.get_user_ds_profile(
+ organization_id=org_id,
+ user_id=user_id)
+ #ds-snippet-end:Admin7Step3
+
+ return results
diff --git a/app/admin/examples/eg008_update_user_product_permission_profile.py b/app/admin/examples/eg008_update_user_product_permission_profile.py
new file mode 100644
index 00000000..8a76a0ce
--- /dev/null
+++ b/app/admin/examples/eg008_update_user_product_permission_profile.py
@@ -0,0 +1,86 @@
+from docusign_admin import (
+ ApiClient,
+ ProductPermissionProfilesApi,
+ UserProductPermissionProfilesRequest,
+ ProductPermissionProfileRequest)
+from flask import session, request
+
+from ...ds_config import DS_CONFIG
+from app.admin.utils import get_organization_id
+
+class Eg008UpdateUserProductPermissionProfileController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id, # Represents your {ORGANIZATION_ID}
+ "product_id": request.form.get("product"),
+ "clm_email": session["clm_email"],
+ }
+
+ @staticmethod
+ def get_permission_profiles():
+ """Get permission profiles"""
+
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {session['ds_access_token']}"
+ )
+
+ product_permission_profiles_api = ProductPermissionProfilesApi(api_client=api_client)
+ profiles = product_permission_profiles_api.get_product_permission_profiles(
+ organization_id=get_organization_id(),
+ account_id=session["ds_account_id"]
+ )
+ profiles_list = profiles.to_dict()["product_permission_profiles"]
+ return profiles_list
+
+ @staticmethod
+ def worker(self, args):
+ """
+ 1. Create an API client with headers
+ 2. Get your monitor data via SDK
+ """
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+ org_id = args["organization_id"]
+ clm_email = args["clm_email"]
+ permission_profile_id = args["permission_profile_id"]
+ product_id = args["product_id"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin8Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin8Step2
+
+ #ds-snippet-start:Admin8Step3
+ product_permission_profile = ProductPermissionProfileRequest(
+ permission_profile_id=permission_profile_id,
+ product_id=product_id
+ )
+ user_product_permission_profile_request = UserProductPermissionProfilesRequest(
+ email=clm_email,
+ product_permission_profiles=[product_permission_profile]
+ )
+ #ds-snippet-end:Admin8Step3
+
+ #ds-snippet-start:Admin8Step4
+ product_permission_profiles_api = ProductPermissionProfilesApi(api_client=api_client)
+ response = product_permission_profiles_api.add_user_product_permission_profiles_by_email(
+ organization_id=org_id,
+ account_id=account_id,
+ user_product_permission_profiles_request=user_product_permission_profile_request
+ )
+ #ds-snippet-end:Admin8Step4
+
+ return response.to_dict()
diff --git a/app/admin/examples/eg009_delete_user_product_permission_profile.py b/app/admin/examples/eg009_delete_user_product_permission_profile.py
new file mode 100644
index 00000000..05b6538f
--- /dev/null
+++ b/app/admin/examples/eg009_delete_user_product_permission_profile.py
@@ -0,0 +1,81 @@
+from docusign_admin import (
+ ApiClient,
+ ProductPermissionProfilesApi,
+ UserProductProfileDeleteRequest)
+from flask import session, request
+
+from ...ds_config import DS_CONFIG
+from app.admin.utils import get_organization_id
+
+class Eg009DeleteUserProductPermissionProfileController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id, # Represents your {ORGANIZATION_ID}
+ "product_id": request.form.get("product_id"),
+ "clm_email": session["clm_email"],
+ }
+
+ @staticmethod
+ def get_permission_profiles_by_email():
+ """Get permission profiles"""
+
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {session['ds_access_token']}"
+ )
+ #ds-snippet-start:Admin9Step3
+ product_permission_profiles_api = ProductPermissionProfilesApi(api_client=api_client)
+ profiles = product_permission_profiles_api.get_user_product_permission_profiles_by_email(
+ organization_id=get_organization_id(),
+ account_id=session["ds_account_id"],
+ email=session["clm_email"]
+ )
+ profiles_list = profiles.to_dict()["product_permission_profiles"]
+ #ds-snippet-end:Admin9Step3
+ return profiles_list
+
+ @staticmethod
+ def worker(self, args):
+ """
+ 1. Create an API client with headers
+ 2. Get your monitor data via SDK
+ """
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+ org_id = args["organization_id"]
+ email = args["clm_email"]
+ product_id = args["product_id"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin9Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin9Step2
+
+ #ds-snippet-start:Admin9Step4
+ user_product_profile_delete_request = UserProductProfileDeleteRequest(
+ user_email=email,
+ product_ids=[product_id]
+ )
+ #ds-snippet-end:Admin9Step4
+
+ #ds-snippet-start:Admin9Step5
+ product_permission_profiles_api = ProductPermissionProfilesApi(api_client=api_client)
+ response = product_permission_profiles_api.remove_user_product_permission(
+ organization_id=org_id,
+ account_id=account_id,
+ user_product_permission_profiles_request=user_product_profile_delete_request
+ )
+ #ds-snippet-end:Admin9Step5
+
+ return response.to_dict()
diff --git a/app/admin/examples/eg010_delete_user_data_from_organization.py b/app/admin/examples/eg010_delete_user_data_from_organization.py
new file mode 100644
index 00000000..7da5e8d2
--- /dev/null
+++ b/app/admin/examples/eg010_delete_user_data_from_organization.py
@@ -0,0 +1,58 @@
+from docusign_admin import ApiClient, UsersApi, OrganizationsApi, IndividualUserDataRedactionRequest, \
+ MembershipDataRedactionRequest
+from flask import session, request
+
+from ...ds_config import DS_CONFIG
+from app.admin.utils import get_organization_id
+
+
+class Eg010DeleteUserDataFromOrganizationController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id, # Represents your {ORGANIZATION_ID},
+ "email": request.form.get("email"),
+ }
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Get user profile data
+ 3. Delete user data
+ """
+
+ access_token = args["access_token"]
+ org_id = args["organization_id"]
+ email = args["email"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin10Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin10Step2
+
+ users_api = UsersApi(api_client=api_client)
+ results = users_api.get_user_ds_profiles_by_email(organization_id=org_id, email=email)
+ user = results.users[0]
+
+ #ds-snippet-start:Admin10Step3
+ organizations_api = OrganizationsApi(api_client=api_client)
+ user_data_redaction_request = IndividualUserDataRedactionRequest(
+ user_id=user.id,
+ memberships=[MembershipDataRedactionRequest(account_id=user.memberships[0].account_id)]
+ )
+ #ds-snippet-end:Admin10Step3
+
+ #ds-snippet-start:Admin10Step4
+ results = organizations_api.redact_individual_user_data(org_id, user_data_redaction_request)
+ #ds-snippet-end:Admin10Step4
+
+ return results
diff --git a/app/admin/examples/eg011_delete_user_data_from_account.py b/app/admin/examples/eg011_delete_user_data_from_account.py
new file mode 100644
index 00000000..40d3f790
--- /dev/null
+++ b/app/admin/examples/eg011_delete_user_data_from_account.py
@@ -0,0 +1,46 @@
+from docusign_admin import ApiClient, AccountsApi, IndividualMembershipDataRedactionRequest
+from flask import session, request
+
+from ...ds_config import DS_CONFIG
+
+
+class Eg011DeleteUserDataFromAccountController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ return {
+ "account_id": session["ds_account_id"], # Represents your {ACCOUNT_ID}
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "user_id": request.form.get("user_id"),
+ }
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Delete user data
+ """
+
+ access_token = args["access_token"]
+ account_id = args["account_id"]
+ user_id = args["user_id"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin11Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin11Step2
+
+ #ds-snippet-start:Admin11Step3
+ accounts_api = AccountsApi(api_client=api_client)
+ membership_redaction_request = IndividualMembershipDataRedactionRequest(user_id=user_id)
+ #ds-snippet-end:Admin11Step3
+
+ #ds-snippet-start:Admin11Step4
+ results = accounts_api.redact_individual_membership_data(account_id, membership_redaction_request)
+ #ds-snippet-end:Admin11Step4
+
+ return results
diff --git a/app/admin/examples/eg012_clone_account.py b/app/admin/examples/eg012_clone_account.py
new file mode 100644
index 00000000..e2f16247
--- /dev/null
+++ b/app/admin/examples/eg012_clone_account.py
@@ -0,0 +1,85 @@
+from docusign_admin import ApiClient, ProvisionAssetGroupApi, AssetGroupAccountClone, \
+ AssetGroupAccountCloneSourceAccount, AssetGroupAccountCloneTargetAccount, \
+ AssetGroupAccountCloneTargetAccountAdmin
+from flask import session, request
+
+from ..utils import get_organization_id
+from ...ds_config import DS_CONFIG
+
+
+class Eg012CloneAccountController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+
+ return {
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id,
+ "source_account_id": request.form.get("source_account_id"),
+ "target_account_name": request.form.get("target_account_name"),
+ "target_account_user_name": request.form.get("target_account_user_name"),
+ "target_account_first_name": request.form.get("target_account_first_name"),
+ "target_account_last_name": request.form.get("target_account_last_name"),
+ "target_account_email": request.form.get("target_account_email"),
+ }
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Get the list of eligible accounts
+ 3. Construct the request body
+ 4. Clone the account
+ """
+
+ access_token = args["access_token"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin12Step2
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin12Step2
+
+ #ds-snippet-start:Admin12Step4
+ account_data = AssetGroupAccountClone(
+ source_account=AssetGroupAccountCloneSourceAccount(
+ id=args["source_account_id"]
+ ),
+ target_account=AssetGroupAccountCloneTargetAccount(
+ name=args["target_account_name"],
+ admin=AssetGroupAccountCloneTargetAccountAdmin(
+ first_name=args["target_account_first_name"],
+ last_name=args["target_account_last_name"],
+ email=args["target_account_email"]
+ ),
+ country_code="US"
+ )
+ )
+ #ds-snippet-end:Admin12Step4
+
+ #ds-snippet-start:Admin12Step5
+ asset_group_api = ProvisionAssetGroupApi(api_client=api_client)
+ results = asset_group_api.clone_asset_group_account(args["organization_id"], account_data)
+ #ds-snippet-end:Admin12Step5
+
+ return results
+
+ @staticmethod
+ def get_accounts(args):
+ access_token = args["access_token"]
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+
+ #ds-snippet-start:Admin12Step3
+ asset_group_api = ProvisionAssetGroupApi(api_client=api_client)
+ accounts = asset_group_api.get_asset_group_accounts(args["organization_id"], compliant=True)
+ #ds-snippet-end:Admin12Step3
+
+ return accounts
diff --git a/app/admin/examples/eg013_create_account.py b/app/admin/examples/eg013_create_account.py
new file mode 100644
index 00000000..c57208fd
--- /dev/null
+++ b/app/admin/examples/eg013_create_account.py
@@ -0,0 +1,89 @@
+from docusign_admin import ApiClient, ProvisionAssetGroupApi, SubAccountCreateRequest, \
+ SubAccountCreateRequestSubAccountCreationSubscription, \
+ SubAccountCreateRequestSubAccountCreationTargetAccountDetails, \
+ SubAccountCreateRequestSubAccountCreationTargetAccountAdmin
+from flask import session, request
+
+from ..utils import get_organization_id
+from ...ds_config import DS_CONFIG
+
+
+class Eg013CreateAccountController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ organization_id = get_organization_id()
+
+ return {
+ "access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
+ "organization_id": organization_id,
+ "base_path": DS_CONFIG["admin_api_client_host"],
+ "email": request.form.get("email"),
+ "first_name": request.form.get("first_name"),
+ "last_name": request.form.get("last_name"),
+ "subscription_id": session.get("subscription_id"),
+ "plan_id": session.get("plan_id"),
+ }
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Get the list of eligible accounts
+ 3. Construct the request body
+ 4. Create the account
+ """
+
+ access_token = args["access_token"]
+
+ # Create an API client with headers
+ #ds-snippet-start:Admin13Step2
+ api_client = ApiClient(host=args["base_path"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ #ds-snippet-end:Admin13Step2
+
+ #ds-snippet-start:Admin13Step4
+ account_data = SubAccountCreateRequest(
+ subscription_details=SubAccountCreateRequestSubAccountCreationSubscription(
+ id=args["subscription_id"],
+ plan_id=args["plan_id"],
+ modules=[]
+ ),
+ target_account=SubAccountCreateRequestSubAccountCreationTargetAccountDetails(
+ name="CreatedThroughAPI",
+ country_code="US",
+ admin=SubAccountCreateRequestSubAccountCreationTargetAccountAdmin(
+ email=args["email"],
+ first_name=args["first_name"],
+ last_name=args["last_name"],
+ locale="en"
+ )
+ )
+ )
+ #ds-snippet-end:Admin13Step4
+
+ #ds-snippet-start:Admin13Step5
+ asset_group_api = ProvisionAssetGroupApi(api_client=api_client)
+ results = asset_group_api.create_asset_group_account(args["organization_id"], account_data)
+ #ds-snippet-end:Admin13Step5
+
+ return results
+
+ @staticmethod
+ def get_organization_plan_items(args):
+ access_token = args["access_token"]
+ api_client = ApiClient(host=args["base_path"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+
+ #ds-snippet-start:Admin13Step3
+ asset_group_api = ProvisionAssetGroupApi(api_client=api_client)
+ plan_items = asset_group_api.get_organization_plan_items(args["organization_id"])
+ #ds-snippet-end:Admin13Step3
+
+ return plan_items
diff --git a/app/admin/utils.py b/app/admin/utils.py
new file mode 100644
index 00000000..cf87c5f0
--- /dev/null
+++ b/app/admin/utils.py
@@ -0,0 +1,47 @@
+from docusign_admin import ApiClient, AccountsApi, UsersApi
+from flask import session
+
+from app.ds_config import DS_CONFIG
+
+
+def create_admin_api_client(access_token):
+ """Create API client and construct API headers"""
+
+ # return api_client
+ api_client = ApiClient(
+ host=DS_CONFIG["admin_api_client_host"],
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+ return api_client
+
+def get_organization_id():
+ account_id = session["ds_account_id"]
+ access_token = session["ds_access_token"]
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+
+ accounts_api = AccountsApi(api_client)
+ organizations = accounts_api.get_organizations()
+ org_dict = organizations.to_dict()
+ first_org = org_dict["organizations"][0]
+ org_id = first_org["id"]
+
+ return org_id
+
+def check_user_exists_by_email(user_email):
+ access_token = session["ds_access_token"]
+ api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
+ api_client.set_default_header(
+ header_name="Authorization",
+ header_value=f"Bearer {access_token}"
+ )
+
+ users_api = UsersApi(api_client)
+ response = users_api.get_users(organization_id=get_organization_id(), email=user_email)
+
+ return len(response.users) > 0 and response.users[0].user_status != "closed"
+
diff --git a/app/admin/views/__init__.py b/app/admin/views/__init__.py
new file mode 100644
index 00000000..a9230335
--- /dev/null
+++ b/app/admin/views/__init__.py
@@ -0,0 +1,13 @@
+from .eg001_create_a_new_user import aeg001
+from .eg002_create_active_clm_esign_user import aeg002
+from .eg003_bulk_export_user_data import aeg003
+from .eg004_add_users_via_bulk_import import aeg004
+from .eg005_audit_users import aeg005
+from .eg006_get_user_profile_by_email import aeg006
+from .eg007_get_user_profile_by_user_id import aeg007
+from .eg008_update_user_product_permission_profile import aeg008
+from .eg009_delete_user_product_permission_profile import aeg009
+from .eg010_delete_user_data_from_organization import aeg010
+from .eg011_delete_user_data_from_account import aeg011
+from .eg012_clone_account import aeg012
+from .eg013_create_account import aeg013
diff --git a/app/admin/views/eg001_create_a_new_user.py b/app/admin/views/eg001_create_a_new_user.py
new file mode 100644
index 00000000..6e595cfc
--- /dev/null
+++ b/app/admin/views/eg001_create_a_new_user.py
@@ -0,0 +1,80 @@
+"""Example 001: Create a new user"""
+
+import json
+from os import path
+
+from flask import Blueprint, render_template, request, current_app, session
+from docusign_admin.client.api_exception import ApiException
+
+from app.error_handlers import process_error
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+from ..examples.eg001_create_a_new_user import Eg001CreateNewUserController
+
+example_number = 1
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg001 = Blueprint(eg, __name__)
+
+@aeg001.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_user_data():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ controller = Eg001CreateNewUserController()
+
+ # 1. Get required arguments
+ args = Eg001CreateNewUserController.get_args(request)
+
+ # 2. Call the worker method
+ try:
+ results = Eg001CreateNewUserController.worker(controller, args)
+ current_app.logger.info(f"ID of the created user: {results.id}")
+ except ApiException as err:
+ return process_error(err)
+
+ # 3. Render the response
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message="Results from eSignUserManagement:createUser method:",
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+@aeg001.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """
+ Responds with the form for the example
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ args = Eg001CreateNewUserController.get_args(request)
+
+ try:
+ profiles = Eg001CreateNewUserController.get_permission_profiles(args)
+ groups = Eg001CreateNewUserController.get_groups(args)
+
+ except ApiException as err:
+ return process_error(err)
+
+ # Render the response
+ return render_template(
+ "admin/eg001_create_a_new_user.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file= "eg001_create_a_new_user.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg001_create_a_new_user.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ permission_profiles=profiles,
+ groups=groups
+ )
diff --git a/app/admin/views/eg002_create_active_clm_esign_user.py b/app/admin/views/eg002_create_active_clm_esign_user.py
new file mode 100644
index 00000000..5ec5575f
--- /dev/null
+++ b/app/admin/views/eg002_create_active_clm_esign_user.py
@@ -0,0 +1,89 @@
+"""Example 002: Create a new active user for CLM and eSignature. """
+
+import json
+from os import path
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, current_app, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg002_create_active_clm_esign_user import Eg002CreateActiveClmEsignUserController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 2
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg002 = Blueprint(eg, __name__)
+
+@aeg002.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def create_active_clm_esign_user():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ controller = Eg002CreateActiveClmEsignUserController()
+
+ # 1. Get required arguments
+ args = Eg002CreateActiveClmEsignUserController.get_args()
+ try:
+ # 2. Call the worker method to get your monitor data
+ results = Eg002CreateActiveClmEsignUserController.worker(controller, args)
+ current_app.logger.info(f"""Got your monitor data""")
+ except ApiException as err:
+ return process_error(err)
+
+ session["clm_email"] = results["email"] # Save for use by other examples which need an email of CLM user
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message="Results from MultiProductUserManagement:addOrUpdateUser method:",
+ json=json.dumps(json.dumps(results, default=str))
+ )
+
+@aeg002.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # Get the required arguments
+ args = Eg002CreateActiveClmEsignUserController.get_args()
+
+ try:
+ profiles = Eg002CreateActiveClmEsignUserController.get_permission_profiles(args)
+ clm_permission_profiles_list = []
+ esign_permission_profiles_list = []
+ for profile in profiles:
+ permission_profiles = profile["permission_profiles"]
+ for permission_profile in permission_profiles:
+ if profile["product_name"] == "CLM":
+ clm_permission_profiles_list.append(permission_profile["permission_profile_name"])
+ else:
+ esign_permission_profiles_list.append(permission_profile["permission_profile_name"])
+
+ ds_groups = Eg002CreateActiveClmEsignUserController.get_groups(args)
+ ds_groups_dict = ds_groups.to_dict()
+ ds_groups_list = ds_groups_dict["ds_groups"]
+
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "admin/eg002_create_active_clm_esign_user.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file= "eg002_create_active_clm_esign_user.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg002_create_active_clm_esign_user.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ clm_permission_profiles_list=clm_permission_profiles_list,
+ esign_permission_profiles_list=esign_permission_profiles_list,
+ ds_groups=ds_groups_list
+ )
diff --git a/app/admin/views/eg003_bulk_export_user_data.py b/app/admin/views/eg003_bulk_export_user_data.py
new file mode 100644
index 00000000..10e233d4
--- /dev/null
+++ b/app/admin/views/eg003_bulk_export_user_data.py
@@ -0,0 +1,106 @@
+"""Example 003: Bulk export user data"""
+
+import json
+import time
+import os
+from os import path
+from pathlib import Path
+
+from flask import Blueprint, render_template, Response, current_app, session
+from docusign_admin.client.api_exception import ApiException
+
+from app.error_handlers import process_error
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.ds_config import DS_CONFIG
+from ..examples.eg003_bulk_export_user_data import Eg003BulkExportUserDataController
+from ...consts import API_TYPE
+
+example_number = 3
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg003 = Blueprint(eg, __name__)
+
+@aeg003.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_user_list_data():
+ """
+ 1. Call the worker method
+ 2. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Call the worker method
+ try:
+ results = Eg003BulkExportUserDataController.worker()
+ current_app.logger.info(f"User list export ID: {results.id}")
+ except ApiException as err:
+ return process_error(err)
+
+ csv_ready = False
+ while csv_ready == False:
+ csv_ready = check_if_csv_ready()
+ time.sleep(5)
+
+ if csv_ready == True:
+ get_csv()
+
+ file_path = Path("app/admin/examples/exported_user_data.csv").absolute()
+
+ # 2. Render the response
+ return render_template(
+ "example_done.html",
+ get_csv=True,
+ title=example["ExampleName"],
+ message=f"User data exported to {file_path}. Results from UserExport:getUserListExport:",
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+@aeg003.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """
+ Responds with the form for the example
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # Render the response
+ return render_template(
+ "admin/eg003_bulk_export_user_data.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file= "eg003_bulk_export_user_data.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg003_bulk_export_user_data.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ )
+
+def check_if_csv_ready():
+ """
+ 1. Checking if a CSV file exists
+ 2. Render the response
+ """
+
+ # 1. Checking if a CSV file exists
+ try:
+ csv_file = Eg003BulkExportUserDataController.get_csv_user_list()
+ except ApiException as err:
+ return process_error(err)
+
+ return bool(csv_file)
+
+def get_csv():
+ """
+ 1. Getting an existing CSV file
+ 2. Returns the finished csv file to the user
+ """
+
+ # 1. Getting an existing CSV file
+ try:
+ csv_file = Eg003BulkExportUserDataController.get_csv_user_list()
+ except ApiException as err:
+ return process_error(err)
+
+ results_file = open("app/admin/examples/exported_user_data.csv", "w")
+ results_file.write(csv_file)
+
\ No newline at end of file
diff --git a/app/admin/views/eg004_add_users_via_bulk_import.py b/app/admin/views/eg004_add_users_via_bulk_import.py
new file mode 100644
index 00000000..b31b8cb2
--- /dev/null
+++ b/app/admin/views/eg004_add_users_via_bulk_import.py
@@ -0,0 +1,117 @@
+"""Example 004: Add users via bulk import"""
+
+import json
+import os
+from os import path
+import time
+
+from flask import Blueprint, render_template, request, Response, current_app, session
+from docusign_admin.client.api_exception import ApiException
+
+from app.error_handlers import process_error
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.ds_config import DS_CONFIG
+from ..examples.eg004_add_users_via_bulk_import import Eg004AddUsersViaBulkImportController
+from ...consts import API_TYPE
+
+example_number = 4
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference(and URL) for this example
+aeg004 = Blueprint(eg, __name__)
+
+
+@aeg004.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def add_users_via_bulk_import():
+ """
+ 1. Call the worker method
+ 2. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ controller = Eg004AddUsersViaBulkImportController()
+
+ # 1. Call the worker method
+ try:
+ results = Eg004AddUsersViaBulkImportController.worker(controller, request)
+ current_app.logger.info(f"Bulk import request ID: {results.id}")
+ except ApiException as err:
+ return process_error(err)
+
+ # 2. Render the response
+ return render_template(
+ "example_done.html",
+ check_status = True,
+ title=example["ExampleName"],
+ message=f"Results from UserImport:addBulkUserImport method:",
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+@aeg004.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """
+ Responds with the form for the example
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # Render the response
+ return render_template(
+ "admin/eg004_add_users_via_bulk_import.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file="eg004_add_users_via_bulk_import.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg004_add_users_via_bulk_import.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ )
+
+@aeg004.route("/eg004examplecsv", methods=["GET"])
+@authenticate(eg=eg, api=api)
+def get_csv():
+ """
+ 1. Creates an example of a CSV file
+ 2. Returns an example of a CSV file to the user
+ """
+
+ # 1. Creates an example of a CSV file
+ csv_file = Eg004AddUsersViaBulkImportController.get_example_csv()
+
+ # 2. Returns an example of a CSV file to the user
+ return Response(
+ csv_file,
+ mimetype="text/csv",
+ headers={
+ "Content-disposition":"attachment; filename=bulk_import_demo.csv"
+ }
+ )
+
+@aeg004.route("/eg004check", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def check_if_request_ready():
+ """
+ 1. Checking if the request is complete
+ 2. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # Check if request is complete
+ try:
+ results = Eg004AddUsersViaBulkImportController.check_status()
+ except ApiException as err:
+ return process_error(err)
+
+ if not results:
+ return render_template(
+ "admin/eg004_file_state.html",
+ )
+ else:
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message=f"Results from UserImport:getBulkUserImportRequest method:",
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
\ No newline at end of file
diff --git a/app/admin/views/eg005_audit_users.py b/app/admin/views/eg005_audit_users.py
new file mode 100644
index 00000000..4e9ef173
--- /dev/null
+++ b/app/admin/views/eg005_audit_users.py
@@ -0,0 +1,62 @@
+"""Example 005: Audit users. """
+
+import json
+from os import path
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, current_app, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg005_audit_users import Eg005AuditUsersController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 5
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg005 = Blueprint(eg, __name__)
+
+@aeg005.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def audit_users():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Get required arguments
+ args = Eg005AuditUsersController.get_args()
+ try:
+ # 2. Call the worker method to get your monitor data
+ results = Eg005AuditUsersController.worker(args)
+ current_app.logger.info(f"""Auditing users""")
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message="Results from eSignUserManagement:getUserProfiles method:",
+ json=json.dumps(json.dumps(results, default=str))
+ )
+
+@aeg005.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ return render_template(
+ "admin/eg005_audit_users.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file= "eg005_audit_users.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg005_audit_users.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ )
+
diff --git a/app/admin/views/eg006_get_user_profile_by_email.py b/app/admin/views/eg006_get_user_profile_by_email.py
new file mode 100644
index 00000000..8265edbe
--- /dev/null
+++ b/app/admin/views/eg006_get_user_profile_by_email.py
@@ -0,0 +1,60 @@
+"""Example 006: Get user profile data by email. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg006_get_user_profile_by_email import Eg006GetUserProfileByEmailController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 6
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg006 = Blueprint(eg, __name__)
+
+@aeg006.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def audit_users():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Get required arguments
+ args = Eg006GetUserProfileByEmailController.get_args()
+ try:
+ # 2. Call the worker method to get user profile data by email
+ results = Eg006GetUserProfileByEmailController.worker(args)
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message="Results from MultiProductUserManagement:getUserDSProfilesByEmail method:",
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+@aeg006.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ return render_template(
+ f"admin/eg006_get_user_profile_by_email.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file=f"eg006_get_user_profile_by_email.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg006_get_user_profile_by_email.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ )
+
diff --git a/app/admin/views/eg007_get_user_profile_by_user_id.py b/app/admin/views/eg007_get_user_profile_by_user_id.py
new file mode 100644
index 00000000..7031d72e
--- /dev/null
+++ b/app/admin/views/eg007_get_user_profile_by_user_id.py
@@ -0,0 +1,60 @@
+"""Example 007: Get user profile data by user ID. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg007_get_user_profile_by_user_id import Eg007GetUserProfileByUserIdController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 7
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg007 = Blueprint(eg, __name__)
+
+@aeg007.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def audit_users():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Get required arguments
+ args = Eg007GetUserProfileByUserIdController.get_args()
+ try:
+ # 2. Call the worker method to get user profile data by user ID
+ results = Eg007GetUserProfileByUserIdController.worker(args)
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message="Results from MultiProductUserManagement:getUserDSProfile method:",
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+@aeg007.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ return render_template(
+ f"admin/eg007_get_user_profile_by_user_id.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file=f"eg007_get_user_profile_by_user_id.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg007_get_user_profile_by_user_id.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ )
+
diff --git a/app/admin/views/eg008_update_user_product_permission_profile.py b/app/admin/views/eg008_update_user_product_permission_profile.py
new file mode 100644
index 00000000..6779379c
--- /dev/null
+++ b/app/admin/views/eg008_update_user_product_permission_profile.py
@@ -0,0 +1,125 @@
+"""Example 008: Update user product permission profiles using an email address. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, request, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg008_update_user_product_permission_profile import Eg008UpdateUserProductPermissionProfileController
+from ...ds_config import DS_CONFIG
+from ..utils import check_user_exists_by_email
+from ...consts import API_TYPE
+
+example_number = 8
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg008 = Blueprint(eg, __name__)
+
+@aeg008.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def create_active_clm_esign_user():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ if "clm_email" in session and check_user_exists_by_email(session["clm_email"]):
+ controller = Eg008UpdateUserProductPermissionProfileController()
+
+ # 1. Get required arguments
+ args = Eg008UpdateUserProductPermissionProfileController.get_args()
+ profiles = Eg008UpdateUserProductPermissionProfileController.get_permission_profiles()
+
+ for profile in profiles:
+ if profile["product_id"] == args["product_id"]:
+ if profile["product_name"] == "CLM":
+ args["permission_profile_id"] = request.form.get("clm_permission_profile")
+ else:
+ args["permission_profile_id"] = request.form.get("esign_permission_profile")
+
+ try:
+ # 2. Call the worker method
+ results = Eg008UpdateUserProductPermissionProfileController.worker(controller, args)
+ except ApiException as err:
+ return process_error(err)
+
+ template = render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message="Results from MultiProductUserManagement:addUserProductPermissionProfilesByEmail method:",
+ json=json.dumps(json.dumps(results, default=str))
+ )
+ else:
+ template = render_template(
+ f"admin/eg008_create_active_clm_esign_user.html",
+ title=example["ExampleName"],
+ example=example,
+ email_ok=False,
+ source_file=f"eg008_create_active_clm_esign_user.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg008_create_active_clm_esign_user.py",
+ documentation=DS_CONFIG["documentation"] + eg
+ )
+
+ return template
+
+@aeg008.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ if "clm_email" in session and check_user_exists_by_email(session["clm_email"]):
+ try:
+ profiles = Eg008UpdateUserProductPermissionProfileController.get_permission_profiles()
+ clm_permission_profiles_list = []
+ esign_permission_profiles_list = []
+ clm_product_id = ""
+ esign_product_id = ""
+ products_list = []
+ for profile in profiles:
+ permission_profiles = profile["permission_profiles"]
+ for permission_profile in permission_profiles:
+ if profile["product_name"] == "CLM":
+ clm_permission_profiles_list.append(permission_profile)
+ clm_product_id = profile["product_id"]
+ else:
+ esign_permission_profiles_list.append(permission_profile)
+ esign_product_id = profile["product_id"]
+
+ products_list.append({"product_id": clm_product_id, "product_name": "CLM"})
+ products_list.append({"product_id": esign_product_id, "product_name": "eSignature"})
+
+ except ApiException as err:
+ return process_error(err)
+
+ template = render_template(
+ f"admin/eg008_update_user_product_permission_profile.html",
+ title=example["ExampleName"],
+ example=example,
+ email_ok="clm_email" in session,
+ source_file=f"eg008_update_user_product_permission_profile.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg008_update_user_product_permission_profile.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ product_list=products_list,
+ email=session["clm_email"],
+ clm_permission_profiles_list=clm_permission_profiles_list,
+ esign_permission_profiles_list=esign_permission_profiles_list
+ )
+ else:
+ template = render_template(
+ f"admin/eg008_update_user_product_permission_profile.html",
+ title=example["ExampleName"],
+ example=example,
+ email_ok=False,
+ source_file=f"eg008_update_user_product_permission_profile.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg008_update_user_product_permission_profile.py",
+ documentation=DS_CONFIG["documentation"] + eg
+ )
+
+ return template
diff --git a/app/admin/views/eg009_delete_user_product_permission_profile.py b/app/admin/views/eg009_delete_user_product_permission_profile.py
new file mode 100644
index 00000000..b93e458e
--- /dev/null
+++ b/app/admin/views/eg009_delete_user_product_permission_profile.py
@@ -0,0 +1,115 @@
+"""Example 009: Delete user product permission profiles using an email address. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, current_app, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg009_delete_user_product_permission_profile import Eg009DeleteUserProductPermissionProfileController
+from ...ds_config import DS_CONFIG
+from ..utils import check_user_exists_by_email
+from ...consts import API_TYPE
+
+example_number = 9
+api = API_TYPE["ADMIN"]
+eg = f"aeg00{example_number}" # Reference (and URL) for this example
+aeg009 = Blueprint(eg, __name__)
+
+@aeg009.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def create_active_clm_esign_user():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ if "clm_email" in session and check_user_exists_by_email(session["clm_email"]):
+ controller = Eg009DeleteUserProductPermissionProfileController()
+
+ # 1. Get required arguments
+ args = Eg009DeleteUserProductPermissionProfileController.get_args()
+ try:
+ # 2. Call the worker method
+ results = Eg009DeleteUserProductPermissionProfileController.worker(controller, args)
+ except ApiException as err:
+ return process_error(err)
+
+ template = render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message="Results from MultiProductUserManagement:removeUserProductPermission method:",
+ json=json.dumps(json.dumps(results, default=str))
+ )
+ else:
+ template = render_template(
+ f"admin/eg009_delete_user_product_permission_profile.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file=f"eg009_delete_user_product_permission_profile.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg009_delete_user_product_permission_profile.py",
+ documentation=DS_CONFIG["documentation"] + eg
+ )
+
+ return template
+
+@aeg009.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ if "clm_email" in session and check_user_exists_by_email(session["clm_email"]):
+ try:
+ profiles = Eg009DeleteUserProductPermissionProfileController.get_permission_profiles_by_email()
+ permission_profile_list = []
+ clm_product_id = None
+ clm_permission_profile_name = None
+ esign_product_id = None
+ esign_permission_profile_name = None
+ for profile in profiles:
+ permission_profiles = profile["permission_profiles"]
+ for permission_profile in permission_profiles:
+ if profile["product_name"] == "CLM":
+ clm_permission_profile_name = permission_profile["permission_profile_name"]
+ clm_product_id = profile["product_id"]
+ else:
+ esign_permission_profile_name = permission_profile["permission_profile_name"]
+ esign_product_id = profile["product_id"]
+
+ if clm_product_id is not None:
+ permission_profile_list.append({"product_id": clm_product_id, "permission_name": f"CLM - {clm_permission_profile_name}"})
+
+ if esign_product_id is not None:
+ permission_profile_list.append({"product_id": esign_product_id, "permission_name": f"eSignature - {esign_permission_profile_name}"})
+
+ except ApiException as err:
+ return process_error(err)
+
+ template = render_template(
+ f"admin/eg009_delete_user_product_permission_profile.html",
+ title=example["ExampleName"],
+ example=example,
+ email_ok="clm_email" in session,
+ source_file=f"eg009_delete_user_product_permission_profile.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg009_delete_user_product_permission_profile.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ email=session["clm_email"],
+ permission_profile_list=permission_profile_list
+ )
+ else:
+ template = render_template(
+ f"admin/eg009_delete_user_product_permission_profile.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file=f"eg009_delete_user_product_permission_profile.py",
+ source_url=DS_CONFIG["admin_github_url"] + f"eg009_delete_user_product_permission_profile.py",
+ documentation=DS_CONFIG["documentation"] + eg
+ )
+
+ return template
diff --git a/app/admin/views/eg010_delete_user_data_from_organization.py b/app/admin/views/eg010_delete_user_data_from_organization.py
new file mode 100644
index 00000000..caea398c
--- /dev/null
+++ b/app/admin/views/eg010_delete_user_data_from_organization.py
@@ -0,0 +1,62 @@
+"""Example 010: Delete user data from an account as an organization admin. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg010_delete_user_data_from_organization import Eg010DeleteUserDataFromOrganizationController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 10
+api = API_TYPE["ADMIN"]
+eg = f"aeg0{example_number}" # Reference (and URL) for this example
+aeg010 = Blueprint(eg, __name__)
+
+
+@aeg010.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def audit_users():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Get required arguments
+ args = Eg010DeleteUserDataFromOrganizationController.get_args()
+ try:
+ # 2. Call the worker method to delete user data by email
+ results = Eg010DeleteUserDataFromOrganizationController.worker(args)
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message=example["ResultsPageText"],
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+
+@aeg010.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ return render_template(
+ "admin/eg010_delete_user_data_from_organization.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file="eg010_delete_user_data_from_organization.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg010_delete_user_data_from_organization.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ )
+
diff --git a/app/admin/views/eg011_delete_user_data_from_account.py b/app/admin/views/eg011_delete_user_data_from_account.py
new file mode 100644
index 00000000..a5cf43d5
--- /dev/null
+++ b/app/admin/views/eg011_delete_user_data_from_account.py
@@ -0,0 +1,62 @@
+"""Example 011: Delete user data from an account as an account admin. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg011_delete_user_data_from_account import Eg011DeleteUserDataFromAccountController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 11
+api = API_TYPE["ADMIN"]
+eg = f"aeg0{example_number}" # Reference (and URL) for this example
+aeg011 = Blueprint(eg, __name__)
+
+
+@aeg011.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def audit_users():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Get required arguments
+ args = Eg011DeleteUserDataFromAccountController.get_args()
+ try:
+ # 2. Call the worker method to delete user data by user ID
+ results = Eg011DeleteUserDataFromAccountController.worker(args)
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message=example["ResultsPageText"],
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+
+@aeg011.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ return render_template(
+ "admin/eg011_delete_user_data_from_account.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file="eg011_delete_user_data_from_account.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg011_delete_user_data_from_account.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ )
+
diff --git a/app/admin/views/eg012_clone_account.py b/app/admin/views/eg012_clone_account.py
new file mode 100644
index 00000000..c4c2289c
--- /dev/null
+++ b/app/admin/views/eg012_clone_account.py
@@ -0,0 +1,70 @@
+"""Example 012: How to clone an account. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg012_clone_account import Eg012CloneAccountController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 12
+api = API_TYPE["ADMIN"]
+eg = f"aeg0{example_number}" # Reference (and URL) for this example
+aeg012 = Blueprint(eg, __name__)
+
+
+@aeg012.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def audit_users():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Get required arguments
+ args = Eg012CloneAccountController.get_args()
+ try:
+ # 2. Call the worker method to clone the account
+ results = Eg012CloneAccountController.worker(args)
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message=example["ResultsPageText"],
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+
+@aeg012.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ args = Eg012CloneAccountController.get_args()
+
+ try:
+ accounts = Eg012CloneAccountController.get_accounts(args)
+ except ApiException as err:
+ process_error(err)
+
+ return render_template(
+ "admin/eg012_clone_account.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file="eg012_clone_account.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg012_clone_account.py",
+ documentation=DS_CONFIG["documentation"] + eg,
+ accounts=accounts.asset_group_accounts
+ )
+
diff --git a/app/admin/views/eg013_create_account.py b/app/admin/views/eg013_create_account.py
new file mode 100644
index 00000000..0be7df3e
--- /dev/null
+++ b/app/admin/views/eg013_create_account.py
@@ -0,0 +1,72 @@
+"""Example 013: How to create an account. """
+
+import json
+
+from docusign_admin.client.api_exception import ApiException
+from flask import Blueprint, render_template, session
+
+from app.docusign import authenticate, ensure_manifest, get_example_by_number
+from app.error_handlers import process_error
+from ..examples.eg013_create_account import Eg013CreateAccountController
+from ...ds_config import DS_CONFIG
+from ...consts import API_TYPE
+
+example_number = 13
+api = API_TYPE["ADMIN"]
+eg = f"aeg0{example_number}" # Reference (and URL) for this example
+aeg013 = Blueprint(eg, __name__)
+
+
+@aeg013.route(f"/{eg}", methods=["POST"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def create_account():
+ """
+ 1. Get required arguments
+ 2. Call the worker method
+ 3. Render the response
+ """
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ # 1. Get required arguments
+ args = Eg013CreateAccountController.get_args()
+ try:
+ # 2. Call the worker method to create an account
+ results = Eg013CreateAccountController.worker(args)
+ except ApiException as err:
+ return process_error(err)
+
+ return render_template(
+ "example_done.html",
+ title=example["ExampleName"],
+ message=example["ResultsPageText"],
+ json=json.dumps(json.dumps(results.to_dict(), default=str))
+ )
+
+
+@aeg013.route(f"/{eg}", methods=["GET"])
+@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
+@authenticate(eg=eg, api=api)
+def get_view():
+ """ Responds with the form for the example"""
+ example = get_example_by_number(session["manifest"], example_number, api)
+
+ args = Eg013CreateAccountController.get_args()
+
+ try:
+ plan_items = Eg013CreateAccountController.get_organization_plan_items(args)
+ session["subscription_id"] = plan_items[0].subscription_id
+ session["plan_id"] = plan_items[0].plan_id
+
+ except ApiException as err:
+ process_error(err)
+
+ return render_template(
+ "admin/eg013_create_account.html",
+ title=example["ExampleName"],
+ example=example,
+ source_file="eg013_create_account.py",
+ source_url=DS_CONFIG["admin_github_url"] + "eg013_create_account.py",
+ documentation=DS_CONFIG["documentation"] + eg
+ )
+
diff --git a/app/api_type.py b/app/api_type.py
new file mode 100644
index 00000000..0bc16fb5
--- /dev/null
+++ b/app/api_type.py
@@ -0,0 +1 @@
+EXAMPLES_API_TYPE ={'Rooms': False, 'ESignature': True, 'Click': False, 'Monitor': False, 'Admin': False, 'Notary': False}
\ No newline at end of file
diff --git a/app/click/examples/__init__.py b/app/click/examples/__init__.py
deleted file mode 100644
index c5ea6a03..00000000
--- a/app/click/examples/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from .eg001_create_clickwrap import eg001
-from .eg002_activate_clickwrap import eg002
-from .eg003_create_new_clickwrap_version import eg003
-from .eg004_list_clickwraps import eg004
-from .eg005_clickwrap_responses import eg005
diff --git a/app/click/examples/eg001_create_clickwrap/controller.py b/app/click/examples/eg001_create_clickwrap.py
similarity index 79%
rename from app/click/examples/eg001_create_clickwrap/controller.py
rename to app/click/examples/eg001_create_clickwrap.py
index 7e550864..46d7920e 100644
--- a/app/click/examples/eg001_create_clickwrap/controller.py
+++ b/app/click/examples/eg001_create_clickwrap.py
@@ -5,12 +5,12 @@
Document
from flask import session, request
-from ....consts import demo_docs_path
-from ....ds_config import DS_CONFIG
-from ...utils import create_click_api_client
+from ...consts import demo_docs_path
+from ...ds_config import DS_CONFIG
+from ..utils import create_click_api_client
-class Eg001Controller:
+class Eg001CreateClickwrapController:
@staticmethod
def get_args():
"""Get required session and request arguments"""
@@ -29,19 +29,21 @@ def worker(args):
4. Create a clickwrap request model
5. Create a clickwrap using SDK
"""
- # Step 1. Create an API client with headers
+ # Create an API client with headers
+ #ds-snippet-start:Click1Step2
api_client = create_click_api_client(
access_token=args["access_token"]
)
-
- # Step 2. Create a display settings model
+ #ds-snippet-end
+
+ #ds-snippet-start:Click1Step3
+ # Create a display settings model
display_settings = DisplaySettings(
consent_button_text="I Agree",
display_name="Terms of Service",
downloadable=True,
format="modal",
must_read=True,
- must_view=True,
require_accept=True,
document_display="document"
)
@@ -53,7 +55,7 @@ def worker(args):
doc_docx_bytes = file.read()
doc_b64 = base64.b64encode(doc_docx_bytes).decode("ascii")
- # Step 3. Create a document model.
+ # Create a document model.
document = Document( # Create the DocuSign document object
document_base64=doc_b64,
document_name="Terms of Service", # Can be different from actual file name
@@ -61,19 +63,22 @@ def worker(args):
order=0
)
- # Step 4. Create a clickwrap request model
+ # Create a clickwrap request model
clickwrap_request = ClickwrapRequest(
display_settings=display_settings,
documents=[document, ],
name=args.get("clickwrap_name"),
require_reacceptance=True
)
+ #ds-snippet-end:Click1Step3
- # Step 5. Create a clickwrap using SDK
+ # Create a clickwrap using SDK
+ #ds-snippet-start:Click1Step4
accounts_api = AccountsApi(api_client)
response = accounts_api.create_clickwrap(
clickwrap_request=clickwrap_request,
account_id=args["account_id"]
)
+ #ds-snippet-end:Click1Step4
return response
diff --git a/app/click/examples/eg001_create_clickwrap/__init__.py b/app/click/examples/eg001_create_clickwrap/__init__.py
deleted file mode 100644
index 11c5cf04..00000000
--- a/app/click/examples/eg001_create_clickwrap/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .views import eg001
diff --git a/app/click/examples/eg002_activate_clickwrap.py b/app/click/examples/eg002_activate_clickwrap.py
new file mode 100644
index 00000000..3eb6e65e
--- /dev/null
+++ b/app/click/examples/eg002_activate_clickwrap.py
@@ -0,0 +1,77 @@
+from docusign_click import AccountsApi, ClickwrapRequest
+from flask import session, request
+import ast
+
+from ..utils import create_click_api_client
+
+
+class Eg002ActivateClickwrapController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ return {
+ "account_id": session.get("ds_account_id"), # Represents your {ACCOUNT_ID}
+ "access_token": session.get("ds_access_token"), # Represents your {ACCESS_TOKEN}
+ "clickwrap": request.form.get("clickwrap"),
+ "statuses": ["inactive", "draft"]
+ }
+
+ @staticmethod
+ def get_inactive_clickwraps(args):
+ """
+ 1. Create an API client with hheaders
+ 2. Get a list of inactive clickwraps
+ """
+ # Step 1. Create an API client with headers
+ api_client = create_click_api_client(
+ access_token=args["access_token"]
+ )
+
+ # Step 2. Get a list of inactive clickwraps
+ accounts_api = AccountsApi(api_client)
+ clickwraps = []
+
+ for status in args["statuses"]:
+ response = accounts_api.get_clickwraps(
+ account_id=args["account_id"],
+ status=status
+ )
+ clickwraps += response.clickwraps
+
+ return {"clickwraps": clickwraps}
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Create a clickwrap request model
+ 3. Update a clickwrap using SDK
+ """
+ # Step 1. Create an API client with headers
+ #ds-snippet-start:Click2Step2
+ api_client = create_click_api_client(
+ access_token=args["access_token"]
+ )
+ #ds-snippet-end:Click2Step2
+
+ # Step 2. Create a clickwrap request model
+ #ds-snippet-start:Click2Step3
+ clickwrap_request = ClickwrapRequest(status="active")
+ #ds-snippet-end:Click2Step3
+
+ # Step 3. Update a clickwrap using SDK
+ #ds-snippet-start:Click2Step4
+ accounts_api = AccountsApi(api_client)
+ #ds-snippet-end:Click2Step4
+ clickwrap = ast.literal_eval(args["clickwrap"])
+ print(type(clickwrap))
+ #ds-snippet-start:Click2Step4
+ response = accounts_api.update_clickwrap_version(
+ account_id=args["account_id"],
+ clickwrap_id=clickwrap["clickwrap_id"],
+ version_id=clickwrap["version_number"],
+ clickwrap_request=clickwrap_request,
+ )
+ #ds-snippet-end:Click2Step4
+
+ return response
diff --git a/app/click/examples/eg002_activate_clickwrap/__init__.py b/app/click/examples/eg002_activate_clickwrap/__init__.py
deleted file mode 100644
index 1b2ca36d..00000000
--- a/app/click/examples/eg002_activate_clickwrap/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .views import eg002
diff --git a/app/click/examples/eg002_activate_clickwrap/controller.py b/app/click/examples/eg002_activate_clickwrap/controller.py
deleted file mode 100644
index 87c697eb..00000000
--- a/app/click/examples/eg002_activate_clickwrap/controller.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from docusign_click import AccountsApi, ClickwrapRequest
-from flask import session
-
-from ...utils import create_click_api_client
-
-
-class Eg002Controller:
- @staticmethod
- def get_args():
- """Get required session and request arguments"""
- return {
- "account_id": session.get("ds_account_id"), # Represents your {ACCOUNT_ID}
- "access_token": session.get("ds_access_token"), # Represents your {ACCESS_TOKEN}
- "clickwrap_id": session.get("clickwrap_id"),
- "clickwrap_name": session.get("clickwrap_name"),
- }
-
- @staticmethod
- def worker(args):
- """
- 1. Create an API client with headers
- 2. Create a clickwrap request model
- 3. Update a clickwrap using SDK
- """
- # Step 1. Create an API client with headers
- api_client = create_click_api_client(
- access_token=args["access_token"]
- )
-
- # Step 2. Create a clickwrap request model
- clickwrap_request = ClickwrapRequest(status="active")
-
- # Step 3. Update a clickwrap using SDK
- accounts_api = AccountsApi(api_client)
- response = accounts_api.update_clickwrap_version(
- account_id=args["account_id"],
- clickwrap_id=args["clickwrap_id"],
- clickwrap_request=clickwrap_request,
- version_id="1"
- )
-
- return response
diff --git a/app/click/examples/eg002_activate_clickwrap/views.py b/app/click/examples/eg002_activate_clickwrap/views.py
deleted file mode 100644
index 0b4f82d0..00000000
--- a/app/click/examples/eg002_activate_clickwrap/views.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""Example 002: Activating a clickwrap"""
-
-from os import path
-import json
-
-from docusign_click.client.api_exception import ApiException
-from flask import render_template, current_app, Blueprint, session
-
-from .controller import Eg002Controller
-from app.docusign import authenticate
-from app.ds_config import DS_CONFIG
-from app.error_handlers import process_error
-
-eg = "eg002" # Reference (and URL) for this example
-eg002 = Blueprint("eg002", __name__)
-
-
-@eg002.route("/eg002", methods=["POST"])
-@authenticate(eg=eg)
-def activate_clickwrap():
- """
- 1. Get required arguments
- 2. Call the worker method
- 3. Render the response
- """
- # 1. Get required arguments
- args = Eg002Controller.get_args()
-
- try:
- # 2. Call the worker method to create a new clickwrap
- results = Eg002Controller.worker(args)
- current_app.logger.info(
- f"""The clickwrap "{args['clickwrap_name']}" has been activated!"""
- )
- except ApiException as err:
- return process_error(err)
-
- # Save for use by other examples which need an clickwrap params.
- session["clickwrap_is_active"] = True
-
- # 3. Render the response
- return render_template(
- "example_done.html",
- title="Activating a clickwrap",
- h1="Activating a clickwrap",
- message=f"""The clickwrap "{args['clickwrap_name']}" has been activated!""",
- json=json.dumps(json.dumps(results.to_dict(), default=str))
- )
-
-
-@eg002.route("/eg002", methods=["GET"])
-@authenticate(eg=eg)
-def get_view():
- """responds with the form for the example"""
- return render_template(
- "eg002_activate_clickwrap.html",
- title="Activating a clickwrap",
- clickwrap_ok="clickwrap_id" in session,
- source_file=path.basename(path.dirname(__file__)) + "/controller.py",
- source_url=DS_CONFIG["github_example_url"] + path.basename(
- path.dirname(__file__)) + "/controller.py",
- )
diff --git a/app/click/examples/eg003_create_new_clickwrap_version/controller.py b/app/click/examples/eg003_create_new_clickwrap_version.py
similarity index 76%
rename from app/click/examples/eg003_create_new_clickwrap_version/controller.py
rename to app/click/examples/eg003_create_new_clickwrap_version.py
index 9796cf6e..c3ebe4d7 100644
--- a/app/click/examples/eg003_create_new_clickwrap_version/controller.py
+++ b/app/click/examples/eg003_create_new_clickwrap_version.py
@@ -3,22 +3,22 @@
from docusign_click import AccountsApi, ClickwrapRequest, DisplaySettings, \
Document
-from flask import session
+from flask import session, request
-from ....consts import demo_docs_path
-from ....ds_config import DS_CONFIG
-from ...utils import create_click_api_client
+from ...consts import demo_docs_path
+from ...ds_config import DS_CONFIG
+from ..utils import create_click_api_client
-class Eg003Controller:
+class Eg003CrateNewClickwrapVersionController:
@staticmethod
def get_args():
"""Get required session and request arguments"""
return {
"account_id": session.get("ds_account_id"), # Represents your {ACCOUNT_ID}
"access_token": session.get("ds_access_token"), # Represents your {ACCESS_TOKEN}
- "clickwrap_id": session.get("clickwrap_id"),
- "clickwrap_name": session.get("clickwrap_name"),
+ "clickwrap_id": request.form.get("clickwrap_id"),
+ "clickwrap_name": request.form.get("clickwrap_name"),
}
@staticmethod
@@ -30,19 +30,21 @@ def worker(args):
4. Create a clickwrap request model
5. Create a new clickwrap version using SDK
"""
- # Step 1. Create an API client with headers
+ # Create an API client with headers
+ #ds-snippet-start:Click3Step2
api_client = create_click_api_client(
access_token=args["access_token"]
)
+ #ds-snippet-end
- # Step 2. Create a display settings model
+ # Create a display settings model
+ #ds-snippet-start:Click3Step3
display_settings = DisplaySettings(
consent_button_text="I Agree",
display_name=f"{args.get('clickwrap_name')} v2",
downloadable=False,
format="modal",
must_read=True,
- must_view=False,
require_accept=False,
document_display="document",
send_to_email=False
@@ -55,7 +57,7 @@ def worker(args):
doc_docx_bytes = file.read()
doc_b64 = base64.b64encode(doc_docx_bytes).decode("ascii")
- # Step 3. Create a document model.
+ # Create a document model.
document = Document( # Create the DocuSign document object
document_base64=doc_b64,
document_name="Terms of Service", # Can be different from actual file name
@@ -63,7 +65,7 @@ def worker(args):
order=0
)
- # Step 4. Create a clickwrap request model
+ # Create a clickwrap request model
clickwrap_request = ClickwrapRequest(
display_settings=display_settings,
documents=[document, ],
@@ -71,13 +73,16 @@ def worker(args):
require_reacceptance=True,
status="active"
)
+ #ds-snippet-end
- # Step 5. Create a new clickwrap version using SDK
+ # Create a new clickwrap version using SDK
+ #ds-snippet-start:Click3Step4
accounts_api = AccountsApi(api_client)
response = accounts_api.create_clickwrap_version(
account_id=args["account_id"],
clickwrap_id=args["clickwrap_id"],
clickwrap_request=clickwrap_request,
)
+ #ds-snippet-end
return response
diff --git a/app/click/examples/eg003_create_new_clickwrap_version/__init__.py b/app/click/examples/eg003_create_new_clickwrap_version/__init__.py
deleted file mode 100644
index c5813bf4..00000000
--- a/app/click/examples/eg003_create_new_clickwrap_version/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .views import eg003
diff --git a/app/click/examples/eg003_create_new_clickwrap_version/views.py b/app/click/examples/eg003_create_new_clickwrap_version/views.py
deleted file mode 100644
index 482b077c..00000000
--- a/app/click/examples/eg003_create_new_clickwrap_version/views.py
+++ /dev/null
@@ -1,59 +0,0 @@
-"""Example 003: Creating a new clickwrap version"""
-
-from os import path
-import json
-
-from docusign_click.client.api_exception import ApiException
-from flask import render_template, current_app, Blueprint, session
-
-from .controller import Eg003Controller
-from app.docusign import authenticate
-from app.ds_config import DS_CONFIG
-from app.error_handlers import process_error
-
-eg = "eg003" # Reference (and URL) for this example
-eg003 = Blueprint("eg003", __name__)
-
-
-@eg003.route("/eg003", methods=["POST"])
-@authenticate(eg=eg)
-def create_new_clickwrap_version():
- """
- 1. Get required arguments
- 2. Call the worker method
- 3. Render the response
- """
- # 1. Get required arguments
- args = Eg003Controller.get_args()
-
- try:
- # 2. Call the worker method to create a new clickwrap version
- results = Eg003Controller.worker(args)
- current_app.logger.info(
- f"""The 2nd version of clickwrap "{args['clickwrap_name']}" has been created!"""
- )
- except ApiException as err:
- return process_error(err)
-
- # 3. Render the response
- return render_template(
- "example_done.html",
- title="Creating a new clickwrap version",
- h1="Creating a new clickwrap version",
- message=f"""The 2nd version of clickwrap "{args['clickwrap_name']}" has been created!""",
- json=json.dumps(json.dumps(results.to_dict(), default=str))
- )
-
-
-@eg003.route("/eg003", methods=["GET"])
-@authenticate(eg=eg)
-def get_view():
- """responds with the form for the example"""
- return render_template(
- "eg003_create_new_clickwrap_version.html",
- title="Creating a new clickwrap version",
- clickwrap_ok="clickwrap_id" in session,
- source_file=path.basename(path.dirname(__file__)) + "/controller.py",
- source_url=DS_CONFIG["github_example_url"] + path.basename(
- path.dirname(__file__)) + "/controller.py",
- )
diff --git a/app/click/examples/eg004_list_clickwraps/controller.py b/app/click/examples/eg004_list_clickwraps.py
similarity index 65%
rename from app/click/examples/eg004_list_clickwraps/controller.py
rename to app/click/examples/eg004_list_clickwraps.py
index 99075fff..2c986bc5 100644
--- a/app/click/examples/eg004_list_clickwraps/controller.py
+++ b/app/click/examples/eg004_list_clickwraps.py
@@ -1,10 +1,10 @@
from docusign_click import AccountsApi, ClickwrapRequest
from flask import session
-from ...utils import create_click_api_client
+from ..utils import create_click_api_client
-class Eg004Controller:
+class Eg004ListClickwrapsController:
@staticmethod
def get_args():
"""Get required session and request arguments"""
@@ -16,18 +16,22 @@ def get_args():
@staticmethod
def worker(args):
"""
- 1. Create an API client with headers
- 2. Get a list of all clickwraps
+ Create an API client with headers
+ Get a list of all elastic templates
"""
- # Step 1. Create an API client with headers
+ # Create an API client with headers
+ #ds-snippet-start:Click4Step2
api_client = create_click_api_client(
access_token=args["access_token"]
)
+ #ds-snippet-end
- # Step 2. Get a list of all clickwraps
+ # Get a list of all elastic templates
+ #ds-snippet-start:Click4Step3
accounts_api = AccountsApi(api_client)
response = accounts_api.get_clickwraps(
account_id=args["account_id"]
)
+ #ds-snippet-end
return response
diff --git a/app/click/examples/eg004_list_clickwraps/__init__.py b/app/click/examples/eg004_list_clickwraps/__init__.py
deleted file mode 100644
index 4af46e78..00000000
--- a/app/click/examples/eg004_list_clickwraps/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .views import eg004
diff --git a/app/click/examples/eg004_list_clickwraps/views.py b/app/click/examples/eg004_list_clickwraps/views.py
deleted file mode 100644
index ad104db2..00000000
--- a/app/click/examples/eg004_list_clickwraps/views.py
+++ /dev/null
@@ -1,55 +0,0 @@
-"""Example 004: Getting a list of clickwraps"""
-
-from os import path
-import json
-
-from docusign_click.client.api_exception import ApiException
-from flask import render_template, current_app, Blueprint, session
-
-from .controller import Eg004Controller
-from app.docusign import authenticate
-from app.ds_config import DS_CONFIG
-from app.error_handlers import process_error
-
-eg = "eg004" # Reference (and URL) for this example
-eg004 = Blueprint("eg004", __name__)
-
-
-@eg004.route("/eg004", methods=["POST"])
-@authenticate(eg=eg)
-def clickwrap_list():
- """
- 1. Get required arguments
- 2. Call the worker method
- 3. Render the response
- """
- # 1. Get required arguments
- args = Eg004Controller.get_args()
-
- try:
- # 2. Call the worker method to get a list of clickwraps
- results = Eg004Controller.worker(args)
- except ApiException as err:
- return process_error(err)
-
- # 3. Render the response
- return render_template(
- "example_done.html",
- title="List clickwraps results",
- h1="List clickwraps results",
- message="Results from the ClickWraps::getClickwraps method:",
- json=json.dumps(json.dumps(results.to_dict(), default=str))
- )
-
-
-@eg004.route("/eg004", methods=["GET"])
-@authenticate(eg=eg)
-def get_view():
- """Responds with the form for the example"""
- return render_template(
- "eg004_list_clickwraps.html",
- title="Getting a list of clickwraps",
- source_file=path.basename(path.dirname(__file__)) + "/controller.py",
- source_url=DS_CONFIG["github_example_url"] + path.basename(
- path.dirname(__file__)) + "/controller.py",
- )
diff --git a/app/click/examples/eg005_clickwrap_responses/controller.py b/app/click/examples/eg005_clickwrap_responses.py
similarity index 77%
rename from app/click/examples/eg005_clickwrap_responses/controller.py
rename to app/click/examples/eg005_clickwrap_responses.py
index 3f82bcd2..6809d966 100644
--- a/app/click/examples/eg005_clickwrap_responses/controller.py
+++ b/app/click/examples/eg005_clickwrap_responses.py
@@ -1,18 +1,17 @@
from docusign_click import AccountsApi
from flask import request, session
-from ...utils import create_click_api_client
+from ..utils import create_click_api_client
-class Eg005Controller:
+class Eg005ClickwrapResponsesController:
@staticmethod
def get_args():
"""Get required session and request arguments"""
return {
"account_id": session.get("ds_account_id"), # Represents your {ACCOUNT_ID}
"access_token": session.get("ds_access_token"), # Represents your {ACCESS_TOKEN}
- "clickwrap_id": session.get("clickwrap_id"),
- "client_user_id": request.form.get("client_user_id"),
+ "clickwrap_id": request.form.get("clickwrap_id"),
}
@staticmethod
@@ -22,17 +21,20 @@ def worker(args):
2. Get clickwrap responses using SDK
"""
# Step 1. Create an API client with headers
+ #ds-snippet-start:Click5Step2
api_client = create_click_api_client(
access_token=args["access_token"]
)
+ #ds-snippet-end:Click5Step2
# Step 2. Get clickwrap responses using SDK
+ #ds-snippet-start:Click5Step3
accounts_api = AccountsApi(api_client)
response = accounts_api.get_clickwrap_agreements(
account_id=args["account_id"],
clickwrap_id=args["clickwrap_id"],
- client_user_id=args["client_user_id"],
status="agreed"
)
+ #ds-snippet-end:Click5Step3
return response
diff --git a/app/click/examples/eg005_clickwrap_responses/__init__.py b/app/click/examples/eg005_clickwrap_responses/__init__.py
deleted file mode 100644
index 45102c7a..00000000
--- a/app/click/examples/eg005_clickwrap_responses/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .views import eg005
diff --git a/app/click/examples/eg005_clickwrap_responses/views.py b/app/click/examples/eg005_clickwrap_responses/views.py
deleted file mode 100644
index 29e32c7e..00000000
--- a/app/click/examples/eg005_clickwrap_responses/views.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""Example 005: Getting clickwrap responses"""
-
-from os import path
-import json
-
-from docusign_click.client.api_exception import ApiException
-from flask import render_template, current_app, Blueprint, session
-
-from .controller import Eg005Controller
-from app.docusign import authenticate
-from app.ds_config import DS_CONFIG
-from app.error_handlers import process_error
-
-eg = "eg005" # Reference (and URL) for this example
-eg005 = Blueprint("eg005", __name__)
-
-
-@eg005.route("/eg005", methods=["POST"])
-@authenticate(eg=eg)
-def clickwrap_responses():
- """
- 1. Get required arguments
- 2. Call the worker method
- 3. Render the response
- """
- # 1. Get required arguments
- args = Eg005Controller.get_args()
-
- try:
- # 2. Call the worker method to get clickwrap responses
- results = Eg005Controller.worker(args)
- except ApiException as err:
- return process_error(err)
-
- # 3. Render the response
- return render_template(
- "example_done.html",
- title="Getting clickwrap responses",
- h1="Getting clickwrap responses",
- message="Results from the ClickWraps::getClickwrapAgreements method:",
- json=json.dumps(json.dumps(results.to_dict(), default=str))
- )
-
-
-@eg005.route("/eg005", methods=["GET"])
-@authenticate(eg=eg)
-def get_view():
- """Responds with the form for the example"""
- return render_template(
- "eg005_clickwrap_responses.html",
- title="Getting clickwrap responses",
- clickwrap_ok="clickwrap_id" in session,
- source_file=path.basename(path.dirname(__file__)) + "/controller.py",
- source_url=DS_CONFIG["github_example_url"] + path.basename(
- path.dirname(__file__)) + "/controller.py",
- )
diff --git a/app/click/examples/eg006_embed_clickwrap.py b/app/click/examples/eg006_embed_clickwrap.py
new file mode 100644
index 00000000..acd5a2e7
--- /dev/null
+++ b/app/click/examples/eg006_embed_clickwrap.py
@@ -0,0 +1,84 @@
+from docusign_click import AccountsApi, UserAgreementRequest
+from flask import session, request
+import ast
+
+from ..utils import create_click_api_client
+
+
+class Eg006EmbedClickwrapController:
+ @staticmethod
+ def get_args():
+ """Get required session and request arguments"""
+ return {
+ "account_id": session.get("ds_account_id"), # Represents your {ACCOUNT_ID}
+ "access_token": session.get("ds_access_token"), # Represents your {ACCESS_TOKEN}
+ "clickwrap": request.form.get("clickwrap"),
+ "fullName": request.form.get("fullName"),
+ "email": request.form.get("email"),
+ "company": request.form.get("company"),
+ "title": request.form.get("title"),
+ "date": request.form.get("date"),
+ "statuses": ["inactive", "draft"]
+ }
+
+ @staticmethod
+ def get_active_clickwraps(args):
+ """
+ 1. Create an API client with hheaders
+ 2. Get a list of active clickwraps
+ """
+ # Step 1. Create an API client with headers
+ #ds-snippet-start:Click6Step2
+ api_client = create_click_api_client(
+ access_token=args["access_token"]
+ )
+ #ds-snippet-end:Click6Step2
+
+ # Step 2. Get a list of active clickwraps
+ accounts_api = AccountsApi(api_client)
+ response = accounts_api.get_clickwraps(
+ account_id=args["account_id"],
+ status="active"
+ )
+
+ return response
+
+ @staticmethod
+ def worker(args):
+ """
+ 1. Create an API client with headers
+ 2. Create a clickwrap request model
+ 3. Update a clickwrap using SDK
+ """
+ # Create an API client with headers
+ api_client = create_click_api_client(
+ access_token=args["access_token"]
+ )
+
+ # Create a user agreement request model
+ #ds-snippet-start:Click6Step3
+ user_agreement_request = UserAgreementRequest(
+ client_user_id=args["email"],
+ document_data={
+ "fullName": args["fullName"],
+ "email": args["email"],
+ "company": args["company"],
+ "title": args["title"],
+ "date": args["date"]
+ },
+ )
+ #ds-snippet-end:Click6Step3
+
+ # Retrieve Agreement URL using SDK
+ #ds-snippet-start:Click6Step4
+ accounts_api = AccountsApi(api_client)
+ clickwrap = ast.literal_eval(args["clickwrap"])
+ print(type(clickwrap))
+ response = accounts_api.create_has_agreed(
+ account_id=args["account_id"],
+ clickwrap_id=clickwrap["clickwrap_id"],
+ user_agreement_request=user_agreement_request,
+ )
+ #ds-snippet-end:Click6Step4
+
+ return response
diff --git a/app/click/templates/404.html b/app/click/templates/404.html
deleted file mode 100644
index 307da311..00000000
--- a/app/click/templates/404.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-{% extends "base.html" %}
-
-{% block content %}
-
This example demonstrates how to use DocuSign Click to activate a new
- clickwrap that you have already created. By default, new
- clickwraps are inactive. You must activate your clickwrap before
- you can use it.
This example demonstrates how to use the Click API to create a new version
- of a clickwrap. You can specify whether you require users who have
- previously accepted the clickwrap to accept the new version when they
- return to your website.
-
-{% include 'github_source.html' %}
-
-{% if clickwrap_ok %}
-
The clickwrap you created via example 1 will be queried.
- Please enter a value that uniquely identifies a user, such as an email
- address or employee ID
-
-
-
-{% else %}
-
Problem: please first create a clickwrap using example
- 1. Thank you.