fix(management): invalidate RoleMappingCache after role-mapping and scope-rule mutations commit (review 2026-10-21 lane K M1)
This commit is contained in:
@@ -2820,6 +2820,21 @@ public class ManagementActor : ReceiveActor
|
||||
$"Role '{role}' is not a recognized role. Valid roles are: {string.Join(", ", Roles.All)}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drops this node's <see cref="RoleMappingCache"/> snapshot once a mapping / scope-rule
|
||||
/// change has committed, so the next role mapping on this node sees it immediately rather
|
||||
/// than after the cache TTL (lane K review M1). Queued post-commit: invalidating before the
|
||||
/// commit would let a concurrent mapping re-cache the pre-change table. Other central
|
||||
/// nodes still converge within <c>RoleMappingCacheSeconds</c>.
|
||||
/// </summary>
|
||||
private static Task InvalidateRoleMappingCacheAfterCommit(IServiceProvider sp)
|
||||
{
|
||||
var cache = sp.GetService<RoleMappingCache>();
|
||||
return cache is null
|
||||
? Task.CompletedTask
|
||||
: AfterConfigurationCommit(sp, () => { cache.Invalidate(); return Task.CompletedTask; });
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleCreateRoleMapping(IServiceProvider sp, CreateRoleMappingCommand cmd, string user)
|
||||
{
|
||||
var role = CanonicalizeMappingRole(cmd.Role);
|
||||
@@ -2827,6 +2842,7 @@ public class ManagementActor : ReceiveActor
|
||||
var mapping = new LdapGroupMapping(cmd.LdapGroupName, role);
|
||||
await repo.AddMappingAsync(mapping);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateRoleMappingCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Create", "RoleMapping", mapping.Id.ToString(), $"{mapping.LdapGroupName}->{mapping.Role}", mapping);
|
||||
return mapping;
|
||||
}
|
||||
@@ -2841,6 +2857,7 @@ public class ManagementActor : ReceiveActor
|
||||
mapping.Role = role;
|
||||
await repo.UpdateMappingAsync(mapping);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateRoleMappingCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Update", "RoleMapping", mapping.Id.ToString(), $"{mapping.LdapGroupName}->{mapping.Role}", mapping);
|
||||
return mapping;
|
||||
}
|
||||
@@ -2850,6 +2867,7 @@ public class ManagementActor : ReceiveActor
|
||||
var repo = sp.GetRequiredService<ISecurityRepository>();
|
||||
await repo.DeleteMappingAsync(cmd.MappingId);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateRoleMappingCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Delete", "RoleMapping", cmd.MappingId.ToString(), cmd.MappingId.ToString(), null);
|
||||
return true;
|
||||
}
|
||||
@@ -3807,6 +3825,7 @@ public class ManagementActor : ReceiveActor
|
||||
var rule = new SiteScopeRule { LdapGroupMappingId = cmd.MappingId, SiteId = cmd.SiteId };
|
||||
await repo.AddScopeRuleAsync(rule);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateRoleMappingCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Create", "ScopeRule", rule.Id.ToString(), $"Mapping:{cmd.MappingId}/Site:{cmd.SiteId}", rule);
|
||||
return rule;
|
||||
}
|
||||
@@ -3816,6 +3835,7 @@ public class ManagementActor : ReceiveActor
|
||||
var repo = sp.GetRequiredService<ISecurityRepository>();
|
||||
await repo.DeleteScopeRuleAsync(cmd.ScopeRuleId);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateRoleMappingCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Delete", "ScopeRule", cmd.ScopeRuleId.ToString(), cmd.ScopeRuleId.ToString(), null);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user