Differences between various permission levels in Django - django

As far as I know, there are 3 permission levels available to use in django (whether by django itself or by using 3rd party apps).
1) Model-based permission
2) Object based permission
3) Row-based permission
It would be great if you tell me the exact differences between these 3 levels of permission system.

Not sure where you got that info, but it's not even remotely correct. Django technically doesn't have any permission system. The auth contrib app adds a system of "permissions" but it's optional and could be replaced entirely with something else. The admin app (also a contrib package, and optional) uses auth, so if you're talking about the Django admin, or using the auth package with your own app(s), then we can talk.
In auth, you have Users, Groups and Permissions. Users come in either "superuser" or "regular" user flavors, and every model in your project gets three Permissions automatically when you run syncdb (with auth included in INSTALLED_APPS): can_add, can_change, and can_delete. Users marked as "superusers" (is_superuser == True), can take any action on any model. Other users need to have Permissions explicitly assigned to them. Further, Groups may have Permissions assigned to them, and then, any User assigned to that Group inherits those permissions.
So, a user could have no ability to do anything with any model, some combination of add, change or delete capability with some or all models or complete access to do anything with any model. There's no concept of "object-based" permissions, in the sense of an "instance". You can either either edit every instance of an model or none. There's also no concept of "row-based" permission. A row in the database table is merely an instance of the model, anyways.

Related

How to prevent staff users from editing/deleting superuser in django

I want to be able to allow certain staff users the rights to add other users and staff but what seems weird to me is that 1) a staff member can just change their own privileges to superuser or just make a new user and grant superuser privileges to them. 2) delete a superuser or revoke their superuser status
Some staff users should be able to modify/create/delete users but they should not be able to delete super users nor assign permissions to themselves or other users that they do not have the permission themselves.
This has always been logic I have incorporated into my user systems that I've written in PHP and I was just wondering if there was a way to change these settings in Django as I really like Python/Django (I'm just beginning to learn it) and can see myself migrating away from PHP. But part of the beauty for me lied in the admin panel and if that is something that cannot be changed, that's kind of cringe-worthy.
It reminds me of a restaurant POS system that I used to use when I was a GM. As the GM, I had powers that shift managers did not have. However, the shift managers could add a fingerprint to my profile (theirs) and then just log in as me and do anything they wanted to. I always felt this was a severe security breach and even took disciplinary action on an employee for doing this. It also allowed the shift managers to create new employees with titles that were above theirs which created the same problem as they could just create a new GM or Area Manager, login, do whatever they wanted, and see all kinds of things that they shouldn't (like their colleagues' salaries), and then hide (not delete) the user. (this is how he got caught)
If anyone has a fix or any ideas and suggestions, I'd love to hear them and keep learning this exciting new language. Thanks in advance!
Django admin is a basic CRUD system, it is not recommended to use in that way. Django views (your custom views) give you more power to control the process.
First of all, Django Permissions might be a good start point. Create Groups for user types and assign desired permissions for each group. Do not give permission for non-superusers to change group or permissions.
Second thing is using Django Signals to check data before saving it. For example, a pre_save signal for User creation can be used to check if is_superuser, is_staff values of the user are set by non-superuser. You can add added_by value to the user model and verify your checks using this value.
Also, using custom forms for Django admin is also possible and might be the simplest solution for it. Just make a custom form for creating and editing users and verify changes in the form directly before allowing the view to save anything. It is also possible to inform user that they don't have access for changes they made and also notify the management about the attempt.

Django Admin: Restrict certain staff users to database records in their own group

I want to build the admin site in a way such that, users in a certain group will be able to perform CRUD operations - to records related to their group only.
Is there a way this can be accomplished?
You can easily use the Django Permissions and Group to create this. As the documentation states:
When django.contrib.auth is listed in your INSTALLED_APPS setting, it will ensure that four default permissions – add, change, delete, and view – are created for each Django model defined in one of your installed applications. Read here
You can then easily create Groups with certain permissions such as assigning only read permission to certain group and R/W to another in the Django Admin. If you need more finer record level access certain third party apps will help you such as Django Guardian or Django role permissions

Rolling out own permission app or modifying django permission

I am working on a project which needs a separate admin interface. The django admin interface is for the super super user, there will be companies who will sign up for our app and then they will have their own admin interface. Everything is set and done despite the permission. We want model level permission that's what Django provides.
What I did is:
class CompanyGroup(models.Model):
name = models.CharField(max_length=254)
permissions = models.ManyToManyField(Permissions)
Now this list all the permissions of the site itself. So, Should I start working on my own permission app or I can modify django Permissions to provide object level permissions for only some models.
Thanks
Try one of the several existing 'row level' / 'per object' permissions apps for Django:
http://django-guardian.readthedocs.org/en/v1.2/
http://django-object-permissions.readthedocs.org/en/latest/
...there are probably others, those are just the first two in Google
We are using django-guardian in current project at work, seems fine.
I am assuming that you need to control access to sub-sets of each model's objects, depending on which company the current user belongs to (i.e. you don't want people from Company A to see items from Company B). For this reason you need row level permissions.
You probably also need to limit the permissions of all 'company users' to only certain actions:
You do not need to create a CompanyGroup class.
Instead just enable the admin site, log in as super user and create a django.contrib.auth.models.Group which contains the global permissions applicable to company users.
then ensure when you create any new company user logins that they are added to that Group

The use of various `auth` models

Other than auth_user, I have never used auth_group, auth_group_permissions, auth_permission, auth_user_user_permissions, and auth_user_user_permissions. What are the specific uses for each of these models? Is it common that one would not need any of these? If so, what would be the best way to get rid of them (doing a straight DROP TABLE or at the django-level)? Would there ever be a downside of removing these?
I'd recommend reading the User authentication section in the Django documentation. It describes the components of the auth system as:
Users
Permissions: Binary (yes/no) flags designating whether a user may perform a certain task.
Groups: A generic way of applying labels and permissions to more than one user.
The simplest use of permissions is to control the actions a certain user can take in the Django Admin site. You can also use permissions to restrict access to your own views using the django.contrib.auth.decorators.permission_required decorator.
When this is combined with groups you can easily assign the same permissions to a whole group of users.
The other database tables you mention (auth_group_permissions, etc.) store the relationships between users and permissions or groups and permissions.
While you may not be using these parts of the authentication system directly you are almost certainly using other code from django.contrib.auth that relies on them. If you're using an app you didn't write (whether it's part of Django or not) then it's probably a bad idea to drop the database tables that app creates.

I'm having difficulty working out how to do permissions for my Django models? (not admin)

I have a range of models for my Django project. Everyone with a login has a Profile. A Profile will have certain permission access to the different parts of the website... Be able to view or edit certain accounts in the Account model. Be able to view or edit certain accounts in the Module model. Be able to delete or be blocked from accessing other Profiles. etc. People with Profiles do not access the normal Django built-in admin, it's all a custom website-side area where all of this stuff will take place.
Django's built in permissions stuff didn't seem to cover this sort of module/row level permissions. I was thinking of having a simple Permissions model with Profile and Permission Type foreign keys in them. Then all the things I want to be accessable only by Profiles with permissions will have a many to many to this Permissions model. But I'm not sure that's how to go about it?
What is an ideal way of doing permissions for the profiles to restrict access to rows of other models?
Check out Florian Apolloner's Django Advent post on Object Permissions. I found it to be a decent way of doing object-level permissions.