feff0fa73d
- AppConstants: add Accountant to CompanyRoles; add CanManageBills and CanManageAccounting to Policies - ApplicationUser: add CanManageBills and CanManageAccounting bool fields - UserManagementDtos: expose new fields in all three DTOs - ClaimsPrincipalFactory: emit ManageBills and ManageAccounting claims - Program.cs: add CanManageBills and CanManageAccounting policies; update CanManageInvoices, CanViewReports, CanManagePurchaseOrders, and CanManageVendors to auto-pass for Accountant role - BillsController: replace CanManageInventory with CanManageBills on all write actions (correct policy — bills are not inventory) - BankReconciliationsController: replace CanManageJobs with CanManageAccounting on write actions - CompanyUsersController: add Accountant to validCompanyRoles (both Create/Edit), legacyRole switch, and all permission assignment blocks - Create/Edit views: add Accountant option to role dropdown; add CanManageBills and CanManageAccounting checkboxes; JS auto-checks financial permissions when Accountant role is selected - Migration AddAccountantRolePermissions: adds columns + backfills CanManageBills=1 and CanManageAccounting=1 for all CompanyAdmin users Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
153 lines
5.0 KiB
C#
153 lines
5.0 KiB
C#
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Options;
|
|
using PowderCoating.Core.Entities;
|
|
using PowderCoating.Infrastructure.Data;
|
|
using System.Security.Claims;
|
|
|
|
namespace PowderCoating.Infrastructure.Services;
|
|
|
|
/// <summary>
|
|
/// Custom claims principal factory that adds company-specific claims to the user's identity
|
|
/// </summary>
|
|
public class ApplicationUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
|
|
{
|
|
private readonly ApplicationDbContext _context;
|
|
|
|
public ApplicationUserClaimsPrincipalFactory(
|
|
UserManager<ApplicationUser> userManager,
|
|
RoleManager<IdentityRole> roleManager,
|
|
IOptions<IdentityOptions> options,
|
|
ApplicationDbContext context)
|
|
: base(userManager, roleManager, options)
|
|
{
|
|
_context = context;
|
|
}
|
|
|
|
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
|
|
{
|
|
var identity = await base.GenerateClaimsAsync(user);
|
|
|
|
// Add CompanyId claim if user has a company
|
|
if (user.CompanyId > 0)
|
|
{
|
|
identity.AddClaim(new Claim("CompanyId", user.CompanyId.ToString()));
|
|
|
|
// Add subscription plan display name from DB (for display in nav)
|
|
var company = await _context.Companies.IgnoreQueryFilters()
|
|
.Where(c => c.Id == user.CompanyId && !c.IsDeleted)
|
|
.Select(c => new { c.SubscriptionPlan })
|
|
.FirstOrDefaultAsync();
|
|
if (company != null)
|
|
{
|
|
// Look up the DisplayName from SubscriptionPlanConfig so it reflects DB values
|
|
var planConfig = await _context.SubscriptionPlanConfigs.IgnoreQueryFilters()
|
|
.Where(p => p.Plan == company.SubscriptionPlan && p.IsActive && !p.IsDeleted)
|
|
.Select(p => new { p.DisplayName })
|
|
.FirstOrDefaultAsync();
|
|
var planName = planConfig?.DisplayName ?? company.SubscriptionPlan.ToString();
|
|
identity.AddClaim(new Claim("SubscriptionPlan", planName));
|
|
}
|
|
}
|
|
|
|
// Add CompanyRole claim if user has a company role
|
|
if (!string.IsNullOrEmpty(user.CompanyRole))
|
|
{
|
|
identity.AddClaim(new Claim("CompanyRole", user.CompanyRole));
|
|
}
|
|
|
|
// Add user's full name for display purposes
|
|
identity.AddClaim(new Claim("FullName", user.FullName));
|
|
|
|
// Add appearance claims
|
|
identity.AddClaim(new Claim("Theme", user.Theme ?? "light"));
|
|
identity.AddClaim(new Claim("SidebarColor", user.SidebarColor ?? "ocean"));
|
|
identity.AddClaim(new Claim("HasProfilePicture",
|
|
(!string.IsNullOrEmpty(user.ProfilePictureFilePath)).ToString().ToLower()));
|
|
identity.AddClaim(new Claim("ProfilePictureVersion", (user.UpdatedAt ?? DateTime.UtcNow).Ticks.ToString()));
|
|
|
|
// Add permission claims for easier authorization
|
|
if (user.CanManageJobs)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageJobs"));
|
|
}
|
|
|
|
if (user.CanManageInventory)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageInventory"));
|
|
}
|
|
|
|
if (user.CanManageCustomers)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageCustomers"));
|
|
}
|
|
|
|
if (user.CanCreateQuotes)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "CreateQuotes"));
|
|
}
|
|
|
|
if (user.CanApproveQuotes)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ApproveQuotes"));
|
|
}
|
|
|
|
if (user.CanManageCalendar)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageCalendar"));
|
|
}
|
|
|
|
if (user.CanViewCalendar)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ViewCalendar"));
|
|
}
|
|
|
|
if (user.CanManageProducts)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageProducts"));
|
|
}
|
|
|
|
if (user.CanViewProducts)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ViewProducts"));
|
|
}
|
|
|
|
if (user.CanManageEquipment)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageEquipment"));
|
|
}
|
|
|
|
if (user.CanManageVendors)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageVendors"));
|
|
}
|
|
|
|
if (user.CanManageMaintenance)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageMaintenance"));
|
|
}
|
|
|
|
if (user.CanManageInvoices)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageInvoices"));
|
|
}
|
|
|
|
if (user.CanViewReports)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ViewReports"));
|
|
}
|
|
|
|
if (user.CanManageBills)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageBills"));
|
|
}
|
|
|
|
if (user.CanManageAccounting)
|
|
{
|
|
identity.AddClaim(new Claim("Permission", "ManageAccounting"));
|
|
}
|
|
|
|
return identity;
|
|
}
|
|
}
|