Skip to content

Commit

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

Signed-off-by: Harold Wanyama <[email protected]>
  • Loading branch information
nickmango committed Sep 5, 2023
1 parent 506338c commit ae88d14
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 97 deletions.
75 changes: 36 additions & 39 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
64 changes: 6 additions & 58 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

0 comments on commit ae88d14

Please sign in to comment.