Symfony3 Entity Field Level Permissions - php

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.

Related

model permissions - laravel fillable

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.

Validate username in Symfony2 form

I have a form in Symfony2 where an Admin have to write the username of another user.
Is it possible to check before to send the form, if the username exist in my database? I use doctrine.
Thanks!
You could write a custom constraint, which is injected with your Entity Manager and checks if the username exists. See the documentation for creating a custom constraint here.
Another option would be to write a data transformer which converts a username string into a User object, which should ensure that user existed throwing a TransformationFailedException if she doesn't. This might be a bit easier because the example in the docs already creates the transformer as a service and shows you how to inject the entity manager.
Also, depending on how many users you have in your app, you could make the username option an entity choice type, and allow symfony to create a drop down with all of your users already in there.
EDIT:
Sorry, I missed the part about checking before you submit the form. The ideas above are still how you could implement on the server, but for the first two options you would need to use an Ajax request to test if the username was valid.

Where do you put common data setters in DDD for update/insert?

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.

User permission and software security

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...

Drupal Register user upon node create

How can I add user register form to node create form in Drupal? There is a module http://drupal.org/project/inline_registration , but it has some bugs. I think I saw alternative one, but I cant find it now.
Beware the many security problems possible when giving essentially anonymous users access to node creation. That said, here are some thoughts.
If you can live without having the form registration on the same page, a much easier solution would be to redirect the user to the node create form after successful login. This amounts to perhaps just one line of code (more if you only want to redirect on certain conditions - e.g. the user registers for a certain type of account). That way you can use the built-in validation and submit handlers of the user module.
If you must have both on the same page, you could use hook_form_FORM_ID_alter, and output the user registration form fields if $form['#node']->nid isn't set. Be sure to validate the input as well.

Categories