Skip to content

Commit da040c2

Browse files
committed
Completed EFCore Session Store
1 parent 3a4097f commit da040c2

File tree

12 files changed

+115
-143
lines changed

12 files changed

+115
-143
lines changed

src/CodeBeam.UltimateAuth.Core/Domain/Session/UAuthSession.cs

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

55
namespace CodeBeam.UltimateAuth.Core.Domain;
66

7-
// TODO: Add ISoftDeleteable
87
public sealed class UAuthSession : IVersionedEntity
98
{
109
public AuthSessionId SessionId { get; }
@@ -13,21 +12,21 @@ public sealed class UAuthSession : IVersionedEntity
1312
public SessionChainId ChainId { get; }
1413
public DateTimeOffset CreatedAt { get; }
1514
public DateTimeOffset ExpiresAt { get; }
16-
public bool IsRevoked { get; }
1715
public DateTimeOffset? RevokedAt { get; }
1816
public long SecurityVersionAtCreation { get; }
1917
public ClaimsSnapshot Claims { get; }
2018
public SessionMetadata Metadata { get; }
2119
public long Version { get; set; }
2220

21+
public bool IsRevoked => RevokedAt != null;
22+
2323
private UAuthSession(
2424
AuthSessionId sessionId,
2525
TenantKey tenant,
2626
UserKey userKey,
2727
SessionChainId chainId,
2828
DateTimeOffset createdAt,
2929
DateTimeOffset expiresAt,
30-
bool isRevoked,
3130
DateTimeOffset? revokedAt,
3231
long securityVersionAtCreation,
3332
ClaimsSnapshot claims,
@@ -40,7 +39,6 @@ private UAuthSession(
4039
ChainId = chainId;
4140
CreatedAt = createdAt;
4241
ExpiresAt = expiresAt;
43-
IsRevoked = isRevoked;
4442
RevokedAt = revokedAt;
4543
SecurityVersionAtCreation = securityVersionAtCreation;
4644
Claims = claims;
@@ -66,7 +64,6 @@ public static UAuthSession Create(
6664
chainId,
6765
createdAt: now,
6866
expiresAt: expiresAt,
69-
isRevoked: false,
7067
revokedAt: null,
7168
securityVersionAtCreation: securityVersion,
7269
claims: claims ?? ClaimsSnapshot.Empty,
@@ -77,7 +74,8 @@ public static UAuthSession Create(
7774

7875
public UAuthSession Revoke(DateTimeOffset at)
7976
{
80-
if (IsRevoked) return this;
77+
if (IsRevoked)
78+
return this;
8179

8280
return new UAuthSession(
8381
SessionId,
@@ -86,7 +84,6 @@ public UAuthSession Revoke(DateTimeOffset at)
8684
ChainId,
8785
CreatedAt,
8886
ExpiresAt,
89-
true,
9087
at,
9188
SecurityVersionAtCreation,
9289
Claims,
@@ -102,7 +99,6 @@ internal static UAuthSession FromProjection(
10299
SessionChainId chainId,
103100
DateTimeOffset createdAt,
104101
DateTimeOffset expiresAt,
105-
bool isRevoked,
106102
DateTimeOffset? revokedAt,
107103
long securityVersionAtCreation,
108104
ClaimsSnapshot claims,
@@ -116,7 +112,6 @@ internal static UAuthSession FromProjection(
116112
chainId,
117113
createdAt,
118114
expiresAt,
119-
isRevoked,
120115
revokedAt,
121116
securityVersionAtCreation,
122117
claims,
@@ -148,7 +143,6 @@ public UAuthSession WithChain(SessionChainId chainId)
148143
chainId: chainId,
149144
createdAt: CreatedAt,
150145
expiresAt: ExpiresAt,
151-
isRevoked: IsRevoked,
152146
revokedAt: RevokedAt,
153147
securityVersionAtCreation: SecurityVersionAtCreation,
154148
claims: Claims,

src/CodeBeam.UltimateAuth.Core/Domain/Session/UAuthSessionChain.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using CodeBeam.UltimateAuth.Core.Abstractions;
22
using CodeBeam.UltimateAuth.Core.MultiTenancy;
3-
using static CodeBeam.UltimateAuth.Core.Defaults.UAuthActions;
43

54
namespace CodeBeam.UltimateAuth.Core.Domain;
65

src/CodeBeam.UltimateAuth.Core/Domain/Session/UAuthSessionRoot.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,19 @@ public sealed class UAuthSessionRoot : IVersionedEntity
1111

1212
public DateTimeOffset CreatedAt { get; }
1313
public DateTimeOffset? UpdatedAt { get; }
14-
15-
public bool IsRevoked { get; }
1614
public DateTimeOffset? RevokedAt { get; }
1715

1816
public long SecurityVersion { get; }
1917
public long Version { get; set; }
2018

19+
public bool IsRevoked => RevokedAt != null;
20+
2121
private UAuthSessionRoot(
2222
SessionRootId rootId,
2323
TenantKey tenant,
2424
UserKey userKey,
2525
DateTimeOffset createdAt,
2626
DateTimeOffset? updatedAt,
27-
bool isRevoked,
2827
DateTimeOffset? revokedAt,
2928
long securityVersion,
3029
long version)
@@ -34,7 +33,6 @@ private UAuthSessionRoot(
3433
UserKey = userKey;
3534
CreatedAt = createdAt;
3635
UpdatedAt = updatedAt;
37-
IsRevoked = isRevoked;
3836
RevokedAt = revokedAt;
3937
SecurityVersion = securityVersion;
4038
Version = version;
@@ -51,7 +49,6 @@ public static UAuthSessionRoot Create(
5149
userKey,
5250
at,
5351
null,
54-
false,
5552
null,
5653
0,
5754
0
@@ -66,7 +63,6 @@ public UAuthSessionRoot IncreaseSecurityVersion(DateTimeOffset at)
6663
UserKey,
6764
CreatedAt,
6865
at,
69-
IsRevoked,
7066
RevokedAt,
7167
SecurityVersion + 1,
7268
Version + 1
@@ -84,7 +80,6 @@ public UAuthSessionRoot Revoke(DateTimeOffset at)
8480
UserKey,
8581
CreatedAt,
8682
at,
87-
true,
8883
at,
8984
SecurityVersion + 1,
9085
Version + 1
@@ -97,7 +92,6 @@ internal static UAuthSessionRoot FromProjection(
9792
UserKey userKey,
9893
DateTimeOffset createdAt,
9994
DateTimeOffset? updatedAt,
100-
bool isRevoked,
10195
DateTimeOffset? revokedAt,
10296
long securityVersion,
10397
long version)
@@ -108,7 +102,6 @@ internal static UAuthSessionRoot FromProjection(
108102
userKey,
109103
createdAt,
110104
updatedAt,
111-
isRevoked,
112105
revokedAt,
113106
securityVersion,
114107
version

src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Data/UAuthSessionDbContext.cs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ protected override void OnModelCreating(ModelBuilder b)
3434
e.HasKey(x => x.Id);
3535

3636
e.Property(x => x.Version).IsConcurrencyToken();
37-
38-
e.Property(x => x.UserKey)
37+
e.Property(x => x.UserKey).IsRequired();
38+
e.Property(x => x.CreatedAt).IsRequired();
39+
e.Property(x => x.Tenant)
40+
.HasConversion(
41+
v => v.Value,
42+
v => TenantKey.FromInternal(v))
43+
.HasMaxLength(128)
3944
.IsRequired();
4045

4146
e.HasIndex(x => new { x.Tenant, x.UserKey }).IsUnique();
@@ -48,6 +53,7 @@ protected override void OnModelCreating(ModelBuilder b)
4853
.HasConversion(
4954
v => v.Value,
5055
v => SessionRootId.From(v))
56+
.HasMaxLength(128)
5157
.IsRequired();
5258
});
5359

@@ -56,18 +62,43 @@ protected override void OnModelCreating(ModelBuilder b)
5662
e.HasKey(x => x.Id);
5763

5864
e.Property(x => x.Version).IsConcurrencyToken();
59-
60-
e.Property(x => x.UserKey)
65+
e.Property(x => x.UserKey).IsRequired();
66+
e.Property(x => x.CreatedAt).IsRequired();
67+
e.Property(x => x.Tenant)
68+
.HasConversion(
69+
v => v.Value,
70+
v => TenantKey.FromInternal(v))
71+
.HasMaxLength(128)
6172
.IsRequired();
6273

6374
e.HasIndex(x => new { x.Tenant, x.ChainId }).IsUnique();
75+
e.HasIndex(x => new { x.Tenant, x.UserKey });
76+
e.HasIndex(x => new { x.Tenant, x.UserKey, x.DeviceId });
77+
e.HasIndex(x => new { x.Tenant, x.RootId });
78+
79+
e.HasOne<SessionRootProjection>()
80+
.WithMany()
81+
.HasForeignKey(x => new { x.Tenant, x.RootId })
82+
.HasPrincipalKey(x => new { x.Tenant, x.RootId })
83+
.OnDelete(DeleteBehavior.Restrict);
6484

6585
e.Property(x => x.ChainId)
6686
.HasConversion(
6787
v => v.Value,
6888
v => SessionChainId.From(v))
6989
.IsRequired();
7090

91+
e.Property(x => x.DeviceId)
92+
.HasConversion(
93+
v => v.Value,
94+
v => DeviceId.Create(v))
95+
.HasMaxLength(64)
96+
.IsRequired();
97+
98+
e.Property(x => x.Device)
99+
.HasConversion(new JsonValueConverter<DeviceContext>())
100+
.IsRequired();
101+
71102
e.Property(x => x.ActiveSessionId)
72103
.HasConversion(new NullableAuthSessionIdConverter());
73104

@@ -83,9 +114,26 @@ protected override void OnModelCreating(ModelBuilder b)
83114
{
84115
e.HasKey(x => x.Id);
85116
e.Property(x => x.Version).IsConcurrencyToken();
117+
e.Property(x => x.CreatedAt).IsRequired();
118+
e.Property(x => x.Tenant)
119+
.HasConversion(
120+
v => v.Value,
121+
v => TenantKey.FromInternal(v))
122+
.HasMaxLength(128)
123+
.IsRequired();
86124

87125
e.HasIndex(x => new { x.Tenant, x.SessionId }).IsUnique();
126+
e.HasIndex(x => new { x.Tenant, x.ChainId });
88127
e.HasIndex(x => new { x.Tenant, x.ChainId, x.RevokedAt });
128+
e.HasIndex(x => new { x.Tenant, x.UserKey, x.RevokedAt });
129+
e.HasIndex(x => new { x.Tenant, x.ExpiresAt });
130+
e.HasIndex(x => new { x.Tenant, x.RevokedAt });
131+
132+
e.HasOne<SessionChainProjection>()
133+
.WithMany()
134+
.HasForeignKey(x => new { x.Tenant, x.ChainId })
135+
.HasPrincipalKey(x => new { x.Tenant, x.ChainId })
136+
.OnDelete(DeleteBehavior.Restrict);
89137

90138
e.Property(x => x.SessionId)
91139
.HasConversion(new AuthSessionIdConverter())

src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/EntityProjections/SessionChainProjection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ internal sealed class SessionChainProjection
1515
public DateTimeOffset CreatedAt { get; init; }
1616
public DateTimeOffset LastSeenAt { get; set; }
1717
public DateTimeOffset? AbsoluteExpiresAt { get; set; }
18+
public DeviceId DeviceId { get; set; }
1819
public DeviceContext Device { get; set; }
1920
public ClaimsSnapshot ClaimsSnapshot { get; set; } = ClaimsSnapshot.Empty;
2021
public AuthSessionId? ActiveSessionId { get; set; }

src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/EntityProjections/SessionProjection.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ internal sealed class SessionProjection
1515

1616
public DateTimeOffset CreatedAt { get; set; }
1717
public DateTimeOffset ExpiresAt { get; set; }
18-
public DateTimeOffset? LastSeenAt { get; set; }
1918

20-
public bool IsRevoked { get; set; }
19+
2120
public DateTimeOffset? RevokedAt { get; set; }
2221

2322
public long SecurityVersionAtCreation { get; set; }
@@ -27,4 +26,6 @@ internal sealed class SessionProjection
2726
public SessionMetadata Metadata { get; set; } = SessionMetadata.Empty;
2827

2928
public long Version { get; set; }
29+
30+
public bool IsRevoked => RevokedAt != null;
3031
}

src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/EntityProjections/SessionRootProjection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ internal sealed class SessionRootProjection
1313
public DateTimeOffset CreatedAt { get; set; }
1414
public DateTimeOffset? UpdatedAt { get; set; }
1515

16-
public bool IsRevoked { get; set; }
1716
public DateTimeOffset? RevokedAt { get; set; }
1817

1918
public long SecurityVersion { get; set; }
2019
public long Version { get; set; }
20+
21+
public bool IsRevoked => RevokedAt != null;
2122
}

src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Extensions/ServiceCollectionExtensions.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
using Microsoft.EntityFrameworkCore;
1+
using CodeBeam.UltimateAuth.Core.Abstractions;
2+
using Microsoft.EntityFrameworkCore;
23
using Microsoft.Extensions.DependencyInjection;
34

45
namespace CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore;
56

67
public static class ServiceCollectionExtensions
78
{
8-
public static IServiceCollection AddUltimateAuthEntityFrameworkCoreSessions<TUserId>(this IServiceCollection services,Action<DbContextOptionsBuilder> configureDb)where TUserId : notnull
9+
public static IServiceCollection AddUltimateAuthEntityFrameworkCoreSessions(this IServiceCollection services,Action<DbContextOptionsBuilder> configureDb)
910
{
10-
services.AddDbContext<UltimateAuthSessionDbContext>(configureDb);
11-
services.AddScoped<EfCoreSessionStore>();
11+
services.AddDbContextPool<UltimateAuthSessionDbContext>(configureDb);
12+
services.AddScoped<ISessionStoreFactory, EfCoreSessionStoreFactory>();
1213

1314
return services;
1415
}

src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Mappers/SessionChainProjectionMapper.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public static UAuthSessionChain ToDomain(this SessionChainProjection p)
2727

2828
public static SessionChainProjection ToProjection(this UAuthSessionChain chain)
2929
{
30+
if (chain.Device.DeviceId is not DeviceId deviceId)
31+
throw new ArgumentException("Device id required.");
32+
3033
return new SessionChainProjection
3134
{
3235
ChainId = chain.ChainId,
@@ -36,6 +39,7 @@ public static SessionChainProjection ToProjection(this UAuthSessionChain chain)
3639
CreatedAt = chain.CreatedAt,
3740
LastSeenAt = chain.LastSeenAt,
3841
AbsoluteExpiresAt = chain.AbsoluteExpiresAt,
42+
DeviceId = deviceId,
3943
Device = chain.Device,
4044
ClaimsSnapshot = chain.ClaimsSnapshot,
4145
ActiveSessionId = chain.ActiveSessionId,

src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Mappers/SessionProjectionMapper.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ public static UAuthSession ToDomain(this SessionProjection p)
1313
p.ChainId,
1414
p.CreatedAt,
1515
p.ExpiresAt,
16-
p.IsRevoked,
1716
p.RevokedAt,
1817
p.SecurityVersionAtCreation,
1918
p.Claims,
@@ -33,8 +32,6 @@ public static SessionProjection ToProjection(this UAuthSession s)
3332

3433
CreatedAt = s.CreatedAt,
3534
ExpiresAt = s.ExpiresAt,
36-
37-
IsRevoked = s.IsRevoked,
3835
RevokedAt = s.RevokedAt,
3936

4037
SecurityVersionAtCreation = s.SecurityVersionAtCreation,
@@ -43,5 +40,4 @@ public static SessionProjection ToProjection(this UAuthSession s)
4340
Version = s.Version
4441
};
4542
}
46-
4743
}

0 commit comments

Comments
 (0)