Skip to content

Commit 4c4300e

Browse files
Ticket #96 : Support WS-HumanTask in CMMN
1 parent 1446bc0 commit 4c4300e

426 files changed

Lines changed: 6342 additions & 5013 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CaseManagement.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CaseManagement.CMMN.SqlServ
3131
EndProject
3232
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01. Apis", "01. Apis", "{E33157EC-243C-4EA0-A60B-57F2C248CE53}"
3333
EndProject
34-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01. CaseManagement", "01. CaseManagement", "{7452122A-3758-4AFD-BBC0-B3C576D12D80}"
34+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01. CMMN", "01. CMMN", "{7452122A-3758-4AFD-BBC0-B3C576D12D80}"
3535
EndProject
3636
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "04. Security", "04. Security", "{E5E1A1EB-90BC-4CB7-9893-75224AF27170}"
3737
EndProject

src/CaseManagement.BPMN.AspNetCore/Apis/ProcessInstancesController.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,25 @@ public async Task<IActionResult> MakeTransition(string id, [FromBody] MakeStateT
100100
}, HttpStatusCode.NotFound, Request);
101101
}
102102
}
103+
104+
[HttpPost("{id}/complete/{eltId}")]
105+
public async Task<IActionResult> Complete(string id, string eltId, [FromBody] MakeStateTransitionCommand stateTransitionCommand, CancellationToken token)
106+
{
107+
try
108+
{
109+
stateTransitionCommand.FlowNodeInstanceId = id;
110+
stateTransitionCommand.FlowNodeElementInstanceId = eltId;
111+
stateTransitionCommand.State = "COMPLETED";
112+
await _mediator.Send(stateTransitionCommand, token);
113+
return new OkResult();
114+
}
115+
catch (UnknownFlowInstanceException ex)
116+
{
117+
return this.ToError(new List<KeyValuePair<string, string>>
118+
{
119+
new KeyValuePair<string, string>("bad_request", ex.Message)
120+
}, HttpStatusCode.NotFound, Request);
121+
}
122+
}
103123
}
104124
}

src/CaseManagement.BPMN.Host/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public void ConfigureServices(IServiceCollection services)
6363
services.AddProcessJobServer(callbackServerOpts: opts =>
6464
{
6565
opts.WSHumanTaskAPI = "http://localhost:60006";
66+
opts.CallbackUrl = "http://localhost:60007/processinstances/{id}/complete/{eltId}";
6667
}).AddProcessFiles(files);
6768
services.AddSwaggerGen();
6869
services.Configure<ForwardedHeadersOptions>(options =>

src/CaseManagement.BPMN.SqlServer.Host/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public void ConfigureServices(IServiceCollection services)
7373
services.AddProcessJobServer(callbackServerOpts: opts =>
7474
{
7575
opts.WSHumanTaskAPI = "http://localhost:60006";
76+
opts.CallbackUrl = "http://localhost:60007/processinstances/{id}/complete/{eltId}";
7677
});
7778
services.AddBPMNStoreEF(opts =>
7879
{

src/CaseManagement.BPMN/BPMNServerOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@ public BPMNServerOptions()
5858
public string ClientId { get; set; }
5959
public string ClientSecret { get; set; }
6060
public string OAuthTokenEndpoint { get; set; }
61+
public string CallbackUrl { get; set; }
6162
}
6263
}

src/CaseManagement.BPMN/ProcessInstance/Processors/Activities/Handlers/WsHumanTaskHandler.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ public async Task<ICollection<MessageToken>> Execute(BPMNExecutionContext execut
4141
{
4242
var operationParameters = new JObject
4343
{
44-
{ "flowNodeInstanceId", executionContext.Instance.AggregateId },
45-
{ "flowNodeElementInstanceId", pointer.InstanceFlowNodeId },
4644
{ "nameIdentifier", executionContext.Instance.NameIdentifier }
4745
};
4846
var ctx = new ConditionalExpressionContext(pointer.Incoming);
@@ -60,6 +58,10 @@ public async Task<ICollection<MessageToken>> Execute(BPMNExecutionContext execut
6058
}
6159
}
6260

61+
var jArr = new JArray();
62+
var link = _options.CallbackUrl.Replace("{id}", executionContext.Instance.AggregateId);
63+
link = link.Replace("{eltId}", pointer.InstanceFlowNodeId);
64+
jArr.Add(link);
6365
var tokenResponse = await httpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
6466
{
6567
Address = _options.OAuthTokenEndpoint,
@@ -75,7 +77,8 @@ public async Task<ICollection<MessageToken>> Execute(BPMNExecutionContext execut
7577
var obj = new JObject
7678
{
7779
{ "humanTaskName", userTask.HumanTaskName },
78-
{ "operationParameters", operationParameters }
80+
{ "operationParameters", operationParameters },
81+
{ "callbackUrls", jArr }
7982
};
8083
var content = new StringContent(obj.ToString(), Encoding.UTF8, "application/json");
8184
var request = new HttpRequestMessage

src/CaseManagement.CMMN.AspNetCore/Apis/CasePlanInstancesController.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System;
1111
using System.Collections.Generic;
1212
using System.Net;
13+
using System.Security.Claims;
1314
using System.Threading;
1415
using System.Threading.Tasks;
1516

@@ -54,6 +55,8 @@ public async Task<IActionResult> Create([FromBody] CreateCaseInstanceCommand cre
5455
{
5556
try
5657
{
58+
var nameIdentifier = User.GetClaims().GetUserNameIdentifier();
59+
createCaseInstance.NameIdentifier = nameIdentifier;
5760
var result = await _mediator.Send(createCaseInstance, token);
5861
return new OkObjectResult(result);
5962
}
@@ -286,13 +289,15 @@ public async Task<IActionResult> Resume(string id, string elt, CancellationToken
286289
}
287290
}
288291

289-
[HttpGet("{id}/complete/{elt}")]
292+
[HttpPost("{id}/complete/{elt}")]
290293
[Authorize("complete_caseplaninstance")]
291-
public async Task<IActionResult> Complete(string id, string elt, CancellationToken token)
294+
public async Task<IActionResult> Complete(string id, string elt, [FromBody] CompleteCommand command, CancellationToken token)
292295
{
293296
try
294297
{
295-
await _mediator.Send(new CompleteCommand(id, elt), token);
298+
command.CaseInstanceId = id;
299+
command.CaseInstanceElementId = elt;
300+
await _mediator.Send(command, token);
296301
return new OkResult();
297302
}
298303
catch (UnknownCasePlanInstanceException)

src/CaseManagement.CMMN.Host/CaseManagement.CMMN.Host.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
<ProjectReference Include="..\CaseManagement.CMMN.AspNetCore\CaseManagement.CMMN.AspNetCore.csproj" />
1818
</ItemGroup>
1919
<ItemGroup>
20+
<None Update="Cmmns\claimCase.cmmn">
21+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
22+
</None>
23+
<None Update="oauth_puk.txt">
24+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
25+
</None>
2026
<None Update="openid_puk.txt">
2127
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2228
</None>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<cmmn:definitions xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC" xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI" xmlns:cmmn="http://www.omg.org/spec/CMMN/20151109/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cmg="https://github.com/simpleidserver/CaseManagement" id="Definitions_0m2br72" targetNamespace="http://bpmn.io/schema/cmmn" exporter="cmmn-js (https://demo.bpmn.io/cmmn)" exporterVersion="0.19.2">
3+
<cmmn:case id="Case_0t7z7vp">
4+
<cmmn:casePlanModel id="CasePlanModel_3394a428-486a-43f5-b491-7b31e417e0db" name="Claim case">
5+
<cmmn:planItem id="PlanItem_0zl4ucq" name="Receive claim" definitionRef="Stage_1elok9z" />
6+
<cmmn:stage id="Stage_1elok9z" name="Receive claim">
7+
<cmmn:planItem id="PlanItem_1dphpiz" name="Capture claim details" definitionRef="HumanTask_1oeedji" />
8+
<cmmn:humanTask id="HumanTask_1oeedji" cmg:formId="captureClaimDetails" cmg:implementation="##WsHumanTask">
9+
<cmmn:extensionElements>
10+
<cmg:parameters />
11+
</cmmn:extensionElements>
12+
</cmmn:humanTask>
13+
</cmmn:stage>
14+
</cmmn:casePlanModel>
15+
</cmmn:case>
16+
<cmmndi:CMMNDI>
17+
<cmmndi:CMMNDiagram id="CMMNDiagram_1">
18+
<cmmndi:Size width="500" height="500" />
19+
<cmmndi:CMMNShape id="DI_CasePlanModel_3394a428-486a-43f5-b491-7b31e417e0db" cmmnElementRef="CasePlanModel_3394a428-486a-43f5-b491-7b31e417e0db">
20+
<dc:Bounds x="155" y="99" width="537" height="209" />
21+
<cmmndi:CMMNLabel />
22+
</cmmndi:CMMNShape>
23+
<cmmndi:CMMNShape id="PlanItem_1qbrgp3_di" cmmnElementRef="PlanItem_1dphpiz">
24+
<dc:Bounds x="200" y="166" width="100" height="80" />
25+
<cmmndi:CMMNLabel />
26+
</cmmndi:CMMNShape>
27+
<cmmndi:CMMNShape id="PlanItem_0zl4ucq_di" cmmnElementRef="PlanItem_0zl4ucq">
28+
<dc:Bounds x="175" y="136" width="317" height="144" />
29+
<cmmndi:CMMNLabel />
30+
</cmmndi:CMMNShape>
31+
</cmmndi:CMMNDiagram>
32+
</cmmndi:CMMNDI>
33+
</cmmn:definitions>

src/CaseManagement.CMMN.Host/Startup.cs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public Startup(IHostingEnvironment env, IConfiguration configuration)
3131

3232
public void ConfigureServices(IServiceCollection services)
3333
{
34+
var files = Directory.EnumerateFiles(Path.Combine(Directory.GetCurrentDirectory(), "Cmmns"), "*.cmmn").ToList();
3435
services.AddMvc(opts => opts.EnableEndpointRouting = false).AddNewtonsoftJson();
3536
services.AddAuthentication(options =>
3637
{
@@ -53,7 +54,23 @@ public void ConfigureServices(IServiceCollection services)
5354
"http://simpleidserver.northeurope.cloudapp.azure.com/openid"
5455
}
5556
};
56-
});
57+
})
58+
.AddJwtBearer("OAuthScheme", options =>
59+
{
60+
options.TokenValidationParameters = new TokenValidationParameters
61+
{
62+
IssuerSigningKey = ExtractKey("oauth_puk.txt"),
63+
ValidAudiences = new List<string>
64+
{
65+
"humanTaskClient"
66+
},
67+
ValidIssuers = new List<string>
68+
{
69+
"http://localhost:60001",
70+
"http://simpleidserver.northeurope.cloudapp.azure.com/oauth"
71+
}
72+
};
73+
}); ;
5774
services.AddAuthorization(policy =>
5875
{
5976
// Case file
@@ -73,7 +90,31 @@ public void ConfigureServices(IServiceCollection services)
7390
policy.AddPolicy("resume_caseplaninstance", p => p.RequireAuthenticatedUser());
7491
policy.AddPolicy("terminate_caseplaninstance", p => p.RequireAuthenticatedUser());
7592
policy.AddPolicy("activate_caseplaninstance", p => p.RequireAuthenticatedUser());
76-
policy.AddPolicy("complete_caseplaninstance", p => p.RequireAuthenticatedUser());
93+
policy.AddPolicy("complete_caseplaninstance", p =>
94+
{
95+
p.AddAuthenticationSchemes("OAuthScheme");
96+
p.RequireAssertion(_ =>
97+
{
98+
if (_.User == null || _.User.Claims == null || !_.User.Claims.Any())
99+
{
100+
return false;
101+
}
102+
103+
var cl = _.User.Claims.FirstOrDefault(_ => _.Type == "scope" && _.Value == "complete_humantask");
104+
if (cl != null)
105+
{
106+
return true;
107+
}
108+
109+
cl = _.User.Claims.FirstOrDefault(_ => _.Type == "sub");
110+
if (cl != null)
111+
{
112+
return true;
113+
}
114+
115+
return false;
116+
});
117+
});
77118
// Case plan
78119
policy.AddPolicy("get_caseplan", p => p.RequireAuthenticatedUser());
79120
// Case worker task
@@ -84,7 +125,11 @@ public void ConfigureServices(IServiceCollection services)
84125
.AllowAnyHeader()));
85126
services.AddHostedService<CMMNJobServerHostedService>();
86127
services.AddCaseApi();
87-
services.AddCaseJobServer();
128+
services.AddCaseJobServer(callback: opt =>
129+
{
130+
opt.CallbackUrl = "http://localhost:60005/case-plan-instances/{id}/complete/{eltId}";
131+
opt.WSHumanTaskAPI = "http://localhost:60006";
132+
}).AddDefinitions(files);
88133
services.AddSwaggerGen();
89134
services.Configure<ForwardedHeadersOptions>(options =>
90135
{

0 commit comments

Comments
 (0)