first commit
CI/CD / CI · Admin API (dotnet build) (push) Successful in 41s
CI/CD / CI · Admin Web (tsc) (push) Failing after 5s
CI/CD / CI · Website (tsc) (push) Failing after 4s
CI/CD / CI · Koja (tsc) (push) Failing after 5s
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m13s
CI/CD / CI · Dashboard (tsc) (push) Failing after 2m32s
CI/CD / Deploy · all services (push) Has been skipped

This commit is contained in:
soroush.asadi
2026-05-31 11:06:24 +03:30
parent 51e422272d
commit 345ae0a4b5
69 changed files with 11964 additions and 152 deletions
@@ -0,0 +1,41 @@
namespace Meezi.Core.Authorization;
/// <summary>
/// Capabilities a café employee can be granted. These are the single source of
/// truth for authorization — controllers check a <see cref="Permission"/> rather
/// than hard-coding role names, so the role→capability mapping lives in exactly
/// one place (<see cref="RolePermissions"/>).
/// </summary>
public enum Permission
{
// Café-level administration (Owner only)
ManageCafeSettings,
ManageBilling,
ManageBranches,
// Management (Owner + Manager)
ManageStaff,
ManageMenu,
ManageInventory,
ManageExpenses,
ManageTaxes,
ManageCoupons,
ManageReservations,
ManageTables,
ViewReports,
ReviewLeave,
ManageSalaries,
ManagePrintSettings,
// Front-of-house operations
ProcessOrders,
HandlePayments,
OperateRegister,
ManageQueue,
// Kitchen
ViewKitchen,
// Delivery
HandleDelivery,
}
@@ -0,0 +1,76 @@
using Meezi.Core.Enums;
namespace Meezi.Core.Authorization;
/// <summary>
/// The authoritative role→capability matrix. Change what a role can do here and
/// every controller that calls <c>EnsurePermission</c> updates automatically.
/// </summary>
public static class RolePermissions
{
private static readonly IReadOnlyDictionary<EmployeeRole, HashSet<Permission>> Matrix =
new Dictionary<EmployeeRole, HashSet<Permission>>
{
[EmployeeRole.Owner] = AllPermissions(),
[EmployeeRole.Manager] = new()
{
Permission.ManageStaff,
Permission.ManageMenu,
Permission.ManageInventory,
Permission.ManageExpenses,
Permission.ManageTaxes,
Permission.ManageCoupons,
Permission.ManageReservations,
Permission.ManageTables,
Permission.ViewReports,
Permission.ReviewLeave,
Permission.ManageSalaries,
Permission.ManagePrintSettings,
Permission.ProcessOrders,
Permission.HandlePayments,
Permission.OperateRegister,
Permission.ManageQueue,
Permission.ViewKitchen,
Permission.HandleDelivery,
},
[EmployeeRole.Cashier] = new()
{
Permission.ProcessOrders,
Permission.HandlePayments,
Permission.OperateRegister,
Permission.ManageQueue,
Permission.ManageReservations,
},
[EmployeeRole.Waiter] = new()
{
Permission.ProcessOrders,
Permission.ManageReservations,
Permission.ManageQueue,
},
[EmployeeRole.Chef] = new()
{
Permission.ViewKitchen,
},
[EmployeeRole.Delivery] = new()
{
Permission.HandleDelivery,
},
};
public static bool Has(EmployeeRole role, Permission permission) =>
Matrix.TryGetValue(role, out var set) && set.Contains(permission);
public static IReadOnlySet<Permission> For(EmployeeRole role) =>
Matrix.TryGetValue(role, out var set) ? set : new HashSet<Permission>();
/// <summary>True for roles that administer the whole café across all branches.</summary>
public static bool IsCafeWide(EmployeeRole role) => role == EmployeeRole.Owner;
private static HashSet<Permission> AllPermissions() =>
new(Enum.GetValues<Permission>());
}