/** * Permission universe — the single source of truth for every permission * recognized by the dynamic RBAC system. * * Permissions are hardcoded here in application code. The Payload admin panel * reads this list when rendering the permission selector on the `roles` * collection. Roles are dynamic (created/edited in the admin panel), but the * set of assignable permissions is NOT — it can only grow by adding entries * here. * * Format: `{collection-slug}:{create|read|update|delete}` for collection CRUD, * plus domain-specific special permissions for feature areas that don't map * cleanly to CRUD (e.g. `logistics:manage`, `discord:announce`). */ export interface PermissionOption { /** Machine-readable key, e.g. `"users:create"`. */ value: string; /** Human-readable label, e.g. `"Create"`. */ label: string | string[]; } export interface PermissionGroup { /** Group label shown as a header in the admin UI, e.g. `"Users"`. */ group: string; /** Permissions within this group. */ permissions: PermissionOption[]; } // --------------------------------------------------------------------------- // Permission groups // --------------------------------------------------------------------------- export const PERMISSION_GROUPS: PermissionGroup[] = [ { group: "System", permissions: [{ value: "system:admin-access", label: "Access Admin Panel" }], }, // ---- Users --------------------------------------------------------------- { group: "Users", permissions: [ { value: "users:create", label: "Create Users" }, { value: "users:read", label: "Read Users" }, { value: "users:update", label: "Update Users" }, { value: "users:delete", label: "Delete Users" }, { value: "users:unlock", label: "Unlock User Accounts" }, { value: "users:assign-roles", label: "Assign Roles to Users" }, ], }, { group: "Ranks", permissions: [ { value: "ranks:create", label: "Create" }, { value: "ranks:read", label: "Read" }, { value: "ranks:update", label: "Update" }, { value: "ranks:delete", label: "Delete" }, ], }, { group: "Profiles", permissions: [ { value: "profiles:create", label: "Create" }, { value: "profiles:read", label: "Read" }, { value: "profiles:update", label: "Update" }, { value: "profiles:delete", label: "Delete" }, ], }, { group: "Awards", permissions: [ { value: "awards:create", label: "Create" }, { value: "awards:read", label: "Read" }, { value: "awards:update", label: "Update" }, { value: "awards:delete", label: "Delete" }, ], }, { group: "Qualifications", permissions: [ { value: "qualifications:create", label: "Create" }, { value: "qualifications:read", label: "Read" }, { value: "qualifications:update", label: "Update" }, { value: "qualifications:delete", label: "Delete" }, ], }, { group: "Assignments", permissions: [ { value: "assignments:create", label: "Create" }, { value: "assignments:read", label: "Read" }, { value: "assignments:update", label: "Update" }, { value: "assignments:delete", label: "Delete" }, ], }, { group: "Experience", permissions: [ { value: "experience:create", label: "Create" }, { value: "experience:read", label: "Read" }, { value: "experience:update", label: "Update" }, { value: "experience:delete", label: "Delete" }, ], }, { group: "User Notifications", permissions: [ { value: "user-notifications:create", label: "Create" }, { value: "user-notifications:read", label: "Read" }, { value: "user-notifications:update", label: "Update" }, { value: "user-notifications:delete", label: "Delete" }, ], }, // ---- Intelligence -------------------------------------------------------- { group: "Missions", permissions: [ { value: "missions:create", label: "Create" }, { value: "missions:read", label: "Read" }, { value: "missions:update", label: "Update" }, { value: "missions:delete", label: "Delete" }, { value: "missions:read-sensitive", label: "Read Sensitive Fields (server passwords)" }, ], }, { group: "Mission Attendances", permissions: [ { value: "mission-attendances:create", label: "Create" }, { value: "mission-attendances:read", label: "Read" }, { value: "mission-attendances:update", label: "Update" }, { value: "mission-attendances:delete", label: "Delete" }, ], }, { group: "Campaigns", permissions: [ { value: "campaigns:create", label: "Create" }, { value: "campaigns:read", label: "Read" }, { value: "campaigns:update", label: "Update" }, { value: "campaigns:delete", label: "Delete" }, ], }, { group: "Factions", permissions: [ { value: "factions:create", label: "Create" }, { value: "factions:read", label: "Read" }, { value: "factions:update", label: "Update" }, { value: "factions:delete", label: "Delete" }, ], }, { group: "Technologies", permissions: [ { value: "technologies:create", label: "Create" }, { value: "technologies:read", label: "Read" }, { value: "technologies:update", label: "Update" }, { value: "technologies:delete", label: "Delete" }, ], }, // ---- Logistics ----------------------------------------------------------- { group: "Assets", permissions: [ { value: "assets:create", label: "Create" }, { value: "assets:read", label: "Read" }, { value: "assets:update", label: "Update" }, { value: "assets:delete", label: "Delete" }, ], }, { group: "Resources", permissions: [ { value: "resources:create", label: "Create" }, { value: "resources:read", label: "Read" }, { value: "resources:update", label: "Update" }, { value: "resources:delete", label: "Delete" }, ], }, { group: "Vehicles", permissions: [ { value: "vehicles:create", label: "Create" }, { value: "vehicles:read", label: "Read" }, { value: "vehicles:update", label: "Update" }, { value: "vehicles:delete", label: "Delete" }, ], }, { group: "Structures", permissions: [ { value: "structures:create", label: "Create" }, { value: "structures:read", label: "Read" }, { value: "structures:update", label: "Update" }, { value: "structures:delete", label: "Delete" }, ], }, { group: "Shipments", permissions: [ { value: "shipments:create", label: "Create" }, { value: "shipments:read", label: "Read" }, { value: "shipments:update", label: "Update" }, { value: "shipments:delete", label: "Delete" }, ], }, // ---- Banking ------------------------------------------------------------- { group: "Bank Accounts", permissions: [ { value: "bank-accounts:create", label: "Create" }, { value: "bank-accounts:read", label: "Read" }, { value: "bank-accounts:update", label: "Update" }, { value: "bank-accounts:delete", label: "Delete" }, ], }, { group: "Bank Transactions", permissions: [ { value: "bank-transactions:create", label: "Create" }, { value: "bank-transactions:read", label: "Read" }, { value: "bank-transactions:update", label: "Update" }, { value: "bank-transactions:delete", label: "Delete" }, ], }, { group: "Ledger Entries", permissions: [ { value: "ledger-entries:create", label: "Create" }, { value: "ledger-entries:read", label: "Read" }, { value: "ledger-entries:update", label: "Update" }, { value: "ledger-entries:delete", label: "Delete" }, ], }, // ---- Locker -------------------------------------------------------------- { group: "Locker Storages", permissions: [ { value: "locker-storages:create", label: "Create" }, { value: "locker-storages:read", label: "Read" }, { value: "locker-storages:update", label: "Update" }, { value: "locker-storages:delete", label: "Delete" }, ], }, { group: "Loadouts", permissions: [ { value: "loadouts:create", label: "Create" }, { value: "loadouts:read", label: "Read" }, { value: "loadouts:update", label: "Update" }, { value: "loadouts:delete", label: "Delete" }, ], }, // ---- Market -------------------------------------------------------------- { group: "Market Listings", permissions: [ { value: "market-listings:create", label: "Create" }, { value: "market-listings:read", label: "Read" }, { value: "market-listings:update", label: "Update" }, { value: "market-listings:delete", label: "Delete" }, ], }, { group: "Market Negotiations", permissions: [ { value: "market-negotiations:create", label: "Create" }, { value: "market-negotiations:read", label: "Read" }, { value: "market-negotiations:update", label: "Update" }, { value: "market-negotiations:delete", label: "Delete" }, ], }, // ---- Helpdesk ------------------------------------------------------------ { group: "Tickets", permissions: [ { value: "tickets:create", label: "Create" }, { value: "tickets:read", label: "Read" }, { value: "tickets:update", label: "Update" }, { value: "tickets:delete", label: "Delete" }, ], }, // ---- Game ---------------------------------------------------------------- { group: "Game Structures", permissions: [ { value: "game-structures:create", label: "Create" }, { value: "game-structures:read", label: "Read" }, { value: "game-structures:update", label: "Update" }, { value: "game-structures:delete", label: "Delete" }, ], }, { group: "Game Vehicles", permissions: [ { value: "game-vehicles:create", label: "Create" }, { value: "game-vehicles:read", label: "Read" }, { value: "game-vehicles:update", label: "Update" }, { value: "game-vehicles:delete", label: "Delete" }, ], }, { group: "Game NPCs", permissions: [ { value: "game-npcs:create", label: "Create" }, { value: "game-npcs:read", label: "Read" }, { value: "game-npcs:update", label: "Update" }, { value: "game-npcs:delete", label: "Delete" }, ], }, { group: "Game Hard Resources", permissions: [ { value: "game-hard-resources:create", label: "Create" }, { value: "game-hard-resources:read", label: "Read" }, { value: "game-hard-resources:update", label: "Update" }, { value: "game-hard-resources:delete", label: "Delete" }, ], }, { group: "Game Event Logs", permissions: [ { value: "game-event-logs:create", label: "Create" }, { value: "game-event-logs:read", label: "Read" }, { value: "game-event-logs:update", label: "Update" }, { value: "game-event-logs:delete", label: "Delete" }, ], }, // ---- World --------------------------------------------------------------- { group: "Maps", permissions: [ { value: "maps:create", label: "Create" }, { value: "maps:read", label: "Read" }, { value: "maps:update", label: "Update" }, { value: "maps:delete", label: "Delete" }, ], }, { group: "Narrative Events", permissions: [ { value: "narrative-events:create", label: "Create" }, { value: "narrative-events:read", label: "Read" }, { value: "narrative-events:update", label: "Update" }, { value: "narrative-events:delete", label: "Delete" }, ], }, // ---- Server -------------------------------------------------------------- { group: "Mission Files", permissions: [ { value: "mission-files:create", label: "Create" }, { value: "mission-files:read", label: "Read" }, { value: "mission-files:update", label: "Update" }, { value: "mission-files:delete", label: "Delete" }, ], }, { group: "Mod Lists", permissions: [ { value: "mod-lists:create", label: "Create" }, { value: "mod-lists:read", label: "Read" }, { value: "mod-lists:update", label: "Update" }, { value: "mod-lists:delete", label: "Delete" }, ], }, // ---- Globals ------------------------------------------------------------- { group: "Game Rules (Global)", permissions: [ { value: "game-rules:read", label: "Read" }, { value: "game-rules:update", label: "Update" }, ], }, { group: "Shims (Global)", permissions: [ { value: "shims:read", label: "Read" }, { value: "shims:update", label: "Update" }, ], }, // ---- Special / Feature-area ---------------------------------------------- { group: "Logistics", permissions: [{ value: "logistics:manage", label: "Manage Logistics (manager bypass)" }], }, { group: "Intelligence", permissions: [ { value: "intelligence:manage", label: "Manage Intelligence (manager bypass)" }, { value: "profiles:intel_excerpt:update", label: ["Profile", "Intel Excerpt", "Update"] }, ], }, { group: "Banking", permissions: [{ value: "banking:manage", label: "Manage Banking (manager bypass)" }], }, { group: "Helpdesk", permissions: [{ value: "tickets:staff", label: "Staff Helpdesk Tickets" }], }, { group: "Discord Bot", permissions: [ { value: "discord:staff", label: "Bot Staff (isStaff)" }, { value: "discord:announce", label: "Post Announcements (/announce)" }, ], }, ]; // --------------------------------------------------------------------------- // Derived exports // --------------------------------------------------------------------------- /** Flat array of all permission value strings, as a const tuple for type inference. */ export const ALL_PERMISSION_VALUES = PERMISSION_GROUPS.flatMap((g) => g.permissions.map((p) => p.value), ) as unknown as readonly [ "system:admin-access", "users:create", "users:read", "users:update", "users:delete", "users:unlock", "users:assign-roles", "ranks:create", "ranks:read", "ranks:update", "ranks:delete", "profiles:create", "profiles:read", "profiles:update", "profiles:delete", "awards:create", "awards:read", "awards:update", "awards:delete", "qualifications:create", "qualifications:read", "qualifications:update", "qualifications:delete", "assignments:create", "assignments:read", "assignments:update", "assignments:delete", "experience:create", "experience:read", "experience:update", "experience:delete", "user-notifications:create", "user-notifications:read", "user-notifications:update", "user-notifications:delete", "missions:create", "missions:read", "missions:update", "missions:delete", "missions:read-sensitive", "mission-attendances:create", "mission-attendances:read", "mission-attendances:update", "mission-attendances:delete", "campaigns:create", "campaigns:read", "campaigns:update", "campaigns:delete", "factions:create", "factions:read", "factions:update", "factions:delete", "technologies:create", "technologies:read", "technologies:update", "technologies:delete", "assets:create", "assets:read", "assets:update", "assets:delete", "resources:create", "resources:read", "resources:update", "resources:delete", "vehicles:create", "vehicles:read", "vehicles:update", "vehicles:delete", "structures:create", "structures:read", "structures:update", "structures:delete", "shipments:create", "shipments:read", "shipments:update", "shipments:delete", "bank-accounts:create", "bank-accounts:read", "bank-accounts:update", "bank-accounts:delete", "bank-transactions:create", "bank-transactions:read", "bank-transactions:update", "bank-transactions:delete", "ledger-entries:create", "ledger-entries:read", "ledger-entries:update", "ledger-entries:delete", "locker-storages:create", "locker-storages:read", "locker-storages:update", "locker-storages:delete", "loadouts:create", "loadouts:read", "loadouts:update", "loadouts:delete", "market-listings:create", "market-listings:read", "market-listings:update", "market-listings:delete", "market-negotiations:create", "market-negotiations:read", "market-negotiations:update", "market-negotiations:delete", "tickets:create", "tickets:read", "tickets:update", "tickets:delete", "game-structures:create", "game-structures:read", "game-structures:update", "game-structures:delete", "game-vehicles:create", "game-vehicles:read", "game-vehicles:update", "game-vehicles:delete", "game-npcs:create", "game-npcs:read", "game-npcs:update", "game-npcs:delete", "game-hard-resources:create", "game-hard-resources:read", "game-hard-resources:update", "game-hard-resources:delete", "game-event-logs:create", "game-event-logs:read", "game-event-logs:update", "game-event-logs:delete", "maps:create", "maps:read", "maps:update", "maps:delete", "narrative-events:create", "narrative-events:read", "narrative-events:update", "narrative-events:delete", "mission-files:create", "mission-files:read", "mission-files:update", "mission-files:delete", "mod-lists:create", "mod-lists:read", "mod-lists:update", "mod-lists:delete", "game-rules:read", "game-rules:update", "shims:read", "shims:update", "logistics:manage", "banking:manage", "tickets:staff", "discord:staff", "discord:announce", "intelligence:manage", "profiles:intel_excerpt:update", ]; /** * Union type of every valid permission string. * Use this to type-check permission arguments at compile time. */ export type Permission = (typeof ALL_PERMISSION_VALUES)[number]; /** * Payload `select` field options, flattened with group-prefixed labels. * e.g. `{ label: "Users › Create Users", value: "users:create" }` */ export const permissionSelectOptions: { label: string; value: string }[] = PERMISSION_GROUPS.flatMap((g) => g.permissions.map((p) => { let label = p.label; if (Array.isArray(p.label)) label = p.label.join(" › "); return { label: `${g.group} › ${label}`, value: p.value, }; }), ); /** * Guard function — returns true if the given string is a valid permission. * Useful for runtime validation of permission strings from DB or API input. */ export function isPermission(value: string): value is Permission { return (ALL_PERMISSION_VALUES as readonly string[]).includes(value); }