diff --git a/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs b/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs index 8be29e2..bd44bd8 100644 --- a/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs +++ b/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs @@ -1787,7 +1787,10 @@ public static class DbInitializer var tree = new List<(string Key, string Label, string? Parent, int Order, string Icon)> { (MenuKeys.Dashboard, "Tổng quan", null, 10, "LayoutDashboard"), - (MenuKeys.Master, "Danh mục", null, 20, "Database"), + // [S58 2026-06-11] "Danh mục" 20→80: anh yêu cầu đưa xuống CUỐI sidebar + // (sau Reports 50, trước vùng System 90 admin). Main upsert tự re-set + // Order trên DB cũ. Con (21-25) giữ nguyên — order chỉ so trong siblings. + (MenuKeys.Master, "Danh mục", null, 80, "Database"), (MenuKeys.Suppliers, "Nhà cung cấp", MenuKeys.Master, 21, "Building2"), (MenuKeys.Projects, "Dự án", MenuKeys.Master, 22, "FolderKanban"), (MenuKeys.Departments, "Phòng ban", MenuKeys.Master, 23, "Users"), @@ -2050,7 +2053,15 @@ public static class DbInitializer // [S57] Mở quyền XEM (Read-only) cho TẤT CẢ role để mọi bộ phận review/góp ý // các module HRM + Văn phòng số + Danh mục (master). KHÔNG đụng Duyệt NCC // (Pe_*/PeWf_*/AwV2 — sắp go-live, giữ phân quyền cũ), Contracts/Budgets/System. + // [S58] Scope grant THU HẸP còn Master/Catalogs/Pe_* — xem note trong method. await SeedAllRolesReviewReadPermissionsAsync(db, roleManager, logger); + + // [S58 2026-06-11] TẠM ẨN module chưa golive với user thường (anh yêu cầu, + // screenshot eoffice): thu hồi quyền HRM (Hrm*) + Văn phòng số (Off*) + + // Cá nhân (Personal) khỏi MỌI role TRỪ Admin. Menu tự ẩn cả 2 app + // (GetMyMenuTree lọc CanRead). Chạy SAU grant seed để revoke thắng. + // Mở lại sau golive: gỡ prefix khỏi revoke + thêm lại vào InReviewScope. + await RevokeTemporarilyHiddenModulesAsync(db, roleManager, logger); } // [S57] Cấp CanRead (CHỈ xem) cho MỌI role trên menu HRM + Office + Master để mọi @@ -2068,12 +2079,13 @@ public static class DbInitializer private static async Task SeedAllRolesReviewReadPermissionsAsync( ApplicationDbContext db, RoleManager roleManager, ILogger logger) { - // Scope read-only = HRM (Hrm*) + Office (Off*) + Personal + Master + Catalogs. + // Scope grant = Master + Catalogs + Pe_*. // [S57bis] +Pe_* (Duyệt NCC) — semantics riêng read+create xử lý bên dưới. - // Loại trừ tự nhiên (không match prefix): PeWf_* (4th char 'W' ≠ '_'), - // AwV2_*, Ct_*, Bg_*, Wf_*, System keys. + // [S58] BỎ Hrm*/Off*/Personal khỏi grant — sếp yêu cầu TẠM ẨN HRM + Văn phòng + // 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("Hrm") || key.StartsWith("Off") || key == MenuKeys.Personal || key.StartsWith("Catalog") || key == MenuKeys.Master || key == MenuKeys.Suppliers || key == MenuKeys.Projects || key == MenuKeys.Departments || key.StartsWith("Pe_"); @@ -2151,6 +2163,50 @@ public static class DbInitializer } } + // [S58 2026-06-11] Thu hồi quyền các module TẠM ẨN (chưa golive — anh yêu cầu từ + // screenshot eoffice) khỏi mọi role non-Admin: HRM (Hrm* gồm Hrm_Config*) + + // Văn phòng số (Off* gồm Off_ChamCong đã re-parent về Cá nhân) + root Cá nhân + // (Personal). Set cả 4 cờ CRUD=false (KHÔNG xóa row — giữ vết, flip lại nhanh + // khi golive). Admin GIỮ nguyên để quản trị/chuẩn bị dữ liệu. + // Lưu ý mức che: ẩn menu (GetMyMenuTree lọc CanRead) + permission matrix; FE + // KHÔNG có PermissionGuard per-route nên gõ URL trực tiếp vẫn render trang + // (API self-service vẫn [Authorize] thường) — chấp nhận cho mức "tạm ẩn". + // Idempotent: lần 2 không row nào còn cờ true → 0 update. + private static async Task RevokeTemporarilyHiddenModulesAsync( + ApplicationDbContext db, RoleManager roleManager, ILogger logger) + { + var adminRole = await roleManager.FindByNameAsync(AppRoles.Admin); + if (adminRole is null) + { + logger.LogWarning("RevokeTemporarilyHiddenModulesAsync: skip — Admin role chưa seed."); + return; + } + var adminRoleId = adminRole.Id; + + var rows = await db.Permissions + .Where(p => p.RoleId != adminRoleId + && (p.MenuKey.StartsWith("Hrm") || p.MenuKey.StartsWith("Off") + || p.MenuKey == MenuKeys.Personal) + && (p.CanRead || p.CanCreate || p.CanUpdate || p.CanDelete)) + .ToListAsync(); + + foreach (var row in rows) + { + row.CanRead = false; + row.CanCreate = false; + row.CanUpdate = false; + row.CanDelete = false; + } + + if (rows.Count > 0) + { + 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)", + rows.Count); + } + } + // [Plan CA S29 2026-05-22] Permission defaults cho role CatalogManager. // Strategy: full CRUD trên 9 menu key danh mục dùng chung: // - Master (root group) + Suppliers + Projects + Departments