refactor: Remove ICurrentUserService dependency from query handlers and update user ID handling logic
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 8s

This commit is contained in:
masoodafar-web
2026-02-10 23:01:49 +03:30
parent b42d9e141d
commit d1ca72300d
13 changed files with 77 additions and 95 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
} }
DAEMON DAEMON
echo "🚀 Starting Docker daemon..." echo "🚀 Starting Docker daemon..."
dockerd & dockerd --iptables=false --ip6tables=false --bridge=none &
# Wait up to 3 minutes for Docker to be ready # Wait up to 3 minutes for Docker to be ready
for i in $(seq 1 90); do for i in $(seq 1 90); do
@@ -4,16 +4,13 @@ public class GetUserCommissionPayoutsQueryHandler : IRequestHandler<GetUserCommi
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository; private readonly IWeekDefinitionRepository _weekDefinitionRepository;
private readonly ICurrentUserService _currentUser;
public GetUserCommissionPayoutsQueryHandler( public GetUserCommissionPayoutsQueryHandler(
IApplicationDbContext context, IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository, IWeekDefinitionRepository weekDefinitionRepository)
ICurrentUserService currentUser)
{ {
_context = context; _context = context;
_weekDefinitionRepository = weekDefinitionRepository; _weekDefinitionRepository = weekDefinitionRepository;
_currentUser = currentUser;
} }
public async Task<GetUserCommissionPayoutsResponseDto> Handle(GetUserCommissionPayoutsQuery request, CancellationToken cancellationToken) public async Task<GetUserCommissionPayoutsResponseDto> Handle(GetUserCommissionPayoutsQuery request, CancellationToken cancellationToken)
@@ -24,17 +21,11 @@ public class GetUserCommissionPayoutsQueryHandler : IRequestHandler<GetUserCommi
.AsNoTracking() .AsNoTracking()
.AsQueryable(); .AsQueryable();
// اگر UserId داده نشده، از CurrentUser بگیر (برای Customer API) // UserId > 0 → filter by that user
// UserId == 0 or null → show ALL users (admin mode)
// Customer endpoints resolve UserId from JWT before calling this handler
long? userId = request.UserId; long? userId = request.UserId;
if (!userId.HasValue || userId.Value == 0)
{
if (long.TryParse(_currentUser.UserId, out var currentUserId))
{
userId = currentUserId;
}
}
// فیلترها
if (userId.HasValue && userId.Value > 0) if (userId.HasValue && userId.Value > 0)
{ {
query = query.Where(x => x.UserId == userId.Value); query = query.Where(x => x.UserId == userId.Value);
@@ -4,16 +4,13 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler<GetUserWeeklyBa
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository; private readonly IWeekDefinitionRepository _weekDefinitionRepository;
private readonly ICurrentUserService _currentUser;
public GetUserWeeklyBalancesQueryHandler( public GetUserWeeklyBalancesQueryHandler(
IApplicationDbContext context, IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository, IWeekDefinitionRepository weekDefinitionRepository)
ICurrentUserService currentUser)
{ {
_context = context; _context = context;
_weekDefinitionRepository = weekDefinitionRepository; _weekDefinitionRepository = weekDefinitionRepository;
_currentUser = currentUser;
} }
public async Task<GetUserWeeklyBalancesResponseDto> Handle(GetUserWeeklyBalancesQuery request, CancellationToken cancellationToken) public async Task<GetUserWeeklyBalancesResponseDto> Handle(GetUserWeeklyBalancesQuery request, CancellationToken cancellationToken)
@@ -24,17 +21,11 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler<GetUserWeeklyBa
.AsNoTracking() .AsNoTracking()
.AsQueryable(); .AsQueryable();
// اگر UserId داده نشده، از CurrentUser بگیر (برای Customer API) // UserId > 0 → filter by that user
// UserId == 0 or null → show ALL users (admin mode)
// Customer endpoints resolve UserId from JWT before calling this handler
long? userId = request.UserId; long? userId = request.UserId;
if (!userId.HasValue || userId.Value == 0)
{
if (long.TryParse(_currentUser.UserId, out var currentUserId))
{
userId = currentUserId;
}
}
// فیلترها
if (userId.HasValue && userId.Value > 0) if (userId.HasValue && userId.Value > 0)
{ {
query = query.Where(x => x.UserId == userId.Value); query = query.Where(x => x.UserId == userId.Value);
@@ -3,7 +3,7 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStat
public class GetNetworkStatisticsQuery : IRequest<GetNetworkStatisticsResponseDto> public class GetNetworkStatisticsQuery : IRequest<GetNetworkStatisticsResponseDto>
{ {
/// <summary> /// <summary>
/// شناسه کاربر برای محاسبه آمار شبکه او - 0 یا null یعنی کاربر جاری /// شناسه کاربر برای محاسبه آمار شبکه او - 0 یعنی آمار کل شبکه (root user)
/// </summary> /// </summary>
public long UserId { get; set; } public long UserId { get; set; }
} }
@@ -5,30 +5,33 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStat
public class GetNetworkStatisticsQueryHandler : IRequestHandler<GetNetworkStatisticsQuery, GetNetworkStatisticsResponseDto> public class GetNetworkStatisticsQueryHandler : IRequestHandler<GetNetworkStatisticsQuery, GetNetworkStatisticsResponseDto>
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public GetNetworkStatisticsQueryHandler( public GetNetworkStatisticsQueryHandler(
IApplicationDbContext context, IApplicationDbContext context)
ICurrentUserService currentUser)
{ {
_context = context; _context = context;
_currentUser = currentUser;
} }
public async Task<GetNetworkStatisticsResponseDto> Handle(GetNetworkStatisticsQuery request, CancellationToken cancellationToken) public async Task<GetNetworkStatisticsResponseDto> Handle(GetNetworkStatisticsQuery request, CancellationToken cancellationToken)
{ {
// Get userId - use current user if not specified or is 0 // UserId > 0 → stats for that user's network
var userId = request.UserId == 0 // UserId == 0 → global stats (find root user of the network)
? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) var userId = request.UserId;
: request.UserId;
// Get all users (needed for descendant calculation anyway)
var allUsers = await _context.Users.ToListAsync(cancellationToken);
if (userId == 0) if (userId == 0)
{ {
throw new UnauthorizedAccessException("User ID not found"); // Find root user (user with no NetworkParentId)
var rootUser = allUsers.FirstOrDefault(x => x.NetworkParentId == null || x.NetworkParentId == 0);
if (rootUser != null)
userId = rootUser.Id;
else if (allUsers.Count > 0)
userId = allUsers.First().Id;
else
throw new InvalidOperationException("No users found in the system");
} }
// Get all descendants recursively
var allUsers = await _context.Users.ToListAsync(cancellationToken);
var allDescendants = GetAllDescendants(userId, allUsers); var allDescendants = GetAllDescendants(userId, allUsers);
// Statistics for the user's network (all descendants) // Statistics for the user's network (all descendants)
@@ -8,28 +8,23 @@ public class GetNetworkTreeQueryHandler : IRequestHandler<GetNetworkTreeQuery, N
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly ILogger<GetNetworkTreeQueryHandler> _logger; private readonly ILogger<GetNetworkTreeQueryHandler> _logger;
private readonly ICurrentUserService _currentUser;
public GetNetworkTreeQueryHandler( public GetNetworkTreeQueryHandler(
IApplicationDbContext context, IApplicationDbContext context,
ILogger<GetNetworkTreeQueryHandler> logger, ILogger<GetNetworkTreeQueryHandler> logger)
ICurrentUserService currentUser)
{ {
_context = context; _context = context;
_logger = logger; _logger = logger;
_currentUser = currentUser;
} }
public async Task<NetworkTreeDto?> Handle(GetNetworkTreeQuery request, CancellationToken cancellationToken) public async Task<NetworkTreeDto?> Handle(GetNetworkTreeQuery request, CancellationToken cancellationToken)
{ {
// Get userId - use current user if UserId is 0 // UserId must be provided - customer endpoints resolve from JWT before calling
var userId = request.UserId == 0 var userId = request.UserId;
? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0)
: request.UserId;
if (userId == 0) if (userId == 0)
{ {
throw new UnauthorizedAccessException("User ID not found"); throw new ArgumentException("UserId is required for network tree query");
} }
// Create a new request with the resolved userId // Create a new request with the resolved userId
@@ -2,21 +2,19 @@ namespace CMSMicroservice.Application.UserCQ.Queries.GetUser;
public class GetUserQueryHandler : IRequestHandler<GetUserQuery, GetUserResponseDto> public class GetUserQueryHandler : IRequestHandler<GetUserQuery, GetUserResponseDto>
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public GetUserQueryHandler(IApplicationDbContext context, ICurrentUserService currentUser) public GetUserQueryHandler(IApplicationDbContext context)
{ {
_context = context; _context = context;
_currentUser = currentUser;
} }
public async Task<GetUserResponseDto> Handle(GetUserQuery request, public async Task<GetUserResponseDto> Handle(GetUserQuery request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// If Id is 0 or not provided, get the current authenticated user's ID // UserId must be provided - customer endpoints resolve from JWT before calling
var userId = request.Id == 0 var userId = request.Id;
? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) if (userId == 0)
: request.Id; throw new ArgumentException("UserId is required");
var response = await _context.Users var response = await _context.Users
.AsNoTracking() .AsNoTracking()
@@ -7,29 +7,22 @@ namespace CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrder;
public class GetCustomerOrderQueryHandler : IRequestHandler<GetCustomerOrderQuery, GetCustomerOrderResponseDto> public class GetCustomerOrderQueryHandler : IRequestHandler<GetCustomerOrderQuery, GetCustomerOrderResponseDto>
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public GetCustomerOrderQueryHandler( public GetCustomerOrderQueryHandler(
IApplicationDbContext context, IApplicationDbContext context)
ICurrentUserService currentUser)
{ {
_context = context; _context = context;
_currentUser = currentUser;
} }
public async Task<GetCustomerOrderResponseDto> Handle(GetCustomerOrderQuery request, CancellationToken cancellationToken) public async Task<GetCustomerOrderResponseDto> Handle(GetCustomerOrderQuery request, CancellationToken cancellationToken)
{ {
// Resolve UserId from JWT if not specified // UserId > 0 → filter by that user (customer security)
var userId = request.UserId == 0 // UserId == 0 → no user filter (admin can view any order by ID)
? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) var userId = request.UserId;
: request.UserId;
if (userId == 0)
throw new UnauthorizedAccessException("User ID not found");
var order = await _context.UserOrders var order = await _context.UserOrders
.AsNoTracking() .AsNoTracking()
.Where(x => x.Id == request.OrderId && x.UserId == userId) .Where(x => x.Id == request.OrderId && (userId == 0 || x.UserId == userId))
.Include(x => x.Package) .Include(x => x.Package)
.Include(x => x.Transaction) .Include(x => x.Transaction)
.Include(x => x.UserAddress) .Include(x => x.UserAddress)
@@ -8,29 +8,22 @@ namespace CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrders;
public class GetCustomerOrdersQueryHandler : IRequestHandler<GetCustomerOrdersQuery, GetCustomerOrdersResponseDto> public class GetCustomerOrdersQueryHandler : IRequestHandler<GetCustomerOrdersQuery, GetCustomerOrdersResponseDto>
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public GetCustomerOrdersQueryHandler( public GetCustomerOrdersQueryHandler(
IApplicationDbContext context, IApplicationDbContext context)
ICurrentUserService currentUser)
{ {
_context = context; _context = context;
_currentUser = currentUser;
} }
public async Task<GetCustomerOrdersResponseDto> Handle(GetCustomerOrdersQuery request, CancellationToken cancellationToken) public async Task<GetCustomerOrdersResponseDto> Handle(GetCustomerOrdersQuery request, CancellationToken cancellationToken)
{ {
// Resolve UserId from JWT if not specified // UserId > 0 → filter by that user
var userId = request.UserId == 0 // UserId == 0 → show ALL users (admin mode)
? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) var userId = request.UserId;
: request.UserId;
if (userId == 0)
throw new UnauthorizedAccessException("User ID not found");
var query = _context.UserOrders var query = _context.UserOrders
.AsNoTracking() .AsNoTracking()
.Where(x => x.UserId == userId) .Where(x => userId == 0 || x.UserId == userId)
.Include(x => x.Package) .Include(x => x.Package)
.Include(x => x.Transaction) .Include(x => x.Transaction)
.Include(x => x.UserAddress) .Include(x => x.UserAddress)
@@ -2,21 +2,19 @@ namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
public class GetUserWalletQueryHandler : IRequestHandler<GetUserWalletQuery, GetUserWalletResponseDto> public class GetUserWalletQueryHandler : IRequestHandler<GetUserWalletQuery, GetUserWalletResponseDto>
{ {
private readonly IApplicationDbContext _context; private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public GetUserWalletQueryHandler(IApplicationDbContext context, ICurrentUserService currentUser) public GetUserWalletQueryHandler(IApplicationDbContext context)
{ {
_context = context; _context = context;
_currentUser = currentUser;
} }
public async Task<GetUserWalletResponseDto> Handle(GetUserWalletQuery request, public async Task<GetUserWalletResponseDto> Handle(GetUserWalletQuery request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// If Id is 0 or not provided, get the current authenticated user's ID // UserId must be provided - customer endpoints resolve from JWT before calling
var userId = request.Id == 0 var userId = request.Id;
? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) if (userId == 0)
: request.Id; throw new ArgumentException("UserId is required");
var response = await _context.UserWallets var response = await _context.UserWallets
.AsNoTracking() .AsNoTracking()
@@ -8,6 +8,7 @@ using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkTree;
using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkMembershipHistory; using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkMembershipHistory;
using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStatistics; using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStatistics;
using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetMyNetworkTree; using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetMyNetworkTree;
using CMSMicroservice.Application.Common.Interfaces;
using Mapster; using Mapster;
using CMSMicroservice.Domain.Enums; using CMSMicroservice.Domain.Enums;
@@ -17,13 +18,16 @@ public class NetworkMembershipService : NetworkMembershipContract.NetworkMembers
{ {
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS; private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
private readonly ISender _sender; private readonly ISender _sender;
private readonly ICurrentUserService _currentUserService;
public NetworkMembershipService( public NetworkMembershipService(
IDispatchRequestToCQRS dispatchRequestToCQRS, IDispatchRequestToCQRS dispatchRequestToCQRS,
ISender sender) ISender sender,
ICurrentUserService currentUserService)
{ {
_dispatchRequestToCQRS = dispatchRequestToCQRS; _dispatchRequestToCQRS = dispatchRequestToCQRS;
_sender = sender; _sender = sender;
_currentUserService = currentUserService;
} }
public override async Task<Empty> JoinNetwork(JoinNetworkRequest request, ServerCallContext context) public override async Task<Empty> JoinNetwork(JoinNetworkRequest request, ServerCallContext context)
@@ -128,8 +132,11 @@ public class NetworkMembershipService : NetworkMembershipContract.NetworkMembers
public override async Task<GetMyNetworkStatisticsResponse> GetMyNetworkStatistics(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context) public override async Task<GetMyNetworkStatisticsResponse> GetMyNetworkStatistics(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
{ {
// Get statistics for current user's network // Customer endpoint: resolve userId from JWT
var query = new GetNetworkStatisticsQuery { UserId = 0 }; // Will use ICurrentUserService if (!long.TryParse(_currentUserService.UserId, out var userId) || userId <= 0)
throw new RpcException(new Status(StatusCode.Unauthenticated, "کاربر احراز هویت نشده است"));
var query = new GetNetworkStatisticsQuery { UserId = userId };
var stats = await _sender.Send(query, context.CancellationToken); var stats = await _sender.Send(query, context.CancellationToken);
return stats.Adapt<GetMyNetworkStatisticsResponse>(); return stats.Adapt<GetMyNetworkStatisticsResponse>();
@@ -101,7 +101,7 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
var query = new GetCustomerOrderQuery var query = new GetCustomerOrderQuery
{ {
OrderId = request.Id, OrderId = request.Id,
UserId = 0 // از JWT دریافت می‌شود UserId = 0 // Admin: no user filter, can view any order by ID
}; };
var result = await _sender.Send(query, context.CancellationToken); var result = await _sender.Send(query, context.CancellationToken);
@@ -582,9 +582,14 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
public override async Task<GetAllUserOrderByFilterResponse> GetCustomerOrders(GetAllUserOrderByFilterRequest request, ServerCallContext context) public override async Task<GetAllUserOrderByFilterResponse> GetCustomerOrders(GetAllUserOrderByFilterRequest request, ServerCallContext context)
{ {
// Customer endpoint: ALWAYS resolve userId from JWT (customer can only see own orders)
var customerUserId = long.TryParse(_currentUserService.UserId, out var uid) ? uid : 0;
if (customerUserId == 0)
throw new RpcException(new Status(StatusCode.Unauthenticated, "کاربر احراز هویت نشده است"));
var query = new GetCustomerOrdersQuery var query = new GetCustomerOrdersQuery
{ {
UserId = request.Filter?.UserId ?? 0, UserId = customerUserId,
PaginationState = request.PaginationState?.Adapt<AppModels.PaginationState>(), PaginationState = request.PaginationState?.Adapt<AppModels.PaginationState>(),
PaymentStatusFilter = request.Filter?.PaymentStatus != null PaymentStatusFilter = request.Filter?.PaymentStatus != null
? (int?)request.Filter.PaymentStatus ? (int?)request.Filter.PaymentStatus
@@ -652,10 +657,15 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
public override async Task<GetUserOrderResponse> GetCustomerOrder(GetUserOrderRequest request, ServerCallContext context) public override async Task<GetUserOrderResponse> GetCustomerOrder(GetUserOrderRequest request, ServerCallContext context)
{ {
// Customer endpoint: ALWAYS resolve userId from JWT (customer can only see own orders)
var customerUserId = long.TryParse(_currentUserService.UserId, out var uid) ? uid : 0;
if (customerUserId == 0)
throw new RpcException(new Status(StatusCode.Unauthenticated, "کاربر احراز هویت نشده است"));
var query = new GetCustomerOrderQuery var query = new GetCustomerOrderQuery
{ {
OrderId = request.Id, OrderId = request.Id,
UserId = 0 // از JWT دریافت می‌شود UserId = customerUserId
}; };
var result = await _sender.Send(query, context.CancellationToken); var result = await _sender.Send(query, context.CancellationToken);
@@ -57,8 +57,11 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
public override async Task<GetCustomerWalletResponse> GetCustomerWallet(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context) public override async Task<GetCustomerWalletResponse> GetCustomerWallet(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
{ {
// Use GetUserWallet with Id=0 to automatically use current user from JWT // Customer endpoint: resolve userId from JWT
var walletQuery = new GetUserWalletQuery { Id = 0 }; if (!long.TryParse(_currentUserService.UserId, out var userId) || userId <= 0)
throw new RpcException(new Status(StatusCode.Unauthenticated, "کاربر احراز هویت نشده است"));
var walletQuery = new GetUserWalletQuery { Id = userId };
var wallet = await _sender.Send(walletQuery, context.CancellationToken); var wallet = await _sender.Send(walletQuery, context.CancellationToken);
return new GetCustomerWalletResponse return new GetCustomerWalletResponse