Skip to content

Commit

Permalink
Feature/Docusign Legacy Authentication
Browse files Browse the repository at this point in the history
- Reverted to legacy authentication for docusign

Signed-off-by: Harold Wanyama <[email protected]>
  • Loading branch information
nickmango committed Sep 5, 2023
1 parent 506338c commit bc6e7cb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 99 deletions.
77 changes: 37 additions & 40 deletions cla-backend/cla/models/docusign_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,26 @@
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse

import cla
import pydocusign # type: ignore
import requests
from attr import dataclass
from pydocusign.exceptions import DocuSignException # type: ignore

import cla
from cla.controllers.lf_group import LFGroup
from cla.models import DoesNotExist, signing_service_interface
from cla.docusign_auth import request_access_token
from cla.models.dynamo_models import (Company, Document, Event, Gerrit,
Project, Signature, User)
from cla.models.event_types import EventType
from cla.models.s3_storage import S3Storage
from cla.user_service import UserService
from cla.utils import (append_email_help_sign_off_content, get_corporate_url,
get_email_help_content, get_project_cla_group_instance)
from pydocusign.exceptions import DocuSignException # type: ignore

api_base_url = os.environ.get('CLA_API_BASE', '')
root_url = os.environ.get('DOCUSIGN_ROOT_URL', '')
integrator_key = cla.config.DOCUSIGN_INTEGRATOR_KEY
user_id = cla.config.DOCUSIGN_USER_ID
private_key = cla.config.DOCUSIGN_PRIVATE_KEY
auth_server = os.environ.get('DOCUSIGN_AUTH_SERVER')
token_endpoint = f'https://{auth_server}/oauth/token'

username = os.environ.get('DOCUSIGN_USERNAME', '')
password = os.environ.get('DOCUSIGN_PASSWORD', '')
integrator_key = os.environ.get('DOCUSIGN_INTEGRATOR_KEY', '')

lf_group_client_url = os.environ.get('LF_GROUP_CLIENT_URL', '')
lf_group_client_id = os.environ.get('LF_GROUP_CLIENT_ID', '')
Expand Down Expand Up @@ -106,14 +101,28 @@ def __init__(self):
self.s3storage = None

def initialize(self, config):
try:
cla.log.debug('Initializing DocuSign client...')
token = request_access_token()
self.client = pydocusign.DocuSignClient(root_url=root_url,oauth2_token=token)
except (Exception) as ex:
cla.log.error("Error authenticating Docusign: {}".format(ex))
return {'errors': {'Error authenticating Docusign'}}
self.client = pydocusign.DocuSignClient(root_url=root_url,
username=username,
password=password,
integrator_key=integrator_key)

try:
login_data = self.client.login_information()
login_account = login_data['loginAccounts'][0]
base_url = login_account['baseUrl']
account_id = login_account['accountId']
url = urlparse(base_url)
parsed_root_url = '{}://{}/restapi/v2'.format(url.scheme, url.netloc)
except Exception as e:
cla.log.error('Error logging in to DocuSign: {}'.format(e))
return {'errors': {'Error initializing DocuSign'}}

self.client = pydocusign.DocuSignClient(root_url=parsed_root_url,
account_url=base_url,
account_id=account_id,
username=username,
password=password,
integrator_key=integrator_key)
self.s3storage = S3Storage()
self.s3storage.initialize(None)

Expand Down Expand Up @@ -1362,26 +1371,16 @@ def populate_sign_url(self, signature, callback_url=None,
emailBody='CLA Sign Request for {}'.format(user_identifier),
supportedLanguage='en',
)



content_type = document.get_document_content_type()
try:
cla.log.debug(f'{fn} - {sig_type} - docusign document content type: {content_type}')
if document.get_document_s3_url() is not None:
pdf = self.get_document_resource(document.get_document_s3_url())
elif content_type.startswith('url+'):
pdf_url = document.get_document_content()
pdf = self.get_document_resource(pdf_url)
else:
cla.log.debug(f'{fn} - getting document content...')
content = document.get_document_content()
pdf = io.BytesIO(content)

except Exception as e:
cla.log.warning(f'{fn} - {sig_type} - error getting document resource: {e}')
return


if document.get_document_s3_url() is not None:
pdf = self.get_document_resource(document.get_document_s3_url())
elif content_type.startswith('url+'):
pdf_url = document.get_document_content()
pdf = self.get_document_resource(pdf_url)
else:
content = document.get_document_content()
pdf = io.BytesIO(content)

doc_name = document.get_document_name()
cla.log.debug(f'{fn} - {sig_type} - docusign document '
Expand Down Expand Up @@ -1411,7 +1410,6 @@ def populate_sign_url(self, signature, callback_url=None,
status=pydocusign.Envelope.STATUS_SENT,
recipients=[signer])

cla.log.debug(f'{fn} - {sig_type} - sending signature request to DocuSign...')
envelope = self.prepare_sign_request(envelope)

if not send_as_email:
Expand Down Expand Up @@ -1969,8 +1967,7 @@ def get_document_resource(self, url): # pylint: disable=no-self-use
:return: A resource that can be read()'d.
:rtype: Resource
"""
return requests.get(url, stream=True).raw
# return urllib.request.urlopen(url)
return urllib.request.urlopen(url)

def prepare_sign_request(self, envelope):
"""
Expand Down Expand Up @@ -2420,4 +2417,4 @@ def cla_signatory_email_content(params: ClaSignatoryEmailParams) -> (str, str):
email_body += f'<p>After you sign, {params.cla_manager_name} (as the initial CLA Manager for your company) will be able to maintain the list of specific employees authorized to contribute to the project(s) under this signed CLA.</p>'
email_body += f'<p>If you are authorized to sign on your company’s behalf, and if you approve {params.cla_manager_name} as your initial CLA Manager, please review the document and sign the CLA. If you have questions, or if you are not an authorized signatory of this company, please contact the requester at {params.cla_manager_email}.</p>'
email_body = append_email_help_sign_off_content(email_body, params.project_version)
return email_subject, email_body
return email_subject, email_body
66 changes: 7 additions & 59 deletions cla-backend/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: MIT

service: cla-backend
frameworkVersion: '^3.34.0'
frameworkVersion: '^3.28.1'

package:
# Exclude all first - selectively add in lambda functions
Expand All @@ -25,23 +25,14 @@ package:
- '!node_modules/**'
- '!package-lock.json'
- '!yarn.lock'
- '!**/test/**'
- '!**/tests/**'
- '!**/*test*.py'
- '!tests/**'
- '!**/_pytest/**'
- '!**/pytest*/**'
- '!**/test_*'
- '!**/LICENSE'
- '!**/README*'
- '.serverless-wsgi'

custom:
allowed_origins: ${file(./env.json):cla-allowed-origins-${sls:stage}, ssm:/cla-allowed-origins-${sls:stage}}
wsgi:
app: cla.routes.__hug_wsgi__
pythonBin: python
pythonRequirements: false
packRequirements: false
# Config for serverless-prune-plugin - remove all but the 10 most recent
# versions to avoid the "Code storage limit exceeded" error
prune:
Expand Down Expand Up @@ -107,10 +98,6 @@ custom:
dev: [email protected]
staging: [email protected]
prod: [email protected]
ecr_img:
dev: 395594542180.dkr.ecr.us-east-1.amazonaws.com/lfx-easycla-${sls:stage}:latest
staging: 844390194980.dkr.ecr.us-east-1.amazonaws.com/lfx-easycla-${sls:stage}:latest
prod: 716487311010.dkr.ecr.us-east-1.amazonaws.com/lfx-easycla-${sls:stage}:latest

provider:
name: aws
Expand All @@ -121,12 +108,6 @@ provider:
logRetentionInDays: 14
lambdaHashingVersion: '20201221' # Resolution of lambda version hashes was improved with better algorithm, which will be used in next major release. Switch to it now by setting "provider.lambdaHashingVersion" to "20201221"

ecr:
# In this section you can define images that will be built locally and uploaded to ECR
images:
easyclaPythonAppImage:
uri: ${self:custom.ecr_img.${sls:stage}

apiGateway:
# https://www.serverless.com/framework/docs/deprecations/#AWS_API_GATEWAY_NAME_STARTING_WITH_SERVICE
shouldStartNameWithService: true
Expand Down Expand Up @@ -340,6 +321,9 @@ provider:
DOCUSIGN_ROOT_URL: ${file(./env.json):docusign-root-url, ssm:/cla-docusign-root-url-${sls:stage}}
DOCUSIGN_USERNAME: ${file(./env.json):docusign-username, ssm:/cla-docusign-username-${sls:stage}}
DOCUSIGN_PASSWORD: ${file(./env.json):docusign-password, ssm:/cla-docusign-password-${sls:stage}}
DOCUSIGN_INTEGRATOR_KEY: ${file(./env.json):docusign-integrator-key, ssm:/cla-docusign-integrator-key-${sls:stage}}
DOCUSIGN_PRIVATE_KEY: ${file(./env.json):docusign-private-key, ssm:/cla-docusign-private-key-${sls:stage}}
DOCUSIGN_USER_ID: ${file(./env.json):docusign-user-id, ssm:/cla-docusign-user-id-${sls:stage}}
DOCUSIGN_AUTH_SERVER: ${file(./env.json):docusign-auth-server, ssm:/cla-docusign-auth-server-${sls:stage}}
CLA_API_BASE: ${file(./env.json):cla-api-base, ssm:/cla-api-base-${sls:stage}}
CLA_CONTRIBUTOR_BASE: ${file(./env.json):cla-contributor-base, ssm:/cla-contributor-base-${sls:stage}}
Expand Down Expand Up @@ -398,7 +382,7 @@ provider:
Owner: "David Deal"

plugins:
#- serverless-python-requirements
- serverless-python-requirements
- serverless-wsgi
- serverless-plugin-tracing
# Serverless Finch does s3 uploading. Called with 'sls client deploy'.
Expand Down Expand Up @@ -602,12 +586,6 @@ functions:
apiv1:
handler: wsgi_handler.handler
description: "EasyCLA Python API handler for the /v1 endpoints"
image:
name: easyclaPythonAppImage
command:
- 'wsgi_handler.handler'
#entryPoint:
# - '/lambda-entrypoint.sh'
events:
- http:
method: ANY
Expand All @@ -617,12 +595,6 @@ functions:
apiv2:
handler: wsgi_handler.handler
description: "EasyCLA Python API handler for the /v2 endpoints"
image:
name: easyclaPythonAppImage
command:
- 'wsgi_handler.handler'
# layers:
# - Ref: PythonRequirementsLambdaLayer
events:
- http:
method: ANY
Expand All @@ -632,12 +604,6 @@ functions:
salesforceprojects:
handler: cla.salesforce.get_projects
description: "EasyCLA API Callback Handler for fetching all SalesForce projects"
image:
name: easyclaPythonAppImage
command:
- 'cla.salesforce.get_projects'
# layers:
# - Ref: PythonRequirementsLambdaLayer
events:
- http:
method: ANY
Expand All @@ -647,12 +613,6 @@ functions:
salesforceprojectbyID:
handler: cla.salesforce.get_project
description: "EasyCLA API Callback Handler for fetching SalesForce projects by ID"
image:
name: easyclaPythonAppImage
command:
- 'cla.salesforce.get_project'
# layers:
# - Ref: PythonRequirementsLambdaLayer
events:
- http:
method: ANY
Expand All @@ -663,12 +623,6 @@ functions:
githubinstall:
handler: wsgi_handler.handler
description: "EasyCLA API Callback Handler for GitHub bot installations"
image:
name: easyclaPythonAppImage
command:
- 'wsgi_handler.handler'
# layers:
# - Ref: PythonRequirementsLambdaLayer
events:
- http:
method: ANY
Expand All @@ -678,12 +632,6 @@ functions:
githubactivity:
handler: wsgi_handler.handler
description: "EasyCLA API Callback Handler for GitHub activity"
image:
name: easyclaPythonAppImage
command:
- 'wsgi_handler.handler'
# layers:
# - Ref: PythonRequirementsLambdaLayer
events:
- http:
method: POST
Expand Down Expand Up @@ -738,4 +686,4 @@ resources:
- ApiGatewayRestApi
- RootResourceId
Export:
Name: APIGatewayRootResourceID
Name: APIGatewayRootResourceID

0 comments on commit bc6e7cb

Please sign in to comment.