From d1ca72300d379e8cd2a8c203d5d29aa6e7129273 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Tue, 10 Feb 2026 23:01:49 +0330 Subject: [PATCH] refactor: Remove ICurrentUserService dependency from query handlers and update user ID handling logic --- .gitea/workflows/kub-deploy.yml | 2 +- .../GetUserCommissionPayoutsQueryHandler.cs | 17 +++--------- .../GetUserWeeklyBalancesQueryHandler.cs | 17 +++--------- .../GetNetworkStatisticsQuery.cs | 2 +- .../GetNetworkStatisticsQueryHandler.cs | 27 ++++++++++--------- .../GetNetworkTreeQueryHandler.cs | 13 +++------ .../Queries/GetUser/GetUserQueryHandler.cs | 12 ++++----- .../GetCustomerOrderQueryHandler.cs | 17 ++++-------- .../GetCustomerOrdersQueryHandler.cs | 17 ++++-------- .../GetUserWalletQueryHandler.cs | 12 ++++----- .../Services/NetworkMembershipService.cs | 13 ++++++--- .../Services/UserOrderService.cs | 16 ++++++++--- .../Services/UserWalletService.cs | 7 +++-- 13 files changed, 77 insertions(+), 95 deletions(-) diff --git a/.gitea/workflows/kub-deploy.yml b/.gitea/workflows/kub-deploy.yml index 607ae34..28e45ca 100644 --- a/.gitea/workflows/kub-deploy.yml +++ b/.gitea/workflows/kub-deploy.yml @@ -26,7 +26,7 @@ jobs: } DAEMON echo "🚀 Starting Docker daemon..." - dockerd & + dockerd --iptables=false --ip6tables=false --bridge=none & # Wait up to 3 minutes for Docker to be ready for i in $(seq 1 90); do diff --git a/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserCommissionPayouts/GetUserCommissionPayoutsQueryHandler.cs b/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserCommissionPayouts/GetUserCommissionPayoutsQueryHandler.cs index 111e1af..8674908 100644 --- a/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserCommissionPayouts/GetUserCommissionPayoutsQueryHandler.cs +++ b/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserCommissionPayouts/GetUserCommissionPayoutsQueryHandler.cs @@ -4,16 +4,13 @@ public class GetUserCommissionPayoutsQueryHandler : IRequestHandler Handle(GetUserCommissionPayoutsQuery request, CancellationToken cancellationToken) @@ -24,17 +21,11 @@ public class GetUserCommissionPayoutsQueryHandler : IRequestHandler 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; - if (!userId.HasValue || userId.Value == 0) - { - if (long.TryParse(_currentUser.UserId, out var currentUserId)) - { - userId = currentUserId; - } - } - // فیلترها if (userId.HasValue && userId.Value > 0) { query = query.Where(x => x.UserId == userId.Value); diff --git a/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserWeeklyBalances/GetUserWeeklyBalancesQueryHandler.cs b/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserWeeklyBalances/GetUserWeeklyBalancesQueryHandler.cs index 2aac4cb..2ffe742 100644 --- a/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserWeeklyBalances/GetUserWeeklyBalancesQueryHandler.cs +++ b/src/CMSMicroservice.Application/CommissionCQ/Queries/GetUserWeeklyBalances/GetUserWeeklyBalancesQueryHandler.cs @@ -4,16 +4,13 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler Handle(GetUserWeeklyBalancesQuery request, CancellationToken cancellationToken) @@ -24,17 +21,11 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler 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; - if (!userId.HasValue || userId.Value == 0) - { - if (long.TryParse(_currentUser.UserId, out var currentUserId)) - { - userId = currentUserId; - } - } - // فیلترها if (userId.HasValue && userId.Value > 0) { query = query.Where(x => x.UserId == userId.Value); diff --git a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQuery.cs b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQuery.cs index 37bda3a..da5b186 100644 --- a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQuery.cs +++ b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQuery.cs @@ -3,7 +3,7 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStat public class GetNetworkStatisticsQuery : IRequest { /// - /// شناسه کاربر برای محاسبه آمار شبکه او - 0 یا null یعنی کاربر جاری + /// شناسه کاربر برای محاسبه آمار شبکه او - 0 یعنی آمار کل شبکه (root user) /// public long UserId { get; set; } } diff --git a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQueryHandler.cs b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQueryHandler.cs index 1df8b22..903a370 100644 --- a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQueryHandler.cs +++ b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkStatistics/GetNetworkStatisticsQueryHandler.cs @@ -5,30 +5,33 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStat public class GetNetworkStatisticsQueryHandler : IRequestHandler { private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUser; public GetNetworkStatisticsQueryHandler( - IApplicationDbContext context, - ICurrentUserService currentUser) + IApplicationDbContext context) { _context = context; - _currentUser = currentUser; } public async Task Handle(GetNetworkStatisticsQuery request, CancellationToken cancellationToken) { - // Get userId - use current user if not specified or is 0 - var userId = request.UserId == 0 - ? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) - : request.UserId; + // UserId > 0 → stats for that user's network + // UserId == 0 → global stats (find root user of the network) + var userId = request.UserId; + + // Get all users (needed for descendant calculation anyway) + var allUsers = await _context.Users.ToListAsync(cancellationToken); 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); // Statistics for the user's network (all descendants) diff --git a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs index 9813eab..98236a8 100644 --- a/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs +++ b/src/CMSMicroservice.Application/NetworkMembershipCQ/Queries/GetNetworkTree/GetNetworkTreeQueryHandler.cs @@ -8,28 +8,23 @@ public class GetNetworkTreeQueryHandler : IRequestHandler _logger; - private readonly ICurrentUserService _currentUser; public GetNetworkTreeQueryHandler( IApplicationDbContext context, - ILogger logger, - ICurrentUserService currentUser) + ILogger logger) { _context = context; _logger = logger; - _currentUser = currentUser; } public async Task Handle(GetNetworkTreeQuery request, CancellationToken cancellationToken) { - // Get userId - use current user if UserId is 0 - var userId = request.UserId == 0 - ? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) - : request.UserId; + // UserId must be provided - customer endpoints resolve from JWT before calling + var userId = request.UserId; 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 diff --git a/src/CMSMicroservice.Application/UserCQ/Queries/GetUser/GetUserQueryHandler.cs b/src/CMSMicroservice.Application/UserCQ/Queries/GetUser/GetUserQueryHandler.cs index aeab2b9..016517e 100644 --- a/src/CMSMicroservice.Application/UserCQ/Queries/GetUser/GetUserQueryHandler.cs +++ b/src/CMSMicroservice.Application/UserCQ/Queries/GetUser/GetUserQueryHandler.cs @@ -2,21 +2,19 @@ namespace CMSMicroservice.Application.UserCQ.Queries.GetUser; public class GetUserQueryHandler : IRequestHandler { private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUser; - public GetUserQueryHandler(IApplicationDbContext context, ICurrentUserService currentUser) + public GetUserQueryHandler(IApplicationDbContext context) { _context = context; - _currentUser = currentUser; } public async Task Handle(GetUserQuery request, CancellationToken cancellationToken) { - // If Id is 0 or not provided, get the current authenticated user's ID - var userId = request.Id == 0 - ? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) - : request.Id; + // UserId must be provided - customer endpoints resolve from JWT before calling + var userId = request.Id; + if (userId == 0) + throw new ArgumentException("UserId is required"); var response = await _context.Users .AsNoTracking() diff --git a/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrder/GetCustomerOrderQueryHandler.cs b/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrder/GetCustomerOrderQueryHandler.cs index 7817996..0368f24 100644 --- a/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrder/GetCustomerOrderQueryHandler.cs +++ b/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrder/GetCustomerOrderQueryHandler.cs @@ -7,29 +7,22 @@ namespace CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrder; public class GetCustomerOrderQueryHandler : IRequestHandler { private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUser; public GetCustomerOrderQueryHandler( - IApplicationDbContext context, - ICurrentUserService currentUser) + IApplicationDbContext context) { _context = context; - _currentUser = currentUser; } public async Task Handle(GetCustomerOrderQuery request, CancellationToken cancellationToken) { - // Resolve UserId from JWT if not specified - var userId = request.UserId == 0 - ? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) - : request.UserId; - - if (userId == 0) - throw new UnauthorizedAccessException("User ID not found"); + // UserId > 0 → filter by that user (customer security) + // UserId == 0 → no user filter (admin can view any order by ID) + var userId = request.UserId; var order = await _context.UserOrders .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.Transaction) .Include(x => x.UserAddress) diff --git a/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrders/GetCustomerOrdersQueryHandler.cs b/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrders/GetCustomerOrdersQueryHandler.cs index 879d379..0dba3de 100644 --- a/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrders/GetCustomerOrdersQueryHandler.cs +++ b/src/CMSMicroservice.Application/UserOrderCQ/Queries/GetCustomerOrders/GetCustomerOrdersQueryHandler.cs @@ -8,29 +8,22 @@ namespace CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrders; public class GetCustomerOrdersQueryHandler : IRequestHandler { private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUser; public GetCustomerOrdersQueryHandler( - IApplicationDbContext context, - ICurrentUserService currentUser) + IApplicationDbContext context) { _context = context; - _currentUser = currentUser; } public async Task Handle(GetCustomerOrdersQuery request, CancellationToken cancellationToken) { - // Resolve UserId from JWT if not specified - var userId = request.UserId == 0 - ? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) - : request.UserId; - - if (userId == 0) - throw new UnauthorizedAccessException("User ID not found"); + // UserId > 0 → filter by that user + // UserId == 0 → show ALL users (admin mode) + var userId = request.UserId; var query = _context.UserOrders .AsNoTracking() - .Where(x => x.UserId == userId) + .Where(x => userId == 0 || x.UserId == userId) .Include(x => x.Package) .Include(x => x.Transaction) .Include(x => x.UserAddress) diff --git a/src/CMSMicroservice.Application/UserWalletCQ/Queries/GetUserWallet/GetUserWalletQueryHandler.cs b/src/CMSMicroservice.Application/UserWalletCQ/Queries/GetUserWallet/GetUserWalletQueryHandler.cs index 497d607..fd1b17c 100644 --- a/src/CMSMicroservice.Application/UserWalletCQ/Queries/GetUserWallet/GetUserWalletQueryHandler.cs +++ b/src/CMSMicroservice.Application/UserWalletCQ/Queries/GetUserWallet/GetUserWalletQueryHandler.cs @@ -2,21 +2,19 @@ namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet; public class GetUserWalletQueryHandler : IRequestHandler { private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUser; - public GetUserWalletQueryHandler(IApplicationDbContext context, ICurrentUserService currentUser) + public GetUserWalletQueryHandler(IApplicationDbContext context) { _context = context; - _currentUser = currentUser; } public async Task Handle(GetUserWalletQuery request, CancellationToken cancellationToken) { - // If Id is 0 or not provided, get the current authenticated user's ID - var userId = request.Id == 0 - ? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0) - : request.Id; + // UserId must be provided - customer endpoints resolve from JWT before calling + var userId = request.Id; + if (userId == 0) + throw new ArgumentException("UserId is required"); var response = await _context.UserWallets .AsNoTracking() diff --git a/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs b/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs index 7cb0625..5f0d4e0 100644 --- a/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs +++ b/src/CMSMicroservice.WebApi/Services/NetworkMembershipService.cs @@ -8,6 +8,7 @@ using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkTree; using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkMembershipHistory; using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStatistics; using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetMyNetworkTree; +using CMSMicroservice.Application.Common.Interfaces; using Mapster; using CMSMicroservice.Domain.Enums; @@ -17,13 +18,16 @@ public class NetworkMembershipService : NetworkMembershipContract.NetworkMembers { private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS; private readonly ISender _sender; + private readonly ICurrentUserService _currentUserService; public NetworkMembershipService( IDispatchRequestToCQRS dispatchRequestToCQRS, - ISender sender) + ISender sender, + ICurrentUserService currentUserService) { _dispatchRequestToCQRS = dispatchRequestToCQRS; _sender = sender; + _currentUserService = currentUserService; } public override async Task JoinNetwork(JoinNetworkRequest request, ServerCallContext context) @@ -128,8 +132,11 @@ public class NetworkMembershipService : NetworkMembershipContract.NetworkMembers public override async Task GetMyNetworkStatistics(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context) { - // Get statistics for current user's network - var query = new GetNetworkStatisticsQuery { UserId = 0 }; // Will use ICurrentUserService + // Customer endpoint: resolve userId from JWT + 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); return stats.Adapt(); diff --git a/src/CMSMicroservice.WebApi/Services/UserOrderService.cs b/src/CMSMicroservice.WebApi/Services/UserOrderService.cs index a9fac9a..46c2148 100644 --- a/src/CMSMicroservice.WebApi/Services/UserOrderService.cs +++ b/src/CMSMicroservice.WebApi/Services/UserOrderService.cs @@ -101,7 +101,7 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase var query = new GetCustomerOrderQuery { 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); @@ -582,9 +582,14 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase public override async Task 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 { - UserId = request.Filter?.UserId ?? 0, + UserId = customerUserId, PaginationState = request.PaginationState?.Adapt(), PaymentStatusFilter = request.Filter?.PaymentStatus != null ? (int?)request.Filter.PaymentStatus @@ -652,10 +657,15 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase public override async Task 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 { OrderId = request.Id, - UserId = 0 // از JWT دریافت می‌شود + UserId = customerUserId }; var result = await _sender.Send(query, context.CancellationToken); diff --git a/src/CMSMicroservice.WebApi/Services/UserWalletService.cs b/src/CMSMicroservice.WebApi/Services/UserWalletService.cs index cafa59a..1f51dae 100644 --- a/src/CMSMicroservice.WebApi/Services/UserWalletService.cs +++ b/src/CMSMicroservice.WebApi/Services/UserWalletService.cs @@ -57,8 +57,11 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase public override async Task GetCustomerWallet(Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context) { - // Use GetUserWallet with Id=0 to automatically use current user from JWT - var walletQuery = new GetUserWalletQuery { Id = 0 }; + // Customer endpoint: resolve userId from JWT + 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); return new GetCustomerWalletResponse