feat: Implement user permission checks and manual payment functionalities

- Added CheckUserPermissionQuery and CheckUserPermissionQueryHandler for permission validation.
- Introduced GetUserRolesQuery and GetUserRolesQueryHandler to retrieve user roles.
- Created IPermissionService interface and its implementation in PermissionService.
- Defined permission and role constants in PermissionDefinitions.
- Developed SetDefaultVatPercentageCommand and its handler for VAT configuration.
- Implemented GetCurrentVatPercentageQuery and handler to fetch current VAT settings.
- Added manual payment commands: CreateManualPayment, ApproveManualPayment, and RejectManualPayment with respective handlers and validators.
- Created GetManualPaymentsQuery and handler for retrieving manual payment records.
- Integrated gRPC services for manual payments with appropriate permission checks.
- Established Protobuf definitions for manual payment operations and metadata.
This commit is contained in:
masoodafar-web
2025-12-05 17:27:38 +03:30
parent 67b43fea7a
commit 4aa9f28f6e
51 changed files with 1294 additions and 107 deletions

View File

@@ -0,0 +1,79 @@
using System;
using System.Threading.Tasks;
using BackOffice.BFF.Application.Common.Interfaces;
using Grpc.AspNetCore.Server;
using Grpc.Core;
using Grpc.Core.Interceptors;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace BackOffice.BFF.WebApi.Common.Authorization;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public sealed class RequiresPermissionAttribute : Attribute
{
public RequiresPermissionAttribute(string permission)
{
Permission = permission ?? throw new ArgumentNullException(nameof(permission));
}
public string Permission { get; }
}
public class PermissionInterceptor : Interceptor
{
private readonly IPermissionService _permissionService;
private readonly ILogger<PermissionInterceptor> _logger;
private readonly IHttpContextAccessor _httpContextAccessor;
public PermissionInterceptor(
IPermissionService permissionService,
ILogger<PermissionInterceptor> logger,
IHttpContextAccessor httpContextAccessor)
{
_permissionService = permissionService;
_logger = logger;
_httpContextAccessor = httpContextAccessor;
}
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request,
ServerCallContext context,
UnaryServerMethod<TRequest, TResponse> continuation)
{
await EnsureHasPermissionAsync(context);
return await continuation(request, context);
}
private async Task EnsureHasPermissionAsync(ServerCallContext context)
{
var httpContext = context.GetHttpContext() ?? _httpContextAccessor.HttpContext;
if (httpContext == null)
{
return;
}
var endpoint = httpContext.GetEndpoint();
if (endpoint == null)
{
return;
}
var permissionAttributes = endpoint.Metadata.GetOrderedMetadata<RequiresPermissionAttribute>();
if (permissionAttributes == null || permissionAttributes.Count == 0)
{
return;
}
foreach (var attribute in permissionAttributes)
{
var hasPermission = await _permissionService.HasPermissionAsync(attribute.Permission, httpContext.RequestAborted);
if (!hasPermission)
{
_logger.LogWarning("Permission denied for permission {Permission}", attribute.Permission);
throw new RpcException(new Status(StatusCode.PermissionDenied, "Permission denied"));
}
}
}
}