diff --git a/PoweredSoft.CQRS.AspNetCore/Mvc/CommandController.cs b/PoweredSoft.CQRS.AspNetCore/Mvc/CommandController.cs index 17bf1fd..7901ca3 100644 --- a/PoweredSoft.CQRS.AspNetCore/Mvc/CommandController.cs +++ b/PoweredSoft.CQRS.AspNetCore/Mvc/CommandController.cs @@ -11,7 +11,7 @@ namespace PoweredSoft.CQRS.AspNetCore.Mvc public class CommandController : Controller where TCommand : class { - [HttpPost] + [HttpPost, CommandControllerAuthorization] public async Task Handle([FromServices] ICommandHandler handler, [FromBody] TCommand command) { @@ -27,7 +27,7 @@ namespace PoweredSoft.CQRS.AspNetCore.Mvc public class CommandController : Controller where TCommand : class { - [HttpPost] + [HttpPost, CommandControllerAuthorization] public async Task> Handle([FromServices] ICommandHandler handler, [FromBody] TCommand command) { diff --git a/PoweredSoft.CQRS.AspNetCore/Mvc/CommandControllerAsyncAuthorizationFilter.cs b/PoweredSoft.CQRS.AspNetCore/Mvc/CommandControllerAsyncAuthorizationFilter.cs new file mode 100644 index 0000000..7fa7934 --- /dev/null +++ b/PoweredSoft.CQRS.AspNetCore/Mvc/CommandControllerAsyncAuthorizationFilter.cs @@ -0,0 +1,44 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using System.Reflection; +using PoweredSoft.CQRS.Abstractions.Security; + +namespace PoweredSoft.CQRS.AspNetCore.Mvc +{ + public class CommandControllerAsyncAuthorizationFilter : IAsyncAuthorizationFilter + { + private readonly ICommandAuthorizationService _authorizationService; + + public CommandControllerAsyncAuthorizationFilter(IServiceProvider serviceProvider) + { + _authorizationService = serviceProvider.GetService(); + } + + public async Task OnAuthorizationAsync(AuthorizationFilterContext context) + { + if (_authorizationService == null) + return; + + var action = context.ActionDescriptor as Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor; + if (action == null) + throw new Exception("Only Supports controller action descriptor"); + + var attribute = action.MethodInfo.GetCustomAttribute(); + Type commandType; + if (attribute?.CommandType != null) + commandType = attribute.CommandType; + else + commandType = action.ControllerTypeInfo.GenericTypeArguments.First(); + + var ar = await _authorizationService.IsAllowedAsync(commandType); + if (ar == AuthorizationResult.Forbidden) + context.Result = new StatusCodeResult(403); + else if(ar == AuthorizationResult.Unauthorized) + context.Result = new StatusCodeResult(401); + } + } +} diff --git a/PoweredSoft.CQRS.AspNetCore/Mvc/CommandControllerAuthorizationAttribute.cs b/PoweredSoft.CQRS.AspNetCore/Mvc/CommandControllerAuthorizationAttribute.cs new file mode 100644 index 0000000..a114640 --- /dev/null +++ b/PoweredSoft.CQRS.AspNetCore/Mvc/CommandControllerAuthorizationAttribute.cs @@ -0,0 +1,21 @@ +using System; +using Microsoft.AspNetCore.Mvc; + +namespace PoweredSoft.CQRS.AspNetCore.Mvc +{ + [AttributeUsage(AttributeTargets.Method)] + public class CommandControllerAuthorizationAttribute : TypeFilterAttribute + { + public CommandControllerAuthorizationAttribute() : base(typeof(CommandControllerAsyncAuthorizationFilter)) + { + + } + + public CommandControllerAuthorizationAttribute(Type commandType) : base(typeof(CommandControllerAsyncAuthorizationFilter)) + { + CommandType = commandType; + } + + public Type CommandType { get; } = null; + } +} diff --git a/PoweredSoft.CQRS.AspNetCore/Mvc/QueryController.cs b/PoweredSoft.CQRS.AspNetCore/Mvc/QueryController.cs index 8c05703..3695bf2 100644 --- a/PoweredSoft.CQRS.AspNetCore/Mvc/QueryController.cs +++ b/PoweredSoft.CQRS.AspNetCore/Mvc/QueryController.cs @@ -11,7 +11,7 @@ namespace PoweredSoft.CQRS.AspNetCore.Mvc public class QueryController : Controller where TQuery : class { - [HttpPost] + [HttpPost, QueryControllerAuthorization] public async Task> Handle([FromServices] IQueryHandler handler, [FromBody] TQuery query) { diff --git a/PoweredSoft.CQRS.AspNetCore/Mvc/QueryControllerAsyncAuthorizationFilter.cs b/PoweredSoft.CQRS.AspNetCore/Mvc/QueryControllerAsyncAuthorizationFilter.cs new file mode 100644 index 0000000..1caaa5c --- /dev/null +++ b/PoweredSoft.CQRS.AspNetCore/Mvc/QueryControllerAsyncAuthorizationFilter.cs @@ -0,0 +1,44 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using System.Reflection; +using PoweredSoft.CQRS.Abstractions.Security; + +namespace PoweredSoft.CQRS.AspNetCore.Mvc +{ + public class QueryControllerAsyncAuthorizationFilter : IAsyncAuthorizationFilter + { + private readonly IQueryAuthorizationService _authorizationService; + + public QueryControllerAsyncAuthorizationFilter(IServiceProvider serviceProvider) + { + _authorizationService = serviceProvider.GetService(); + } + + public async Task OnAuthorizationAsync(AuthorizationFilterContext context) + { + if (_authorizationService == null) + return; + + var action = context.ActionDescriptor as Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor; + if (action == null) + throw new Exception("Only Supports controller action descriptor"); + + var attribute = action.MethodInfo.GetCustomAttribute(); + Type queryType; + if (attribute?.QueryType != null) + queryType = attribute.QueryType; + else + queryType = action.ControllerTypeInfo.GenericTypeArguments.First(); + + var ar = await _authorizationService.IsAllowedAsync(queryType); + if (ar == AuthorizationResult.Forbidden) + context.Result = new StatusCodeResult(403); + else if (ar == AuthorizationResult.Unauthorized) + context.Result = new StatusCodeResult(401); + } + } +} diff --git a/PoweredSoft.CQRS.AspNetCore/Mvc/QueryControllerAuthorizationAttribute.cs b/PoweredSoft.CQRS.AspNetCore/Mvc/QueryControllerAuthorizationAttribute.cs new file mode 100644 index 0000000..3daedbe --- /dev/null +++ b/PoweredSoft.CQRS.AspNetCore/Mvc/QueryControllerAuthorizationAttribute.cs @@ -0,0 +1,21 @@ +using System; +using Microsoft.AspNetCore.Mvc; + +namespace PoweredSoft.CQRS.AspNetCore.Mvc +{ + [AttributeUsage(AttributeTargets.Method)] + public class QueryControllerAuthorizationAttribute : TypeFilterAttribute + { + public QueryControllerAuthorizationAttribute() : base(typeof(QueryControllerAsyncAuthorizationFilter)) + { + + } + + public QueryControllerAuthorizationAttribute(Type queryType) : base(typeof(QueryControllerAsyncAuthorizationFilter)) + { + QueryType = queryType; + } + + public Type QueryType { get; } = null; + } +} diff --git a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs index e4ac69d..49b8ebc 100644 --- a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs +++ b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/Mvc/DynamicQueryController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using PoweredSoft.CQRS.AspNetCore.Mvc; using PoweredSoft.CQRS.DynamicQuery.Abstractions; using PoweredSoft.DynamicQuery.Core; using System; @@ -13,7 +14,7 @@ namespace PoweredSoft.CQRS.DynamicQuery.AspNetCore.Mvc where TSource : class where TDestination : class { - [HttpPost] + [HttpPost, QueryControllerAuthorization] public async Task> HandleAsync( [FromBody] DynamicQuery query, [FromServices]PoweredSoft.CQRS.Abstractions.IQueryHandler, IQueryExecutionResult> queryHandler @@ -30,7 +31,7 @@ namespace PoweredSoft.CQRS.DynamicQuery.AspNetCore.Mvc where TDestination : class where TParams : class { - [HttpPost] + [HttpPost, QueryControllerAuthorization] public async Task> HandleAsync( [FromBody] DynamicQuery query, [FromServices] PoweredSoft.CQRS.Abstractions.IQueryHandler, IQueryExecutionResult> queryHandler diff --git a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/PoweredSoft.CQRS.DynamicQuery.AspNetCore.csproj b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/PoweredSoft.CQRS.DynamicQuery.AspNetCore.csproj index 1dffb01..d3bb98b 100644 --- a/PoweredSoft.CQRS.DynamicQuery.AspNetCore/PoweredSoft.CQRS.DynamicQuery.AspNetCore.csproj +++ b/PoweredSoft.CQRS.DynamicQuery.AspNetCore/PoweredSoft.CQRS.DynamicQuery.AspNetCore.csproj @@ -11,6 +11,7 @@ +