fix(identity): select active role store for remediation
This commit is contained in:
parent
f9d41ee85b
commit
77da232bba
|
|
@ -147,7 +147,9 @@ public sealed class ExternalAuthenticationRoleDeletionDependencyContributor(
|
|||
|
||||
if (request.SelectedReferences is not null && removesLastDefaultRole)
|
||||
{
|
||||
var roleStore = roleStores.SingleOrDefault();
|
||||
// Match the default DI container's direct-service semantics: when persistence
|
||||
// replaces the in-memory store, the last registration is the active store.
|
||||
var roleStore = roleStores.LastOrDefault();
|
||||
if (roleStore is null)
|
||||
return new RoleReferenceRemovalResult.Failed("replacement_role_unavailable_or_unauthorized", changedOwnerIds);
|
||||
var replacement = await roleStore.FindAsync(new() { Id = request.ReplacementRoleId }, cancellationToken);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,47 @@ public class ExternalAuthenticationRoleDeletionDependencyContributorTests
|
|||
Assert.Equal(["replacement-role"], updated.UnlinkedPolicy!.Settings.GetProperty("defaultRoleIds").EnumerateArray().Select(x => x.GetString()!).ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UsesTheActiveRoleStoreWhenPersistenceReplacesTheDefaultStore()
|
||||
{
|
||||
var databaseConnection = Connection(
|
||||
"database",
|
||||
new PolicySelection(
|
||||
CreateUserUnlinkedIdentityPolicy.PolicyType,
|
||||
1,
|
||||
JsonSerializer.SerializeToElement(new { defaultRoleIds = new[] { "workflow-user" } })));
|
||||
var connectionStore = new InMemoryIdentityProviderConnectionStore();
|
||||
Assert.IsType<ConnectionMutationResult.Created>(await connectionStore.CreateAsync(databaseConnection));
|
||||
var replacedStore = new MemoryRoleStore(new MemoryStore<Role>(), TestTenantAccessor.Default);
|
||||
var activeStore = new MemoryRoleStore(new MemoryStore<Role>(), TestTenantAccessor.Default);
|
||||
await activeStore.SaveAsync(new Role { Id = "workflow-user", Name = "Workflow user", Permissions = [] });
|
||||
await activeStore.SaveAsync(new Role { Id = "replacement-role", Name = "Replacement role", Permissions = [] });
|
||||
var roleAuthorizationService = new RoleAuthorizationService(new StoreBasedRoleProvider(activeStore), new PermissionEvaluator());
|
||||
var services = new ServiceCollection().BuildServiceProvider();
|
||||
var contributor = new ExternalAuthenticationRoleDeletionDependencyContributor(
|
||||
connectionStore,
|
||||
new MutableOptionsMonitor<ExternalAuthenticationOptions>(new ExternalAuthenticationOptions()),
|
||||
[roleAuthorizationService],
|
||||
[replacedStore, activeStore],
|
||||
new InMemoryConnectionRegistryVersionStore(),
|
||||
new ConnectionRevisionCalculator(),
|
||||
new ExternalAuthenticationSecurityNotifier(services),
|
||||
new PermissionEvaluator());
|
||||
var snapshot = await contributor.InspectAsync("workflow-user");
|
||||
var request = new RoleReferenceRemovalRequest(
|
||||
"workflow-user",
|
||||
Administrator(),
|
||||
snapshot.Version,
|
||||
snapshot.Dependencies)
|
||||
{
|
||||
SelectedReferences = [new RoleDeletionReferenceSelection(ExternalAuthenticationRoleDeletionDependencyContributor.SourceName, databaseConnection.Id)],
|
||||
ReplacementRoleId = "replacement-role"
|
||||
};
|
||||
|
||||
Assert.IsType<RoleReferenceRemovalValidationResult.Valid>(await contributor.ValidateRemovalAsync(request));
|
||||
Assert.IsType<RoleReferenceRemovalResult.Success>(await contributor.RemoveEditableReferencesAsync(request));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RejectsMissingReplacementForSelectedFinalDefaultRole()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue