Document_Manager #129
@ -14,6 +14,8 @@ namespace Marco.Pms.Model.ViewModels.DocumentManager
|
||||
public BasicEmployeeVM? UploadedBy { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public BasicEmployeeVM? UpdatedBy { get; set; }
|
||||
public DateTime? VerifiedAt { get; set; }
|
||||
public BasicEmployeeVM? VerifiedBy { get; set; }
|
||||
public bool? IsVerified { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -424,8 +424,13 @@ namespace Marco.Pms.Services.Controllers
|
||||
var versionMappingsQuery = _context.AttachmentVersionMappings
|
||||
.Include(av => av.ChildAttachment)
|
||||
.ThenInclude(da => da!.UploadedBy)
|
||||
.ThenInclude(e => e!.JobRole)
|
||||
.Include(av => av.ChildAttachment)
|
||||
.ThenInclude(da => da!.UpdatedBy)
|
||||
.ThenInclude(e => e!.JobRole)
|
||||
.Include(av => av.ChildAttachment)
|
||||
.ThenInclude(da => da!.VerifiedBy)
|
||||
.ThenInclude(e => e!.JobRole)
|
||||
.Include(av => av.ChildAttachment)
|
||||
.ThenInclude(da => da!.Document)
|
||||
.Where(av => av.ParentAttachmentId == parentAttachmentId && av.TenantId == tenantId);
|
||||
|
@ -477,6 +477,13 @@ namespace MarcoBMS.Services.Controllers
|
||||
var response = await _projectServices.AssignProjectLevelModulesAsync(tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
[HttpGet("get/proejct-level/employees/{projectId}")]
|
||||
public async Task<IActionResult> GetEmployeeToWhomProjectLevelAssigned(Guid projectId)
|
||||
{
|
||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _projectServices.GetEmployeeToWhomProjectLevelAssignedAsync(projectId, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
@ -19,16 +19,100 @@ namespace Marco.Pms.Services.Service
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public async Task<bool> HasPermission(Guid featurePermissionId, Guid employeeId)
|
||||
//public async Task<bool> HasPermission(Guid featurePermissionId, Guid employeeId, Guid? projectId = null)
|
||||
//{
|
||||
// var featurePermissionIds = await _cache.GetPermissions(employeeId);
|
||||
// if (featurePermissionIds == null)
|
||||
// {
|
||||
// List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeId(employeeId);
|
||||
// featurePermissionIds = featurePermission.Select(fp => fp.Id).ToList();
|
||||
// }
|
||||
// if (projectId != null)
|
||||
// {
|
||||
// var projectLevelPerissionIds = await _context.ProjectLevelPermissionMappings
|
||||
// .Where(pl => pl.ProjectId == projectId.Value && pl.EmployeeId == employeeId).Select(pl => pl.PermissionId).ToListAsync();
|
||||
|
||||
// var projectLevelModuleIds = new HashSet<Guid>
|
||||
// {
|
||||
// Guid.Parse("53176ebf-c75d-42e5-839f-4508ffac3def"),
|
||||
// Guid.Parse("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"),
|
||||
// Guid.Parse("81ab8a87-8ccd-4015-a917-0627cee6a100"),
|
||||
// Guid.Parse("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"),
|
||||
// Guid.Parse("a8cf4331-8f04-4961-8360-a3f7c3cc7462")
|
||||
// };
|
||||
|
||||
// var allProjectLevelPermissionIds = await _context.FeaturePermissions
|
||||
// .Where(fp => projectLevelModuleIds.Contains(fp.FeatureId) && !projectLevelPerissionIds.Contains(fp.Id)).Select(fp => fp.Id).ToListAsync();
|
||||
// featurePermissionIds.RemoveRange(allProjectLevelPermissionIds);
|
||||
|
||||
// featurePermissionIds.AddRange(projectLevelPerissionIds);
|
||||
// featurePermissionIds = featurePermissionIds.Distinct().ToList();
|
||||
// }
|
||||
// var hasPermission = featurePermissionIds.Contains(featurePermissionId);
|
||||
// return hasPermission;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether an employee has a specific feature permission, optionally within a project context.
|
||||
/// </summary>
|
||||
/// <param name="featurePermissionId">The target feature permission ID to check.</param>
|
||||
/// <param name="employeeId">The ID of the employee.</param>
|
||||
/// <param name="projectId">Optional project ID for project-scoped permissions.</param>
|
||||
/// <returns>True if the user has the permission, otherwise false.</returns>
|
||||
public async Task<bool> HasPermission(Guid featurePermissionId, Guid employeeId, Guid? projectId = null)
|
||||
{
|
||||
// 1. Try fetching permissions from cache (fast-path lookup).
|
||||
var featurePermissionIds = await _cache.GetPermissions(employeeId);
|
||||
|
||||
// If not found in cache, fallback to database (slower).
|
||||
if (featurePermissionIds == null)
|
||||
{
|
||||
List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeId(employeeId);
|
||||
featurePermissionIds = featurePermission.Select(fp => fp.Id).ToList();
|
||||
var featurePermissions = await _rolesHelper.GetFeaturePermissionByEmployeeId(employeeId);
|
||||
featurePermissionIds = featurePermissions.Select(fp => fp.Id).ToList();
|
||||
}
|
||||
var hasPermission = featurePermissionIds.Contains(featurePermissionId);
|
||||
return hasPermission;
|
||||
|
||||
// 2. Handle project-level permission overrides if a project is specified.
|
||||
if (projectId.HasValue)
|
||||
{
|
||||
// Fetch permissions explicitly assigned to this employee in the project.
|
||||
var projectLevelPermissionIds = await _context.ProjectLevelPermissionMappings
|
||||
.Where(pl => pl.ProjectId == projectId.Value && pl.EmployeeId == employeeId)
|
||||
.Select(pl => pl.PermissionId)
|
||||
.ToListAsync();
|
||||
|
||||
if (projectLevelPermissionIds?.Any() ?? false)
|
||||
{
|
||||
|
||||
// Define modules where project-level overrides apply.
|
||||
var projectLevelModuleIds = new HashSet<Guid>
|
||||
{
|
||||
Guid.Parse("53176ebf-c75d-42e5-839f-4508ffac3def"),
|
||||
Guid.Parse("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"),
|
||||
Guid.Parse("81ab8a87-8ccd-4015-a917-0627cee6a100"),
|
||||
Guid.Parse("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"),
|
||||
Guid.Parse("a8cf4331-8f04-4961-8360-a3f7c3cc7462")
|
||||
};
|
||||
|
||||
// Get all feature permissions under those modules where the user didn't have explicit project-level grants.
|
||||
var allOverriddenPermissions = await _context.FeaturePermissions
|
||||
.Where(fp => projectLevelModuleIds.Contains(fp.FeatureId) &&
|
||||
!projectLevelPermissionIds.Contains(fp.Id))
|
||||
.Select(fp => fp.Id)
|
||||
.ToListAsync();
|
||||
|
||||
// Apply overrides:
|
||||
// - Remove global permissions overridden by project-level rules.
|
||||
// - Add explicit project-level permissions.
|
||||
featurePermissionIds = featurePermissionIds
|
||||
.Except(allOverriddenPermissions) // Remove overridden
|
||||
.Concat(projectLevelPermissionIds) // Add project-level
|
||||
.Distinct() // Ensure no duplicates
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Final check: does the employee have the requested permission?
|
||||
return featurePermissionIds.Contains(featurePermissionId);
|
||||
}
|
||||
public async Task<bool> HasPermissionAny(List<Guid> featurePermissionIds, Guid employeeId)
|
||||
{
|
||||
|
@ -1484,6 +1484,14 @@ namespace Marco.Pms.Services.Service
|
||||
_logger.LogInfo("ManageProjectLevelPermissionAsync started for EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, TenantId: {TenantId}",
|
||||
model.EmployeeId, model.ProjectId, tenantId);
|
||||
|
||||
var hasTeamPermission = await _permission.HasPermission(PermissionsMaster.ManageTeam, loggedInEmployee.Id, model.ProjectId);
|
||||
if (!hasTeamPermission)
|
||||
{
|
||||
_logger.LogWarning("Access Denied. User {UserId} tried to Manage the project-level permission for Employee {EmployeeId} and Project {ProjectId}"
|
||||
, loggedInEmployee.Id, model.EmployeeId, model.ProjectId);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage the project-level permission", 403);
|
||||
}
|
||||
|
||||
// Fetch all required entities in parallel where possible
|
||||
var featurePermissionIds = model.Permission.Select(p => p.Id).ToList();
|
||||
|
||||
@ -1677,7 +1685,7 @@ namespace Marco.Pms.Services.Service
|
||||
_logger.LogInfo("AssignProjectLevelModulesAsync called for TenantId: {TenantId}, EmployeeId: {EmployeeId}", tenantId, loggedInEmployee.Id);
|
||||
|
||||
// Define target module IDs. These could alternatively be stored in a config file or DB.
|
||||
var projectModuleIds = new HashSet<Guid>
|
||||
var projectLevelModuleIds = new HashSet<Guid>
|
||||
{
|
||||
Guid.Parse("53176ebf-c75d-42e5-839f-4508ffac3def"),
|
||||
Guid.Parse("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"),
|
||||
@ -1689,13 +1697,13 @@ namespace Marco.Pms.Services.Service
|
||||
try
|
||||
{
|
||||
// Query features associated with specified modules. Also include module and permissions.
|
||||
_logger.LogDebug("Querying Features with module filters: {ModuleIds}", string.Join(", ", projectModuleIds));
|
||||
_logger.LogDebug("Querying Features with module filters: {ModuleIds}", string.Join(", ", projectLevelModuleIds));
|
||||
|
||||
var features = await _context.Features
|
||||
.AsNoTracking() // Improves read-only query performance
|
||||
.Include(f => f.FeaturePermissions)
|
||||
.Include(f => f.Module)
|
||||
.Where(f => projectModuleIds.Contains(f.Id) && f.Module != null)
|
||||
.Where(f => projectLevelModuleIds.Contains(f.Id) && f.Module != null)
|
||||
.Select(f => new FeatureVM
|
||||
{
|
||||
Id = f.Id,
|
||||
@ -1724,6 +1732,23 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse<object>> GetEmployeeToWhomProjectLevelAssignedAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee)
|
||||
{
|
||||
var assignedEmployees = await _context.ProjectLevelPermissionMappings
|
||||
.Include(pl => pl.Employee)
|
||||
.ThenInclude(e => e!.JobRole)
|
||||
.AsNoTracking()
|
||||
.Where(pl => pl.ProjectId == projectId
|
||||
&& pl.TenantId == tenantId)
|
||||
.Select(pl => pl.Employee)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
|
||||
var response = _mapper.Map<List<BasicEmployeeVM>>(assignedEmployees);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, "The list of employees with project-level permissions has been successfully retrieved.", 200);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Helper Functions ===================================================================
|
||||
|
@ -39,6 +39,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
Task<ApiResponse<object>> ManageProjectLevelPermissionAsync(ProjctLevelPermissionDto model, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetAssignedProjectLevelPermissionAsync(Guid employeeId, Guid projectId, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> AssignProjectLevelModulesAsync(Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetEmployeeToWhomProjectLevelAssignedAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee);
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user