Skip to content

Commit a40896b

Browse files
authored
Add a ClientSvc to front the Client aggregate (#124)
* Adds a ClientSvc to front the Client aggregate * Update version info to 0.9.2 * Add methods to get commands/permissions from a msgs class
1 parent 91d8ef5 commit a40896b

17 files changed

+198
-55
lines changed

src/ReactiveDomain.Debug.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>ReactiveDomain</id>
5-
<version>0.9.1.0</version>
5+
<version>0.9.2.0</version>
66
<authors>PerkinElmer,Linedata</authors>
77
<requireLicenseAcceptance>false</requireLicenseAcceptance>
88
<license type="expression">MIT</license>

src/ReactiveDomain.IdentityStorage/Domain/Client.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55

66
namespace ReactiveDomain.IdentityStorage.Domain
77
{
8-
98
public class Client : AggregateRoot
109
{
1110
public string ClientName { get; private set; }
1211
public string[] RedirectUris { get; private set; }
1312
public string[] LogoutRedirectUris { get; private set; }
14-
public string FrontChannlLogoutUri { get; private set; }
13+
public string FrontChannelLogoutUri { get; private set; }
1514

1615
private Client()
1716
{
@@ -26,7 +25,7 @@ private void RegisterEvents()
2625
ClientName = @event.ClientName;
2726
RedirectUris = @event.RedirectUris;
2827
LogoutRedirectUris = @event.PostLogoutRedirectUris;
29-
FrontChannlLogoutUri = @event.FrontChannelLogoutUri;
28+
FrontChannelLogoutUri = @event.FrontChannelLogoutUri;
3029
});
3130
Register<ClientSecretAdded>(@event => { });
3231
Register<ClientSecretRemoved>(@event => { });
@@ -56,12 +55,12 @@ public Client(
5655
Raise(new ClientCreated(
5756
id,
5857
applicationId,
59-
clientName,
60-
new[] { "client_credentials", "password", "authorization_code" },
61-
new[] { "openid", "profile", "rd-policy", "enabled-policies" },
62-
redirectUris,
63-
postLogoutRedirectUris,
64-
frontChannelLogoutUri));
58+
clientName,
59+
new[] { "client_credentials", "password", "authorization_code" },
60+
new[] { "openid", "profile", "rd-policy", "enabled-policies" },
61+
redirectUris,
62+
postLogoutRedirectUris,
63+
frontChannelLogoutUri));
6564

6665
Raise(new ClientSecretAdded(id, encryptedClientSecret));
6766
}

src/ReactiveDomain.IdentityStorage/Messages/ClientMsgs.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,35 @@ namespace ReactiveDomain.IdentityStorage.Messages
55
{
66
public class ClientMsgs
77
{
8+
public class CreateClient : Command
9+
{
10+
public readonly Guid ClientId;
11+
public readonly Guid ApplicationId;
12+
public readonly string ClientName;
13+
public readonly string[] RedirectUris;
14+
public readonly string[] PostLogoutRedirectUris;
15+
public readonly string FrontChannelLogoutUri;
16+
public readonly string EncryptedClientSecret;
17+
18+
public CreateClient(
19+
Guid clientId,
20+
Guid applicationId,
21+
string clientName,
22+
string[] redirectUris,
23+
string[] postLogoutRedirectUris,
24+
string frontChannelLogoutUri,
25+
string encryptedClientSecret)
26+
{
27+
ClientId = clientId;
28+
ApplicationId = applicationId;
29+
ClientName = clientName;
30+
RedirectUris = redirectUris;
31+
PostLogoutRedirectUris = postLogoutRedirectUris;
32+
FrontChannelLogoutUri = frontChannelLogoutUri;
33+
EncryptedClientSecret = encryptedClientSecret;
34+
}
35+
}
36+
837
public class ClientCreated : Event
938
{
1039
public readonly Guid ClientId;
@@ -36,9 +65,21 @@ public ClientCreated(
3665
FrontChannelLogoutUri = frontChannelLogoutUri;
3766
}
3867
}
39-
public class ClientSecretAdded : Event
68+
69+
public class AddClientSecret : Command
4070
{
71+
public readonly Guid ClientId;
72+
public readonly string EncryptedClientSecret;
73+
74+
public AddClientSecret(Guid clientId, string encryptedClientSecret)
75+
{
76+
ClientId = clientId;
77+
EncryptedClientSecret = encryptedClientSecret;
78+
}
79+
}
4180

81+
public class ClientSecretAdded : Event
82+
{
4283
public readonly Guid ClientId;
4384
public readonly string EncryptedClientSecret;
4485

@@ -48,6 +89,19 @@ public ClientSecretAdded(Guid clientId, string encryptedClientSecret)
4889
EncryptedClientSecret = encryptedClientSecret;
4990
}
5091
}
92+
93+
public class RemoveClientSecret : Command
94+
{
95+
public readonly Guid ClientId;
96+
public readonly string EncryptedClientSecret;
97+
98+
public RemoveClientSecret(Guid clientId, string encryptedClientSecret)
99+
{
100+
ClientId = clientId;
101+
EncryptedClientSecret = encryptedClientSecret;
102+
}
103+
}
104+
51105
public class ClientSecretRemoved : Event
52106
{
53107
public readonly Guid ClientId;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using ReactiveDomain.Foundation;
2+
using ReactiveDomain.IdentityStorage.Domain;
3+
using ReactiveDomain.IdentityStorage.Messages;
4+
using ReactiveDomain.Messaging;
5+
using ReactiveDomain.Messaging.Bus;
6+
7+
namespace ReactiveDomain.IdentityStorage.Services
8+
{
9+
public class ClientSvc :
10+
TransientSubscriber,
11+
IHandleCommand<ClientMsgs.CreateClient>,
12+
IHandleCommand<ClientMsgs.AddClientSecret>,
13+
IHandleCommand<ClientMsgs.RemoveClientSecret>
14+
{
15+
private readonly CorrelatedStreamStoreRepository _repo;
16+
17+
public ClientSvc(IRepository repo, IDispatcher bus) : base(bus)
18+
{
19+
_repo = new CorrelatedStreamStoreRepository(repo);
20+
Subscribe<ClientMsgs.CreateClient>(this);
21+
Subscribe<ClientMsgs.AddClientSecret>(this);
22+
Subscribe<ClientMsgs.RemoveClientSecret>(this);
23+
}
24+
25+
public CommandResponse Handle(ClientMsgs.CreateClient command)
26+
{
27+
var client = new Client(
28+
command.ClientId,
29+
command.ApplicationId,
30+
command.ClientName,
31+
command.EncryptedClientSecret,
32+
command.RedirectUris,
33+
command.PostLogoutRedirectUris,
34+
command.FrontChannelLogoutUri,
35+
command);
36+
try
37+
{
38+
_repo.Save(client);
39+
}
40+
catch (WrongExpectedVersionException)
41+
{
42+
throw new DuplicateClientException(command.ClientId, command.ClientName);
43+
}
44+
return command.Succeed();
45+
}
46+
47+
public CommandResponse Handle(ClientMsgs.AddClientSecret command)
48+
{
49+
var client = _repo.GetById<Client>(command.ClientId, command);
50+
client.AddClientSecret(command.EncryptedClientSecret);
51+
_repo.Save(client);
52+
return command.Succeed();
53+
}
54+
55+
public CommandResponse Handle(ClientMsgs.RemoveClientSecret command)
56+
{
57+
var client = _repo.GetById<Client>(command.ClientId, command);
58+
client.RemoveClientSecret(command.EncryptedClientSecret);
59+
_repo.Save(client);
60+
return command.Succeed();
61+
}
62+
}
63+
}

src/ReactiveDomain.IdentityStorage/UserExceptions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ public DuplicateUserException(Guid id, string fullName, string email)
1414
: base($"User {id}: {fullName}\\{email} already exists.")
1515
{ }
1616
}
17-
1817

19-
2018
/// <summary>
2119
/// Throw this exception when a user lookup returns no results.
2220
/// </summary>
@@ -44,4 +42,11 @@ public UserDeactivatedException(string message)
4442
{
4543
}
4644
}
45+
46+
public class DuplicateClientException : Exception
47+
{
48+
public DuplicateClientException(Guid id, string name)
49+
: base($"Client {name} with ID {id} already exists.")
50+
{ }
51+
}
4752
}

src/ReactiveDomain.Policy.Debug.nuspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
<package>
33
<metadata>
44
<id>ReactiveDomain.Policy</id>
5-
<version>0.9.1.0</version>
5+
<version>0.9.2.0</version>
66
<authors>PerkinElmer,Linedata</authors>
77
<requireLicenseAcceptance>false</requireLicenseAcceptance>
88
<license type="expression">MIT</license>
99
<description>Package includes all ReactiveDomain Identity and Policy assemblies</description>
1010
<dependencies>
1111
<group targetFramework="netstandard2.0">
12-
<dependency id="ReactiveDomain" version="0.9.1" exclude="Build,Analyzers" />
12+
<dependency id="ReactiveDomain" version="0.9.2" exclude="Build,Analyzers" />
1313
<dependency id="DynamicData" version="7.1.17" exclude="Build,Analyzers" />
1414
<dependency id="IdentityModel" version="4.6.0" exclude="Build,Analyzers" />
1515
<dependency id="IdentityServer4.Storage" version="4.1.2" exclude="Build,Analyzers"/>

src/ReactiveDomain.Policy.nuspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
<package>
33
<metadata>
44
<id>ReactiveDomain.Policy</id>
5-
<version>0.9.1.0</version>
5+
<version>0.9.2.0</version>
66
<authors>PerkinElmer,Linedata</authors>
77
<requireLicenseAcceptance>false</requireLicenseAcceptance>
88
<license type="expression">MIT</license>
99
<description>Package includes all ReactiveDomain Core assemblies</description>
1010
<copyright>Copyright © 2014-2022 PerkinElmer Inc., Linedata Inc.</copyright>
1111
<dependencies>
1212
<group targetFramework="netstandard2.0">
13-
<dependency id="ReactiveDomain" version="0.9.1" exclude="Build,Analyzers" />
13+
<dependency id="ReactiveDomain" version="0.9.2" exclude="Build,Analyzers" />
1414
<dependency id="DynamicData" version="7.1.17" exclude="Build,Analyzers" />
1515
<dependency id="IdentityModel" version="4.6.0" exclude="Build,Analyzers" />
1616
<dependency id="IdentityServer4.Storage" version="4.1.2" exclude="Build,Analyzers"/>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using ReactiveDomain.Messaging;
5+
6+
namespace ReactiveDomain.Policy
7+
{
8+
public static class Permissions
9+
{
10+
private static readonly Type CommandType = typeof(Command);
11+
12+
public static Permission[] GetCommandPermissions(Type type)
13+
{
14+
return GetCommands(type).Select(t => new Permission(t)).ToArray();
15+
}
16+
17+
public static IEnumerable<Type> GetCommands(Type type)
18+
{
19+
return type.GetNestedTypes().Where(t => CommandType.IsAssignableFrom(t));
20+
}
21+
}
22+
}

src/ReactiveDomain.PolicyTool/Program.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static int Main(string[] args)
5151
//Root CMD w/ global required AppName
5252
var appName = new Option<string>(
5353
name: "--app-name",
54-
description: "Taget Application name.")
54+
description: "Target Application name.")
5555
{
5656
IsRequired = true
5757
};
@@ -135,6 +135,7 @@ static int Main(string[] args)
135135
var userRm = new UsersRm(EsConnection);
136136
var subjectsRm = new SubjectsRm(EsConnection);
137137
var userSvc = new UserSvc(EsConnection.GetRepository(), mainBus);
138+
var clientSvc = new ClientSvc(EsConnection.GetRepository(), mainBus);
138139
var clientStore = new ClientStore(EsConnection);
139140
addApp.SetHandler(
140141
(string name, string secret, Guid id, string uri) =>
@@ -148,19 +149,18 @@ static int Main(string[] args)
148149
false));
149150
if (mainBus.TrySend(cmd, out _))
150151
{
151-
//todo: wrap this in a service
152-
//todo: look at making this a correlated message
153-
var client = new ReactiveDomain.IdentityStorage.Domain.Client(
154-
Guid.NewGuid(),
155-
id,
156-
name,
157-
secret,
158-
new[] { uri },
159-
new[] { uri },
160-
uri,
161-
new CorrelatedRoot());
162-
var repo = EsConnection.GetRepository();
163-
repo.Save(client);
152+
mainBus.TrySend(
153+
RDMsg.MessageBuilder
154+
.From(cmd)
155+
.Build(() => new ClientMsgs.CreateClient(
156+
Guid.NewGuid(),
157+
id,
158+
name,
159+
new[] { uri },
160+
new[] { uri },
161+
uri,
162+
secret)),
163+
out _);
164164
}
165165

166166
}, appName, clientSecret, appId, appUri);

src/ReactiveDomain.Testing.Debug.nuspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>ReactiveDomain.Testing</id>
5-
<version>0.9.1.0</version>
5+
<version>0.9.2.0</version>
66
<authors>PerkinElmer,Linedata</authors>
77
<owners>PerkinElmer,Linedata</owners>
88
<requireLicenseAcceptance>false</requireLicenseAcceptance>
@@ -14,7 +14,7 @@
1414
<dependency id="Microsoft.NET.Test.Sdk" version="16.11.0" exclude="Build,Analyzers" />
1515
<dependency id="xunit" version="2.4.1" exclude="Build,Analyzers" />
1616
<dependency id="xunit.runner.console" version="2.4.1" exclude="Build,Analyzers" />
17-
<dependency id="ReactiveDomain" version="0.9.1.0" exclude="Build,Analyzers" />
17+
<dependency id="ReactiveDomain" version="0.9.2.0" exclude="Build,Analyzers" />
1818
</group>
1919
</dependencies>
2020
<references>

0 commit comments

Comments
 (0)