From c491df8d23a48336373b4117898e81cb7ff32a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Mon, 20 Apr 2026 00:45:58 +0300 Subject: [PATCH] Fix EfCore Session Store Transaction & Save Changes --- .../Pages/DocsSidebar.razor | 1 - .../uauthhub.db-shm | Bin 32768 -> 32768 bytes .../uauthhub.db-wal | Bin 1211312 -> 716912 bytes .../Dialogs/CreateUserDialog.razor.cs | 2 +- .../Dialogs/CredentialDialog.razor.cs | 2 +- .../Components/Dialogs/ProfileDialog.razor.cs | 2 +- .../Components/Pages/Register.razor.cs | 2 +- .../Components/Pages/ResetCredential.razor.cs | 2 +- .../uauth.db | Bin 311296 -> 4096 bytes .../uauth.db-shm | Bin 0 -> 32768 bytes .../uauth.db-wal | Bin 0 -> 935272 bytes .../Dialogs/CreateUserDialog.razor.cs | 2 +- .../Dialogs/CredentialDialog.razor.cs | 2 +- .../Components/Dialogs/ProfileDialog.razor.cs | 2 +- .../Components/Pages/Register.razor.cs | 2 +- .../Components/Pages/ResetCredential.razor.cs | 2 +- .../Dialogs/CreateUserDialog.razor.cs | 2 +- .../Dialogs/CredentialDialog.razor.cs | 2 +- .../Components/Dialogs/ProfileDialog.razor.cs | 2 +- .../Pages/Register.razor.cs | 2 +- .../Pages/ResetCredential.razor.cs | 2 +- .../Services/SessionApplicationService.cs | 44 ++++++++---- .../Stores/EfCoreSessionStore.cs | 65 ++++++++++++++++++ .../EfCoreSessionStoreTests.cs | 7 +- 24 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/uauth.db-shm create mode 100644 samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/uauth.db-wal diff --git a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/Pages/DocsSidebar.razor b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/Pages/DocsSidebar.razor index 08c0b652..8743c5d6 100644 --- a/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/Pages/DocsSidebar.razor +++ b/docs/website/CodeBeam.UltimateAuth.Docs.Wasm/CodeBeam.UltimateAuth.Docs.Wasm.Client/Pages/DocsSidebar.razor @@ -35,7 +35,6 @@ @code { private Dictionary>? _groups; - private DocIndexItem? _selectedValue; private bool _expanded = true; [Parameter] diff --git a/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub.EFCore/uauthhub.db-shm b/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub.EFCore/uauthhub.db-shm index c6cedbd528aee1b8a0ea2a6ef1c664d3bad8602f..3b286565f3252c116e01ea39ae905a848e128bdb 100644 GIT binary patch delta 448 zcmZo@U}|V!s+V}A%K!pmK+MR%Ag~Td`v7tF_r}nNSwL{isPEeO00F0|2eJMti-Cp zIQfzbMBtArL}2p;_iKz`smP~J0#qa;SqEY#qdM5E$Jodf#O7^zP`(3%zoii7=1nCq)`oH@i%}0^+KpH1(ks}w^pL*8UX)}@TD HK(ZbH)u)pS delta 926 zcmcJOOGs2<6vzMP-bSxC8^=mh$FUhr$Avv03Mwc^6d`J1$^;e>L{KhcTnJ zo5Yq1uVU@MARc2BW3W<++}$hutG$Zaf@5;o@Kx4pJ$MO~GNZ|&agA58oklMn;T67P z5=|qAoHUBv>k3G1#c{bOs@8Lez=>$HX+r@~r|_t5vbfQPlOnvam*~8yKHif?@nbYV6{gw?@c% z75DH2pD~Uknjr@nq|ZSgMqr^V(`XEA3u;|>iV38diar-N@EUP6)9m9jP!1pN^6L-S TN^lML@eE)1542Ib{C58@TaV?? diff --git a/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub.EFCore/uauthhub.db-wal b/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub.EFCore/uauthhub.db-wal index a23ad2d540f522ad5063c0cf51278b4f91a4dc47..db39603ee424a73224ac643a836d7d0987634ede 100644 GIT binary patch delta 8945 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 diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/uauth.db-shm b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/uauth.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..f64b9c90f143a9cc183059d3bc8a17ba03fcadff GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CreateUserDialog.razor.cs b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CreateUserDialog.razor.cs index ec16e78f..af13ee27 100644 --- a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CreateUserDialog.razor.cs +++ b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CreateUserDialog.razor.cs @@ -18,7 +18,7 @@ public partial class CreateUserDialog private async Task CreateUserAsync() { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) return; diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CredentialDialog.razor.cs b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CredentialDialog.razor.cs index ee48c215..887707c5 100644 --- a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CredentialDialog.razor.cs +++ b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/CredentialDialog.razor.cs @@ -31,7 +31,7 @@ private async Task ChangePasswordAsync() if (_form is null) return; - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) { Snackbar.Add("Form is not valid.", Severity.Error); diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/ProfileDialog.razor.cs b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/ProfileDialog.razor.cs index 24fd603e..d2186593 100644 --- a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/ProfileDialog.razor.cs +++ b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/ProfileDialog.razor.cs @@ -70,7 +70,7 @@ private async Task SaveAsync() if (_form is not null) { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) return; } diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Register.razor.cs b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Register.razor.cs index d1e67865..6adc7dc6 100644 --- a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Register.razor.cs +++ b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Register.razor.cs @@ -20,7 +20,7 @@ protected override async Task OnInitializedAsync() private async Task HandleRegisterAsync() { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) return; diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/ResetCredential.razor.cs b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/ResetCredential.razor.cs index db40becc..9bcaf5f7 100644 --- a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/ResetCredential.razor.cs +++ b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/ResetCredential.razor.cs @@ -12,7 +12,7 @@ public partial class ResetCredential private async Task ResetPasswordAsync() { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) { Snackbar.Add("Please fix the validation errors.", Severity.Error); diff --git a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CreateUserDialog.razor.cs b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CreateUserDialog.razor.cs index 61aa56fb..b10d7d9d 100644 --- a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CreateUserDialog.razor.cs +++ b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CreateUserDialog.razor.cs @@ -18,7 +18,7 @@ public partial class CreateUserDialog private async Task CreateUserAsync() { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) return; diff --git a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CredentialDialog.razor.cs b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CredentialDialog.razor.cs index 926eba3d..a9c76d1c 100644 --- a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CredentialDialog.razor.cs +++ b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/CredentialDialog.razor.cs @@ -31,7 +31,7 @@ private async Task ChangePasswordAsync() if (_form is null) return; - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) { Snackbar.Add("Form is not valid.", Severity.Error); diff --git a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/ProfileDialog.razor.cs b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/ProfileDialog.razor.cs index c0442702..c96497e8 100644 --- a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/ProfileDialog.razor.cs +++ b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Components/Dialogs/ProfileDialog.razor.cs @@ -72,7 +72,7 @@ private async Task SaveAsync() if (_form is not null) { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) return; } diff --git a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/Register.razor.cs b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/Register.razor.cs index db73fd6a..8219cee3 100644 --- a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/Register.razor.cs +++ b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/Register.razor.cs @@ -20,7 +20,7 @@ protected override async Task OnInitializedAsync() private async Task HandleRegisterAsync() { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) return; diff --git a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/ResetCredential.razor.cs b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/ResetCredential.razor.cs index 726c4864..b76e12b1 100644 --- a/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/ResetCredential.razor.cs +++ b/samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/ResetCredential.razor.cs @@ -12,7 +12,7 @@ public partial class ResetCredential private async Task ResetPasswordAsync() { - await _form.Validate(); + await _form.ValidateAsync(); if (!_form.IsValid) { Snackbar.Add("Please fix the validation errors.", Severity.Error); diff --git a/src/CodeBeam.UltimateAuth.Server/Services/SessionApplicationService.cs b/src/CodeBeam.UltimateAuth.Server/Services/SessionApplicationService.cs index 4b62d6ab..d7640693 100644 --- a/src/CodeBeam.UltimateAuth.Server/Services/SessionApplicationService.cs +++ b/src/CodeBeam.UltimateAuth.Server/Services/SessionApplicationService.cs @@ -164,7 +164,9 @@ public async Task RevokeUserSessionAsync(AccessContext context, UserKey userKey, var expected = session.Version; var revoked = session.Revoke(now); - await store.SaveSessionAsync(revoked, expected); + await store.ExecuteAsync(async innerCt2 => { + await store.SaveSessionAsync(revoked, expected); + }); }); await _accessOrchestrator.ExecuteAsync(context, command, ct); @@ -176,7 +178,10 @@ public async Task RevokeUserChainAsync(AccessContext context, User { var isCurrent = context.ActorChainId == chainId; var store = _storeFactory.Create(context.ResourceTenant); - await store.RevokeChainCascadeAsync(chainId, _clock.UtcNow); + + await store.ExecuteAsync(async innerCt2 => { + await store.RevokeChainCascadeAsync(chainId, _clock.UtcNow); + }); return new RevokeResult { @@ -198,15 +203,18 @@ public async Task RevokeAllChainsAsync(AccessContext context, UserKey userKey, S var command = new AccessCommand(async innerCt => { var store = _storeFactory.Create(context.ResourceTenant); - var chains = await store.GetChainsByUserAsync(userKey); - foreach (var chain in chains) - { - if (exceptChainId.HasValue && chain.ChainId == exceptChainId.Value) - continue; + await store.ExecuteAsync(async innerCt2 => { + var chains = await store.GetChainsByUserAsync(userKey); - await store.RevokeChainCascadeAsync(chain.ChainId, _clock.UtcNow); - } + foreach (var chain in chains) + { + if (exceptChainId.HasValue && chain.ChainId == exceptChainId.Value) + continue; + + await store.RevokeChainCascadeAsync(chain.ChainId, _clock.UtcNow); + } + }); }); await _accessOrchestrator.ExecuteAsync(context, command, ct); @@ -220,7 +228,9 @@ public async Task LogoutDeviceAsync(AccessContext context, Session var store = _storeFactory.Create(context.ResourceTenant); var now = _clock.UtcNow; - await store.LogoutChainAsync(currentChainId, now, innerCt); + await store.ExecuteAsync(async innerCt2 => { + await store.LogoutChainAsync(currentChainId, now, innerCt2); + }); return new RevokeResult { @@ -239,7 +249,10 @@ public async Task LogoutOtherDevicesAsync(AccessContext context, UserKey userKey var store = _storeFactory.Create(context.ResourceTenant); var now = _clock.UtcNow; - await store.RevokeOtherSessionsAsync(userKey, currentChainId, now, innerCt); + await store.ExecuteAsync(async innerCt2 => { + await store.RevokeOtherSessionsAsync(userKey, currentChainId, now, innerCt2); + }); + }); await _accessOrchestrator.ExecuteAsync(context, command, ct); @@ -252,7 +265,9 @@ public async Task LogoutAllDevicesAsync(AccessContext context, UserKey userKey, var store = _storeFactory.Create(context.ResourceTenant); var now = _clock.UtcNow; - await store.RevokeAllSessionsAsync(userKey, now, innerCt); + await store.ExecuteAsync(async innerCt2 => { + await store.RevokeAllSessionsAsync(userKey, now, innerCt2); + }); }); await _accessOrchestrator.ExecuteAsync(context, command, ct); @@ -263,7 +278,10 @@ public async Task RevokeRootAsync(AccessContext context, UserKey userKey, Cancel var command = new AccessCommand(async innerCt => { var store = _storeFactory.Create(context.ResourceTenant); - await store.RevokeRootCascadeAsync(userKey, _clock.UtcNow); + + await store.ExecuteAsync(async innerCt2 => { + await store.RevokeRootCascadeAsync(userKey, _clock.UtcNow); + }); }); await _accessOrchestrator.ExecuteAsync(context, command, ct); diff --git a/src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Stores/EfCoreSessionStore.cs b/src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Stores/EfCoreSessionStore.cs index a1108ca4..99824242 100644 --- a/src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Stores/EfCoreSessionStore.cs +++ b/src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/Stores/EfCoreSessionStore.cs @@ -11,6 +11,7 @@ internal sealed class EfCoreSessionStore : ISessionStore where TDbCo { private readonly TDbContext _db; private readonly TenantKey _tenant; + private bool _inExecution; public EfCoreSessionStore(TDbContext db, TenantExecutionContext tenant) { @@ -32,6 +33,7 @@ await strategy.ExecuteAsync(async () => try { + _inExecution = true; await action(ct); await _db.SaveChangesAsync(ct); await tx.CommitAsync(ct); @@ -46,6 +48,10 @@ await strategy.ExecuteAsync(async () => await tx.RollbackAsync(ct); throw; } + finally + { + _inExecution = false; + } }); } @@ -59,6 +65,7 @@ public async Task ExecuteAsync(Func ExecuteAsync(Func x.Tenant == _tenant && x.SessionId == session.SessionId); if (projection == null) @@ -122,6 +136,9 @@ public Task CreateSessionAsync(UAuthSession session, CancellationToken ct = defa { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = session.ToProjection(); if (session.Version != 0) @@ -136,6 +153,9 @@ public async Task RevokeSessionAsync(AuthSessionId sessionId, DateTimeOffs { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = await DbSetSession.SingleOrDefaultAsync(x => x.Tenant == _tenant && x.SessionId == sessionId, ct); if (projection is null || projection.RevokedAt is not null) @@ -152,6 +172,9 @@ public async Task RevokeAllSessionsAsync(UserKey user, DateTimeOffset at, Cancel { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var chains = await DbSetChain .Where(x => x.Tenant == _tenant && x.UserKey == user) .ToListAsync(ct); @@ -188,6 +211,9 @@ public async Task RevokeOtherSessionsAsync(UserKey user, SessionChainId keepChai { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var chains = await DbSetChain .Where(x => x.Tenant == _tenant && x.UserKey == user && x.ChainId != keepChain) .ToListAsync(ct); @@ -267,6 +293,9 @@ public async Task SaveChainAsync(UAuthSessionChain chain, long expectedVersion, { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = DbSetChain.Local.FirstOrDefault(x => x.Tenant == _tenant && x.ChainId == chain.ChainId); if (projection is null) @@ -289,6 +318,9 @@ public Task CreateChainAsync(UAuthSessionChain chain, CancellationToken ct = def { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + if (chain.Version != 0) throw new InvalidOperationException("New chain must have version 0."); @@ -304,6 +336,9 @@ public async Task RevokeChainAsync(SessionChainId chainId, DateTimeOffset at, Ca { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = await DbSetChain .SingleOrDefaultAsync(x => x.Tenant == _tenant && x.ChainId == chainId, ct); @@ -319,6 +354,9 @@ public async Task LogoutChainAsync(SessionChainId chainId, DateTimeOffset at, Ca { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var chainProjection = await DbSetChain .SingleOrDefaultAsync(x => x.Tenant == _tenant && x.ChainId == chainId, ct); @@ -352,6 +390,9 @@ public async Task RevokeOtherChainsAsync(UserKey userKey, SessionChainId current { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projections = await DbSetChain .Where(x => x.Tenant == _tenant && @@ -372,6 +413,9 @@ public async Task RevokeAllChainsAsync(UserKey userKey, DateTimeOffset at, Cance { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projections = await DbSetChain .Where(x => x.Tenant == _tenant && @@ -402,6 +446,9 @@ public async Task SetActiveSessionIdAsync(SessionChainId chainId, AuthSessionId { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = DbSetChain.Local.FirstOrDefault(x => x.Tenant == _tenant && x.ChainId == chainId); if (projection is null) @@ -428,6 +475,9 @@ public async Task SaveRootAsync(UAuthSessionRoot root, long expectedVersion, Can { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = await DbSetRoot .SingleOrDefaultAsync(x => x.Tenant == _tenant && @@ -448,6 +498,9 @@ public Task CreateRootAsync(UAuthSessionRoot root, CancellationToken ct = defaul { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + if (root.Version != 0) throw new InvalidOperationException("New root must have version 0."); @@ -462,6 +515,9 @@ public async Task RevokeRootAsync(UserKey userKey, DateTimeOffset at, Cancellati { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = await DbSetRoot .SingleOrDefaultAsync(x => x.Tenant == _tenant && x.UserKey == userKey, ct); @@ -540,6 +596,9 @@ public async Task RemoveSessionAsync(AuthSessionId sessionId, CancellationToken { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var projection = await DbSetSession.SingleOrDefaultAsync(x => x.Tenant == _tenant && x.SessionId == sessionId, ct); if (projection is null) @@ -552,6 +611,9 @@ public async Task RevokeChainCascadeAsync(SessionChainId chainId, DateTimeOffset { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var chainProjection = await DbSetChain .SingleOrDefaultAsync(x => x.Tenant == _tenant && x.ChainId == chainId, ct); @@ -581,6 +643,9 @@ public async Task RevokeRootCascadeAsync(UserKey userKey, DateTimeOffset at, Can { ct.ThrowIfCancellationRequested(); + if (!_inExecution) + throw new InvalidOperationException("Must be called inside ExecuteAsync"); + var rootProjection = await DbSetRoot .SingleOrDefaultAsync(x => x.Tenant == _tenant && x.UserKey == userKey, ct); diff --git a/tests/CodeBeam.UltimateAuth.Tests.Unit/EntityFrameworkCore/EfCoreSessionStoreTests.cs b/tests/CodeBeam.UltimateAuth.Tests.Unit/EntityFrameworkCore/EfCoreSessionStoreTests.cs index 6eb7d7c9..504bcf49 100644 --- a/tests/CodeBeam.UltimateAuth.Tests.Unit/EntityFrameworkCore/EfCoreSessionStoreTests.cs +++ b/tests/CodeBeam.UltimateAuth.Tests.Unit/EntityFrameworkCore/EfCoreSessionStoreTests.cs @@ -261,6 +261,8 @@ public async Task Revoke_Session_Should_Work() ClaimsSnapshot.Empty, SessionMetadata.Empty); + bool revoked = false; + await store.ExecuteAsync(async ct => { await store.CreateRootAsync(root, ct); @@ -268,7 +270,10 @@ await store.ExecuteAsync(async ct => await store.CreateSessionAsync(session, ct); }); - var revoked = await store.RevokeSessionAsync(sessionId, DateTimeOffset.UtcNow); + await store.ExecuteAsync(async ct => + { + revoked = await store.RevokeSessionAsync(sessionId, DateTimeOffset.UtcNow); + }); Assert.True(revoked); }