Skip to content

Commit

Permalink
- Added initiate sign request (void and create envelope)
Browse files Browse the repository at this point in the history
Signed-off-by: Harold Wanyama <[email protected]>
  • Loading branch information
nickmango committed Oct 19, 2023
1 parent c1bedfc commit 03a695d
Show file tree
Hide file tree
Showing 15 changed files with 591 additions and 43 deletions.
35 changes: 35 additions & 0 deletions cla-backend-go/github/github_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,3 +643,38 @@ func CreateStatus(ctx context.Context, client *github.Client, owner, repo, sha s

return c, resp, nil
}

func GetReturnURL(ctx context.Context, installationID, repositoryID int64, pullRequestID int) (string, error) {
f := logrus.Fields{
"functionName": "github.github_repository.GetReturnURL",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"installationID": installationID,
"repositoryID": repositoryID,
"pullRequestID": pullRequestID,
}

client, err := NewGithubAppClient(installationID)

if err != nil {
log.WithFields(f).WithError(err).Warn("unable to create Github client")
return "", err
}

log.WithFields(f).Debugf("getting github repository by id: %d", repositoryID)
repo, _, err := client.Repositories.GetByID(ctx, repositoryID)
if err != nil {
log.WithFields(f).WithError(err).Warnf("unable to get repository by ID: %d", repositoryID)
return "", err
}

log.WithFields(f).Debugf("getting pull request by id: %d", pullRequestID)
pullRequest, _, err := client.PullRequests.Get(ctx, *repo.Owner.Login, *repo.Name, pullRequestID)
if err != nil {
log.WithFields(f).WithError(err).Warnf("unable to get pull request by ID: %d", pullRequestID)
return "", err
}

log.WithFields(f).Debugf("returning pull request html url: %s", *pullRequest.HTMLURL)

return *pullRequest.HTMLURL, nil
}
27 changes: 20 additions & 7 deletions cla-backend-go/project/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ func GetCurrentDocument(ctx context.Context, docs []models.ClaGroupDocument) (mo
continue
}

// No previous, use the first...
if currentDoc == (models.ClaGroupDocument{}) {
currentDoc = doc
currentDocVersion = version
currentDocDateTime = dateTime
continue
}
// // No previous, use the first...
// if currentDoc == (models.ClaGroupDocument{}) {
// currentDoc = doc
// currentDocVersion = version
// currentDocDateTime = dateTime
// continue
// }

// Newer version...
if version > currentDocVersion {
Expand All @@ -127,3 +127,16 @@ func GetCurrentDocument(ctx context.Context, docs []models.ClaGroupDocument) (mo

return currentDoc, nil
}

func AreClaGroupDocumentsEqual(doc1, doc2 models.ClaGroupDocument) bool {
return doc1.DocumentName == doc2.DocumentName &&
doc1.DocumentAuthorName == doc2.DocumentAuthorName &&
doc1.DocumentContentType == doc2.DocumentContentType &&
doc1.DocumentFileID == doc2.DocumentFileID &&
doc1.DocumentLegalEntityName == doc2.DocumentLegalEntityName &&
doc1.DocumentPreamble == doc2.DocumentPreamble &&
doc1.DocumentS3URL == doc2.DocumentS3URL &&
doc1.DocumentMajorVersion == doc2.DocumentMajorVersion &&
doc1.DocumentMinorVersion == doc2.DocumentMinorVersion &&
doc1.DocumentCreationDate == doc2.DocumentCreationDate
}
8 changes: 4 additions & 4 deletions cla-backend-go/project/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ func (s ProjectService) GetCLAGroupCurrentICLATemplateURLByID(ctx context.Contex
}
}

if currentDoc == (models.ClaGroupDocument{}) {
log.WithFields(f).WithError(err).Warn("problem determining current ICLA for this CLA Group")
if common.AreClaGroupDocumentsEqual(currentDoc, models.ClaGroupDocument{}) {
log.WithFields(f).WithError(err).Warn("problem determining current ICLA for this CLA Group - document is empty")
return "", &utils.CLAGroupICLANotConfigured{
CLAGroupID: claGroupID,
CLAGroupName: claGroupModel.ProjectName,
Expand Down Expand Up @@ -288,8 +288,8 @@ func (s ProjectService) GetCLAGroupCurrentCCLATemplateURLByID(ctx context.Contex
}
}

if currentDoc == (models.ClaGroupDocument{}) {
log.WithFields(f).WithError(err).Warn("problem determining current CCLA for this CLA Group")
if common.AreClaGroupDocumentsEqual(currentDoc, models.ClaGroupDocument{}) {
log.WithFields(f).WithError(err).Warn("problem determining current CCLA for this CLA Group - document is empty")
return "", &utils.CLAGroupCCLANotConfigured{
CLAGroupID: claGroupID,
CLAGroupName: claGroupModel.ProjectName,
Expand Down
1 change: 1 addition & 0 deletions cla-backend-go/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ provider:
DOCUSIGN_INTEGRATOR_KEY: ${file(./env.json):docusign-integrator-key, ssm:/cla-docusign-integrator-key-${opt:stage}}
DOCUSIGN_AUTH_SERVER: ${file(./env.json):docusign-auth-server, ssm:/cla-docusign-auth-server-${opt:stage}}
DOCUSIGN_USER_ID: ${file(./env.json):docusign-auth-server, ssm:/cla-docusign-user-id-${opt:stage}}
DOCUSIGN_ACCOUNT_ID: ${file(./env.json):docusign-account-id, ssm:/cla-docusign-account-id-${opt:stage}}
CLA_API_BASE: ${file(./env.json):cla-api-base, ssm:/cla-api-base-${opt:stage}}
CLA_CONTRIBUTOR_BASE: ${file(./env.json):cla-contributor-base, ssm:/cla-contributor-base-${opt:stage}}
CLA_CONTRIBUTOR_V2_BASE: ${file(./env.json):cla-contributor-v2-base, ssm:/cla-contributor-v2-base-${opt:stage}}
Expand Down
1 change: 1 addition & 0 deletions cla-backend-go/signatures/converters.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func (repo repository) buildProjectSignatureModels(ctx context.Context, results
SignatureCallbackURL: dbSignature.SignatureCallbackURL,
SignatureReturnURL: dbSignature.SignatureReturnURL,
SignatureReturnURLType: dbSignature.SignatureReturnURLType,
SignatureEnvelopeID: dbSignature.SignatureEnvelopeID,
}

sigs = append(sigs, sig)
Expand Down
1 change: 1 addition & 0 deletions cla-backend-go/signatures/dbmodels.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type ItemSignature struct {
SignatureProjectID string `json:"signature_project_id"`
SignatureReferenceType string `json:"signature_reference_type"`
SignatureType string `json:"signature_type"`
SignatureEnvelopeID string `json:"signature_envelope_id"`
SignatureUserCompanyID string `json:"signature_user_ccla_company_id"`
EmailApprovalList []string `json:"email_whitelist"`
EmailDomainApprovalList []string `json:"domain_whitelist"`
Expand Down
3 changes: 3 additions & 0 deletions cla-backend-go/swagger/cla.v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2854,6 +2854,9 @@ definitions:

cla-group-document:
$ref: './common/cla-group-document.yaml'

document-tab:
$ref: './common/document-tab.yaml'

create-cla-group-template:
$ref: './common/create-cla-group-template.yaml'
Expand Down
3 changes: 3 additions & 0 deletions cla-backend-go/swagger/cla.v2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5680,6 +5680,9 @@ definitions:

cla-group-summary:
$ref: './common/cla-group-summary.yaml'

document-tab:
$ref: './common/document-tab.yaml'

cla-group-project:
type: object
Expand Down
4 changes: 4 additions & 0 deletions cla-backend-go/swagger/common/cla-group-document.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ properties:
description: the document creation date
example: '2019-08-01T06:55:09Z'
type: string
documentTabs:
type: array
items:
$ref: '#/definitions/document-tab'
41 changes: 41 additions & 0 deletions cla-backend-go/swagger/common/document-tab.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright The Linux Foundation and each contributor to CommunityBridge.
# SPDX-License-Identifier: MIT

type: object
x-nullable: false
title: Docusign Document Tab
description: Docusign Document Tab
properties:
document_tab_type:
type: string
document_tab_id:
type: string
document_tab_name:
type: string
document_tab_page:
type: integer
document_tab_position_x:
type: integer
document_tab_position_y:
type: integer
document_tab_width:
type: integer
document_tab_height:
type: integer
document_tab_is_locked:
type: boolean
document_tab_is_required:
type: boolean
document_tab_anchor_string:
type: string
document_tab_anchor_ignore_if_not_present:
type: boolean
document_tab_anchor_x_offset:
type: integer
document_tab_anchor_y_offset:
type: integer





3 changes: 3 additions & 0 deletions cla-backend-go/swagger/common/signature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ properties:
signatureReturnURLType:
type: string
description: the signature return URL type
signatureEnvelopeId:
type: string
description: the signature envelope ID
emailApprovalList:
type: array
description: a list of zero or more email addresses in the approval list
Expand Down
68 changes: 68 additions & 0 deletions cla-backend-go/v2/sign/docusign.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,71 @@ func (s *service) getAccessToken(ctx context.Context) (string, error) {
return tokenResponse.AccessToken, nil

}

// Void envelope
func (s *service) VoidEnvelope(ctx context.Context, envelopeID, message string) error {
f := logrus.Fields{
"functionName": "v2.VoidEnvelope",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"envelopeID": envelopeID,
"message": message,
}

accessToken, err := s.getAccessToken(ctx)
if err != nil {
log.WithFields(f).WithError(err).Warnf("problem getting the access token")
return err
}

voidRequest := struct {
VoidReason string `json:"voidReason"`
}{
VoidReason: message,
}

voidRequestJSON, err := json.Marshal(voidRequest)

if err != nil {
log.WithFields(f).WithError(err).Warnf("problem marshalling the void request")
return err
}

url := fmt.Sprintf("https://%s/restapi/v2.1/accounts/%s/envelopes/%s/void", utils.GetProperty("DOCUSIGN_ROOT_URL"), utils.GetProperty("DOCUSIGN_ACCOUNT_ID"), envelopeID)

req, err := http.NewRequest("PUT", url, strings.NewReader(string(voidRequestJSON)))

if err != nil {
return err
}

req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
req.Header.Add("Content-Type", "application/json")

// Make the request
client := &http.Client{}

resp, err := client.Do(req)

if err != nil {
return err
}

defer func() {
if err = resp.Body.Close(); err != nil {
log.WithFields(f).WithError(err).Warnf("problem closing the response body")
}
}()

_, err = io.ReadAll(resp.Body)

if err != nil {
return err
}

if resp.StatusCode != http.StatusOK {
return errors.New("problem making the HTTP request")
}

return nil

}
17 changes: 13 additions & 4 deletions cla-backend-go/v2/sign/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ func Configure(api *operations.EasyclaAPI, service Service) {
if strings.ToLower(params.Input.ReturnURLType) == "github" || strings.ToLower(params.Input.ReturnURLType) == "gitlab" {
if strings.ToLower(params.Input.ReturnURLType) == "github" {
log.WithFields(f).Debug("fetching github emails")
emails, err := fetchGithubEmails(session, clientID)
if err != nil {
emails, fetchErr := fetchGithubEmails(session, clientID)
if fetchErr != nil {
return sign.NewRequestIndividualSignatureBadRequest().WithPayload(errorResponse(reqId, err))
}

Expand All @@ -124,7 +124,9 @@ func Configure(api *operations.EasyclaAPI, service Service) {
}
for _, email := range emails {
if email["verified"].(bool) && email["primary"].(bool) {
preferredEmail = email["email"].(string)
if emailVal, ok := email["email"].(string); ok {
preferredEmail = emailVal
}
break
}
}
Expand Down Expand Up @@ -180,7 +182,14 @@ func getRequestSession(req *http.Request) map[string]interface{} {

func fetchGithubEmails(session map[string]interface{}, clientID string) ([]map[string]interface{}, error) {
var emails []map[string]interface{}
token := session["github_oauth2_token"].(string)
var token string

if tokenVal, ok := session["token"].(string); ok {
token = tokenVal
} else {
return emails, nil
}

if token == "" {
return emails, nil
}
Expand Down
34 changes: 34 additions & 0 deletions cla-backend-go/v2/sign/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,17 @@ type DocuSignRecipient struct {
Tabs DocuSignTab `json:"tabs"` // The tabs associated with the recipient. The tabs property enables you to programmatically position tabs on the document. For example, you can specify that the SIGN_HERE tab is placed at a given (x,y) location on the document. You can also specify the font, font color, font size, and other properties of the text in the tab. You can also specify the location and size of the tab. For example, you can specify that the tab is 50 pixels wide and 20 pixels high. You can also specify the page number on which the tab is located and whether the tab is located in a document, a template, or an inline template. For more information about tabs, see the Tabs section of the REST API documentation.
}

// TextOptionalTab

type TextOptionalTab struct {
Name string `json:"name"`
Value string `json:"value"`
Height int `json:"height"`
Width int `json:"width"`
Locked bool `json:"locked"`
Required bool `json:"required"`
}

// DocuSignTab is the data model for a tab from DocuSign
type DocuSignTab struct {
ApproveTabs []DocuSignTabDetails `json:"approveTabs,omitempty"`
Expand Down Expand Up @@ -170,6 +181,8 @@ type DocuSignTab struct {
TitleTabs []DocuSignTabDetails `json:"titleTabs,omitempty"`
ViewTabs []DocuSignTabDetails `json:"viewTabs,omitempty"`
ZipTabs []DocuSignTabDetails `json:"zipTabs,omitempty"`
TextOptionalTabs []DocuSignTabDetails `json:"textOptionalTabs,omitempty"`
SignHereOptionalTabs []DocuSignTabDetails `json:"signHereOptionalTabs,omitempty"`
}

// DocuSignTabDetails is the data model for a tab from DocuSign
Expand Down Expand Up @@ -204,6 +217,7 @@ type DocuSignTabDetails struct {
YPosition string `json:"yPosition,omitempty"` // x position
ValidationType string `json:"validationType,omitempty"` // validation type, "string", "number", "date", "zipcode", "currency"
Value string `json:"value,omitempty"`
CustomTabId string `json:"customTabId,omitempty"`
}

// DocuSignTemplateRole is the request body for a template role from DocuSign
Expand Down Expand Up @@ -290,3 +304,23 @@ type IndividualMembershipDocuSignDBSummaryModel struct {
Memo sql.NullString `db:"memo"`
//DocuSignEnvelopeSignedDate time.Time `json:"docusign_envelope_signed_date"`
}


package main

import (
"fmt"
"strings"
)

type ClaSignatoryEmailParams struct {
ClaGroupName string
SignatoryName string
ClaManagerName string
ClaManagerEmail string
CompanyName string
ProjectVersion string
ProjectNames []string
}


Loading

0 comments on commit 03a695d

Please sign in to comment.