Skip to content
← Back to Insights

Custom Development

Role-Based Access Control for a Marketplace: Six Roles, One Permissions Matrix

5 September 2026 · 7 min read

The fastest way to get access control wrong is to check job titles instead of permissions. A check like "if the user is an admin" works until you add a support agent who needs to read bookings but not refund them, or a finance role that sees payouts but not profiles. Then every one of those checks has to be found and revised. Here is how a real marketplace build avoids that.

Capabilities, not roles, at the point of decision

Every protected action in the system asks one question: does this user hold the capability this action requires. Refund a booking. Approve a tutor verification. Change another user’s role. View a payout. Roles are just named bundles of capabilities. The code never asks whether someone is an admin. It asks whether they can do the specific thing in front of them.

The matrix

Six roles down the side, capabilities across the top, in one place:

  • Student: manage own profile, book a session, message a matched tutor, review a completed and paid booking.
  • Tutor: manage own profile, submit verification documents, accept or decline a booking, message a matched student.
  • Support: read any booking, message any user, open and annotate a dispute. No financial actions.
  • Finance: view and release payouts, view transaction history, issue refunds. No profile or content edits.
  • Admin: approve tutor verification, moderate reviews, edit any profile, manage subjects and pricing bands.
  • Super admin: everything, including changing another user’s role and managing the capability map itself.

Adding a role is adding a column, not hunting through controllers for every place a permission is assumed.

Every privileged action is logged

A refund, a role change, a verification approval, a review taken down: each writes a row with the actor, the target, the action, and a timestamp, before the action commits. When a tutor asks why their verification was rejected, or a chargeback needs a paper trail, the answer is a query, not a guess.

Where enforcement actually sits

Capability checks run server side, in the plugin, on every request that changes data, not in the interface. The front end hides a button the user cannot use because that is good UX, but the server assumes the button was never there and checks anyway. Anything else is a permission system you can get around with the browser console.

Why this matters beyond marketplaces

Any application with more than two kinds of user, a booking system, a client portal, an internal dashboard, hits this the moment the second staff role appears. Designing the capability model up front costs an afternoon. Retrofitting it into a codebase full of role checks costs a week and a round of bugs.