Skip to content

Commit 9058554

Browse files
committed
2 parents 6fbbc4b + 65df0e0 commit 9058554

Some content is hidden

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

46 files changed

+1510
-85
lines changed

.gitignore

+3
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

Dockerfile

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# start by pulling the python image
2+
FROM python:3.11.9-slim-bullseye
3+
4+
# copy the requirements file into the image
5+
COPY ./requirements.txt /app/requirements.txt
6+
7+
# switch working directory
8+
WORKDIR /app
9+
10+
# install the dependencies and packages in the requirements file
11+
RUN pip install -r requirements.txt
12+
13+
# copy every content from the local file to the image
14+
COPY . /app
15+
16+
# configure the container to run in an executed manner
17+
ENTRYPOINT [ "python" ]
18+
19+
CMD ["run.py", "--docker"]

PAYMENTS_INSTALLATION.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ DocuSign offers built-in connections to multiple payment gateways. The payments
1111

1212
![Skipping the Stripe account form](docs/stripe_skip_account_form_link.png)
1313

14-
An enabled Stripe payment gateway is now associated with your DocuSign developer account and is shown under **Payment Gateway**.
14+
An enabled Stripe payment gateway is now associated with your Docusign developer account and is shown under **Payment Gateway**.
1515

1616
1. Save the **Gateway Account ID** GUID to the code example launcher configuration file.
1717

app/__init__.py

+5
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

+3
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

+8
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

+11-1
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

+2
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://apps-d.docusign.com/api/maestro",
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
@@ -28,6 +29,7 @@
2829
"doc_terms_pdf": "Term_Of_Service.pdf",
2930
"doc_txt": "Welcome.txt",
3031
"doc_offer_letter": "Offer_Letter_Demo.docx",
32+
"doc_dynamic_table": "Offer_Letter_Dynamic_Table.docx",
3133
# Payment gateway information is optional
3234
"gateway_account_id": "{DS_PAYMENT_GATEWAY_ID}",
3335
"gateway_name": "stripe",

app/eSignature/examples/eg011_embedded_sending.py

+40-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import base64
22
from os import path
33

4-
from docusign_esign import EnvelopesApi, ReturnUrlRequest, EnvelopesApi, EnvelopeDefinition, \
5-
Document, Signer, CarbonCopy, SignHere, Tabs, Recipients
4+
from docusign_esign import EnvelopesApi, EnvelopesApi, EnvelopeDefinition, \
5+
Document, Signer, CarbonCopy, SignHere, Tabs, Recipients, EnvelopeViewRequest, EnvelopeViewSettings, \
6+
EnvelopeViewRecipientSettings, EnvelopeViewDocumentSettings, EnvelopeViewTaggerSettings, EnvelopeViewTemplateSettings
67
from flask import url_for, session, request
78

89
from ...consts import pattern, demo_docs_path
@@ -36,6 +37,7 @@ def get_args():
3637
"access_token": session["ds_access_token"],
3738
"envelope_args": envelope_args,
3839
"ds_return_url": url_for("ds.ds_return", _external=True),
40+
"starting_view": starting_view,
3941
}
4042
return args
4143

@@ -58,23 +60,55 @@ def worker(cls, args, doc_docx_path, doc_pdf_path):
5860
@classmethod
5961
#ds-snippet-start:eSign11Step3
6062
def create_sender_view(cls, args, envelope_id):
61-
view_request = ReturnUrlRequest(return_url=args["ds_return_url"])
63+
view_request = cls.make_envelope_view_request(args)
6264
# Exceptions will be caught by the calling function
6365
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
6466

6567
envelope_api = EnvelopesApi(api_client)
6668
sender_view = envelope_api.create_sender_view(
6769
account_id=args["account_id"],
6870
envelope_id=envelope_id,
69-
return_url_request=view_request
71+
envelope_view_request=view_request
7072
)
7173

7274
# Switch to Recipient and Documents view if requested by the user
7375
url = sender_view.url
74-
if args["starting_view"] == "recipient":
75-
url = url.replace("send=1", "send=0")
7676

7777
return url
78+
79+
@classmethod
80+
def make_envelope_view_request(cls, args):
81+
view_request = EnvelopeViewRequest(
82+
return_url=args["ds_return_url"],
83+
view_access="envelope",
84+
settings=EnvelopeViewSettings(
85+
starting_screen=args["starting_view"],
86+
send_button_action="send",
87+
show_back_button="false",
88+
back_button_action="previousPage",
89+
show_header_actions="false",
90+
show_discard_action="false",
91+
lock_token="",
92+
recipient_settings=EnvelopeViewRecipientSettings(
93+
show_edit_recipients="false",
94+
show_contacts_list="false"
95+
),
96+
document_settings=EnvelopeViewDocumentSettings(
97+
show_edit_documents="false",
98+
show_edit_document_visibility="false",
99+
show_edit_pages="false"
100+
),
101+
tagger_settings=EnvelopeViewTaggerSettings(
102+
palette_sections="default",
103+
palette_default="custom"
104+
),
105+
template_settings=EnvelopeViewTemplateSettings(
106+
show_matching_templates_prompt="true"
107+
)
108+
)
109+
)
110+
111+
return view_request
78112
#ds-snippet-end:eSign11Step3
79113

80114
@classmethod

app/eSignature/examples/eg040_document_visibility.py

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def make_envelope(cls, args, doc_docx_path, doc_pdf_path):
8282
"""
8383
env = EnvelopeDefinition(
8484
email_subject = "Please sign this document set",
85+
enforce_signer_visibility = "true",
8586
)
8687

8788
doc1_b64 = base64.b64encode(bytes(cls.create_document1(args), "utf-8")).decode("ascii")

app/eSignature/examples/eg042_document_generation.py

+47-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from os import path
44
from docusign_esign import EnvelopesApi, TemplatesApi, EnvelopeDefinition, Document, Signer, SignHere, \
55
DateSigned, Tabs, Recipients, DocGenFormField, EnvelopeTemplate, TemplateRole, DocGenFormFields, \
6-
DocGenFormFieldRequest, Envelope
6+
DocGenFormFieldRequest, Envelope, DocGenFormFieldRowValue
77

88
from ...consts import demo_docs_path, pattern
99
from ...ds_config import DS_CONFIG
@@ -20,8 +20,9 @@ def get_args():
2020
"manager_name": pattern.sub("", request.form.get("manager_name")),
2121
"job_title": pattern.sub("", request.form.get("job_title")),
2222
"salary": pattern.sub("", request.form.get("salary")),
23+
"rsus": pattern.sub("", request.form.get("rsus")),
2324
"start_date": pattern.sub("", request.form.get("start_date")),
24-
"doc_file": path.join(demo_docs_path, DS_CONFIG["doc_offer_letter"])
25+
"doc_file": path.join(demo_docs_path, DS_CONFIG["doc_dynamic_table"])
2526
}
2627
args = {
2728
"account_id": session["ds_account_id"],
@@ -164,7 +165,7 @@ def recipient_tabs(cls):
164165
anchor_y_offset="-22"
165166
)
166167
date_signed = DateSigned(
167-
anchor_string="Date",
168+
anchor_string="Date Signed",
168169
anchor_units="pixels",
169170
anchor_y_offset="-22"
170171
)
@@ -197,6 +198,7 @@ def make_envelope(cls, template_id, args):
197198
#ds-snippet-start:eSign42Step7
198199
@classmethod
199200
def form_fields(cls, args, document_id_guid):
201+
bonus_value = "20%"
200202
doc_gen_form_field_request = DocGenFormFieldRequest(
201203
doc_gen_form_fields=[
202204
DocGenFormFields(
@@ -214,13 +216,51 @@ def form_fields(cls, args, document_id_guid):
214216
name="Job_Title",
215217
value=args["job_title"]
216218
),
217-
DocGenFormField(
218-
name="Salary",
219-
value=args["salary"]
220-
),
221219
DocGenFormField(
222220
name="Start_Date",
223221
value=args["start_date"]
222+
),
223+
DocGenFormField(
224+
name="Compensation_Package",
225+
type="TableRow",
226+
row_values=[
227+
DocGenFormFieldRowValue(
228+
doc_gen_form_field_list=[
229+
DocGenFormField(
230+
name="Compensation_Component",
231+
value="Salary"
232+
),
233+
DocGenFormField(
234+
name="Details",
235+
value=f"${args['salary']}"
236+
)
237+
]
238+
),
239+
DocGenFormFieldRowValue(
240+
doc_gen_form_field_list=[
241+
DocGenFormField(
242+
name="Compensation_Component",
243+
value="Bonus"
244+
),
245+
DocGenFormField(
246+
name="Details",
247+
value=bonus_value
248+
)
249+
]
250+
),
251+
DocGenFormFieldRowValue(
252+
doc_gen_form_field_list=[
253+
DocGenFormField(
254+
name="Compensation_Component",
255+
value="RSUs"
256+
),
257+
DocGenFormField(
258+
name="Details",
259+
value=args["rsus"]
260+
)
261+
]
262+
)
263+
]
224264
)
225265
]
226266
)

app/eSignature/views/eg020_phone_authentication.py

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ def phone_authentication():
3232

3333
# 1. Get required arguments
3434
args = Eg020PhoneAuthenticationController.get_args()
35+
if args["envelope_args"]["signer_email"] == DS_CONFIG["signer_email"]:
36+
return render_template(
37+
"error.html",
38+
error_code=400,
39+
error_message=session["manifest"]["SupportingTexts"]["IdenticalEmailsNotAllowedErrorMessage"]
40+
)
41+
3542
try:
3643
# Step 2: Call the worker method for authenticating with phone
3744
results = Eg020PhoneAuthenticationController.worker(args)

app/eSignature/views/eg022_kba_authentication.py

+7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ def kba_authentication():
3131

3232
# 1. Get required arguments
3333
args = Eg022KBAAuthenticationController.get_args()
34+
35+
if args["envelope_args"]["signer_email"] == DS_CONFIG["signer_email"]:
36+
return render_template(
37+
"error.html",
38+
error_code=400,
39+
error_message=session["manifest"]["SupportingTexts"]["IdenticalEmailsNotAllowedErrorMessage"]
40+
)
3441
try:
3542
# Step 2: Call the worker method for kba
3643
results = Eg022KBAAuthenticationController.worker(args)

app/eSignature/views/eg023_idv_authentication.py

+7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ def idv_authentication():
3131

3232
# 1. Get required data
3333
args = Eg023IDVAuthenticationController.get_args()
34+
35+
if args["envelope_args"]["signer_email"] == DS_CONFIG["signer_email"]:
36+
return render_template(
37+
"error.html",
38+
error_code=400,
39+
error_message=session["manifest"]["SupportingTexts"]["IdenticalEmailsNotAllowedErrorMessage"]
40+
)
3441
try:
3542
# 2: Call the worker method for idv authentication
3643
results = Eg023IDVAuthenticationController.worker(args)

app/maestro/__init__.py

+3
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

0 commit comments

Comments
 (0)