Confusion with the Django permission system - django-permissions

Django comes with a simple permissions system. It provides a way to assign permissions to specific users and groups of users. Like this: 'app_lable.model_name'. It may be convenient for the django admin, but I think it will be use difficult when I use it to control what people can to do with it.
For example, If I want to control whether a certain user can post a comment or see some portion content of my site. I have to config a permission group to him, but why not just add a user property like can_post or can_view_certain_portion? Its seems more intuitive.
So who can help me understand those things? Thanks in advance.

The reason to keep permissions in a separate model is to leverage groups.
So if you needed to change the permissions on many users at once you could simply update the permissions of the group they are assigned to.
Also since users can belong to more than one group you have more flexibility for customizating permissions per user.
Keep in mind vanilla django permissions are model based so if you need to limit changing only certain fields to different users you will need something more robust like django-guardian.

Related

Restful API: Best practice for admin and user scope

I am building an API where users and admins can interact with the same data, but with different needs.
A user can also have access to the admin panel, if he has the "admin" role.
Let's see for example we have a resource like Badges. A Badge is simply a reward when you achieve some actions into the app.
GET http://localhost/api/v1/badges
An authenticated user can call this endpoint and it returns the list of all badges, if they have it or not, with progress details.
GET http://localhost/api/v1/badges?user_id=2
with user_id parameter, we can see these details of another user (if he allows it).
But from the admin scope, I just need to see the list of all badges, without achievement details (CRUD operations).
So I have 2 options in mind:
Create "admin" endpoints: GET http://localhost/api/v1/admin/badges.
Adding custom header "X-App-Scope" to identify if I am in admin or user.
I don't like the second one because I think I will have so many if statements and behavior in the same endpoint, depending of the scope.
Because I have lots of use cases like this, I want to make sure my API architecture is good to handle user/admin needs.
Do you guys have any idea/example to manage stuff like this?
Thanks!
My personal preference is to separate admin API routes from user ones. i.e. having two routes
/api/v1/badges
/api/admin/v1/badges
You will have two unique documentation, one for each route, which makes it easier to maintain and understand
It will be easier to tell the difference between the user and the admin versions
There is no need extra code to check for request headers or url params.
It makes your middleware less complicated, especially if authentication and permissions are handled there.
It is more scalable for teams as there is only one kind of request and response format per API.
TL;DR: REST is designed in the expectation that you would use two different resources here.
The core problem is this: how would a general purpose component, like a browser, know that your special resource needs to have this custom header added?
In particular, consider the case where I send to you a copy of the URL for this resource, and nothing else. How are you to know to add the customer header to the request?
On the other hand, if you use different resources to share this information with each audience, everything just works.
The only way I found to stay as simple/clear as possible is to make multiple endpoints, for each use case:
GET http://localhost/api/v1/badges to get all badges in raw data
GET http://localhost/api/v1/users/badges to get all badges with user stats (progression, achievement...) in a transformed format
GET http://localhost/api/v1/users/{uuid}/badges to get all badges with user stats (progression, achievement...) in a transformed format for the specified user, if his profile is public
Now I have a lot of /users/XYZ endpoints, but my code seems easier to read & maintain, and I don't really need to see the code to guess what data will be returned, the conditions, etc...
I keep wondering how the other APIs are written when you have an admin section, because having /users everywhere isn't really "pretty", and I don't see that anywhere else.

How to make a custom Laravel policy that overwrites another in certain circumstances?

I am trying to create a Laravel policy (I think this might be best way to do it) that overwrites another policy under certain circumstances. I have two models that have a many to many relationship, accounts and programs.
I have a policy that prohibits viewing of accounts for users that do not have the account associated with a program that belongs to them. This works fine, but this also presents a problem. This makes it so a user cannot attach an account to a program, because they cannot see it.
What would be the best way to go about solving this? I was thinking about creating a custom policy, as Laravel docs say you can name a policy whatever you want and have it control any action, but I don't quite understand how that would work. I wrote an attach method on the program and account policy, but that doesn't seem to be working.
In summary, I want to restrict the user from seeing the account view page (if it is not associated with a program that belongs to them), but I want to allow them to attach the account to their program.

How to uniquely identity a pipedrive account?

We are trying to integrate our platform with Pipedrive. As far as we have researched, in a pipedrive account, there is one admin and he can add multiple users. And the users later can login in their respective accounts.
What we are trying to make sure is that once a Pipedrive account is integrated with our platform, the same account should not be integrated twice. So, I need a unique identifier, that lets me know whether the account has already been integrated.
My initial approach was to check the api key. But it was not successful, since every users in an account have different API Keys.
After a bit of research, I found out that there is an identifier called company_id which is common for all the users in an account. But I could not find anything regarding it in documentation. So, I am not 100% confident to go ahead and implement it in our code.
Does anyone have an idea about this?
Pipedrive support rep here.
The most sure-fire way to ensure this is to make a GET request against http://api.pipedrive.com/v1/users?api_token=your_token_here.
You are correct in assuming the company_id in the additional_data object in the response is static and won't change across any users on the account.
Note that a Pipedrive account may have more than one admin, and that non-admins (regular users) might have visibility (and editing) restrictions in place, which may cause some of your GET, PUT and DELETE requests to fail.
In case you're not doing this already, I'd thus advise filtering the data array from the abovementioned endpoint for user.is_you to equal true and check whether the is_admin property is set to 1 during "registration" to ensure the user setting up the integration is an admin.
Hope this helps!
I'm not quite sure what you're asking for. Are you looking for a unique identifier for each user?
Each user has an id, you can get all users by calling
https://api.pipedrive.com/v1/users?api_token=____
This will return a JSON Object with data on your users, including their names and associated IDs. Admins are just users with different privilege levels. All admins are users, but not all users are admins. All users are part of a company, the company is identified by the first part of the Pipedrive account url ie.
https://FooCompany.pipedrive.com
Are you trying to see if a certain company has been integrated already?

Laravel: ACL and Roles for Users. Am I thinking this right?

I am about to define permissions for users in my project. I checked the laracasts videos regarding ACL, Roles and Permissions.
I have a doubt. Do I need Roles for normal users?
I mean, in my project a user should be able to create / update / delete his own posts, he should be able to comment on his own posts and posts by other users and delete his posts and posts left by others on his own posts.
The point is: do I really need to define Roles for this kind of permissions? Shouldn't I just define some policies like can / can't post / update / delete etc. and only define roles for admins?
You don't necessarily need a full featured, powerful Roles/ACL system but if you are storing both admin and basic users in the same table then you do need something to distinguish between them. This could be something as simple as a Role field as a string on your users table e.g. Admin or Basic, or even a boolean is_admin field.
This would give you the ability to implement a Policy or Middleware to prevent basic users accessing the admin panel, and you can have permission checks to ensure a user can't update other users posts etc.
If you don't foresee needing anything more complex in future then this would suffice. However, as your app becomes more mature, you might wish to have a more advanced roles system, for example where a user needs to have multiple roles.
You don't necessarily need to define a role for every user...
It's probably a good idea to, however, you can 'hardcode' and make some assumptions about some of the access...
For example:
If you assume that anyone who is logged in can make a post and can edit their own post, you don't need to make a role for users to say "can_make_post", just have a check saying "if user is logged in, then let them make a post"
then if you say, have an admin area, then you can go "if user a has role
with the 'admin_access' permission, then allow access"
It would be a good idea to have roles for everything, as it allows more customisation, however, your the one designing it, if you don't need the customisation, you can probably just make some assumptions like above.

restrict create/update/delete to requests with a user only

In Parse.com client APIs, it is possible to perform create/update/delete on object of any class. It would be good to set a minimal level of security that restrict these operations only to requests that are made by a Parse.User. This way, someone with access to say your REST or JS key can't just spam create or delete a ton of objects in your database.
I have 2 working solutions but they seem a tad too complicated for something so simple. If you know of a simpler way to accomplish this on Parse.com, please let me know.
Solution 1: Create a RegularUser role and assign all your users that role. Set up class level permission to this role. Undefined users (from requests made without a user) naturally do not have this role, thus access is revoked.
Solution 2: Create beforeSave and beforeDelete cloud code for every class and reject all requests without a user.
I'm pretty new to Parse and I have a feeling that I've missed a simple setting somewhere that lets you lock down your data for logged in users only. Please point that out if that is the case. If you are experienced in Parse.com and in your experience, there is no simpler way, I'd appreciate the confirmation as well. Thanks
I'm answering this a bit late, but I thought I would answer to help out other readers. Like Akshay pointed out, you should definitely set the appropriate Class Level Permissions. But I think what you were getting at can be addressed through ACLs, as suggested by the Parse docs: https://www.parse.com/docs/ios/guide#security-access-control-lists
You can set different types of ACLs for each class, or if you only want to allow users to access their own objects, it's really easy to implement that across all classes:
To make it super easy to create user-private ACLs for every object, we
have a way to set a default ACL that will be used for every new object
you create:
In Swift for iOS:
PFACL.setDefaultACL(PFACL(), withAccessForCurrentUser: true)
I have this set up in my app's AppDelegate, which has the effect that any object the user creates can only be read/updated/deleted by that user.

Resources