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

mdwdev's avatar

Looking for Direction with ACL Logic

Hello and thank you for glancing at this. I apologize ahead of time if it comes across as rambling or unfocused as I've been trying to sort all this out inside my own head for far too long. I've been put in charge of creating a custom php application at my place of work (where, by the way, I'm hired as a mobile dev...not a php dev...if that matters). I've gone around and around with creating this application first by trying to alter/fix code that someone else had started, then by attempting to follow a haphazard path that is our current "internal application and api", then by simply starting with a blank screen and making it all up!, then finally finding and working through a bunch of it in CodeIgnitor utilizing an envato project as sort of a 'template', and now here...I'm fresh off the "rip my hair out over figuring out Homestead and how to correctly connect/utilize sql databases" bus (meaning i finally DID figure that out...thank goodness), and now I'm down to 6 weeks shy of the "have something major to show us" deadline. Below, I've basically outlined where I'm at, and some of where I'm getting lost. I was hoping someone(s) here might take it as a challenge to help me sort my logic out? Any points in the direction of projects that I could look at would be helpful too. I am not however, looking to integrate already-built packages into this - not that I am against it as a whole...I just find that when I try to do this, and they don't do exactly what I need them to do ...I end up spending far too much time trying to figure out how to get around in someone else's code when I could just be learning how to do it myself. Anyway, without further ado, here it is:

What I'm trying to do/accomplish: The way I'm envisioning utilizing the gate functionality is by having 1 login for all users. * 'At the Gate', I want to determine: 1. Are you a Super Admin (or Dev level user)? yes? you have full access -- full access == can view/update all Customers, Applications, Users -- (my thinking was I could use before Callbacks for this...but I'm having a hard time finding resources for this) DATA HEIRARCHY: - Customer List (can add/view/update any customer list item itself) - Customer Apps (can add/view/update any customer app) - Customer Users (can add/view/update any customer user) 2. No? then which Customer do you belong to? (associate with customer) -- I want to, from this point on for this user, limit all functionality to the apps and users that are associated with this customer only! -- So...I get sidetracked here... * do I build a queue of apps and users for the session? ...if so, * would my super admin/dev level users functionality basically just loop through the queue building process for each customer?...am I making this way more difficult than it need be? * do I namespace something? ie: namespace App\Customer; 3. Now, are you the Customer Admin? Yes? you have 'full access' -- full access == can view/update all Applications and Users, user permissions etc (under this customer) -- 4. No? then which apps do you have access to? If 'full access user role', give access to each/all user_apps to update said app if 'limited access user role' give access to each/all user_apps to view only said app

What I have so far: 1. DATABASE TABLES: - Customers (id, name, timestamps) - Users (id, name, timestamps, email, pass, token etc) - i utilized the user migration that is built in - Applications (id, name, timestamps) - Features (id, name, etc, etc) - this is connected to 'Applications' through versions (but there is no table for versions in itself) ...this is difficult to explain & not important right now - Permissions (id, name, timestamps) - Roles (id, name, timestamps) - Customer_User ([customer_id, user_id] as primary key with relationships set up to appr. base tables) * MODEL RELATIONS: - A Customer can have MANY Users - A User belongs to ONE Customer - Application_Customer([application_id, customer_id] as PK with relations) * MODEL RELATIONS: - An Application belongs to ONE Customer - A Customer owns MANY Applications - Application_User([application_id, user_id] as PK with relations) * MODEL RELATIONS: - An Application has many Users - A User has many Applications - Permission_Role ([permission_id, role_id] as PK with relations) * MODEL RELATIONS: - A Permission can belong to many Roles - A Role can have many Permissions

  1. POLICIES:
    • ApplicationPolicy - I basically 'get' how to implement methods such as update, or show through this policy, but what I'm missing is how to call/build the 'before' method (or if I even should handle it this way) for the Super User/Dev Level users since they have access to all applications. -- Other things I'm unsure of --
      1. should i make a UserPolicy? since Super User/Dev level users/and Customer Admin users will need access to varying levels of typical crud methods? I started this, but it got a bit confusing and I was thinking I could probably utilize the forUser methods that are available...but not sure if that's enough
      2. should i make a CustomerPolicy? the only users that have access to any (and all) customers are the users that would pass the before callback I was thinking of implementing...but that was on the ApplicationPolicy, so I'm not really sure where to go with this...
      3. Lastly (well, for now), the Customer Admin user is a unique instance for each Customer and in the many ways that I've attempted to build this application...I keep getting hung up on them. They are restricted to the Users/Applications within their associated Customer...but I keep feeling like there should be a better way for me to handle their authority besides filtering them out of every time I'm gathering all the users...

Next goals (after I figure all this out!): CUSTOMER-ADMIN-USER-USERS functionality -- I need to allow the admin user to see all users and their connections (or non connections) with all customer applications...I think I've got a decent methodology for this pseudo-coded out, but there are layers that I'm still missing

0 likes
2 replies
awarren's avatar

Rather than trying to cobble together the ACL part from scratch, I'd recommend using an existing package. You can combine that with policies, helpers, and whatever else makes things easier. I'm working with Kodeine on a project. It' just one of a few out there but it serves my needs quite well and is fairly simple to work with. I stared with a base set of roles and permissions and set those up with a migration. One of the things I like about Kodeine is it has magic methods like isAdministrator for is('Administrator') and canViewSomething for can('view.something'). It also a has blade extension for doing things like @role('Administrator') or @permission('view.something') from the template. I'm not even using the permissions and most all of what I need I can get using roles.

For working with individual entities, you can combine a permission with a model method like owns() where there is a relation between the user and the model. You'd use something like $user->canEditCustomer() && $user->owns($customer). For that you can setup a generic method in the user model that just passes an $object and checks to see if $object->user_id == $this->id.

I thought about the ACL and RBAC quite a bit but the more I thought about it the less excited I was about writing it from scratch. The package makes it a lot easier. My next goal is to optimize it a bit by either preloading the entire ACL or using Redis.

Please or to participate in this conversation.