Merge branch 'main' into kub-stage
This commit is contained in:
@@ -7,6 +7,17 @@
|
||||
<DockerfileContext>..\..\..</DockerfileContext>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Exclude services that depend on excluded handlers -->
|
||||
<ItemGroup>
|
||||
<Compile Remove="Services/ConfigurationService.cs" />
|
||||
<Compile Remove="Services/ManualPaymentService.cs" />
|
||||
<Compile Remove="Services/PublicMessageService.cs" />
|
||||
<!-- Exclude mappings with proto type mismatches -->
|
||||
<Compile Remove="Common/Mappings/ProductsProfile.cs" />
|
||||
<Compile Remove="Common/Mappings/UserOrderProfile.cs" />
|
||||
<Compile Remove="Common/Mappings/PublicMessageProfile.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.54.0" />
|
||||
<PackageReference Include="Grpc.AspNetCore.Web" Version="2.54.0" />
|
||||
@@ -31,5 +42,6 @@
|
||||
<ProjectReference Include="..\Protobufs\BackOffice.BFF.Role.Protobuf\BackOffice.BFF.Role.Protobuf.csproj" />
|
||||
<ProjectReference Include="..\Protobufs\BackOffice.BFF.UserRole.Protobuf\BackOffice.BFF.UserRole.Protobuf.csproj" />
|
||||
<ProjectReference Include="..\Protobufs\BackOffice.BFF.Category.Protobuf\BackOffice.BFF.Category.Protobuf.csproj" />
|
||||
<ProjectReference Include="..\Protobufs\BackOffice.BFF.ManualPayment.Protobuf\BackOffice.BFF.ManualPayment.Protobuf.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,3 +9,5 @@ global using Microsoft.AspNetCore.Builder;
|
||||
global using System;
|
||||
global using Microsoft.AspNetCore.Routing;
|
||||
global using System.Linq;
|
||||
global using BackOffice.BFF.WebApi.Common.Authorization;
|
||||
global using BackOffice.BFF.Application.Common.Models;
|
||||
|
||||
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Serilog;
|
||||
using Serilog.Core;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using BackOffice.BFF.WebApi.Common.Authorization;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
@@ -37,6 +38,7 @@ builder.Services.AddGrpc(options =>
|
||||
options.EnableDetailedErrors = true;
|
||||
options.MaxReceiveMessageSize = 1000 * 1024 * 1024; // 1 GB
|
||||
options.MaxSendMessageSize = 1000 * 1024 * 1024; // 1 GB
|
||||
options.Interceptors.Add<PermissionInterceptor>();
|
||||
}).AddJsonTranscoding();
|
||||
builder.Services.AddInfrastructureServices(builder.Configuration);
|
||||
builder.Services.AddApplicationServices();
|
||||
|
||||
@@ -7,7 +7,7 @@ using BackOffice.BFF.Application.CommissionCQ.Queries.GetWithdrawalRequests;
|
||||
using BackOffice.BFF.Application.CommissionCQ.Queries.GetWithdrawalReports;
|
||||
using BackOffice.BFF.Application.CommissionCQ.Commands.ApproveWithdrawal;
|
||||
using BackOffice.BFF.Application.CommissionCQ.Commands.RejectWithdrawal;
|
||||
using BackOffice.BFF.Application.CommissionCQ.Commands.ProcessWithdrawal;
|
||||
// using BackOffice.BFF.Application.CommissionCQ.Commands.ProcessWithdrawal; // Excluded - needs proto fix
|
||||
using CMSMicroservice.Protobuf.Protos.Commission;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
@@ -91,10 +91,8 @@ public class CommissionService : CommissionContract.CommissionContractBase
|
||||
ProcessWithdrawalRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<ProcessWithdrawalRequest, ProcessWithdrawalCommand, ProcessWithdrawalResponseDto>(
|
||||
request,
|
||||
context);
|
||||
return new Empty();
|
||||
// TODO: Implement after ProcessWithdrawalCommand is fixed
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "ProcessWithdrawal is temporarily disabled"));
|
||||
}
|
||||
|
||||
public override async Task<GetWithdrawalReportsResponse> GetWithdrawalReports(
|
||||
|
||||
@@ -21,6 +21,7 @@ public class ConfigurationService : ConfigurationContract.ConfigurationContractB
|
||||
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.SettingsManageConfiguration)]
|
||||
public override async Task<Empty> CreateOrUpdateConfiguration(
|
||||
CreateOrUpdateConfigurationRequest request,
|
||||
ServerCallContext context)
|
||||
@@ -30,6 +31,7 @@ public class ConfigurationService : ConfigurationContract.ConfigurationContractB
|
||||
context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.SettingsManageConfiguration)]
|
||||
public override async Task<Empty> DeactivateConfiguration(
|
||||
DeactivateConfigurationRequest request,
|
||||
ServerCallContext context)
|
||||
@@ -39,6 +41,7 @@ public class ConfigurationService : ConfigurationContract.ConfigurationContractB
|
||||
context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.SettingsView)]
|
||||
public override async Task<GetAllConfigurationsResponse> GetAllConfigurations(
|
||||
GetAllConfigurationsRequest request,
|
||||
ServerCallContext context)
|
||||
|
||||
76
src/BackOffice.BFF.WebApi/Services/ManualPaymentService.cs
Normal file
76
src/BackOffice.BFF.WebApi/Services/ManualPaymentService.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using BackOffice.BFF.ManualPayment.Protobuf;
|
||||
using BackOffice.BFF.WebApi.Common.Services;
|
||||
using BackOffice.BFF.Application.ManualPaymentCQ.Commands.CreateManualPayment;
|
||||
using BackOffice.BFF.Application.ManualPaymentCQ.Commands.ApproveManualPayment;
|
||||
using BackOffice.BFF.Application.ManualPaymentCQ.Commands.RejectManualPayment;
|
||||
using BackOffice.BFF.Application.ManualPaymentCQ.Queries.GetManualPayments;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Mapster;
|
||||
using MediatR;
|
||||
|
||||
namespace BackOffice.BFF.WebApi.Services;
|
||||
|
||||
public class ManualPaymentService : ManualPaymentContract.ManualPaymentContractBase
|
||||
{
|
||||
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
|
||||
private readonly ISender _sender;
|
||||
|
||||
public ManualPaymentService(
|
||||
IDispatchRequestToCQRS dispatchRequestToCQRS,
|
||||
ISender sender)
|
||||
{
|
||||
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||||
_sender = sender;
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.ManualPaymentsCreate)]
|
||||
public override async Task<CreateManualPaymentResponse> CreateManualPayment(
|
||||
CreateManualPaymentRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<CreateManualPaymentRequest, CreateManualPaymentCommand, CreateManualPaymentResponse>(
|
||||
request,
|
||||
context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.ManualPaymentsApprove)]
|
||||
public override async Task<Google.Protobuf.WellKnownTypes.Empty> ApproveManualPayment(
|
||||
ApproveManualPaymentRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<ApproveManualPaymentRequest, ApproveManualPaymentCommand>(
|
||||
request,
|
||||
context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.ManualPaymentsApprove)]
|
||||
public override async Task<Google.Protobuf.WellKnownTypes.Empty> RejectManualPayment(
|
||||
RejectManualPaymentRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<RejectManualPaymentRequest, RejectManualPaymentCommand>(
|
||||
request,
|
||||
context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.ManualPaymentsView)]
|
||||
public override async Task<GetManualPaymentsResponse> GetManualPayments(
|
||||
GetManualPaymentsRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var query = new GetManualPaymentsQuery
|
||||
{
|
||||
PageNumber = request.PageNumber,
|
||||
PageSize = request.PageSize,
|
||||
UserId = request.UserId?.Value,
|
||||
Status = request.Status?.Value,
|
||||
Type = request.Type?.Value,
|
||||
ReferenceNumber = request.ReferenceNumber?.Value,
|
||||
// RequestedBy و OrderByDescending در این نسخه از UI ارسال نمیشود
|
||||
};
|
||||
|
||||
var result = await _sender.Send(query, context.CancellationToken);
|
||||
|
||||
return result.Adapt<GetManualPaymentsResponse>();
|
||||
}
|
||||
}
|
||||
@@ -19,47 +19,62 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
{
|
||||
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersCreate)]
|
||||
public override async Task<CreateNewUserOrderResponse> CreateNewUserOrder(CreateNewUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<CreateNewUserOrderRequest, CreateNewUserOrderCommand, CreateNewUserOrderResponse>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersUpdate)]
|
||||
public override async Task<Empty> UpdateUserOrder(UpdateUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<UpdateUserOrderRequest, UpdateUserOrderCommand>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersDelete)]
|
||||
public override async Task<Empty> DeleteUserOrder(DeleteUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<DeleteUserOrderRequest, DeleteUserOrderCommand>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersView)]
|
||||
public override async Task<GetUserOrderResponse> GetUserOrder(GetUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<GetUserOrderRequest, GetUserOrderQuery, GetUserOrderResponse>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersView)]
|
||||
public override async Task<GetAllUserOrderByFilterResponse> GetAllUserOrderByFilter(GetAllUserOrderByFilterRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<GetAllUserOrderByFilterRequest, GetAllUserOrderByFilterQuery, GetAllUserOrderByFilterResponse>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersUpdate)]
|
||||
public override async Task<UpdateOrderStatusResponse> UpdateOrderStatus(UpdateOrderStatusRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<UpdateOrderStatusRequest, UpdateOrderStatusCommand, UpdateOrderStatusResponse>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.ReportsView)]
|
||||
public override async Task<GetOrdersByDateRangeResponse> GetOrdersByDateRange(GetOrdersByDateRangeRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<GetOrdersByDateRangeRequest, GetOrdersByDateRangeQuery, GetOrdersByDateRangeResponse>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersUpdate)]
|
||||
public override async Task<ApplyDiscountToOrderResponse> ApplyDiscountToOrder(ApplyDiscountToOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<ApplyDiscountToOrderRequest, ApplyDiscountToOrderCommand, ApplyDiscountToOrderResponse>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersView)]
|
||||
public override async Task<CalculateOrderPVResponse> CalculateOrderPV(CalculateOrderPVRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<CalculateOrderPVRequest, CalculateOrderPVQuery, CalculateOrderPVResponse>(request, context);
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersCancel)]
|
||||
public override async Task<CancelOrderResponse> CancelOrder(CancelOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<CancelOrderRequest, CancelOrderCommand, CancelOrderResponse>(request, context);
|
||||
|
||||
Reference in New Issue
Block a user