- RolePermissions.Effective(role, isSuperAdmin, isAdmin, advancedMode) — флаги с учётом роли и простого/расширенного режима; AdvancedOnly — единый список advanced-only прав (зеркалит [RequiresAdvancedMode]). - /api/me теперь отдаёт permissions (имя→bool). Мобильное и веб скрывают одно и то же. - Веб: хук useCan() читает me.permissions (раньше гейтил только по именам ролей). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
126 lines
6.7 KiB
C#
126 lines
6.7 KiB
C#
namespace foodmarket.Domain.Organizations;
|
||
|
||
/// <summary>Набор флагов разрешений роли. Хранится JSON-колонкой
|
||
/// (owned by EmployeeRole). Семантика: false = доступ запрещён.</summary>
|
||
public class RolePermissions
|
||
{
|
||
// Каталог
|
||
public bool ProductsView { get; set; }
|
||
public bool ProductsEdit { get; set; }
|
||
public bool ProductsDelete { get; set; }
|
||
public bool ProductGroupsManage { get; set; }
|
||
public bool PriceTypesManage { get; set; }
|
||
public bool UnitsManage { get; set; }
|
||
|
||
// Закупки
|
||
public bool SuppliesView { get; set; }
|
||
public bool SuppliesEdit { get; set; }
|
||
public bool SuppliesPost { get; set; }
|
||
public bool SuppliesDelete { get; set; }
|
||
|
||
// Продажи (отгрузка контрагенту + POS)
|
||
public bool DemandsView { get; set; }
|
||
public bool DemandsEdit { get; set; }
|
||
public bool DemandsPost { get; set; }
|
||
public bool RetailSalesOperate { get; set; }
|
||
public bool RetailSalesRefund { get; set; }
|
||
|
||
// Контрагенты
|
||
public bool CounterpartiesView { get; set; }
|
||
public bool CounterpartiesEdit { get; set; }
|
||
public bool CounterpartiesDelete { get; set; }
|
||
|
||
// Склад / Остатки
|
||
public bool StocksView { get; set; }
|
||
public bool InventoryEdit { get; set; }
|
||
public bool LossEdit { get; set; }
|
||
public bool EnterEdit { get; set; }
|
||
public bool TransferEdit { get; set; }
|
||
|
||
// Отчёты
|
||
public bool ReportsView { get; set; }
|
||
public bool ReportsFinanceView { get; set; }
|
||
public bool ReportsStockView { get; set; }
|
||
|
||
// Настройки организации
|
||
public bool OrgSettingsManage { get; set; }
|
||
public bool EmployeesManage { get; set; }
|
||
public bool RolesManage { get; set; }
|
||
public bool StoresManage { get; set; }
|
||
public bool RetailPointsManage { get; set; }
|
||
public bool CashRegistersManage { get; set; }
|
||
public bool IntegrationsManage { get; set; }
|
||
|
||
// Sprint 9: лояльность и акции (Admin-only по умолчанию).
|
||
public bool LoyaltyManage { get; set; }
|
||
public bool PromotionsManage { get; set; }
|
||
|
||
// Sprint 33 (модуль «Деньги»):
|
||
// MoneyView — видеть счета, движения, отчёт «Деньги», долги.
|
||
// Кассир — да (видит выручку своей смены); Кладовщик — только через SuppliesView,
|
||
// увидит оплаченность приёмки, но не остатки по счетам.
|
||
// MoneyEdit — создавать/редактировать платежи, ордера, переводы,
|
||
// счета, статьи расходов, корректировки взаиморасчётов.
|
||
// Admin-only по умолчанию.
|
||
// CashShiftOperate — открыть/закрыть смену, вносить/выплачивать деньги
|
||
// в своей смене. Кассир — да.
|
||
public bool MoneyView { get; set; }
|
||
public bool MoneyEdit { get; set; }
|
||
public bool CashShiftOperate { get; set; }
|
||
|
||
/// <summary>Права, доступные только в расширенном режиме организации
|
||
/// (в простом режиме скрыты и на сервере, и в UI). Единый источник правды,
|
||
/// зеркалит контроллеры с <c>[RequiresAdvancedMode]</c>: Оптовые отгрузки,
|
||
/// Перемещения, Лояльность, Акции, Типы цен.</summary>
|
||
public static readonly IReadOnlySet<string> AdvancedOnly = new HashSet<string>(StringComparer.Ordinal)
|
||
{
|
||
nameof(DemandsView), nameof(DemandsEdit), nameof(DemandsPost),
|
||
nameof(TransferEdit), nameof(LoyaltyManage), nameof(PromotionsManage),
|
||
nameof(PriceTypesManage),
|
||
};
|
||
|
||
/// <summary>Все bool-флаги прав в виде словаря имя→значение (через рефлексию).</summary>
|
||
public Dictionary<string, bool> ToDictionary()
|
||
{
|
||
var dict = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||
foreach (var p in typeof(RolePermissions).GetProperties())
|
||
if (p.PropertyType == typeof(bool) && p.CanRead)
|
||
dict[p.Name] = (bool)p.GetValue(this)!;
|
||
return dict;
|
||
}
|
||
|
||
/// <summary>Эффективные права текущего пользователя для клиента (моб./веб):
|
||
/// SuperAdmin — всё без ограничений; Admin — всё, но в простом режиме
|
||
/// advanced-only скрыты; обычная роль — её флаги, в простом режиме с
|
||
/// обнулением advanced-only. Единый источник, чтобы клиенты скрывали одно и то же.</summary>
|
||
public static Dictionary<string, bool> Effective(RolePermissions? role, bool isSuperAdmin, bool isAdmin, bool advancedMode)
|
||
{
|
||
var basePerms = (isSuperAdmin || isAdmin) ? All() : (role ?? new RolePermissions());
|
||
var dict = basePerms.ToDictionary();
|
||
// SuperAdmin обходит гейт расширенного режима; остальным в простом режиме
|
||
// advanced-only права выключаем.
|
||
if (!isSuperAdmin && !advancedMode)
|
||
foreach (var name in AdvancedOnly)
|
||
dict[name] = false;
|
||
return dict;
|
||
}
|
||
|
||
/// <summary>Полный набор всех true — для системной роли «Администратор».</summary>
|
||
public static RolePermissions All() => new()
|
||
{
|
||
ProductsView = true, ProductsEdit = true, ProductsDelete = true,
|
||
ProductGroupsManage = true, PriceTypesManage = true, UnitsManage = true,
|
||
SuppliesView = true, SuppliesEdit = true, SuppliesPost = true, SuppliesDelete = true,
|
||
DemandsView = true, DemandsEdit = true, DemandsPost = true,
|
||
RetailSalesOperate = true, RetailSalesRefund = true,
|
||
CounterpartiesView = true, CounterpartiesEdit = true, CounterpartiesDelete = true,
|
||
StocksView = true, InventoryEdit = true, LossEdit = true, EnterEdit = true, TransferEdit = true,
|
||
ReportsView = true, ReportsFinanceView = true, ReportsStockView = true,
|
||
OrgSettingsManage = true, EmployeesManage = true, RolesManage = true,
|
||
StoresManage = true, RetailPointsManage = true,
|
||
CashRegistersManage = true, IntegrationsManage = true,
|
||
LoyaltyManage = true, PromotionsManage = true,
|
||
MoneyView = true, MoneyEdit = true, CashShiftOperate = true,
|
||
};
|
||
}
|