Permissions
Grant the new routes in thunder-core's RBAC - the step that decides what each role sees in the dashboard.
thunder-core denies every route that no policy grants. You have just added three resources, so right now all of them return 403 - and the dashboard you are about to generate would be empty.
This page is short, but skipping it is the single most common way to get stuck in this example.
The Permission Strings You Created
Permissions are scope.action, where scope is the router's function name and action is the handler's function name. Your three routers produced:
| Scope | Actions |
|---|---|
equipment | create, get, count, update, del |
customers | create, get, count, update, del |
rentals | create, get, count, update, cancelRental |
rentals has no del - you disabled it and replaced it with cancelRental, so that is the string to grant.
A bare scope such as equipment grants every action in that router, and * grants everything. Use the bare form for a role that should have full access to a resource.
Designing the Two Roles
| Role | Should be able to |
|---|---|
| Agent | Look up equipment, manage customers, book and update rentals |
| Manager | Everything, plus cancelling a rental |
Which becomes:
// agent
["equipment.get", "equipment.count", "customers", "rentals.get", "rentals.count", "rentals.create", "rentals.update"]
// manager
["equipment", "customers", "rentals"]Note the agent gets equipment.get and equipment.count but not equipment.create or equipment.update - they can pick equipment for a rental, but not change the catalogue.
Granting Them
Edit scripts/syncAccessControl.ts to add your policies and attach them to roles, then run the plugin setup:
deno task setup:plugin -n Huruf-Tech/thunder-core --envs=developmentsyncAccessControl is idempotent - it upserts through ACManager, so re-running it after adding permissions is safe. See Setup & Lifecycle.
Use the management routes that thunder-core ships, so you do not have to touch the seed or restart:
routes/accessControlPolicies.ts- create or edit a policy (a named bundle of permission strings)routes/accessControl.ts- attach policies to a role
This is the right path once you have real data. See Access Control.
Read scripts/syncAccessControl.ts for the exact document shape and the default role names before you edit it - the seeded defaults include roles like guest, user and admin.
Why This Decides the Dashboard
This is the part worth internalising. Thunder UI shows a module only if:
ThunderSDK.isPermitted(name, "get") || ThunderSDK.isPermitted(name, "create")So your RBAC is the navigation:
- An agent signs in and sees Equipment, Customers and Rentals - but no create button on equipment.
- Strip
equipment.getandequipment.countfrom a role and the Equipment module vanishes from their sidebar entirely. - Hide every module in the group and the Rental Desk group header disappears on its own - a group shows only when a child is visible.
You never write a permission check in the frontend. One role definition drives both the API and the UI.
Permissions are registered before the app renders, via registerPermissions(). That is why visibility never flickers - but it also means a permission change needs a reload to take effect. See Authentication & Multi-Tenancy.
With the roles in place, generate the dashboard. On to the Dashboard.