Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from rest_framework.serializers import Serializer, CharField, EmailField, URLField
from rest_framework.serializers import Serializer, CharField, EmailField, URLField, BooleanField

class RequestMedicalRecordsSerializer(Serializer):
name=CharField()
Expand All @@ -18,6 +18,7 @@ class ApplyForPatientAssistanceSerializer(Serializer):
first_name=CharField()
last_name=CharField()
email=EmailField()
useWithoutExtension=BooleanField()
return_url=URLField(
max_length=200, min_length=None, allow_blank=False
)
1 change: 1 addition & 0 deletions backend/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
path('request-medical-records', views.request_medical_records),
path('covid19-consent-form', views.covid19_consent_form),
path('apply-for-patient-assistance', views.apply_for_patient_assistance),
path('extensions', views.get_extension_apps),
]
53 changes: 43 additions & 10 deletions backend/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from docusign.template import Template
from docusign.envelope import Envelope
from docusign.workflow import get_idv_workflow, is_sms_workflow
from docusign.extensions import Extensions

from .serializers import (
RequestMedicalRecordsSerializer,
Expand Down Expand Up @@ -72,19 +73,51 @@ def apply_for_patient_assistance(request):
"""
The Apply for Patient Assistance flow
"""
serializer = ApplyForPatientAssistanceSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
try:
serializer = ApplyForPatientAssistanceSerializer(data=request.data)
serializer.is_valid(raise_exception=True)

args = serializer.validated_data.copy()
args = serializer.validated_data.copy()

template_request = Template.make_application_for_participation(args)
template_id = Template.create(request.session, template_request)
template_request = Template.make_application_for_participation(args, request.session)
template_id = Template.create(request.session, template_request)

args["template_id"] = template_id
args["template_id"] = template_id

envelope_definition = Envelope.create_application_for_participation_definition(args)
envelope_definition = Envelope.create_application_for_participation_definition(args)

envelope_id = Envelope.send(request.session, envelope_definition)
view_url = Envelope.get_view_url(request.session, envelope_id, args)
envelope_id = Envelope.send(request.session, envelope_definition)
view_url = Envelope.get_view_url(request.session, envelope_id, args)

return Response({"view_url": view_url, "client_id": os.environ.get('CLIENT_ID')})
return Response({"view_url": view_url, "client_id": os.environ.get('CLIENT_ID')})
except Exception as err:
print(err)

@api_view(['GET'])
@error_processing
def get_extension_apps(request):
"""
Retrieve the list of extensions
"""
try:
extensions = Extensions.get_extension_apps(request.session)
actual_extension_app_ids = [item["appId"] for item in extensions]

required_ids = {
Extensions.get_address_extension_id(),
Extensions.get_phone_extension_id(),
Extensions.get_ssn_extension_id(),
}

# Check missing apps one by one
missing_app_ids = [app_id for app_id in required_ids if app_id not in actual_extension_app_ids]
for app_id in missing_app_ids:
result = Extensions.get_extension_app(request.session, app_id)
if result and len(result) > 0 and not "code" in result:
actual_extension_app_ids.append(result[0]["appId"])

has_all_app_ids = all(app_id in actual_extension_app_ids for app_id in required_ids)

return Response({"areExtensionsPresent": has_all_app_ids})
except Exception as err:
print(err)
9 changes: 6 additions & 3 deletions backend/auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ def jwt_auth(request):
"""
Endpoint of user authorization using JWT
"""
auth_data = DsClient.jwt_auth()
try:
auth_data = DsClient.jwt_auth()

SessionData.set_auth_data(request.session, auth_data)
SessionData.set_auth_data(request.session, auth_data)

return Response({"message": "Logged in with JWT"})
return Response({"message": "Logged in with JWT"})
except Exception as err:
print(err.body)
9 changes: 7 additions & 2 deletions backend/docusign/ds_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
TOKEN_EXPIRATION_IN_SECONDS = 3600
TOKEN_REPLACEMENT_IN_SECONDS = 10 * 60

CODE_GRANT_SCOPES = ['signature', 'click.manage']
PERMISSION_SCOPES = ['signature', 'impersonation', 'click.manage']
CODE_GRANT_SCOPES = ['signature', 'click.manage', 'adm_store_unified_repo_read']
PERMISSION_SCOPES = ['signature', 'impersonation', 'click.manage', 'adm_store_unified_repo_read']

CONNECTED_FIELDS_BASE_HOST = 'https://api-d.docusign.com'
PHONE_EXTENSION_ID = "d16f398f-8b9a-4f94-b37c-af6f9c910c04"
SMARTY_EXTENSION_ID = "04bfc1ae-1ba0-42d0-8c02-264417a7b234"
SSN_EXTENSION_ID = "b1adf7ad-38fd-44ba-85f5-38ea87f4af23"

DS_RETURN_URL = os.environ.get('REACT_APP_DS_RETURN_URL')
DS_AUTH_SERVER = os.environ.get('DS_AUTH_SERVER')
Expand Down
78 changes: 78 additions & 0 deletions backend/docusign/extensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import requests
from docusign.ds_config import SMARTY_EXTENSION_ID, PHONE_EXTENSION_ID, SSN_EXTENSION_ID, CONNECTED_FIELDS_BASE_HOST

class Extensions:
@staticmethod
def get_extension_apps(session):
headers = {
"Authorization": "Bearer " + session['access_token'],
"Accept": "application/json",
"Content-Type": "application/json"
}

url = f"{CONNECTED_FIELDS_BASE_HOST}/v1/accounts/{session['account_id']}/connected-fields/tab-groups"
response = requests.get(url, headers=headers)

return response.json()

def get_extension_app(session, appId):
headers = {
"Authorization": "Bearer " + session['access_token'],
"Accept": "application/json",
"Content-Type": "application/json"
}

url = f"{CONNECTED_FIELDS_BASE_HOST}/v1/accounts/{session['account_id']}/connected-fields/tab-groups?appId={appId}"
response = requests.get(url, headers=headers)

return response.json()

@staticmethod
def get_address_extension_id():
return SMARTY_EXTENSION_ID

@staticmethod
def get_phone_extension_id():
return PHONE_EXTENSION_ID

@staticmethod
def get_ssn_extension_id():
return SSN_EXTENSION_ID

@staticmethod
def get_extension_by_app_id(objects, app_id):
return next((obj for obj in objects if obj["appId"] == app_id), None)

@staticmethod
def extract_verification_data(selected_app_id, tab):
extension_data = tab["extensionData"]

return {
"app_id": selected_app_id,
"extension_group_id": extension_data["extensionGroupId"] if "extensionGroupId" in extension_data else "",
"publisher_name": extension_data["publisherName"] if "publisherName" in extension_data else "",
"application_name": extension_data["applicationName"] if "applicationName" in extension_data else "",
"action_name": extension_data["actionName"] if "actionName" in extension_data else "",
"action_input_key": extension_data["actionInputKey"] if "actionInputKey" in extension_data else "",
"action_contract": extension_data["actionContract"] if "actionContract" in extension_data else "",
"extension_name": extension_data["extensionName"] if "extensionName" in extension_data else "",
"extension_contract": extension_data["extensionContract"] if "extensionContract" in extension_data else "",
"required_for_extension": extension_data["requiredForExtension"] if "requiredForExtension" in extension_data else "",
"tab_label": tab["tabLabel"],
}

@staticmethod
def get_extension_data(verification_data):
return {
"extensionGroupId": verification_data["extension_group_id"],
"publisherName": verification_data["publisher_name"],
"applicationId": verification_data["app_id"],
"applicationName": verification_data["application_name"],
"actionName": verification_data["action_name"],
"actionContract": verification_data["action_contract"],
"extensionName": verification_data["extension_name"],
"extensionContract": verification_data["extension_contract"],
"requiredForExtension": verification_data["required_for_extension"],
"actionInputKey": verification_data["action_input_key"],
"extensionPolicy": 'MustVerifyToSign'
}
Binary file modified backend/docusign/pdf/Application_for_participation_v2.pdf
Binary file not shown.
4 changes: 2 additions & 2 deletions backend/docusign/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ def make_covid_19_consent_form(cls, args):
return cls.make_request(template_name, document, signer)

@classmethod
def make_application_for_participation(cls, args):
def make_application_for_participation(cls, args, session):
"""
Make template_request for application_for_participation endpoint
"""
template_name = "ApplicationForParticipationTemplate"
document = create_document("Application_for_participation_v2.pdf")
signer = make_application_for_participation_signer(args)
signer = make_application_for_participation_signer(args, session)

return cls.make_request(template_name, document, signer)
Loading