Skip to content

Commit d37e243

Browse files
Merge branch 'master' into feature/fixes-for-selenium-tests
2 parents 85ca275 + 40793a4 commit d37e243

File tree

58 files changed

+1276
-327
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1276
-327
lines changed

app/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from .click import views as click_views
1212
from .monitor import views as monitor_views
1313
from .admin import views as admin_views
14+
from .connect import views as connect_views
1415
from .views import core
1516

1617
session_path = "/tmp/python_recipe_sessions"
@@ -57,6 +58,7 @@
5758
app.register_blueprint(admin_views.aeg009)
5859
app.register_blueprint(admin_views.aeg010)
5960
app.register_blueprint(admin_views.aeg011)
61+
app.register_blueprint(admin_views.aeg012)
6062

6163
app.register_blueprint(click_views.ceg001)
6264
app.register_blueprint(click_views.ceg002)
@@ -107,6 +109,9 @@
107109
app.register_blueprint(esignature_views.eg041)
108110
app.register_blueprint(esignature_views.eg042)
109111
app.register_blueprint(esignature_views.eg043)
112+
app.register_blueprint(esignature_views.eg044)
113+
114+
app.register_blueprint(connect_views.cneg001)
110115

111116
if "DYNO" in os.environ: # On Heroku?
112117
import logging

app/admin/examples/eg004_add_users_via_bulk_import.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ def worker(self, request):
3737
organization_id = get_organization_id()
3838

3939
# Create the export API object
40-
# Step 2 start
40+
#ds-snippet-start:Admin4Step2
4141
api_client = create_admin_api_client(
4242
access_token=session["ds_access_token"]
4343
)
44-
# Step 2 end
44+
#ds-snippet-end:Admin4Step2
4545

4646
# Getting a CSV file from a form and saving it
4747
uploaded_file = request.files['csv_file']
@@ -59,19 +59,19 @@ def worker(self, request):
5959
file.write(modified_content)
6060

6161
# Creating an import API object
62+
#ds-snippet-start:Admin4Step3
6263
import_api = BulkImportsApi(api_client=api_client)
6364

6465
# Setting headers for creating bulk import request
6566
header_name, header_value = "Content-Disposition", "filename=myfile.csv"
6667
api_client.set_default_header(header_name, header_value)
6768

6869
# Returns the response from the create_bulk_import_add_users_request method
69-
# Step 3 start
7070
response = import_api.create_bulk_import_add_users_request(
7171
organization_id,
7272
csv_file_path
7373
)
74-
# Step 3 end
74+
#ds-snippet-end:Admin4Step3
7575

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

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

9898
if import_results.status == "completed":
9999
return import_results
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from docusign_admin import ApiClient, ProvisionAssetGroupApi, AssetGroupAccountClone, \
2+
AssetGroupAccountCloneSourceAccount, AssetGroupAccountCloneTargetAccount, \
3+
AssetGroupAccountCloneTargetAccountAdmin
4+
from flask import session, request
5+
6+
from ..utils import get_organization_id
7+
from ...ds_config import DS_CONFIG
8+
9+
10+
class Eg012CloneAccountController:
11+
@staticmethod
12+
def get_args():
13+
"""Get required session and request arguments"""
14+
organization_id = get_organization_id()
15+
16+
return {
17+
"access_token": session["ds_access_token"], # Represents your {ACCESS_TOKEN}
18+
"organization_id": organization_id,
19+
"source_account_id": request.form.get("source_account_id"),
20+
"target_account_name": request.form.get("target_account_name"),
21+
"target_account_user_name": request.form.get("target_account_user_name"),
22+
"target_account_first_name": request.form.get("target_account_first_name"),
23+
"target_account_last_name": request.form.get("target_account_last_name"),
24+
"target_account_email": request.form.get("target_account_email"),
25+
}
26+
27+
@staticmethod
28+
def worker(args):
29+
"""
30+
1. Create an API client with headers
31+
2. Get the list of eligible accounts
32+
3. Construct the request body
33+
4. Clone the account
34+
"""
35+
36+
access_token = args["access_token"]
37+
38+
# Create an API client with headers
39+
#ds-snippet-start:Admin12Step2
40+
api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
41+
api_client.set_default_header(
42+
header_name="Authorization",
43+
header_value=f"Bearer {access_token}"
44+
)
45+
#ds-snippet-end:Admin12Step2
46+
47+
#ds-snippet-start:Admin12Step4
48+
account_data = AssetGroupAccountClone(
49+
source_account=AssetGroupAccountCloneSourceAccount(
50+
id=args["source_account_id"]
51+
),
52+
target_account=AssetGroupAccountCloneTargetAccount(
53+
name=args["target_account_name"],
54+
admin=AssetGroupAccountCloneTargetAccountAdmin(
55+
first_name=args["target_account_first_name"],
56+
last_name=args["target_account_last_name"],
57+
email=args["target_account_email"]
58+
),
59+
country_code="US"
60+
)
61+
)
62+
#ds-snippet-end:Admin12Step4
63+
64+
#ds-snippet-start:Admin12Step5
65+
asset_group_api = ProvisionAssetGroupApi(api_client=api_client)
66+
results = asset_group_api.clone_asset_group_account(args["organization_id"], account_data)
67+
#ds-snippet-end:Admin12Step5
68+
69+
return results
70+
71+
@staticmethod
72+
def get_accounts(args):
73+
access_token = args["access_token"]
74+
api_client = ApiClient(host=DS_CONFIG["admin_api_client_host"])
75+
api_client.set_default_header(
76+
header_name="Authorization",
77+
header_value=f"Bearer {access_token}"
78+
)
79+
80+
#ds-snippet-start:Admin12Step3
81+
asset_group_api = ProvisionAssetGroupApi(api_client=api_client)
82+
accounts = asset_group_api.get_asset_group_accounts(args["organization_id"], compliant=True)
83+
#ds-snippet-end:Admin12Step3
84+
85+
return accounts

app/admin/views/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
from .eg009_delete_user_product_permission_profile import aeg009
1010
from .eg010_delete_user_data_from_organization import aeg010
1111
from .eg011_delete_user_data_from_account import aeg011
12+
from .eg012_clone_account import aeg012
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""Example 012: How to clone an account. """
2+
3+
import json
4+
5+
from docusign_admin.client.api_exception import ApiException
6+
from flask import Blueprint, render_template, session
7+
8+
from app.docusign import authenticate, ensure_manifest, get_example_by_number
9+
from app.error_handlers import process_error
10+
from ..examples.eg012_clone_account import Eg012CloneAccountController
11+
from ...ds_config import DS_CONFIG
12+
from ...consts import API_TYPE
13+
14+
example_number = 12
15+
api = API_TYPE["ADMIN"]
16+
eg = f"aeg0{example_number}" # Reference (and URL) for this example
17+
aeg012 = Blueprint(eg, __name__)
18+
19+
20+
@aeg012.route(f"/{eg}", methods=["POST"])
21+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
22+
@authenticate(eg=eg, api=api)
23+
def audit_users():
24+
"""
25+
1. Get required arguments
26+
2. Call the worker method
27+
3. Render the response
28+
"""
29+
example = get_example_by_number(session["manifest"], example_number, api)
30+
31+
# 1. Get required arguments
32+
args = Eg012CloneAccountController.get_args()
33+
try:
34+
# 2. Call the worker method to clone the account
35+
results = Eg012CloneAccountController.worker(args)
36+
except ApiException as err:
37+
return process_error(err)
38+
39+
return render_template(
40+
"example_done.html",
41+
title=example["ExampleName"],
42+
message=example["ResultsPageText"],
43+
json=json.dumps(json.dumps(results.to_dict(), default=str))
44+
)
45+
46+
47+
@aeg012.route(f"/{eg}", methods=["GET"])
48+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
49+
@authenticate(eg=eg, api=api)
50+
def get_view():
51+
""" Responds with the form for the example"""
52+
example = get_example_by_number(session["manifest"], example_number, api)
53+
54+
args = Eg012CloneAccountController.get_args()
55+
56+
try:
57+
accounts = Eg012CloneAccountController.get_accounts(args)
58+
except ApiException as err:
59+
process_error(err)
60+
61+
return render_template(
62+
"admin/eg012_clone_account.html",
63+
title=example["ExampleName"],
64+
example=example,
65+
source_file="eg012_clone_account.py",
66+
source_url=DS_CONFIG["admin_github_url"] + "eg012_clone_account.py",
67+
documentation=DS_CONFIG["documentation"] + eg,
68+
accounts=accounts.asset_group_accounts
69+
)
70+

app/connect/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .views import cneg001
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from flask import request
2+
import hmac
3+
import hashlib
4+
import base64
5+
6+
class Eg001ValidateWebhookMessageController:
7+
@staticmethod
8+
def get_args():
9+
"""Get required session and request arguments"""
10+
return {
11+
"secret": request.form.get("secret"),
12+
"payload": request.form.get("payload"),
13+
}
14+
15+
@staticmethod
16+
def worker(args):
17+
"""
18+
1. Create an API client with headers
19+
2. Get your monitor data via SDK
20+
"""
21+
#ds-snippet-start:Connect1Step1
22+
key = bytes(args['secret'], 'utf-8')
23+
payload = bytes(args['payload'], 'utf-8')
24+
25+
hmac_hash = hmac.new(key, payload, hashlib.sha256)
26+
result = base64.b64encode(hmac_hash.digest()).decode('utf-8')
27+
#ds-snippet-end:Connect1Step1
28+
29+
return result

app/connect/views/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .eg001_validate_webhook_message import cneg001
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Example 001: Validate webhook message using HMAC. """
2+
3+
from docusign_monitor.client.api_exception import ApiException
4+
from flask import Blueprint, render_template, session
5+
6+
from app.docusign import authenticate, ensure_manifest, get_example_by_number
7+
from app.error_handlers import process_error
8+
from ..examples.eg001_validate_webhook_message import Eg001ValidateWebhookMessageController
9+
from ...ds_config import DS_CONFIG
10+
from ...consts import API_TYPE
11+
12+
example_number = 1
13+
api = API_TYPE["CONNECT"]
14+
eg = f"cneg00{example_number}" # Reference (and URL) for this example
15+
cneg001 = Blueprint(eg, __name__)
16+
17+
@cneg001.route(f"/{eg}", methods=["POST"])
18+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
19+
def get_monitoring_data():
20+
"""
21+
1. Get required arguments
22+
2. Call the worker method
23+
3. Render the response
24+
"""
25+
example = get_example_by_number(session["manifest"], example_number, api)
26+
27+
# 1. Get required arguments
28+
args = Eg001ValidateWebhookMessageController.get_args()
29+
try:
30+
# 2. Call the worker method to compute hash
31+
results = Eg001ValidateWebhookMessageController.worker(args)
32+
except ApiException as err:
33+
return process_error(err)
34+
35+
return render_template(
36+
"example_done.html",
37+
title=example["ExampleName"],
38+
message=example["ResultsPageText"].format(results)
39+
)
40+
41+
@cneg001.route(f"/{eg}", methods=["GET"])
42+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
43+
def get_view():
44+
""" Responds with the form for the example"""
45+
example = get_example_by_number(session["manifest"], example_number, api)
46+
47+
return render_template(
48+
"connect/eg001_validate_webhook_message.html",
49+
title=example["ExampleName"],
50+
example=example,
51+
source_file= "eg001_validate_webhook_message.py",
52+
source_url=DS_CONFIG["connect_github_url"] + "eg001_validate_webhook_message.py",
53+
documentation=DS_CONFIG["documentation"] + eg,
54+
)
55+

app/consts.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,6 @@
108108
"MONITOR": "Monitor",
109109
"CLICK": "Click",
110110
"ROOMS": "Rooms",
111-
"ADMIN": "Admin"
111+
"ADMIN": "Admin",
112+
"CONNECT": "Connect"
112113
}

0 commit comments

Comments
 (0)