You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
at the risk of flooding you with feedback (take your time!), I today tried to Wolverine-ify RBAC on the granularity of a command (still talking about IMessageBus).
The code has a comment // TODO: consider reflection performance impact which I'm also after.
From my understanding, the Wolverine equivalent of IPipelineBehavior would be a middleware that would incur the same reflection cost per processed message. My idea was to make use of the code generation capability around the handler and pay that cost only once during setup.
usingSystem.Runtime.CompilerServices;usingApplication.Authorization;usingJasperFx.CodeGeneration;usingJasperFx.CodeGeneration.Frames;usingLamar;usingMicrosoft.Extensions.Logging;usingWolverine.Configuration;usingWolverine.Runtime.Handlers;namespaceInfrastructure.Authorization;publicclassAuthorizationPolicy:IHandlerPolicy{staticreadonlyDictionary<Type,string[]>MessageTypeToPolicies=new();publicvoidApply(HandlerGraphgraph,GenerationRulesrules,IContainercontainer){foreach(varchainingraph.Chains){Apply(chain);}}voidApply(HandlerChainchain){varpolicies=chain.MessageType.GetCustomAttributes(typeof(AuthorizeAttribute),true).Cast<AuthorizeAttribute>().Select(x =>x.Policy).Where(x =>!string.IsNullOrWhiteSpace(x)).ToArray();if(!policies.Any()){return;}MessageTypeToPolicies.Add(chain.MessageType,policies!);varmethod=GetType().GetMethod(nameof(EnforcePolicy)).MakeGenericMethod(chain.MessageType);varmethodCall=newMethodCall(GetType(),method);chain.Middleware.Add(methodCall);}[MethodImpl(MethodImplOptions.AggressiveInlining)]publicstaticasyncTaskEnforcePolicy<T>(IIdentityServiceidentityService,ILoggerlogger,Tmessage){varpolicies=MessageTypeToPolicies[message.GetType()];foreach(varpolicyinpolicies){if(awaitidentityService.AuthorizeAsync(policy)){continue;}logger.LogWarning("Failed {Policy} policy authorization with user {User} for {Message}",policy,identityService.UserId,message);thrownewUnauthorizedAccessException();}}}
The Apply does the reflection bits and then injects a method call, like a middleware's Before(). But the Before() variant would always need to reflect, right?
As you can see the handler policy uses a dictionary to cache the roles per message, but my ultimate goal would be to pass the list of roles directly to EnforcePolicy, perhaps as the first argument.
I tried that for a couple of hours, even cloned JasperFx.CodeGeneration, but I could not find a way to make the first argument a constant expression. Perhaps another way is to register "required roles per message" in the container, but that seems a bit too overboard. It would be great if you could share your ideas!
The text was updated successfully, but these errors were encountered:
@agross I'll have to give this one a better look and get back to you. It's exactly the kind of thing that I think Wolverine should do much more efficiently than MediatR et al.
From #173
Hi @jeremydmiller,
at the risk of flooding you with feedback (take your time!), I today tried to Wolverine-ify RBAC on the granularity of a command (still talking about IMessageBus).
I use KeyCloak for authentication and there is an excellent NuGet with an example to implement RBAC with a Mediatr behavior..
The code has a comment // TODO: consider reflection performance impact which I'm also after.
From my understanding, the Wolverine equivalent of IPipelineBehavior would be a middleware that would incur the same reflection cost per processed message. My idea was to make use of the code generation capability around the handler and pay that cost only once during setup.
The Apply does the reflection bits and then injects a method call, like a middleware's Before(). But the Before() variant would always need to reflect, right?
As you can see the handler policy uses a dictionary to cache the roles per message, but my ultimate goal would be to pass the list of roles directly to EnforcePolicy, perhaps as the first argument.
I tried that for a couple of hours, even cloned JasperFx.CodeGeneration, but I could not find a way to make the first argument a constant expression. Perhaps another way is to register "required roles per message" in the container, but that seems a bit too overboard. It would be great if you could share your ideas!
The text was updated successfully, but these errors were encountered: