Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

krishantalwar's avatar

Request for Guidance on System Design and Permission Strategy

I wanted to share a high-level overview of the system we’re building and request your input on the best way to approach the design — especially in terms of roles and permissions.

🧩 Project Context We’re using Laravel (API) for the backend and React.js for the frontend (as a separate app). Users can log in and choose to operate in one of two modes:

Agent Mode

Employee Mode

A user can be both agent and employee.

✅ Functional Overview We have multiple departments with specific responsibilities:

  1. Data Entry Department Employees input customer insurance details.

Each record includes the issuing agent and the policy type (motor, non-motor, health, etc.).

Workload is divided by insurance type.

  1. Pending Payment Department Employees review and update customer payment status.

Access is restricted by insurance type.

  1. Renewable Department Tracks policies that are near or past expiry.

Employees can update renewal status.

Again, insurance type determines responsibility.

  1. Commission Department Calculates agent commissions based on issued policies.

Tracks whether commissions are pending or paid.

  1. Agent Role Agents operate in a hierarchy (using kalnoy/nestedset).

A head agent can view their subordinate agents’ data.

Each agent can view:

Policies issued by them

Their own commission records

🧠 Tech Stack and Tools Planned Spatie/laravel-permission: for roles and permissions

kalnoy/nestedset: for managing agent hierarchy

Laravel Policies: for fine-grained access control

We’re currently designing the permission model and would love your input.

❓Key Question: What is the Best Way to Implement Permissions? We see three possible strategies:

  1. Direct User Permission Assign permissions directly to users.

Very flexible, but hard to manage at scale.

  1. Role-Based Permission (Preferred Core Strategy) Assign roles like employee agent, etc.

Easy to manage, integrates well with Spatie + Laravel Policies

But we have possibly two roles. So how can I divide the permission role base.

  1. Department-Based Permission Employees access data based on their department and insurance type assignments.

Requires custom logic (scopes or policies), but aligns with real-world responsibilities.

🎯 What We Need Guidance On Which approach (or combination) is ideal for a system like this?

How should we structure user roles and permissions cleanly?

What should my role be in designing and enforcing these rules (e.g., implementing role/permission logic, writing policies, defining relationships)

How should we structure user roles and permissions for flexibility and scalability?

🏷️ Role-Based Permissions – Two Roles (Agent vs Employee) If we go with role-based permissions, I’m considering only two main roles: Agent and Employee.

Agent Role (👩‍💼👨‍💼)

View own issued policies.

View own commission records.

Head Agents can view subordinate agents' data.

Can only view their data (limited access).

Employee Role (🧑‍💻)

Access data related to assigned departments.

Can update data within the department (e.g., renew policies, mark payments as done).

Access could be restricted by insurance type (motor, health, etc.).

📌 Guidance Needed: How should I divide these two roles to ensure the right level of access?

Do you think two roles (Agent and Employee) is granular enough for our system?

🧐 What Should My Role Be? Finally, could you clarify what my role should be in managing this system design? Should I be:

Designing the role/permission logic?

Writing policies for department-specific access?

Defining relationships between agents, departments, and permissions?

💬 Looking Forward to Your Thoughts! I would greatly appreciate any insights you can provide. I’m happy to dive deeper into any specific area, or provide a draft architecture proposal if needed

0 likes
2 replies
jlrdw's avatar

Of course you need authentication - login

I suggest looking at spatie permissions.

Use authorization to determine who can do what.

Just example of one system:

  • Bob is an admin

  • Suzy is admin and does bookkeeping

  • Mary is a bookkeeper only

  • If Bob is logged in, Bob can only do admin stuff and all access to user stuff. But Bob cannot mess with bookkeeping.

  • If Suzy is logged in she can access admin stuff and bookkeeping and accounting stuff.

  • If Mary is logged in she cannot mess with admin stuff, but has access to bookkeeping and accounting stuff.

So I just check at method level if the logged in users role can or cannot access that method / function.

And use query scopes to let a user edit / view their own data or an admin can access all users data.

Each app will be different as to who can do what.

So in pseudocode:

public function makeInvoice()
    {
        if (a required role of bkeep is not true here) {   // bkeep = bookkeeper
            return redirect('somewhere'); // whereever you redirect to if not authorized
        }
        // Rest of method here is accomplished if 
        // the logged in user has the required role of 'bkeep'.
    }

Again just examples.

Also a Spatie example I saw:

public function update(Request $request, Post $post) {
    if ($post->author !== auth()->user()->id || auth()->user()->cannot('edit posts'))
        abort(404);// or redirect, or whatever action 
    }
    //rest of method if all okay
}

But you can do this in the controller or through routing, but I like controller method level

In summary RBAC is at least 3 main steps:

  • A login required
  • An authorization implementation to determine what the logged in person with role can or cannot do
  • Protection of URL and parameters, checking that the logged in users id matches the id used in a query
  • Query scopes to differentiate for example (user sees their own data, admin can see all)

Each application will require unique tweaks in RBAC, no two apps are exactly the same.

Also there are good past discussions on this.

Also https://laracasts.com/series/mastering-permissions-in-laravel

1 like
Snapey's avatar

The answer is always, it depends....

But you have laid out your thoughts, and I dont think they are really different for any application where you use spatie permission. The basic rules are

  • code to permissions not roles. Code should ask, user has permission to xxx? The user acquires that permission through roles. Roles are not used in the code other than to manage a set of permissions for a given role. Permissions are always additive. The user has permission if any of their roles grant it. This is all taken care of by the package.

  • use policies to check permissions against data. Code should ask, user has permission to xxx with yyy data. This where it gets tricky. You need to be able to check permissions against data in your policy. For instance, user has permission to create deal if they have the deal.create permission AND insurance type is x||y.

  • start out by controlling access to routes, controllers etc before fixing the UI. To start with you should be clicking a button and checking you get unauthorised error. Later, when you have proven your security is enforcing the right rules, you can think about hiding things in the UI that the user cannot use. If you do it the other way around, there is a good chance you will forget to secure the actual endpoint/action.

Please or to participate in this conversation.