Skip to content
This repository was archived by the owner on Aug 1, 2021. It is now read-only.

Commit 7926ca4

Browse files
committed
Client management
1 parent 422c5cc commit 7926ca4

41 files changed

Lines changed: 18342 additions & 140 deletions

Some content is hidden

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

src/Backend/Jp.Application/AutoMapper/ViewModelToDomainMappingProfile.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ public ViewModelToDomainMappingProfile()
4444

4545
CreateMap<SaveClientClaimViewModel, SaveClientClaimCommand>().ConstructUsing(c => new SaveClientClaimCommand(c.ClientId, c.Type, c.Value));
4646
CreateMap<RemoveClientClaimViewModel, RemoveClientClaimCommand>().ConstructUsing(c => new RemoveClientClaimCommand(c.Id, c.ClientId));
47+
CreateMap<RemoveClientViewModel, RemoveClientCommand>().ConstructUsing(c => new RemoveClientCommand(c.ClientId));
48+
CreateMap<CopyClientViewModel, CopyClientCommand>().ConstructUsing(c => new CopyClientCommand(c.ClientId));
49+
CreateMap<SaveClientViewModel, SaveClientCommand>().ConstructUsing(c => new SaveClientCommand(c.ClientId, c.ClientName, c.ClientUri, c.LogoUri, c.Description, c.ClientType));
50+
4751
}
4852
}
4953
}

src/Backend/Jp.Application/Interfaces/IClientAppService.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,9 @@ public interface IClientAppService: IDisposable
2020
Task<IEnumerable<ClientClaimViewModel>> GetClaims(string clientId);
2121
Task RemoveClaim(RemoveClientClaimViewModel model);
2222
Task SaveClaim(SaveClientClaimViewModel model);
23+
//Task Save(SaveClientViewModel client);
24+
Task Save(SaveClientViewModel client);
25+
Task Remove(RemoveClientViewModel client);
26+
Task Copy(CopyClientViewModel client);
2327
}
2428
}

src/Backend/Jp.Application/Services/ClientAppService.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ public async Task<IEnumerable<ClientClaimViewModel>> GetClaims(string clientId)
9898

9999
public Task RemoveClaim(RemoveClientClaimViewModel model)
100100
{
101-
102101
var registerCommand = _mapper.Map<RemoveClientClaimCommand>(model);
103102
return Bus.SendCommand(registerCommand);
104103
}
@@ -109,6 +108,24 @@ public Task SaveClaim(SaveClientClaimViewModel model)
109108
return Bus.SendCommand(registerCommand);
110109
}
111110

111+
public Task Save(SaveClientViewModel client)
112+
{
113+
var command = _mapper.Map<SaveClientCommand>(client);
114+
return Bus.SendCommand(command);
115+
}
116+
117+
public Task Remove(RemoveClientViewModel client)
118+
{
119+
var command = _mapper.Map<RemoveClientCommand>(client);
120+
return Bus.SendCommand(command);
121+
}
122+
123+
public Task Copy(CopyClientViewModel client)
124+
{
125+
var command = _mapper.Map<CopyClientCommand>(client);
126+
return Bus.SendCommand(command);
127+
}
128+
112129
public void Dispose()
113130
{
114131
GC.SuppressFinalize(this);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace Jp.Application.ViewModels.ClientsViewModels
4+
{
5+
public class CopyClientViewModel
6+
{
7+
[Required]
8+
public string ClientId { get; set; }
9+
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace Jp.Application.ViewModels.ClientsViewModels
4+
{
5+
public class RemoveClientViewModel
6+
{
7+
[Required]
8+
public string ClientId { get; set; }
9+
10+
}
11+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using Jp.Domain.Commands.Client;
3+
4+
namespace Jp.Application.ViewModels.ClientsViewModels
5+
{
6+
public class SaveClientViewModel
7+
{
8+
/// <summary>
9+
/// Unique ID of the client
10+
/// </summary>
11+
[Required]
12+
public string ClientId { get; set; }
13+
14+
/// <summary>
15+
/// Client display name (used for logging and consent screen)
16+
/// </summary>
17+
[Required]
18+
public string ClientName { get; set; }
19+
20+
/// <summary>
21+
/// URI to further information about client (used on consent screen)
22+
/// </summary>
23+
public string ClientUri { get; set; }
24+
25+
/// <summary>
26+
/// URI to client logo (used on consent screen)
27+
/// </summary>
28+
public string LogoUri { get; set; }
29+
30+
public string Description { get; set; }
31+
32+
public ClientType ClientType { get; set; } = 0;
33+
34+
}
35+
36+
}

src/Backend/Jp.Domain/CommandHandlers/ClientCommandHandler.cs

Lines changed: 107 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1-
using System.Linq;
2-
using System.Threading;
3-
using System.Threading.Tasks;
41
using IdentityServer4.EntityFramework.Entities;
52
using IdentityServer4.EntityFramework.Mappers;
3+
using IdentityServer4.Models;
64
using Jp.Domain.Commands.Client;
75
using Jp.Domain.Core.Bus;
86
using Jp.Domain.Core.Notifications;
97
using Jp.Domain.Events.Client;
108
using Jp.Domain.Interfaces;
119
using MediatR;
10+
using System;
11+
using System.Collections.Generic;
12+
using System.Linq;
13+
using System.Threading;
14+
using System.Threading.Tasks;
1215

1316
namespace Jp.Domain.CommandHandlers
1417
{
1518
public class ClientCommandHandler : CommandHandler,
16-
IRequestHandler<RegisterClientCommand>,
19+
IRequestHandler<RemoveClientCommand>,
1720
IRequestHandler<UpdateClientCommand>,
1821
IRequestHandler<RemoveSecretCommand>,
1922
IRequestHandler<SaveClientSecretCommand>,
2023
IRequestHandler<RemovePropertyCommand>,
2124
IRequestHandler<SaveClientPropertyCommand>,
2225
IRequestHandler<RemoveClientClaimCommand>,
23-
IRequestHandler<SaveClientClaimCommand>
26+
IRequestHandler<SaveClientClaimCommand>,
27+
IRequestHandler<SaveClientCommand>,
28+
IRequestHandler<CopyClientCommand>
2429
{
2530
private readonly IClientRepository _clientRepository;
2631
private readonly IClientSecretRepository _clientSecretRepository;
@@ -43,22 +48,25 @@ public ClientCommandHandler(
4348
}
4449

4550

46-
public Task Handle(RegisterClientCommand request, CancellationToken cancellationToken)
51+
public async Task Handle(RemoveClientCommand request, CancellationToken cancellationToken)
4752
{
4853
if (!request.IsValid())
4954
{
5055
NotifyValidationErrors(request);
51-
return Task.CompletedTask; ;
56+
return; ;
5257
}
5358

54-
// Businness logic here
55-
56-
//if (Commit())
57-
//{
58-
// Bus.RaiseEvent(new ClientRegisteredEvent(Client.Id));
59-
//}
60-
61-
return Task.CompletedTask;
59+
var savedClient = await _clientRepository.GetClient(request.Client.ClientId);
60+
if (savedClient == null)
61+
{
62+
await Bus.RaiseEvent(new DomainNotification("1", "Client not found"));
63+
return;
64+
}
65+
_clientRepository.Remove(savedClient.Id);
66+
if (Commit())
67+
{
68+
await Bus.RaiseEvent(new ClientRemovedEvent(request.Client.ClientId));
69+
}
6270
}
6371

6472
public async Task Handle(UpdateClientCommand request, CancellationToken cancellationToken)
@@ -267,6 +275,90 @@ public async Task Handle(SaveClientClaimCommand request, CancellationToken cance
267275
await Bus.RaiseEvent(new NewClientClaimEvent(request.Id, request.ClientId, property.Type, property.Value));
268276
}
269277
}
278+
279+
public async Task Handle(SaveClientCommand request, CancellationToken cancellationToken)
280+
{
281+
if (!request.IsValid())
282+
{
283+
NotifyValidationErrors(request);
284+
return;
285+
}
286+
287+
var savedClient = await _clientRepository.GetByClientId(request.Client.ClientId);
288+
if (savedClient != null)
289+
{
290+
await Bus.RaiseEvent(new DomainNotification("1", "Client already exists"));
291+
return;
292+
}
293+
294+
PrepareClientTypeForNewClient(request);
295+
var client = request.Client.ToEntity();
296+
client.Description = request.Description;
297+
298+
_clientRepository.Add(client);
299+
300+
if (Commit())
301+
{
302+
await Bus.RaiseEvent(new NewClientEvent(request.Client.ClientId, request.ClientType, request.Client.ClientName));
303+
}
304+
}
305+
306+
private void PrepareClientTypeForNewClient(SaveClientCommand command)
307+
{
308+
switch (command.ClientType)
309+
{
310+
case ClientType.Empty:
311+
break;
312+
case ClientType.WebImplicit:
313+
command.Client.AllowedGrantTypes = GrantTypes.Implicit;
314+
command.Client.AllowAccessTokensViaBrowser = true;
315+
break;
316+
case ClientType.WebHybrid:
317+
command.Client.AllowedGrantTypes = GrantTypes.Hybrid;
318+
break;
319+
case ClientType.Spa:
320+
command.Client.AllowedGrantTypes = GrantTypes.Implicit;
321+
command.Client.AllowAccessTokensViaBrowser = true;
322+
break;
323+
case ClientType.Native:
324+
command.Client.AllowedGrantTypes = GrantTypes.Hybrid;
325+
break;
326+
case ClientType.Machine:
327+
command.Client.AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials;
328+
break;
329+
default:
330+
throw new ArgumentOutOfRangeException();
331+
}
332+
}
333+
334+
public async Task Handle(CopyClientCommand request, CancellationToken cancellationToken)
335+
{
336+
if (!request.IsValid())
337+
{
338+
NotifyValidationErrors(request);
339+
return;
340+
}
341+
342+
var savedClient = await _clientRepository.GetByClientId(request.Client.ClientId);
343+
if (savedClient == null)
344+
{
345+
await Bus.RaiseEvent(new DomainNotification("1", "Client not found"));
346+
return;
347+
}
348+
349+
var copyOf = savedClient.ToModel();
350+
copyOf.ClientId = $"copy-of-{copyOf.ClientId}-{Guid.NewGuid().ToString().Replace("-", string.Empty)}";
351+
copyOf.ClientSecrets = new List<IdentityServer4.Models.Secret>();
352+
copyOf.ClientName = "Copy of " + copyOf.ClientName;
353+
var newClient = copyOf.ToEntity();
354+
355+
_clientRepository.Add(newClient);
356+
357+
if (Commit())
358+
{
359+
await Bus.RaiseEvent(new ClientClonedEvent(request.Client.ClientId, newClient.ClientId));
360+
}
361+
}
270362
}
271363

272364

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace Jp.Domain.Commands.Client
2+
{
3+
public enum ClientType
4+
{
5+
Empty = 0,
6+
WebImplicit = 1,
7+
WebHybrid = 2,
8+
Spa = 3,
9+
Native = 4,
10+
Machine = 5
11+
}
12+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Jp.Domain.Validations.Client;
2+
3+
namespace Jp.Domain.Commands.Client
4+
{
5+
public class CopyClientCommand : ClientCommand
6+
{
7+
8+
public CopyClientCommand(string clientId)
9+
{
10+
this.Client = new IdentityServer4.Models.Client() { ClientId = clientId };
11+
}
12+
13+
public override bool IsValid()
14+
{
15+
ValidationResult = new CopyClientCommandValidation().Validate(this);
16+
return ValidationResult.IsValid;
17+
}
18+
}
19+
}

src/Backend/Jp.Domain/Commands/Client/RegisterClientCommand.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22

33
namespace Jp.Domain.Commands.Client
44
{
5-
public class RegisterClientCommand : ClientCommand
5+
public class RemoveClientCommand : ClientCommand
66
{
7-
public RegisterClientCommand()
8-
{
97

8+
public RemoveClientCommand(string clientId)
9+
{
10+
this.Client = new IdentityServer4.Models.Client() { ClientId = clientId };
1011
}
1112

1213
public override bool IsValid()
1314
{
14-
ValidationResult = new RegisterClientCommandValidation().Validate(this);
15+
ValidationResult = new RemoveClientCommandValidation().Validate(this);
1516
return ValidationResult.IsValid;
1617
}
1718
}

0 commit comments

Comments
 (0)