From d8329f1fab188527032280b08ba0cee2c144097d Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Tue, 30 Sep 2025 17:10:30 +0530 Subject: [PATCH] Removed the tenant check from master services --- .../Controllers/AuthController.cs | 96 +++++++++++++- .../Controllers/EmployeeController.cs | 6 +- Marco.Pms.Services/Helpers/RolesHelper.cs | 4 +- Marco.Pms.Services/Helpers/UserHelper.cs | 2 +- Marco.Pms.Services/Service/MasterService.cs | 119 ------------------ 5 files changed, 103 insertions(+), 124 deletions(-) diff --git a/Marco.Pms.Services/Controllers/AuthController.cs b/Marco.Pms.Services/Controllers/AuthController.cs index abc09fb..d65bd35 100644 --- a/Marco.Pms.Services/Controllers/AuthController.cs +++ b/Marco.Pms.Services/Controllers/AuthController.cs @@ -368,6 +368,100 @@ namespace MarcoBMS.Services.Controllers } } + [HttpPost("login-otp/v1")] + public async Task LoginWithOTP([FromBody] VerifyOTPDto verifyOTP) + { + await using var _context = await _dbContextFactory.CreateDbContextAsync(); + using var scope = _serviceScopeFactory.CreateScope(); + var _refreshTokenService = scope.ServiceProvider.GetRequiredService(); + + try + { + // Validate input + if (string.IsNullOrWhiteSpace(verifyOTP.Email) || + string.IsNullOrWhiteSpace(verifyOTP.OTP) || + verifyOTP.OTP.Length != 4 || + !verifyOTP.OTP.All(char.IsDigit)) + { + _logger.LogWarning("OTP login failed - invalid input provided"); + return BadRequest(ApiResponse.ErrorResponse("Invalid input", "Please provide a valid 4-digit OTP and Email", 400)); + } + + // Fetch employee by email + var requestEmployee = await _context.Employees + .Include(e => e.ApplicationUser) + .FirstOrDefaultAsync(e => e.Email == verifyOTP.Email && e.IsActive); + + if (requestEmployee == null || string.IsNullOrWhiteSpace(requestEmployee.ApplicationUserId)) + { + _logger.LogWarning("OTP login failed - user not found for email {Email}", verifyOTP.Email); + return NotFound(ApiResponse.ErrorResponse("User not found", "User not found", 404)); + } + + Guid userId = Guid.Parse(requestEmployee.ApplicationUserId); + + // Fetch most recent OTP + var otpDetails = await _context.OTPDetails + .Where(o => o.UserId == userId) + .OrderByDescending(o => o.TimeStamp) + .FirstOrDefaultAsync(); + + if (otpDetails == null) + { + _logger.LogWarning("OTP login failed - no OTP found for user {UserId}", userId); + return NotFound(ApiResponse.ErrorResponse("OTP not found", "No OTP was generated for this user", 404)); + } + + // Validate OTP expiration + var validUntil = otpDetails.TimeStamp.AddSeconds(otpDetails.ExpriesInSec); + if (DateTime.UtcNow > validUntil || otpDetails.IsUsed) + { + _logger.LogWarning("OTP login failed - OTP expired for user {UserId}", userId); + return BadRequest(ApiResponse.ErrorResponse("OTP expired", "The OTP has expired, please request a new one", 400)); + } + + // Match OTP + if (otpDetails.OTP != verifyOTP.OTP) + { + _logger.LogWarning("OTP login failed - incorrect OTP entered for user {UserId}", userId); + return Unauthorized(ApiResponse.ErrorResponse("Invalid OTP", "OTP did not match", 401)); + } + + // Generate access and refresh tokens + //var accessToken = _refreshTokenService.GenerateJwtTokenWithOrganization(requestEmployee.ApplicationUser?.UserName, requestEmployee.OrganizationId, _jwtSettings); + //var refreshToken = await _refreshTokenService.CreateRefreshTokenWithOrganization(requestEmployee.ApplicationUserId, requestEmployee.OrganizationId, _jwtSettings); + + var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.OrganizationId == requestEmployee.OrganizationId); + + var accessToken = _refreshTokenService.GenerateJwtToken(requestEmployee.ApplicationUser?.UserName, + tenant?.Id ?? Guid.Empty, requestEmployee.OrganizationId, _jwtSettings); + + var refreshToken = await _refreshTokenService.CreateRefreshToken(requestEmployee.ApplicationUserId, + tenant?.Id.ToString(), requestEmployee.OrganizationId, _jwtSettings); + + // Fetch MPIN token if exists + var mpinDetails = await _context.MPINDetails + .FirstOrDefaultAsync(p => p.UserId == userId); + + // Build and return response + var response = new + { + token = accessToken, + refreshToken, + mpinToken = mpinDetails?.MPINToken + }; + otpDetails.IsUsed = true; + await _context.SaveChangesAsync(); + _logger.LogInfo("OTP login successful for employee {EmployeeId}", requestEmployee.Id); + return Ok(ApiResponse.SuccessResponse(response, "User logged in successfully.", 200)); + } + catch (Exception ex) + { + _logger.LogError(ex, "An unexpected error occurred during OTP login for email {Email}", verifyOTP.Email ?? string.Empty); + return StatusCode(500, ApiResponse.ErrorResponse("Unexpected error", ex.Message, 500)); + } + } + // new login APIs [HttpPost("login")] @@ -944,7 +1038,7 @@ namespace MarcoBMS.Services.Controllers } [HttpPost("login-otp")] - public async Task LoginWithOTP([FromBody] VerifyOTPDto verifyOTP) + public async Task LoginWithOTPAsync([FromBody] VerifyOTPDto verifyOTP) { await using var _context = await _dbContextFactory.CreateDbContextAsync(); using var scope = _serviceScopeFactory.CreateScope(); diff --git a/Marco.Pms.Services/Controllers/EmployeeController.cs b/Marco.Pms.Services/Controllers/EmployeeController.cs index 9c19a81..1cac04c 100644 --- a/Marco.Pms.Services/Controllers/EmployeeController.cs +++ b/Marco.Pms.Services/Controllers/EmployeeController.cs @@ -332,7 +332,7 @@ namespace MarcoBMS.Services.Controllers public async Task GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString) { var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - var employeeQuery = _context.Employees.Where(e => e.TenantId == tenantId); + var employeeQuery = _context.Employees.Where(e => e.IsActive); if (projectId != null && projectId != Guid.Empty) { var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value); @@ -344,6 +344,10 @@ namespace MarcoBMS.Services.Controllers var employeeIds = await _context.ProjectAllocations.Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.TenantId == tenantId).Select(p => p.EmployeeId).ToListAsync(); employeeQuery = employeeQuery.Where(e => employeeIds.Contains(e.Id)); } + else + { + employeeQuery = employeeQuery.Where(e => e.OrganizationId == organizationId); + } if (!string.IsNullOrWhiteSpace(searchString)) { var searchStringLower = searchString.ToLower(); diff --git a/Marco.Pms.Services/Helpers/RolesHelper.cs b/Marco.Pms.Services/Helpers/RolesHelper.cs index a963482..175489e 100644 --- a/Marco.Pms.Services/Helpers/RolesHelper.cs +++ b/Marco.Pms.Services/Helpers/RolesHelper.cs @@ -38,7 +38,7 @@ namespace MarcoBMS.Services.Helpers // This is safe because the query is not executed yet. var employeeRoleIdsQuery = _context.EmployeeRoleMappings .AsNoTracking() - .Where(erm => erm.EmployeeId == EmployeeId && erm.IsEnabled) + .Where(erm => erm.EmployeeId == EmployeeId && erm.IsEnabled && erm.TenantId == tenantId) .Select(erm => erm.RoleId); // --- Step 2: Asynchronously update the cache using the DbContextFactory --- @@ -52,7 +52,7 @@ namespace MarcoBMS.Services.Helpers // Now, re-create and execute the query using this new, isolated context. var roleIds = await contextForCache.EmployeeRoleMappings .AsNoTracking() - .Where(erm => erm.EmployeeId == EmployeeId && erm.IsEnabled) + .Where(erm => erm.EmployeeId == EmployeeId && erm.IsEnabled && erm.TenantId == tenantId) .Select(erm => erm.RoleId) .ToListAsync(); diff --git a/Marco.Pms.Services/Helpers/UserHelper.cs b/Marco.Pms.Services/Helpers/UserHelper.cs index f5d4fc3..856bbcb 100644 --- a/Marco.Pms.Services/Helpers/UserHelper.cs +++ b/Marco.Pms.Services/Helpers/UserHelper.cs @@ -54,7 +54,7 @@ namespace MarcoBMS.Services.Helpers { var user = await GetCurrentUserAsync(); if (user == null) return new Employee { }; - var Employee = await _context.Employees.AsNoTracking().Include(e => e.JobRole).FirstOrDefaultAsync(e => e.ApplicationUserId == user.Id && e.IsActive); + var Employee = await _context.Employees.AsNoTracking().Include(a => a.ApplicationUser).Include(e => e.JobRole).FirstOrDefaultAsync(e => e.ApplicationUserId == user.Id && e.IsActive); return Employee ?? new Employee { }; } diff --git a/Marco.Pms.Services/Service/MasterService.cs b/Marco.Pms.Services/Service/MasterService.cs index eef8a68..c693e05 100644 --- a/Marco.Pms.Services/Service/MasterService.cs +++ b/Marco.Pms.Services/Service/MasterService.cs @@ -1414,13 +1414,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of expense type from different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Featching the list of Expenses Type. var typeList = await _context.ExpensesTypeMaster.Where(et => et.TenantId == tenantId && et.IsActive == isActive).ToListAsync(); var response = _mapper.Map>(typeList); @@ -1439,12 +1432,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to add new expense type in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) { @@ -1477,13 +1464,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to update expense type in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) @@ -1549,13 +1529,6 @@ namespace Marco.Pms.Services.Service string action = isActive ? "restore" : "delete"; try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to {Action} expense type in different tenant", loggedInEmployee.Id, action); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) @@ -1614,13 +1587,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of expense status from different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Featching the list of Expenses Status. var statusList = await _context.ExpensesStatusMaster.ToListAsync(); var response = _mapper.Map>(statusList); @@ -1656,13 +1622,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to fetch the list of payment modes from different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Featching the list of Payment Modes. var paymentModes = await _context.PaymentModeMatser.Where(pm => pm.TenantId == tenantId && pm.IsActive == isActive).ToListAsync(); var response = _mapper.Map>(paymentModes); @@ -1680,12 +1639,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to add new payment mode in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) { @@ -1721,13 +1674,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to update Payment Mode in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) @@ -1793,13 +1739,6 @@ namespace Marco.Pms.Services.Service string action = isActive ? "restore" : "delete"; try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to {Action} Payment Mode in different tenant", loggedInEmployee.Id, action); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) @@ -1867,15 +1806,6 @@ namespace Marco.Pms.Services.Service { try { - // ✅ Tenant validation - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Access denied. Employee {EmployeeId} (TenantId: {EmployeeTenantId}) attempted to fetch document categories for TenantId: {RequestedTenantId}", - loggedInEmployee.Id, loggedInEmployee.TenantId ?? Guid.Empty, tenantId); - - return ApiResponse.ErrorResponse("Access Denied", "You do not have access to this information", 403); - } - // ✅ Build query IQueryable documentCategoryQuery = _context.DocumentCategoryMasters .AsNoTracking() // optimization: read-only @@ -1908,12 +1838,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to add new Document Category in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) { @@ -1957,13 +1881,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to update Document Category in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) @@ -2047,13 +1964,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to delete Document Category in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) @@ -2115,15 +2025,6 @@ namespace Marco.Pms.Services.Service { try { - // ✅ Tenant validation - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Access denied. Employee {EmployeeId} (TenantId: {EmployeeTenantId}) attempted to fetch document types for TenantId: {RequestedTenantId}", - loggedInEmployee.Id, loggedInEmployee.TenantId ?? Guid.Empty, tenantId); - - return ApiResponse.ErrorResponse("Access Denied", "You do not have access to this information", 403); - } - // ✅ Build query IQueryable documentTypeQuery = _context.DocumentTypeMasters .AsNoTracking() // optimization: read-only @@ -2156,12 +2057,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to add new Document Type in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) { @@ -2211,13 +2106,6 @@ namespace Marco.Pms.Services.Service { try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to update Document Type in different tenant", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission) @@ -2303,13 +2191,6 @@ namespace Marco.Pms.Services.Service string action = isActive ? "restore" : "delete"; try { - // Validation if employee is taking action in same tenant - if (tenantId != loggedInEmployee.TenantId) - { - _logger.LogWarning("Employee {EmployeeId} attempted to {Action} Document Type in different tenant", loggedInEmployee.Id, action); - return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); - } - // Checking permssion for managing masters var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); if (!hasManagePermission)