I have an app that has a user type that should have a severely locked down user experience, meaning that they should only be able to update certain attributes of a model, not delete things etc. What approach could I use to make it so users making requests can only do what is set out in the user type rules, so for example I have a project model and the model has attributes,
Name
Price
Start Date
End Date
A limited user should not be able edit the price, start date, end date. Is there a way to use the fillable attribute and reset it based on the on the lever of the user that is making the request?
You can create a repository and handle the execution of that code in there removing fields if the user is "limited". Or you can create a function in your model and call it which would check the permissions of the logged in user.
There is no "default" way to have the fillable fields transpose to what a user role is allowed too. You will need to code that yourself.
Related
I'm working on building an API backend with Symfony3 and have a question about how to apply field level permissions to the PUT endpoint for updating an object (User in this example).
My User entity has multiple fields, firstName, lastName, username, etc.
If a PUT request is sent to the /users/{userId} endpoint, I deserialize the request JSON into an array, pass the array (and the User fetched from the database) into a normalizer which applies the request data to the User properties.
I would like an ADMIN to be able to update all fields, but the user themselves to only be able to update their first and last names.
So somewhere in my code I need to check before I apply the updates to the User object, e.g. if the username field is present in the PUT request, I need to check if the requesting user is an admin before applying that update to the user object.
Injecting security into the normalizer seems like an obvious solution, but feels like security should not be a concern of the normalizer.
I could check the permissions after deserializing the request, and before passing to the normalizer, and then just remove fields from the array if the user does not have access, e.g. if not admin remove [username] from array.
Looking for thoughts/suggestions on the right way to accomplish this....
Thanks!
Wanted to post some feedback I got in #symfony IRC:
I would not have the normalizer write into the user. I'd have the
normalizer generate a DTO, which you would then validate given the
permissions of the target user and user taking the action.
If that validator fails, throw the whole thing out and return a
permission denied error, otherwise apply the DTO to the user and
persist it.
the "validator" could be a form (build a form with acceptable to
modify fields given active and target user; form is not valid if there
are extra fields submitted). Or it could be a security voter, or your
own custom mechanism.
We are developing an application in Laravel 5 where users can login and based on the licenses assigned to the user, multiple "content types" are available within the app. The business logic and presentation logic differs based on the selected content type. The user can select the content type to work with, or, if only one license is available, will be directed to the homepage of that content type.
Now I am trying to figure out how to handle the selected content type. Storing this in a session is imo not the way to go because a user must be able to use multiple content types in one browser session simultaneously.
I figured I need to start with grouping all relevant routes and prefixes them with {contentType}. Also, add a Middleware (named something like SelectContentTypeMiddleware) and let that middleware check if the content type exists, and if the logged in user is allowed to have access to it.
Furthermore, every descending route (in the {contentType} prefix route group) also must handle the route parameter $contentType.
I am trying to figure out of this is the right approach. I was looking at this blogpost which addresses the case for setting the app locale. Using app()->setLocale($locale) the locale for that request is set. I was wondering if a similar approach for my case makes sense, or that including the route parameter $contentType in every route is more advisable.
I have a question regarding Domain Driven Design. Let's imagine a simple scenario.
I have an Entity called "User" that has some properties. One of these properties is "date_created", "date_modified" and "last_login_ip".
Let's say we have a form that creates a user and if the create is successful, it authenticates him.
The controller gets the POST data
Sends the post data to a UsersService via the method "createAndAuthenticateUser"
The service receives the data, validates it (doing it here and NOT in the entity because the validation is tied to repositories, such as to validate if the email already exists, etc).
If the validation is OK, it creates a new Entity, assigns the data to it and then sends the entity to the repository to save it. The repository then saves this user in a datasource.
So far so good. The problem here is that, the date_created/date_modified/last_login_ip have to be set in this service method.
What if I want to set the date_modified ANYTIME when the user object is updated (for instance,at login I want to update the date_modified, at user update i want it again, at user creation I want it again.
Logically, my own answer would be to put this in the repository like...
(meta code here sort of, the syntax doesn't matter)
function save($User) {
if (!$User->id) $User->date_created = 'YYYY-MM-DD HH:II:SS';
$User->date_modified = 'YYYY-MM-DD HH:II:SS';
$DataSource->Save($User);
return $User;
}
However, from what I've been reading, the repository should always just map data between the caller and the datasource (and the reverse) and that's it. It should never SET data or anything like that.
Of course, you could tell me this is a behavior, so I could have a behavior that says $User->markAsUpdated() which would just set the date_modified property. But again, this means that this method must be called from more than one place, instead of having a centralized place to do it. I don't see the benefit of NOT having this code in the repository.
Any ideas?
If the concept of last login ip is actually central to your user for some reason, then it's valid to update the user on login. The fact that you're expressing concern about performing that update to save the last login IP implies that it's not really a user concept, but a security, audit, or otherwise-external-to-user concept.
As for setting the modify and create dates, I'd make the same argument. If it's a requirement of the system that the user both maintain and expose that information, then create a private method on the user that each public method calls when it modifies the state, which will set the modify date. If it's not, then you pretty much have two options - either create an auditing service that is notified of the update and keeps its own audit record, or have the repository set the fields when it updates the record.
I am developing an application in php codeigniter. Now I am worrried abt the permission.
I need page wise permission, page may be add records page, edit page, delete page and print report etc. There will be many users as well, and applicaiton will grow with passage of time.
If I implement ACL that will better for me or not
what can be ideal for me any suggestion.
First, let's clear up some terms: I personally use the security term for things like preventing SQL injection, XSS attacks, where we have to validate input, filter/sanitize values, take care of the dynamically generated SQL commands, take care of properly escaping output (for JSON or HTML text or HTML attributes), etc. This is not about what you are asking, if I understood well.
The access control or permissions system is where you give or deny access to a function for a user. It can be secure or not. I understand that to deny a user which does not have permission the access to a function may sound like "security", but I wouldn't use this specific word in this context, to avoid confusion.
Now, the answer:
I strongly recommend you create a few base controller classes to your needs. Read the following blog post carefully (it is short and useful): http://philsturgeon.co.uk/blog/2010/02/CodeIgniter-base-Classes-Keeping-it-DRY
A code to check if the user is properly authenticated (logged in) is essential. If the user is not logged in, redirect to home page or login page.
For fine-grained control, you could create your ACL in the database using the users table, plus an actions table, plus an acl table...
The users table would contain the users data (id, name, login, password, etc)
The actions table would contain the id field and at least one more field containing what suits best for your application: it can be only the controller class name (the first part of the URL, for example: "products"), granting access to the whole "products" controller or not. Or you may want to include both the controller class AND the method name (the first and second parts of the URL, for example: "products/add" and "products/delete"), and so on.
To decide about the actions table is the most decisive step. Think very well about it, balance your needs (your "true" needs)... I developed a system where each and every action has its entry. It is good, but it needs work to be maintained.
A very useful column for the actions table is a human-readable description of the action.
The acl then would be nothing more than a column for the user id and another column for the action id.
A "master" grant/deny access field in the users table is useful too, in case you want to temporarily deny access from a specific user, without having to delete all his permissions and maybe having to restore it later.
With the database tables and your "controller/method" or "actions" strategy well defined, you can easily code in your base controller class a function which checks if the user have permission to execute the requested action.
This is the basic. In my system, I have the users administration interface, where I can grant/deny the actions for each user (I use an ExtJS tree with checkboxes). One of these actions is the own user management. I have gone one step further, where the user who can access the user management may "delegate" (grant/deny) to other users only the actions he himself has access to.
The system has several modules, and functions. The interface does not show anything the user does not have access. So, I have users who can see only a single or a couple of modules, and they don't even imagine the existence of the other modules.
It requires more work to manage all this, but the result worths.
I also log each granted access, so it is possible to track who did what, and when. This log feature is very very easy to add, since you have this base controller "master function" allowing or disallowing the users to perform the actions.
I hope I have helped. I've just shared a bit of what worked (and works) for me...
This is a follow-up to a previous question: Should sub-objects be fetched in the Model or the Model Mapper?
Let's say a User can have one or more PhoneNumber objects. According to the answer in the above question, these sub-objects will be fetched upon instantiation of the User. If I were to delete a PhoneNumber from the User's phoneNumbers property (an array of PhoneNumbers), or modify one of the PhoneNumber objects, where should this change be propagated?
Should I manually delete/update the sub-objects in the database, or should the User do that automatically on save? Thank you,
Let's see If I got it the right way.
The user is logged and it's on his profile page. On this page the user clicks a link "delete this phone number".
On the page where the action is performed it will executed DELETE FROM phones ETC.
Now after this is performed when you will load the User, the constructor will load the phonenumber etc and considering you performed the DELETE sql early the current user object will not have, of course, the just deleted phonenumber.
This is at least what happens in my MVC framework.