Skip to content

Commit 85deeee

Browse files
Added maestro code examples (#142)
* added examples * updates and fixes * remove redundant scope * update example 1 * adding codeDepot markers --------- Co-authored-by: Paige Rossi <paige.rossi@docusign.com>
1 parent a1b98a1 commit 85deeee

22 files changed

+1290
-3
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,6 @@ private.key
123123
# Current flask session
124124

125125
flask_session/
126+
127+
# Workflow ID file
128+
WORKFLOW_ID.txt

app/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .monitor import views as monitor_views
1313
from .admin import views as admin_views
1414
from .connect import views as connect_views
15+
from .maestro import views as maestro_views
1516
from .webforms import views as webforms_views
1617
from .views import core
1718

@@ -114,6 +115,10 @@
114115

115116
app.register_blueprint(connect_views.cneg001)
116117

118+
app.register_blueprint(maestro_views.mseg001)
119+
app.register_blueprint(maestro_views.mseg002)
120+
app.register_blueprint(maestro_views.mseg003)
121+
117122
app.register_blueprint(webforms_views.weg001)
118123

119124
if "DYNO" in os.environ: # On Heroku?

app/consts.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
# Base uri for callback function
3030
base_uri_suffix = "/restapi"
3131

32+
# Workflow name
33+
workflow_name = "Example workflow - send invite to signer"
3234

3335
# Default languages for brand
3436
languages = {
@@ -114,5 +116,6 @@
114116
"ROOMS": "Rooms",
115117
"ADMIN": "Admin",
116118
"CONNECT": "Connect",
119+
"MAESTRO": "Maestro",
117120
"WEBFORMS": "WebForms"
118121
}

app/docusign/ds_client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
"asset_group_account_read", "asset_group_account_clone_write", "asset_group_account_clone_read"
3434
]
3535

36+
MAESTRO_SCOPES = [
37+
"signature", "aow_manage"
38+
]
39+
3640
WEBFORMS_SCOPES = [
3741
"signature", "webforms_read", "webforms_instance_read", "webforms_instance_write"
3842
]
@@ -61,6 +65,8 @@ def _auth_code_grant(cls, api):
6165
use_scopes.extend(CLICK_SCOPES)
6266
elif api == "Admin":
6367
use_scopes.extend(ADMIN_SCOPES)
68+
elif api == "Maestro":
69+
use_scopes.extend(MAESTRO_SCOPES)
6470
elif api == "WebForms":
6571
use_scopes.extend(WEBFORMS_SCOPES)
6672
else:
@@ -99,6 +105,8 @@ def _jwt_auth(cls, api):
99105
use_scopes.extend(CLICK_SCOPES)
100106
elif api == "Admin":
101107
use_scopes.extend(ADMIN_SCOPES)
108+
elif api == "Maestro":
109+
use_scopes.extend(MAESTRO_SCOPES)
102110
elif api == "WebForms":
103111
use_scopes.extend(WEBFORMS_SCOPES)
104112
else:

app/docusign/utils.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import timedelta, datetime
22
from functools import wraps
33
import requests
4-
import urllib
4+
from urllib.parse import urlparse, parse_qs
55
import json
66
import re
77

@@ -148,6 +148,16 @@ def get_user_info(access_token, base_path, oauth_host_name):
148148
api_client.set_oauth_host_name(oauth_host_name)
149149
return api_client.get_user_info(access_token)
150150

151+
def get_parameter_value_from_url(url, param_name):
152+
parsed_url = urlparse(url)
153+
query_params = parse_qs(parsed_url.query)
154+
155+
# Access the parameter value (returns a list)
156+
param_value_list = query_params.get(param_name, [])
157+
158+
# If the parameter exists, return the first value; otherwise, return None
159+
return param_value_list[0] if param_value_list else None
160+
151161
def replace_template_id(file_path, template_id):
152162
with open(file_path, 'r') as file:
153163
content = file.read()

app/ds_config_sample.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"rooms_api_client_host": "https://demo.rooms.docusign.com/restapi",
1717
"monitor_api_client_host": "https://lens-d.docusign.net",
1818
"admin_api_client_host": "https://api-d.docusign.net/management",
19+
"maestro_api_client_host": "https://demo.services.docusign.net/",
1920
"webforms_api_client_host": "https://apps-d.docusign.com/api/webforms/v1.1",
2021
"allow_silent_authentication": True, # a user can be silently authenticated if they have an
2122
# active login session on another tab of the same browser

app/maestro/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .views import mseg001
2+
from .views import mseg002
3+
from .views import mseg003
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from docusign_maestro import WorkflowManagementApi, WorkflowTriggerApi, TriggerPayload
2+
from flask import session, request
3+
4+
from app.docusign.utils import get_parameter_value_from_url
5+
from app.ds_config import DS_CONFIG
6+
from app.maestro.utils import create_maestro_api_client
7+
from app.consts import pattern
8+
9+
10+
class Eg001TriggerWorkflowController:
11+
@staticmethod
12+
def get_args():
13+
"""Get request and session arguments"""
14+
return {
15+
"account_id": session["ds_account_id"],
16+
"base_path": DS_CONFIG["maestro_api_client_host"],
17+
"access_token": session["ds_access_token"],
18+
"workflow_id": session["workflow_id"],
19+
"instance_name": pattern.sub("", request.form.get("instance_name")),
20+
"signer_email": pattern.sub("", request.form.get("signer_email")),
21+
"signer_name": pattern.sub("", request.form.get("signer_name")),
22+
"cc_email": pattern.sub("", request.form.get("cc_email")),
23+
"cc_name": pattern.sub("", request.form.get("cc_name")),
24+
}
25+
26+
@staticmethod
27+
def get_workflow_definitions(args):
28+
api_client = create_maestro_api_client(args["base_path"], args["access_token"])
29+
workflow_management_api = WorkflowManagementApi(api_client)
30+
workflow_definitions = workflow_management_api.get_workflow_definitions(args["account_id"], status="active")
31+
32+
return workflow_definitions
33+
34+
@staticmethod
35+
def get_workflow_definition(args):
36+
#ds-snippet-start:Maestro1Step2
37+
api_client = create_maestro_api_client(args["base_path"], args["access_token"])
38+
#ds-snippet-end:Maestro1Step2
39+
40+
#ds-snippet-start:Maestro1Step3
41+
workflow_management_api = WorkflowManagementApi(api_client)
42+
workflow_definition = workflow_management_api.get_workflow_definition(args["account_id"], args["workflow_id"])
43+
#ds-snippet-end:Maestro1Step3
44+
45+
return workflow_definition
46+
47+
@staticmethod
48+
def trigger_workflow(workflow, args):
49+
api_client = create_maestro_api_client(args["base_path"], args["access_token"])
50+
51+
#ds-snippet-start:Maestro1Step4
52+
trigger_payload = TriggerPayload(
53+
instance_name=args["instance_name"],
54+
participant={},
55+
payload={
56+
"signerEmail": args["signer_email"],
57+
"signerName": args["signer_name"],
58+
"ccEmail": args["cc_email"],
59+
"ccName": args["cc_name"]
60+
},
61+
metadata={}
62+
)
63+
mtid = get_parameter_value_from_url(workflow.trigger_url, "mtid")
64+
mtsec = get_parameter_value_from_url(workflow.trigger_url, "mtsec")
65+
#ds-snippet-end:Maestro1Step4
66+
67+
#ds-snippet-start:Maestro1Step5
68+
workflow_trigger_api = WorkflowTriggerApi(api_client)
69+
trigger_response = workflow_trigger_api.trigger_workflow(
70+
args["account_id"],
71+
trigger_payload,
72+
mtid=mtid, mtsec=mtsec
73+
)
74+
#ds-snippet-end:Maestro1Step5
75+
return trigger_response
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from docusign_maestro import WorkflowInstanceManagementApi
2+
from flask import session
3+
4+
from app.ds_config import DS_CONFIG
5+
from app.maestro.utils import create_maestro_api_client
6+
7+
8+
class Eg002CancelWorkflowController:
9+
@staticmethod
10+
def get_args():
11+
"""Get request and session arguments"""
12+
return {
13+
"account_id": session["ds_account_id"],
14+
"base_path": DS_CONFIG["maestro_api_client_host"],
15+
"access_token": session["ds_access_token"],
16+
"workflow_id": session["workflow_id"],
17+
"instance_id": session["instance_id"]
18+
}
19+
20+
@staticmethod
21+
def get_instance_state(args):
22+
api_client = create_maestro_api_client(args["base_path"], args["access_token"])
23+
workflow_instance_management_api = WorkflowInstanceManagementApi(api_client)
24+
instance = workflow_instance_management_api.get_workflow_instance(
25+
args["account_id"],
26+
args["workflow_id"],
27+
args["instance_id"]
28+
)
29+
30+
return instance.instance_state
31+
32+
@staticmethod
33+
def cancel_workflow_instance(args):
34+
#ds-snippet-start:Maestro2Step2
35+
api_client = create_maestro_api_client(args["base_path"], args["access_token"])
36+
#ds-snippet-end:Maestro2Step2
37+
38+
#ds-snippet-start:Maestro2Step3
39+
workflow_instance_management_api = WorkflowInstanceManagementApi(api_client)
40+
cancel_result = workflow_instance_management_api.cancel_workflow_instance(
41+
args["account_id"],
42+
args["instance_id"]
43+
)
44+
#ds-snippet-end:Maestro2Step3
45+
return cancel_result
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from docusign_maestro import WorkflowInstanceManagementApi
2+
from flask import session
3+
4+
from app.ds_config import DS_CONFIG
5+
from app.maestro.utils import create_maestro_api_client
6+
7+
8+
class Eg003GetWorkflowStatusController:
9+
@staticmethod
10+
def get_args():
11+
"""Get request and session arguments"""
12+
return {
13+
"account_id": session["ds_account_id"],
14+
"base_path": DS_CONFIG["maestro_api_client_host"],
15+
"access_token": session["ds_access_token"],
16+
"workflow_id": session["workflow_id"],
17+
"instance_id": session["instance_id"]
18+
}
19+
20+
@staticmethod
21+
def get_workflow_instance(args):
22+
#ds-snippet-start:Maestro3Step2
23+
api_client = create_maestro_api_client(args["base_path"], args["access_token"])
24+
#ds-snippet-end:Maestro3Step2
25+
26+
#ds-snippet-start:Maestro3Step3
27+
workflow_instance_management_api = WorkflowInstanceManagementApi(api_client)
28+
instance = workflow_instance_management_api.get_workflow_instance(
29+
args["account_id"],
30+
args["workflow_id"],
31+
args["instance_id"]
32+
)
33+
#ds-snippet-end:Maestro3Step3
34+
35+
return instance

0 commit comments

Comments
 (0)