Skip to content

Commit 98c23be

Browse files
committed
added ability to create workflow
1 parent fd01a79 commit 98c23be

File tree

7 files changed

+823
-82
lines changed

7 files changed

+823
-82
lines changed

launcher-csharp/Maestro/Controllers/Mae001TriggerWorkflowController.cs

Lines changed: 108 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace DocuSign.CodeExamples.Controllers
66
{
7+
using System;
78
using System.Linq;
89
using System.Threading.Tasks;
910
using DocuSign.CodeExamples.Common;
@@ -17,6 +18,8 @@ namespace DocuSign.CodeExamples.Controllers
1718
[Route("mae001")]
1819
public class Mae001TriggerWorkflowController : EgController
1920
{
21+
private const string WorkflowName = "Example workflow - send invite to signer";
22+
2023
public Mae001TriggerWorkflowController(DsConfiguration dsConfig,
2124
LauncherTexts launcherTexts,
2225
IRequestItemsService requestItemsService)
@@ -28,6 +31,96 @@ public Mae001TriggerWorkflowController(DsConfiguration dsConfig,
2831

2932
public override string EgName => "mae001";
3033

34+
[MustAuthenticate]
35+
[HttpGet]
36+
public override IActionResult Get()
37+
{
38+
var actionResult = base.Get();
39+
if (this.RequestItemsService.EgName == this.EgName)
40+
{
41+
return actionResult;
42+
}
43+
44+
var basePath = this.RequestItemsService.Session.IamBasePath;
45+
var accessToken = this.RequestItemsService.User.AccessToken;
46+
var accountId = this.RequestItemsService.Session.AccountId;
47+
48+
try
49+
{
50+
if (this.RequestItemsService.WorkflowId == null)
51+
{
52+
WorkflowsListSuccess workflowsList = TriggerMaestroWorkflow.GetMaestroWorkflow(
53+
basePath,
54+
accessToken,
55+
accountId).GetAwaiter().GetResult();
56+
57+
if (workflowsList.Data != null || workflowsList.Data.Count > 0)
58+
{
59+
var maestroWorkflow = workflowsList.Data.FirstOrDefault(workflow => workflow.Name == WorkflowName);
60+
61+
this.RequestItemsService.WorkflowId = maestroWorkflow?.Id;
62+
}
63+
}
64+
65+
if (this.RequestItemsService.WorkflowId == null && this.RequestItemsService.TemplateId != null)
66+
{
67+
var workflowId = TriggerMaestroWorkflow.CreateWorkflowAsync(
68+
accessToken,
69+
accountId,
70+
this.RequestItemsService.TemplateId,
71+
this.Config.MaestroWorkflowConfig).GetAwaiter().GetResult();
72+
this.RequestItemsService.WorkflowId = workflowId;
73+
74+
var publishLink = TriggerMaestroWorkflow.PublishWorkflowAsync(
75+
accountId,
76+
workflowId,
77+
accessToken).GetAwaiter().GetResult();
78+
79+
this.RequestItemsService.IsWorkflowPublished = true;
80+
this.ViewBag.ConsentLink = this.CodeExampleText.AdditionalPages[0].ResultsPageText
81+
.Replace("{0}", publishLink);
82+
this.ViewBag.WorkflowId = this.RequestItemsService.WorkflowId;
83+
this.ViewBag.TemplateId = this.RequestItemsService.TemplateId;
84+
85+
return this.View("publishWorkflow");
86+
}
87+
88+
if (this.RequestItemsService.IsWorkflowPublished)
89+
{
90+
var publishLink = TriggerMaestroWorkflow.PublishWorkflowAsync(
91+
accountId,
92+
this.RequestItemsService.WorkflowId,
93+
accessToken).GetAwaiter().GetResult();
94+
95+
if (publishLink != string.Empty)
96+
{
97+
this.ViewBag.ConsentLink = this.CodeExampleText.AdditionalPages[0].ResultsPageText
98+
.Replace("{0}", publishLink);
99+
100+
this.ViewBag.WorkflowId = this.RequestItemsService.WorkflowId;
101+
this.ViewBag.TemplateId = this.RequestItemsService.TemplateId;
102+
return this.View("publishWorkflow");
103+
}
104+
105+
this.RequestItemsService.IsWorkflowPublished = false;
106+
}
107+
108+
this.ViewBag.WorkflowId = this.RequestItemsService.WorkflowId;
109+
this.ViewBag.TemplateId = this.RequestItemsService.TemplateId;
110+
111+
return this.View("mae001");
112+
}
113+
catch (Exception apiException)
114+
{
115+
this.ViewBag.errorCode = string.Empty;
116+
this.ViewBag.errorMessage = apiException.Message;
117+
this.ViewBag.SupportingTexts = this.LauncherTexts.ManifestStructure.SupportingTexts;
118+
this.ViewBag.SupportMessage = this.CodeExampleText.CustomErrorTexts[0].ErrorMessage;
119+
120+
return this.View("Error");
121+
}
122+
}
123+
31124
[HttpPost]
32125
[SetViewBag]
33126
public async Task<IActionResult> Create(
@@ -53,48 +146,29 @@ public async Task<IActionResult> Create(
53146
string accessToken = this.RequestItemsService.User.AccessToken;
54147
string basePath = this.RequestItemsService.Session.IamBasePath;
55148
string accountId = this.RequestItemsService.Session.AccountId;
149+
string workflowId = this.RequestItemsService.WorkflowId;
56150

57151
try
58152
{
59-
WorkflowsListSuccess workflowsList = await TriggerMaestroWorkflow.GetMaestroWorkflow(
153+
var instance = await TriggerMaestroWorkflow.TriggerWorkflowInstance(
60154
basePath,
61155
accessToken,
62-
accountId);
156+
accountId,
157+
workflowId,
158+
signerEmail,
159+
signerName,
160+
ccEmail,
161+
ccName,
162+
instanceName);
63163

64-
if (workflowsList.Data != null || workflowsList.Data.Count > 0)
65-
{
66-
var maestroWorkflow = workflowsList.Data.FirstOrDefault(workflow =>
67-
workflow.Status == "active" && workflow.Name == "Example workflow - send invite to signer");
68-
69-
if (maestroWorkflow != null)
70-
{
71-
var instance = await TriggerMaestroWorkflow.TriggerWorkflowInstance(
72-
basePath,
73-
accessToken,
74-
accountId,
75-
maestroWorkflow.Id,
76-
signerEmail,
77-
signerName,
78-
ccEmail,
79-
ccName,
80-
instanceName);
81-
82-
this.RequestItemsService.WorkflowId = maestroWorkflow.Id;
83-
this.RequestItemsService.InstanceId = instance.InstanceId;
84-
85-
this.ViewBag.h1 = this.CodeExampleText.ExampleName;
86-
this.ViewBag.Url = instance.InstanceUrl;
87-
this.ViewBag.message = string.Format(this.CodeExampleText.ResultsPageText);
88-
89-
return this.View("embed");
90-
}
91-
}
164+
this.RequestItemsService.WorkflowId = workflowId;
165+
this.RequestItemsService.InstanceId = instance.InstanceId;
92166

93-
this.ViewBag.errorCode = string.Empty;
94-
this.ViewBag.SupportingTexts = this.LauncherTexts.ManifestStructure.SupportingTexts;
95-
this.ViewBag.SupportMessage = this.CodeExampleText.CustomErrorTexts[0].ErrorMessage;
167+
this.ViewBag.h1 = this.CodeExampleText.ExampleName;
168+
this.ViewBag.Url = instance.InstanceUrl;
169+
this.ViewBag.message = string.Format(this.CodeExampleText.ResultsPageText);
96170

97-
return this.View("Error");
171+
return this.View("embed");
98172
}
99173
catch (APIException exception)
100174
{

launcher-csharp/Maestro/Examples/TriggerMaestroWorkflow.cs

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,21 @@
44

55
namespace DocuSign.CodeExamples.Examples
66
{
7+
using System;
78
using System.Collections.Generic;
9+
using System.IO;
10+
using System.Net.Http;
11+
using System.Net.Http.Headers;
812
using System.Threading.Tasks;
913
using Docusign.IAM.SDK;
1014
using Docusign.IAM.SDK.Models.Components;
15+
using Docusign.IAM.SDK.Models.Requests;
16+
using Newtonsoft.Json.Linq;
1117

1218
public static class TriggerMaestroWorkflow
1319
{
20+
private const string MaestroBasePath = "https://demo.services.docusign.net/aow-manage/v1.0";
21+
1422
/// <summary>
1523
/// Returns a list of Maestro workflows for the account.
1624
/// </summary>
@@ -21,7 +29,7 @@ public static async Task<WorkflowsListSuccess> GetMaestroWorkflow(
2129
string accountId)
2230
{
2331
var client = CreateAuthenticatedClient(basePath, accessToken);
24-
return await client.Maestro.Workflows.GetWorkflowsListAsync(accountId);
32+
return await client.Maestro.Workflows.GetWorkflowsListAsync(accountId, Status.Active);
2533
}
2634

2735
/// <summary>
@@ -61,6 +69,82 @@ public static async Task<TriggerWorkflowSuccess> TriggerWorkflowInstance(
6169
triggerWorkflow);
6270
}
6371

72+
/// <summary>
73+
/// Create a Maestro workflow.
74+
/// </summary>
75+
/// <returns>ID of the maestro workflow.</returns>
76+
public static async Task<string> CreateWorkflowAsync(
77+
string accessToken,
78+
string accountId,
79+
string templateId,
80+
string fileLocation)
81+
{
82+
string signerId = Guid.NewGuid().ToString();
83+
string ccId = Guid.NewGuid().ToString();
84+
var triggerId = "wfTrigger";
85+
86+
var requestJson = PrepareWorkflowDefinition(fileLocation, templateId, signerId, ccId, triggerId, accountId);
87+
88+
using (var httpClient = new HttpClient())
89+
{
90+
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
91+
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
92+
93+
var content = new StringContent(requestJson);
94+
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
95+
96+
var url = $"{MaestroBasePath}/management/accounts/{accountId}/workflowDefinitions";
97+
98+
var response = await httpClient.PostAsync(url, content);
99+
string responseBody = await response.Content.ReadAsStringAsync();
100+
101+
if (!response.IsSuccessStatusCode)
102+
{
103+
throw new Exception("Unable to create a new workflow" + responseBody);
104+
}
105+
106+
var jsonResponse = JObject.Parse(responseBody);
107+
return jsonResponse["workflowDefinitionId"]?.ToString();
108+
}
109+
}
110+
111+
/// <summary>
112+
/// Publish a Maestro workflow.
113+
/// </summary>
114+
/// <returns>Consent URL in case the workflow is yet not published.</returns>
115+
public static async Task<string> PublishWorkflowAsync(
116+
string accountId,
117+
string workflowId,
118+
string accessToken)
119+
{
120+
using var httpClient = new HttpClient();
121+
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
122+
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
123+
124+
var url =
125+
$"{MaestroBasePath}/management/accounts/{accountId}/workflowDefinitions/{workflowId}/publish?isPreRunCheck=true";
126+
127+
var response = await httpClient.PostAsync(url, null);
128+
var responseBody = await response.Content.ReadAsStringAsync();
129+
130+
if ((int)response.StatusCode > 201)
131+
{
132+
var jsonResponse = JObject.Parse(responseBody);
133+
var message = jsonResponse["message"]?.ToString();
134+
var consentUrl = jsonResponse["consentUrl"]?.ToString();
135+
136+
if (message == "Consent required" && !string.IsNullOrEmpty(consentUrl))
137+
{
138+
return consentUrl;
139+
}
140+
141+
throw new Exception("Error publishing workflow. " + message);
142+
}
143+
144+
await Task.Delay(8000);
145+
return string.Empty;
146+
}
147+
64148
/// <summary>
65149
/// Creates an authenticated IAM client.
66150
/// </summary>
@@ -79,5 +163,41 @@ private static TriggerInputs CreateTriggerInput(string value)
79163
{
80164
return new TriggerInputs(TriggerInputsType.Str) { Str = value };
81165
}
166+
167+
/// <summary>
168+
/// Prepares a Maestro workflow definition from file.
169+
/// </summary>
170+
/// <returns>Workflow in string format</returns>
171+
private static string PrepareWorkflowDefinition(
172+
string fileLocation,
173+
string templateId,
174+
string signerId,
175+
string ccId,
176+
string triggerId,
177+
string accountId)
178+
{
179+
string templateIdTargetString = "TEMPLATE_ID";
180+
string accountIdTargetString = "ACCOUNT_ID";
181+
string signerIdTargetString = "SIGNER_ID";
182+
string ccIdTargetString = "CC_ID";
183+
string triggerIdTargetString = "TRIGGER_ID";
184+
185+
try
186+
{
187+
string workflowDefinition = File.ReadAllText(fileLocation);
188+
string workflowDefinitionWithData = workflowDefinition
189+
.Replace(templateIdTargetString, templateId)
190+
.Replace(accountIdTargetString, accountId)
191+
.Replace(signerIdTargetString, signerId)
192+
.Replace(ccIdTargetString, ccId)
193+
.Replace(triggerIdTargetString, triggerId);
194+
195+
return workflowDefinitionWithData;
196+
}
197+
catch (Exception ex)
198+
{
199+
throw new Exception($"An error occurred: {ex.Message}");
200+
}
201+
}
82202
}
83203
}

0 commit comments

Comments
 (0)