Skip to content

Commit 41e1b2e

Browse files
Ticket #110 : Configure Delegate
1 parent b668ab2 commit 41e1b2e

65 files changed

Lines changed: 2391 additions & 50 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.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using CaseManagement.BPMN.DelegateConfiguration.Commands;
2+
using CaseManagement.BPMN.DelegateConfiguration.Queries;
3+
using CaseManagement.BPMN.Exceptions;
4+
using MediatR;
5+
using Microsoft.AspNetCore.Mvc;
6+
using System.Collections.Generic;
7+
using System.Net;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
11+
namespace CaseManagement.BPMN.AspNetCore.Apis
12+
{
13+
[Route(BPMNConstants.RouteNames.DelegateConfigurations)]
14+
public class DelegateConfigurationsController : Controller
15+
{
16+
private readonly IMediator _mediator;
17+
18+
public DelegateConfigurationsController(IMediator mediator)
19+
{
20+
_mediator = mediator;
21+
}
22+
23+
[HttpPost("search")]
24+
public async Task<IActionResult> Search([FromBody] SearchDelegateConfigurationQuery query, CancellationToken token)
25+
{
26+
var result = await _mediator.Send(query, token);
27+
return new OkObjectResult(result);
28+
}
29+
30+
[HttpGet("{id}")]
31+
public async Task<IActionResult> Get(string id, CancellationToken token)
32+
{
33+
try
34+
{
35+
var result = await _mediator.Send(new GetDelegateConfigurationQuery { Id = id }, token);
36+
return new OkObjectResult(result);
37+
}
38+
catch(UnknownDelegateConfigurationException ex)
39+
{
40+
return this.ToError(new List<KeyValuePair<string, string>>
41+
{
42+
new KeyValuePair<string, string>("bad_request", ex.Message)
43+
}, HttpStatusCode.NotFound, Request);
44+
}
45+
}
46+
47+
[HttpGet]
48+
public async Task<IActionResult> GetAll(CancellationToken token)
49+
{
50+
var result = await _mediator.Send(new GetAllDelegatesConfigurationsQuery(), token);
51+
return new OkObjectResult(result);
52+
}
53+
54+
[HttpPut("{id}")]
55+
public async Task<IActionResult> Update(string id, [FromBody] UpdateDelegateConfigurationCommand cmd, CancellationToken token)
56+
{
57+
try
58+
{
59+
cmd.Id = id;
60+
await _mediator.Send(cmd, token);
61+
return new NoContentResult();
62+
}
63+
catch(UnknownDelegateConfigurationException ex)
64+
{
65+
return this.ToError(new List<KeyValuePair<string, string>>
66+
{
67+
new KeyValuePair<string, string>("bad_request", ex.Message)
68+
}, HttpStatusCode.NotFound, Request);
69+
}
70+
}
71+
}
72+
}

src/CaseManagement.BPMN.Host/Delegates/SendEmailDelegate.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using CaseManagement.BPMN.Domains;
22
using CaseManagement.BPMN.Exceptions;
3-
using System;
43
using System.Collections.Generic;
54
using System.Linq;
65
using System.Net;
@@ -14,12 +13,17 @@ public class SendEmailDelegate : IDelegateHandler
1413
{
1514
public Task<ICollection<MessageToken>> Execute(ICollection<MessageToken> incoming, DelegateConfigurationAggregate delegateConfiguration, CancellationToken cancellationToken)
1615
{
17-
var email = incoming.FirstOrDefault(i => i.Name == "email");
18-
if (email == null)
16+
var user = incoming.FirstOrDefault(i => i.Name == "userMessage");
17+
if (user == null)
1918
{
20-
throw new BPMNProcessorException("Email parameter is missing");
19+
throw new BPMNProcessorException("userMessage must be passed in the request");
2120
}
2221

22+
var email = user.GetProperty("email");
23+
if (string.IsNullOrWhiteSpace(email))
24+
{
25+
throw new BPMNProcessorException("email is not passed in the request");
26+
}
2327

2428
var parameter = SendDelegateParameter.Build(delegateConfiguration);
2529
using (var smtpClient = new SmtpClient(parameter.SmtpHost)
@@ -31,17 +35,24 @@ public Task<ICollection<MessageToken>> Execute(ICollection<MessageToken> incomin
3135
{
3236
var mailMessage = new MailMessage
3337
{
34-
38+
From = new MailAddress(parameter.FromEmail),
39+
Subject = parameter.Subject,
40+
Body = parameter.HttpBody,
41+
IsBodyHtml = true
3542
};
43+
44+
mailMessage.To.Add(email);
45+
smtpClient.Send(mailMessage);
3646
}
37-
38-
throw new NotImplementedException();
47+
48+
return Task.FromResult(incoming);
3949
}
4050

4151
private class SendDelegateParameter
4252
{
4353
public string HttpBody { get; set; }
4454
public string Subject { get; set; }
55+
public string FromEmail { get; set; }
4556
public string SmtpHost { get; set; }
4657
public int SmtpPort { get; set; }
4758
public string SmtpUserName { get; set; }
@@ -54,6 +65,7 @@ public static SendDelegateParameter Build(DelegateConfigurationAggregate delegat
5465
{
5566
HttpBody = delegateConfiguration.GetValue("httpBody"),
5667
Subject = delegateConfiguration.GetValue("subject"),
68+
FromEmail = delegateConfiguration.GetValue("fromEmail"),
5769
SmtpHost = delegateConfiguration.GetValue("smtpHost"),
5870
SmtpPort = delegateConfiguration.GetValueNumber("smtpPort"),
5971
SmtpUserName = delegateConfiguration.GetValue("smtpUserName"),
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using CaseManagement.BPMN.Domains;
2+
using CaseManagement.BPMN.Exceptions;
3+
using IdentityModel.Client;
4+
using Newtonsoft.Json.Linq;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Net.Http;
9+
using System.Text;
10+
using System.Threading;
11+
using System.Threading.Tasks;
12+
13+
namespace CaseManagement.BPMN.Host.Delegates
14+
{
15+
public class UpdateUserPasswordDelegate : IDelegateHandler
16+
{
17+
private const string ActivityName = "Activity_12xhvyl";
18+
19+
public async Task<ICollection<MessageToken>> Execute(ICollection<MessageToken> incoming, DelegateConfigurationAggregate delegateConfiguration, CancellationToken cancellationToken)
20+
{
21+
var user = incoming.FirstOrDefault(i => i.Name == "userMessage");
22+
if (user == null)
23+
{
24+
throw new BPMNProcessorException("userMessage must be passed in the request");
25+
}
26+
27+
var userId = user.GetProperty("userId");
28+
if (string.IsNullOrWhiteSpace(userId))
29+
{
30+
throw new BPMNProcessorException("userId is not passed in the request");
31+
}
32+
33+
var messageToken = incoming.FirstOrDefault(m => m.Name == ActivityName);
34+
if (messageToken == null)
35+
{
36+
throw new BPMNProcessorException($"incoming token '{ActivityName}' doesn't exist");
37+
}
38+
39+
var password = messageToken.GetProperty("password");
40+
var parameter = UpdateUserPasswordParameter.Create(delegateConfiguration);
41+
using (var httpClient = new HttpClient())
42+
{
43+
var tokenResponse = await httpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
44+
{
45+
Address = parameter.TokenUrl,
46+
ClientId = parameter.ClientId,
47+
ClientSecret = parameter.ClientSecret,
48+
Scope = parameter.Scope
49+
}, cancellationToken);
50+
if (tokenResponse.IsError)
51+
{
52+
throw new BPMNProcessorException(tokenResponse.Error);
53+
}
54+
55+
var obj = new JObject
56+
{
57+
{ "password", password }
58+
};
59+
var content = new StringContent(obj.ToString(), Encoding.UTF8, "application/json");
60+
var request = new HttpRequestMessage
61+
{
62+
Method = HttpMethod.Put,
63+
Content = content,
64+
RequestUri = new Uri($"{parameter.UserUrl}/{userId}/password")
65+
};
66+
request.Headers.Add("Authorization", $"Bearer {tokenResponse.AccessToken}");
67+
var httpResponse = await httpClient.SendAsync(request, cancellationToken);
68+
httpResponse.EnsureSuccessStatusCode();
69+
}
70+
71+
return incoming;
72+
}
73+
74+
private class UpdateUserPasswordParameter
75+
{
76+
public string TokenUrl { get; set; }
77+
public string UserUrl { get; set; }
78+
public string ClientId { get; set; }
79+
public string ClientSecret { get; set; }
80+
public string Scope { get; set; }
81+
82+
public static UpdateUserPasswordParameter Create(DelegateConfigurationAggregate delegateConfiguration)
83+
{
84+
return new UpdateUserPasswordParameter
85+
{
86+
ClientId = delegateConfiguration.GetValue("clientId"),
87+
ClientSecret = delegateConfiguration.GetValue("clientSecret"),
88+
TokenUrl = delegateConfiguration.GetValue("tokenUrl"),
89+
UserUrl = delegateConfiguration.GetValue("userUrl"),
90+
Scope = delegateConfiguration.GetValue("scope")
91+
};
92+
}
93+
}
94+
}
95+
}

src/CaseManagement.BPMN.Host/Startup.cs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) SimpleIdServer. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
using CaseManagement.BPMN.Domains;
34
using CaseManagement.BPMN.Host.Delegates;
45
using Microsoft.AspNetCore.Authentication.JwtBearer;
56
using Microsoft.AspNetCore.Builder;
@@ -66,10 +67,7 @@ public void ConfigureServices(IServiceCollection services)
6667
{
6768
opts.WSHumanTaskAPI = "http://localhost:60006";
6869
opts.CallbackUrl = "http://localhost:60007/processinstances/{id}/complete/{eltId}";
69-
}).AddProcessFiles(files).AddDelegateConfigurations(new ConcurrentBag<Domains.DelegateConfigurationAggregate>
70-
{
71-
Domains.DelegateConfigurationAggregate.Create("GetWeatherInformationDelegate", typeof(GetWeatherInformationDelegate).FullName)
72-
});
70+
}).AddProcessFiles(files).AddDelegateConfigurations(GetDelegateConfigurations());
7371
services.AddSwaggerGen();
7472
services.Configure<ForwardedHeadersOptions>(options =>
7573
{
@@ -130,5 +128,42 @@ private static byte[] Base64DecodeBytes(string base64EncodedData)
130128
throw new InvalidOperationException("Illegal base64url string!");
131129
}
132130
}
131+
132+
private static ConcurrentBag<DelegateConfigurationAggregate> GetDelegateConfigurations()
133+
{
134+
var getWeatherInformationDelegate = DelegateConfigurationAggregate.Create("GetWeatherInformationDelegate", typeof(GetWeatherInformationDelegate).FullName);
135+
getWeatherInformationDelegate.AddDisplayName("fr", "Récupérer météo");
136+
getWeatherInformationDelegate.AddDescription("fr", "Récupérer les informations sur la météo");
137+
getWeatherInformationDelegate.AddDisplayName("en", "Get meteo");
138+
getWeatherInformationDelegate.AddDescription("en", "Get informations about meteo");
139+
140+
var sendEmailDelegate = DelegateConfigurationAggregate.Create("SendEmailDelegate", typeof(SendEmailDelegate).FullName);
141+
sendEmailDelegate.AddDisplayName("fr", "Envoyer un email");
142+
sendEmailDelegate.AddDisplayName("en", "Send email");
143+
sendEmailDelegate.AddRecord("httpBody", "Please click on this link to update the password");
144+
sendEmailDelegate.AddRecord("subject", "Update password");
145+
sendEmailDelegate.AddRecord("fromEmail", "");
146+
sendEmailDelegate.AddRecord("smtpHost", "");
147+
sendEmailDelegate.AddRecord("smtpPort", "");
148+
sendEmailDelegate.AddRecord("smtpUserName", "");
149+
sendEmailDelegate.AddRecord("smtpPassword", "");
150+
sendEmailDelegate.AddRecord("smtpEnableSsl", "");
151+
152+
var updateUserPasswordDelegate = DelegateConfigurationAggregate.Create("UpdateUserPasswordDelegate", typeof(UpdateUserPasswordDelegate).FullName);
153+
updateUserPasswordDelegate.AddDisplayName("fr", "Mettre à jour le mot de passe");
154+
updateUserPasswordDelegate.AddDisplayName("en", "Update password");
155+
updateUserPasswordDelegate.AddRecord("clientId", "");
156+
updateUserPasswordDelegate.AddRecord("clientSecret", "");
157+
updateUserPasswordDelegate.AddRecord("tokenUrl", "https://localhost:60000/token");
158+
updateUserPasswordDelegate.AddRecord("userUrl", "");
159+
updateUserPasswordDelegate.AddRecord("scope", "update_password");
160+
161+
return new ConcurrentBag<DelegateConfigurationAggregate>
162+
{
163+
getWeatherInformationDelegate,
164+
sendEmailDelegate,
165+
updateUserPasswordDelegate
166+
};
167+
}
133168
}
134169
}

src/CaseManagement.BPMN.Persistence.EF/BPMNDbContext.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using CaseManagement.BPMN.Domains;
2-
using CaseManagement.BPMN.Domains.DelegateConfiguration;
32
using Microsoft.EntityFrameworkCore;
43

54
namespace CaseManagement.BPMN.Persistence.EF

src/CaseManagement.BPMN.Persistence.EF/Configuration/DelegateConfigurationAggregateConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using CaseManagement.BPMN.Domains.DelegateConfiguration;
1+
using CaseManagement.BPMN.Domains;
22
using Microsoft.EntityFrameworkCore;
33
using Microsoft.EntityFrameworkCore.Metadata.Builders;
44

src/CaseManagement.BPMN.Persistence.EF/Configuration/DelegateConfigurationRecordConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using CaseManagement.BPMN.Domains.DelegateConfiguration;
1+
using CaseManagement.BPMN.Domains;
22
using Microsoft.EntityFrameworkCore;
33
using Microsoft.EntityFrameworkCore.Metadata.Builders;
44

src/CaseManagement.BPMN.Persistence.EF/Persistence/DelegateConfigurationRepository.cs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1-
using CaseManagement.BPMN.Domains;
1+
using CaseManagement.BPMN.DelegateConfiguration.Queries;
2+
using CaseManagement.BPMN.DelegateConfiguration.Results;
3+
using CaseManagement.BPMN.Domains;
4+
using CaseManagement.Common.Results;
25
using Microsoft.EntityFrameworkCore;
6+
using System.Collections.Generic;
7+
using System.Linq;
38
using System.Threading;
49
using System.Threading.Tasks;
510

611
namespace CaseManagement.BPMN.Persistence.EF.Persistence
712
{
813
public class DelegateConfigurationRepository : IDelegateConfigurationRepository
914
{
15+
private static Dictionary<string, string> MAPPING_DELEGATECONFIGURATION_TO_PROPERTYNAME = new Dictionary<string, string>
16+
{
17+
{ "create_datetime", "CreateDateTime" },
18+
{ "update_datetime", "UpdateDateTime" }
19+
};
20+
1021
private readonly BPMNDbContext _dbContext;
1122

1223
public DelegateConfigurationRepository(BPMNDbContext dbContext)
@@ -18,5 +29,54 @@ public Task<DelegateConfigurationAggregate> Get(string delegateId, CancellationT
1829
{
1930
return _dbContext.DelegateConfigurations.FirstOrDefaultAsync(d => d.AggregateId == delegateId, cancellationToken);
2031
}
32+
33+
public async Task<DelegateConfigurationResult> GetResult(string delegateId, CancellationToken cancellationToken)
34+
{
35+
var result = await _dbContext.DelegateConfigurations.FirstOrDefaultAsync(d => d.AggregateId == delegateId, cancellationToken);
36+
if (result == null)
37+
{
38+
return null;
39+
}
40+
41+
return DelegateConfigurationResult.ToDto(result);
42+
}
43+
44+
public async Task<SearchResult<DelegateConfigurationResult>> Search(SearchDelegateConfigurationQuery parameter, CancellationToken cancellationToken)
45+
{
46+
IQueryable<DelegateConfigurationAggregate> result = _dbContext.DelegateConfigurations;
47+
if (MAPPING_DELEGATECONFIGURATION_TO_PROPERTYNAME.ContainsKey(parameter.OrderBy))
48+
{
49+
result = result.InvokeOrderBy(MAPPING_DELEGATECONFIGURATION_TO_PROPERTYNAME[parameter.OrderBy], parameter.Order);
50+
}
51+
52+
int totalLength = await result.CountAsync(cancellationToken);
53+
result = result.Skip(parameter.StartIndex).Take(parameter.Count);
54+
var content = await result.ToListAsync(cancellationToken);
55+
content = content.OrderByDescending(r => r.Version).GroupBy(r => r.AggregateId).Select(r => r.First()).ToList();
56+
return new SearchResult<DelegateConfigurationResult>
57+
{
58+
StartIndex = parameter.StartIndex,
59+
Count = parameter.Count,
60+
TotalLength = totalLength,
61+
Content = content.Select(_ => DelegateConfigurationResult.ToDto(_)).ToList()
62+
};
63+
}
64+
65+
public Task<bool> Update(DelegateConfigurationAggregate configuration, CancellationToken cancellationToken)
66+
{
67+
_dbContext.DelegateConfigurations.Update(configuration);
68+
return Task.FromResult(true);
69+
}
70+
71+
public async Task<IEnumerable<string>> GetAll(CancellationToken cancellationToken)
72+
{
73+
IEnumerable<string> result = await _dbContext.DelegateConfigurations.Select(_ => _.AggregateId).ToListAsync(cancellationToken);
74+
return result;
75+
}
76+
77+
public Task<int> SaveChanges(CancellationToken cancellationToken)
78+
{
79+
return _dbContext.SaveChangesAsync(cancellationToken);
80+
}
2181
}
2282
}

0 commit comments

Comments
 (0)