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

secondman's avatar

Organization Centric vs User Centric

I want to get some feedback from folks who've been using the framework longer than I have about how to switch a given Laravel app to become more organization centric.

In the app I work in daily, the company is king, not the user. We have a few different member types that are currently mapped through a company_user pivot table.

But having all the policies always map to the user makes it difficult to write code for.

I'm wondering if anyone else has had any experience in solving a situation like this, and might have some suggestions on how to restructure so that my users can switch between company workspaces and ensure that their permissions for their role within that company remain intact.

So far I've been mapping workspaces using a session key, but the more sections of the app that become available, based on company level permissions, the more brittle this pattern becomes.

Right now we have the following user types:

members -- one primary company
consultants -- multiple companies
verifiers -- multiple companies
preparers -- multiple companies

Then within each company a user can have one of the following roles:

admin: viewAny, view, create, update, delete
editor: viewAny, view, create, update
read only: viewAny, view

Company admins can invite anyone to join their company (primary), both new users and existing users, and sets the role the user will have, should they accept to join.

I took over this project almost 4 years ago and it's now grown very large and unwieldy and the time has come to resolve this once and for all.

All advice would be greatly appreciated.

V

0 likes
8 replies
jlrdw's avatar

I am guessing some have dual roles. I normally handle what a logged in users role can or cannot do:

  • 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'.
    }

Just example, Some users may have several roles.

Just another example:

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
}

In a case like yours it would be a company id and and user id along with roles, this can get messy.

I would require a login per company. In a case where someone has roles in more than one company.

secondman's avatar

@jlrdw

Thanks for the input. While useful, this doesn't address the issue of multiple organizations.

Our system would be fine as is if we were just working within the confines of a single organization, or your role based example. For example, I had one consultant that consults for over 20 different companies, and has access to all those companies once she's logged in.

The question becomes how to manage the state of her roles and permissions per company as she moves about the system doing tasks for various different companies in a single session?

What I've done currently is created a PermissionService class and a base Policy class where this is injected and when a policy is authorized, the user is passed in and their permissions are generated for each company, then my policy methods iterate the collection based on her session('workspace') key to see if she has the correct permission.

But as I said this is brittle and doesn't always hold. It works perfectly when the workspace key is correct for the company ... but I really need a better solution.

I'd like to implement Spatie/Permissions perhaps or something similar but I can't find any documentation on how to set up roles on models besides the User model.

For instance every user would have a user and or editor or admin role on their primary company, and then other roles for other companies where the permissions for the role could be defined per role.

The app currently has over 50 models, trying to write complex rules for each policy method just isn't feasible.

jlrdw's avatar

Your technique sounds fine.

I would do similar, (company user role) type setup. But in cases like this there is no standard correct way, rather something that works, and is secure.

I usually try to keep things simple, I like to protect at method level in the controller.

Company 5, role 3, either can or cannot do a certain method. Makes it straight forward.

Edit: prior to making a decision take a couple of good RBAC tutorials, generic, not just laravel specific.

1 like
secondman's avatar

Cool thanks, I'll check it out right now.

martinbean's avatar

@vkronlein If you have a company_user pivot table, then you could store the role for that user–company combination as a pivot column on that table if you’re not already. Then, a user can have different roles at different companies. You could then do authorisation checks based on the company and role the user has at that company.

secondman's avatar

@martinbean

Yep, that's what we're doing now, and it's simply not sustainable. Way too much code to write.

Thanks for responding!

Please or to participate in this conversation.