[CLAUDE] Infra: ẩn 5 nhóm menu (Hợp đồng + Danh mục + HRM/Office/Cá nhân) chỉ Admin thấy trên eoffice (S92)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m24s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m24s
- RevokeTemporarilyHiddenModulesAsync mở rộng predicate: +Contracts/Ct_* +Master/Suppliers/Projects/Departments/Catalog* (cộng dồn S58 Hrm*/Off*/Personal). - Tắt 2 re-grant public cũ: SeedAllRolesHrmProfileReadPermissions (S65) + SeedAllRolesOfficeModulePermissions (S69). Revoke là bước permission CUỐI trong SeedAdminPermissionsAsync (ungated) → durable, re-ẩn mỗi restart prod (gotcha #75). - Thu hẹp InReviewScope → chỉ Pe_* (Duyệt NCC giữ nguyên cho user thường; master-data GET = any-auth nên form PE vẫn chọn được Dự án/NCC/Hạng mục dù menu ẩn). - 2 method grant giữ private static (reversibility) → 2 seed test cũ vẫn invoke cô-lập, pass. - +AdminOnlyModulesRevokeTests (3 test-before-merge, security): non-Admin revoked 4 cờ / Admin untouched / PE preserved. Test 431→434 PASS (45 Domain + 389 Infra). - Reviewer PASS (5 attack vector: seed-order/under-revoke/over-revoke/test-genuine/prod-impact). FYI: role CatalogManager (0 user hiện tại) cũng bị thu Danh mục — intended-by-spec. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1996,14 +1996,20 @@ public static class DbInitializer
|
||||
// (+ 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
|
||||
// Hrm_Config* VẪN ẨN (revoke che). Read-only (chỉ CanRead).
|
||||
await SeedAllRolesHrmProfileReadPermissionsAsync(db, roleManager, logger);
|
||||
// [S92 2026-06-29] TẮT re-grant "Hồ sơ Nhân sự" public (S65) — anh chốt nhóm
|
||||
// "Nhân sự" CHỈ Admin thấy. RevokeTemporarilyHiddenModulesAsync (chạy ngay trên,
|
||||
// S92 mở rộng phủ thêm Contracts/Master/Catalogs) là bước permission CUỐI → thắng
|
||||
// mọi grant. Bật lại module nào: bỏ comment call tương ứng + gỡ prefix khỏi revoke.
|
||||
// await SeedAllRolesHrmProfileReadPermissionsAsync(db, roleManager, logger); // S65 — TẮT S92
|
||||
|
||||
// [S69 2026-06-17] GOLIVE Văn phòng số: mở Read+Create module Office (self-service)
|
||||
// cho MỌI role — anh chốt "public văn phòng số cho all user eoffice". CHẠY SAU revoke
|
||||
// để THẮNG (mirror S65). Allow-list 16 key (loại Off_PhongHop_Manage admin-CRUD +
|
||||
// Off_AttendanceReport báo-cáo-riêng-tư + Off_ChamCong Cá-nhân — giữ ẩn). HRM (trừ
|
||||
// Hồ sơ NS) + Personal VẪN ẩn (anh chỉ mở Office).
|
||||
await SeedAllRolesOfficeModulePermissionsAsync(db, roleManager, logger);
|
||||
// [S92 2026-06-29] TẮT re-grant "Văn phòng số" public (S69) — anh chốt nhóm
|
||||
// "Văn phòng số" CHỈ Admin thấy.
|
||||
// await SeedAllRolesOfficeModulePermissionsAsync(db, roleManager, logger); // S69 — TẮT S92
|
||||
}
|
||||
|
||||
// [S57] Cấp CanRead (CHỈ xem) cho MỌI role trên menu HRM + Office + Master để mọi
|
||||
@ -2027,10 +2033,12 @@ public static class DbInitializer
|
||||
// số + Cá nhân với user thường (chưa golive các module này). Revoke tương ứng
|
||||
// ở RevokeTemporarilyHiddenModulesAsync (chạy sau). Loại trừ tự nhiên (không
|
||||
// match prefix): PeWf_* (ký tự thứ 3 'W' ≠ '_'), AwV2_*, Ct_*, Bg_*, Wf_*, System.
|
||||
static bool InReviewScope(string key) =>
|
||||
key.StartsWith("Catalog") || key == MenuKeys.Master ||
|
||||
key == MenuKeys.Suppliers || key == MenuKeys.Projects || key == MenuKeys.Departments ||
|
||||
key.StartsWith("Pe_");
|
||||
// [S92 2026-06-29] Narrow: BỎ Master/Catalogs/Suppliers/Projects/Departments khỏi
|
||||
// grant-all-roles (anh chốt "Danh mục" CHỈ Admin). GIỮ Pe_* (Duyệt NCC read+create
|
||||
// cho mọi role — KHÔNG đụng). Master-data GET = any-auth (Suppliers/Projects/Catalogs
|
||||
// controller class-[Authorize]) nên form PE vẫn chọn Dự án/NCC/Hạng mục dù menu ẩn.
|
||||
// Row Master/Catalogs cũ trên prod được RevokeTemporarilyHiddenModulesAsync (dưới) gỡ.
|
||||
static bool InReviewScope(string key) => key.StartsWith("Pe_");
|
||||
|
||||
// Phân biệt key Pe_* (read+create) vs read-only. Pe_* match cờ thứ-3 '_'
|
||||
// → "PeWf_*"/"PeWorkflows" KHÔNG match (loại admin Designer).
|
||||
@ -2128,7 +2136,14 @@ public static class DbInitializer
|
||||
var rows = await db.Permissions
|
||||
.Where(p => p.RoleId != adminRoleId
|
||||
&& (p.MenuKey.StartsWith("Hrm") || p.MenuKey.StartsWith("Off")
|
||||
|| p.MenuKey == MenuKeys.Personal)
|
||||
|| p.MenuKey == MenuKeys.Personal
|
||||
// [S92 2026-06-29] +Hợp đồng (Contracts + Ct_*) + Danh mục (Master +
|
||||
// Suppliers + Projects + Departments + Catalog*) — anh chốt "chỉ Admin
|
||||
// thấy". Pe_* (Duyệt NCC) KHÔNG nằm đây → module PE giữ nguyên cho user.
|
||||
|| p.MenuKey == MenuKeys.Contracts || p.MenuKey.StartsWith("Ct_")
|
||||
|| p.MenuKey == MenuKeys.Master || p.MenuKey == MenuKeys.Suppliers
|
||||
|| p.MenuKey == MenuKeys.Projects || p.MenuKey == MenuKeys.Departments
|
||||
|| p.MenuKey.StartsWith("Catalog"))
|
||||
&& (p.CanRead || p.CanCreate || p.CanUpdate || p.CanDelete))
|
||||
.ToListAsync();
|
||||
|
||||
@ -2144,7 +2159,8 @@ public static class DbInitializer
|
||||
{
|
||||
await db.SaveChangesAsync();
|
||||
logger.LogInformation(
|
||||
"Revoked {Count} permission rows — tạm ẩn HRM/Văn phòng số/Cá nhân khỏi non-Admin (S58)",
|
||||
"Revoked {Count} permission rows — ẩn HRM/Văn phòng số/Cá nhân/Hợp đồng/Danh mục " +
|
||||
"khỏi non-Admin (chỉ Admin thấy — S58 + S92)",
|
||||
rows.Count);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user