Skip to content

Commit

Permalink
Merge branch 'master' into feature/fixes-for-selenium-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanBachaloSigmaSoftware committed Dec 1, 2023
2 parents 85ca275 + 40793a4 commit d37e243
Show file tree
Hide file tree
Showing 58 changed files with 1,276 additions and 327 deletions.
5 changes: 5 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
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 .views import core

session_path = "/tmp/python_recipe_sessions"
Expand Down Expand Up @@ -57,6 +58,7 @@
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(click_views.ceg001)
app.register_blueprint(click_views.ceg002)
Expand Down Expand Up @@ -107,6 +109,9 @@
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(connect_views.cneg001)

if "DYNO" in os.environ: # On Heroku?
import logging
Expand Down
12 changes: 6 additions & 6 deletions app/admin/examples/eg004_add_users_via_bulk_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ def worker(self, request):
organization_id = get_organization_id()

# Create the export API object
# Step 2 start
#ds-snippet-start:Admin4Step2
api_client = create_admin_api_client(
access_token=session["ds_access_token"]
)
# Step 2 end
#ds-snippet-end:Admin4Step2

# Getting a CSV file from a form and saving it
uploaded_file = request.files['csv_file']
Expand All @@ -59,19 +59,19 @@ def worker(self, request):
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
# Step 3 start
response = import_api.create_bulk_import_add_users_request(
organization_id,
csv_file_path
)
# Step 3 end
#ds-snippet-end:Admin4Step3

# Save user list import id in a client session
session['import_data_id'] = response.id
Expand All @@ -91,9 +91,9 @@ def check_status():
# Creating an import API object
import_api = BulkImportsApi(api_client=api_client)

# Step 4 start
#ds-snippet-start:Admin4Step4
import_results = import_api.get_bulk_user_import_request(organization_id, session['import_data_id'])
# Step 4 end
#ds-snippet-end:Admin4Step4

if import_results.status == "completed":
return import_results
Expand Down
85 changes: 85 additions & 0 deletions app/admin/examples/eg012_clone_account.py
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions app/admin/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
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
70 changes: 70 additions & 0 deletions app/admin/views/eg012_clone_account.py
Original file line number Diff line number Diff line change
@@ -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
)

1 change: 1 addition & 0 deletions app/connect/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .views import cneg001
29 changes: 29 additions & 0 deletions app/connect/examples/eg001_validate_webhook_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from flask import request
import hmac
import hashlib
import base64

class Eg001ValidateWebhookMessageController:
@staticmethod
def get_args():
"""Get required session and request arguments"""
return {
"secret": request.form.get("secret"),
"payload": request.form.get("payload"),
}

@staticmethod
def worker(args):
"""
1. Create an API client with headers
2. Get your monitor data via SDK
"""
#ds-snippet-start:Connect1Step1
key = bytes(args['secret'], 'utf-8')
payload = bytes(args['payload'], 'utf-8')

hmac_hash = hmac.new(key, payload, hashlib.sha256)
result = base64.b64encode(hmac_hash.digest()).decode('utf-8')
#ds-snippet-end:Connect1Step1

return result
1 change: 1 addition & 0 deletions app/connect/views/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .eg001_validate_webhook_message import cneg001
55 changes: 55 additions & 0 deletions app/connect/views/eg001_validate_webhook_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""Example 001: Validate webhook message using HMAC. """

from docusign_monitor.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.eg001_validate_webhook_message import Eg001ValidateWebhookMessageController
from ...ds_config import DS_CONFIG
from ...consts import API_TYPE

example_number = 1
api = API_TYPE["CONNECT"]
eg = f"cneg00{example_number}" # Reference (and URL) for this example
cneg001 = Blueprint(eg, __name__)

@cneg001.route(f"/{eg}", methods=["POST"])
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
def get_monitoring_data():
"""
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 = Eg001ValidateWebhookMessageController.get_args()
try:
# 2. Call the worker method to compute hash
results = Eg001ValidateWebhookMessageController.worker(args)
except ApiException as err:
return process_error(err)

return render_template(
"example_done.html",
title=example["ExampleName"],
message=example["ResultsPageText"].format(results)
)

@cneg001.route(f"/{eg}", methods=["GET"])
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
def get_view():
""" Responds with the form for the example"""
example = get_example_by_number(session["manifest"], example_number, api)

return render_template(
"connect/eg001_validate_webhook_message.html",
title=example["ExampleName"],
example=example,
source_file= "eg001_validate_webhook_message.py",
source_url=DS_CONFIG["connect_github_url"] + "eg001_validate_webhook_message.py",
documentation=DS_CONFIG["documentation"] + eg,
)

3 changes: 2 additions & 1 deletion app/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,6 @@
"MONITOR": "Monitor",
"CLICK": "Click",
"ROOMS": "Rooms",
"ADMIN": "Admin"
"ADMIN": "Admin",
"CONNECT": "Connect"
}
3 changes: 2 additions & 1 deletion app/docusign/ds_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@

ADMIN_SCOPES = [
"signature", "organization_read", "group_read", "permission_read", "user_read", "user_write",
"account_read", "domain_read", "identity_provider_read", "impersonation", "user_data_redact"
"account_read", "domain_read", "identity_provider_read", "impersonation", "user_data_redact",
"asset_group_account_read", "asset_group_account_clone_write", "asset_group_account_clone_read"
]


Expand Down
1 change: 1 addition & 0 deletions app/ds_config_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"monitor_github_url": "https://github.com/docusign/code-examples-python/tree/master/app/monitor/examples/",
"admin_github_url": "https://github.com/docusign/code-examples-python/tree/master/app/admin/examples/",
"click_github_url": "https://github.com/docusign/code-examples-python/tree/master/app/click/examples/",
"connect_github_url": "https://github.com/docusign/code-examples-python/tree/master/app/connect/examples/",
"example_manifest_url": "https://raw.githubusercontent.com/docusign/code-examples-csharp/master/manifest/CodeExamplesManifest.json",
"documentation": "", # Use an empty string to indicate no documentation path.
"quickstart": "{QUICKSTART_VALUE}"
Expand Down
10 changes: 7 additions & 3 deletions app/eSignature/examples/eg002_signing_via_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,23 @@ def worker(cls, args, doc_docx_path, doc_pdf_path):
2. Send the envelope
"""

#ds-snippet-start:eSign2Step3
envelope_args = args["envelope_args"]
# 1. Create the envelope request object
# Create the envelope request object
envelope_definition = cls.make_envelope(envelope_args, doc_docx_path, doc_pdf_path)
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
# 2. call Envelopes::create API method
# Call Envelopes::create API method
# Exceptions will be caught by the calling function
envelopes_api = EnvelopesApi(api_client)
results = envelopes_api.create_envelope(account_id=args["account_id"], envelope_definition=envelope_definition)

envelope_id = results.envelope_id

return {"envelope_id": envelope_id}
#ds-snippet-end:eSign2Step3

@classmethod
#ds-snippet-start:eSign2Step2
def make_envelope(cls, args, doc_docx_path, doc_pdf_path):
"""
Creates envelope
Expand Down Expand Up @@ -170,4 +173,5 @@ def create_document1(cls, args):
<h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3>
</body>
</html>
"""
"""
#ds-snippet-end:eSign2Step2
Loading

0 comments on commit d37e243

Please sign in to comment.