[CLAUDE] Auth: PRO role giu quyen Master/NCC qua deploy (seeder chay-sau-revoke) + scope-isolation test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m33s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m33s
Van de (UAT anh Kiet FDC, S118): user tra.bui (Bui Le Thuy Tra, Procurement TP) dang nhap khong
thay menu quan ly NCC/Suppliers. Nguyen nhan: seeder S92 RevokeTemporarilyHiddenModulesAsync (chay
moi startup) set CanRead=false cho Master/Suppliers/Projects/Departments/Catalog* voi moi role
non-Admin ("chi Admin thay").
Fix (owner chot mo ngoai-le CHI role Procurement, ben qua deploy):
- Them SeedProcurementMasterAccessAsync chay NGAY SAU revoke de THANG (mirror pattern Hrm S65 /
Office S69). Chi dung role Procurement -- S92 "chi Admin thay" GIU NGUYEN cho moi role khac.
- Grant 9 key: Suppliers (R+C+U -- quan ly + cong bo NCC, S113 publish can Suppliers.Update);
Master/Projects/Departments/Catalogs + 4 Catalog leaf (Read-only). KHONG Delete.
- Dashboard/Reports CO Y KHONG cap (reviewer bat: Reports lo tong gia tri HD + top NCC/du an theo
gia tri, nguoc S92; owner chot bo).
- Upgrade-only idempotent: nang co desired len true, khong ha co, khong dung role khac.
Test: +4 regression scope-isolation (ProcurementMasterAccessSeedTests) -- Procurement duoc nang
dung ma tran, role khac (DeptManager rieng) VAN bi revoke. 501 -> 505.
Reviewer PASS (scope cach-ly sach, no over-grant). Grant tam da ap prod (tra.bui verified 20 menu);
deploy nay = ban ben. Follow-up: gate ReportsController thieu policy (task rieng).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -2007,6 +2007,12 @@ public static class DbInitializer
|
||||
// Mở lại sau golive: gỡ prefix khỏi revoke + thêm lại vào InReviewScope.
|
||||
await RevokeTemporarilyHiddenModulesAsync(db, roleManager, logger);
|
||||
|
||||
// [S118 2026-07-14 — anh Kiệt FDC] CHẠY SAU revoke để THẮNG: NGOẠI-LỆ role Procurement
|
||||
// (Phòng Cung ứng) — mở lại Danh mục (Master/Suppliers/Projects/Departments/Catalog*) RIÊNG
|
||||
// cho PRO (cần quản lý + CÔNG BỐ NCC — Suppliers R+C+U). S92 "chỉ Admin thấy" GIỮ NGUYÊN cho
|
||||
// MỌI role khác (seeder chỉ đụng role Procurement). Dashboard/Reports KHÔNG cấp (anh chốt bỏ).
|
||||
await SeedProcurementMasterAccessAsync(db, roleManager, logger);
|
||||
|
||||
// [S65 2026-06-16] CHẠY SAU revoke để THẮNG: mở lại quyền XEM "Hồ sơ Nhân sự"
|
||||
// (+ root nhóm "Nhân sự") cho MỌI role — anh chốt public module Nhân sự cho
|
||||
// user thường tra cứu hồ sơ. Dashboard NS (Hrm_Dashboard) + 6 catalog
|
||||
@ -2180,6 +2186,83 @@ public static class DbInitializer
|
||||
}
|
||||
}
|
||||
|
||||
// [S118 2026-07-14 — anh Kiệt FDC] NGOẠI-LỆ role Procurement (Phòng Cung ứng): mở lại quyền
|
||||
// Danh mục (Master + Suppliers + Projects + Departments + Catalog*) RIÊNG cho role Procurement
|
||||
// — anh chốt PRO cần quản lý + CÔNG BỐ NCC (Suppliers R+C+U; S113 publish cần Suppliers.Update).
|
||||
// S92 "chỉ Admin thấy" GIỮ NGUYÊN cho MỌI role khác. CHẠY SAU RevokeTemporarilyHiddenModulesAsync
|
||||
// để THẮNG revoke (mirror pattern S65/S69). Dashboard/Reports CỐ Ý KHÔNG cấp (anh chốt bỏ —
|
||||
// Reports lộ tổng giá trị HĐ + top NCC/dự án theo giá trị, ngược S92; reviewer S118 bắt).
|
||||
// - Suppliers: Read+Create+Update (quản lý + công bố NCC). KHÔNG Delete.
|
||||
// - Master + Catalogs (group) + Projects + Departments + 4 Catalog leaf: Read-only.
|
||||
// - UPGRADE-ONLY (mirror Hrm S65 / Office S69): row đã tồn tại (revoke vừa set false) → NÂNG
|
||||
// cờ desired lên true. Row chưa có (DB mới) → tạo. KHÔNG hạ cờ + KHÔNG đụng role khác.
|
||||
// Thu hồi khi cần: xóa call ở SeedAsync — revoke sẽ tự che Master/Suppliers lại lần seed kế.
|
||||
private static async Task SeedProcurementMasterAccessAsync(
|
||||
ApplicationDbContext db, RoleManager<Role> roleManager, ILogger logger)
|
||||
{
|
||||
var role = await roleManager.FindByNameAsync(AppRoles.Procurement);
|
||||
if (role is null)
|
||||
{
|
||||
logger.LogWarning("SeedProcurementMasterAccessAsync: skip — Procurement role chưa seed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// (MenuKey, CanRead, CanCreate, CanUpdate) — CanDelete luôn giữ nguyên (KHÔNG cấp Delete).
|
||||
var grants = new (string Key, bool R, bool C, bool U)[]
|
||||
{
|
||||
(MenuKeys.Master, true, false, false),
|
||||
(MenuKeys.Suppliers, true, true, true), // quản lý + CÔNG BỐ NCC (S113 cần Update)
|
||||
(MenuKeys.Projects, true, false, false),
|
||||
(MenuKeys.Departments, true, false, false),
|
||||
(MenuKeys.Catalogs, true, false, false),
|
||||
(MenuKeys.CatalogUnits, true, false, false),
|
||||
(MenuKeys.CatalogMaterials, true, false, false),
|
||||
(MenuKeys.CatalogServices, true, false, false),
|
||||
(MenuKeys.CatalogWorkItems, true, false, false),
|
||||
};
|
||||
var keys = grants.Select(g => g.Key).ToArray();
|
||||
|
||||
var existing = (await db.Permissions
|
||||
.Where(p => p.RoleId == role.Id && keys.Contains(p.MenuKey))
|
||||
.ToListAsync())
|
||||
.ToDictionary(p => p.MenuKey);
|
||||
|
||||
var added = 0;
|
||||
var upgraded = 0;
|
||||
foreach (var g in grants)
|
||||
{
|
||||
if (existing.TryGetValue(g.Key, out var row))
|
||||
{
|
||||
var changed = false;
|
||||
if (g.R && !row.CanRead) { row.CanRead = true; changed = true; }
|
||||
if (g.C && !row.CanCreate) { row.CanCreate = true; changed = true; }
|
||||
if (g.U && !row.CanUpdate) { row.CanUpdate = true; changed = true; }
|
||||
if (changed) upgraded++;
|
||||
continue;
|
||||
}
|
||||
|
||||
db.Permissions.Add(new Permission
|
||||
{
|
||||
RoleId = role.Id,
|
||||
MenuKey = g.Key,
|
||||
CanRead = g.R,
|
||||
CanCreate = g.C,
|
||||
CanUpdate = g.U,
|
||||
CanDelete = false,
|
||||
});
|
||||
added++;
|
||||
}
|
||||
|
||||
if (added > 0 || upgraded > 0)
|
||||
{
|
||||
await db.SaveChangesAsync();
|
||||
logger.LogInformation(
|
||||
"Seeded Procurement master access: {Added} added + {Upgraded} upgraded " +
|
||||
"(Master/Suppliers/Projects/Departments/Catalog* — PRO exception to S92, S118)",
|
||||
added, upgraded);
|
||||
}
|
||||
}
|
||||
|
||||
// [S65 2026-06-16] Mở quyền XEM (Read-only) "Hồ sơ Nhân sự" cho MỌI role: anh chốt
|
||||
// public module Nhân sự (trọng tâm Hồ sơ NS) để user thường tra cứu hồ sơ nhân sự.
|
||||
// CHẠY SAU RevokeTemporarilyHiddenModulesAsync (SeedAsync) để THẮNG revoke: revoke
|
||||
|
||||
Reference in New Issue
Block a user