1+ using IamRoles . Mutations ;
2+ using IamRoles . State ;
3+ using ModularityKit . Mutator . Abstractions . Context ;
4+ using ModularityKit . Mutator . Abstractions . Engine ;
5+
6+ namespace IamRoles . Scenarios ;
7+
8+ /// <summary>
9+ /// BatchRoleMigrationScenario
10+ ///
11+ /// Demonstrates batch migration of IAM roles for multiple users using <see cref="IMutation{TState}"/>
12+ /// and <see cref="GrantUserRoleMutation"/> in a single operation.
13+ ///
14+ /// Scenario Details:
15+ /// - Executes multiple <see cref="IMutationEngine.ExecuteBatchAsync{TState}"/> instances in a batch via <see cref="IMutationEngine"/>.
16+ /// - Provides a <see cref="UserPermissionsState"/> with system metadata, including approval info for auditability.
17+ /// - Logs success and failure statistics for each mutation.
18+ /// - Handles policy decisions for each mutation, such as restrictions on role assignments.
19+ /// - Works with <see cref="IMutation{TState}"/> which tracks roles assigned to users.
20+ ///
21+ /// Key Steps:
22+ /// 1. Initialize <see cref="IMutationEngine.ExecuteBatchAsync{TState}"/> with initial roles for each user.
23+ /// 2. Construct an array of <see cref="IMutationEngine"/> representing role grants.
24+ /// 3. Execute the batch with <see cref="IMutationEngine"/>.
25+ /// 4. Count successes and failures, and display any policy decisions that blocked mutations.
26+ ///
27+ /// Example Use Case:
28+ /// - Performing organizational role restructuring
29+ /// - Batch granting of elevated permissions to multiple users
30+ /// - Ensuring compliance and auditability via system metadata and policy evaluation
31+ ///
32+ /// Notes:
33+ /// - Individual mutations in the batch may fail if any policy denies the role change.
34+ /// - Correlation ID or metadata can be used to trace this batch operation in logs.
35+ /// </summary>
36+ internal static class BatchRoleMigrationScenario
37+ {
38+ internal static async Task Run ( IMutationEngine engine )
39+ {
40+ Console . WriteLine ( "\n === Batch Role Migration Scenario ===" ) ;
41+
42+ var state = new UserPermissionsState
43+ {
44+ RolesByUser = new Dictionary < string , HashSet < string > >
45+ {
46+ [ "alice" ] = [ "User" ] ,
47+ [ "bob" ] = [ "User" ] ,
48+ [ "carol" ] = [ "User" ]
49+ }
50+ } ;
51+
52+ var ctx = MutationContext . System ( reason : "Org restructure" )
53+ with
54+ {
55+ Metadata = new Dictionary < string , object >
56+ {
57+ [ "approvedBy" ] = "security-team"
58+ }
59+ } ;
60+
61+ var mutations = new IMutation < UserPermissionsState > [ ]
62+ {
63+ new GrantUserRoleMutation ( "alice" , "Manager" , ctx ) ,
64+ new GrantUserRoleMutation ( "bob" , "Admin" , ctx ) ,
65+ new GrantUserRoleMutation ( "carol" , "Manager" , ctx )
66+ } ;
67+
68+ var result = await engine . ExecuteBatchAsync ( mutations , state ) ;
69+
70+ Console . WriteLine ( $ "Executed: { result . Results . Count } ") ;
71+ Console . WriteLine ( $ "Success: { result . Results . Count ( r => r . IsSuccess ) } ") ;
72+ Console . WriteLine ( $ "Failed: { result . Results . Count ( r => ! r . IsSuccess ) } ") ;
73+
74+ foreach ( var failure in result . Results . Where ( r => ! r . IsSuccess ) )
75+ {
76+ Console . WriteLine ( "✗ Mutation failed:" ) ;
77+ foreach ( var decision in failure . PolicyDecisions )
78+ Console . WriteLine ( $ " Policy: { decision . PolicyName } – { decision . Reason } ") ;
79+ }
80+ }
81+ }
0 commit comments