Django: What is a permission codename? - python

I'm trying to set up a permissions decorator in my Django app. The docs mention it and nowhere could I find explained what this codename represents (a model field? a model method? a permissions method?).
What is the codename and where can I setup codenames?
https://docs.djangoproject.com/en/1.9/topics/auth/default/#the-permission-required-decorator

You can add custom permissions to any model under Meta class. Those permission name are called codename. It goes like this:
class Dish(models.Model):
name = models.CharField()
class Meta:
permissions = (
('can_approve_dish', "Can approve Dish publication"),
('can_delete_dish', "Can Delete Dish")
)
Here, can_approve_dish is a codename. Now, to perform any operation on Dish, you can check for permission like this:
# Assuming Dish model is under app named - `'app'`
if user.has_perm('app.can_delete_dish'):
dish.delete()
These permissions would be available on admin site to be assigned to users after migration. So, if you haven't assigned a can_delete_dish permission to a user, he won't be able to delete that dish.
If you've added different permissions on multiple models under the app named - app, all those permissions will come under name app. That means, you've to have unique codename across models in the same app.

Related

Custom django permissions for group chats?

I have a custom group model like this:
class MyGroup(models.Model):
name = models.CharField(max_length=200,null=True,blank=False,default="Group name")
members = models.ManyToManyField(get_user_model(), blank=True, related_name="grpmembers")
created_by = models.ForeignKey(get_user_model(), on_delete=models.DO_NOTHING, null=True, blank=False, related_name="createdby+")
created_at = models.DateTimeField(editable=False)
It works, it's fine, I override the save method in django admin so the created_by will point to the logged in user on save.
Problem #1
Even if you are the creator of the group, you can select yourself to either be in- or be removed from the group which kinda looks silly. I'm thinking of solving this by saying the user can view the group if they're in members or created_by.
Problem #2
Custom permission. I want to have some permissions, like:
Can view the group: which means the user is either the creator or is in the members list
Can edit the group: which means the user is the creator(can edit their own) or is staff(can edit anyone's stuff) or is superuser(root)
I can write it down and imagine how it would work, but I have no idea how to implement these.
I've found some ways, like creating a Meta and defining permissions there and also making the permissions as def(/functions), but how could I access the currently logged in user?
Like okay let's say I do
def can_view_group(self):
r1 = self.filter(members=req.user) # where req.uset is not accessible bc we're in models.py
, but how do I tell the permission to check the currently logged in user?
The problem is doing all the logic in models.
Over problem 1 you need to verify user is not owner before allow to leave in the views.py.
Over the problem 2 are 2 solutions, or you move can_view_group to views.py, or you define that in models as:
def can_view_group(self, user):
#all the logic
And you pass the user from views.py

Django permissions via related objects permissions

I am relatively new to Django and I'm looking for some guidance in how to setup permissions in a certain way. Basically I have an app that consists of a couple of models similar to this:
class Project(models.Model):
name = models.CharField(max_length=100)
users = models.ManyToManyField(CustomUser, related_name="projects")
class Task(models.Model):
name = models.CharField(max_length=100)
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="tasks")
class Asset(models.Model):
name = models.CharField(max_length=100)
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="assets")
My idea is that if a user is "assigned" to a project (via M2M field), that user will have access to all assets and tasks that are related to that Project. I have looked into django-guardian for per-object permissions and I think that could be the way to go, but to me it seems like I then would have to setup those permissions on each model..?
It feels like this should be a pretty common way of setting up permissions for any project-based app but I have a hard time finding similar examples and starting to wonder if I'm overthinking this or looking in the wrong direction?
Thank you,
Jonas
You can use django-rules to take advantage of object-level permissions without a database; with it, you can add permissions in many levels - models, views, templates, admin or DRF.
So, you'd need to create a predicate like
#rules.predicate
def is_project_manager(user, project):
return project.users == user
which will return True if the project's manager is the given user, False otherwise.
Then, to add it in a model, you'd do something like
import rules
from rules.contrib.models import RulesModel
class Project(RulesModel):
class Meta:
rules_permissions = {
"add": rules.is_project_manager,
"read": rules.is_authenticated,
}
There's ofc other considerations to attend to but I think that gives an overview of how it works.

How to check the permissions as per authenticated user using Django and Python

I need to check the permission required as per authenticate user Using Django and Python. I am providing my code below.
class Permission(models.Model):
"""docstring for Permission"""
user_id = models.ForeignKey(User)
class Meta:
permissions = (
("view_reactor", "1"),
("find_reactor", "1"),
("controll_reactor", "0"),
)
Views.py:
from django.contrib.auth.decorators import permission_required
def view_reactor(request):
""" This function for to get serch screen. """
return render(request, 'plant/view_reactor.html',
{'count': 1})
Here I need to check #permission_required decorator function as per proper userid. Suppose the logged in user has permission ("view_reactor", "1"), then that view_reactor function can access if ("view_reactor", "0") then it can not be accessed.
you add extra permissions to your model, where first value is a name of permission and second is a human readable name, (details here meta permissions) so if i understand you need added it to your Reactor model for example:
class Reactor(models.Model):
# ^^^^^^
# ....
user_id = models.ForeignKey(User)
class Meta:
permissions = (
("view_reactor", "can view reactor"),
("find_reactor", "can find reactor"),
("controll_reactor", "can controll reactor"),
)
and the you can use in views
from django.contrib.auth.decorators import permission_required
#permission_required('reactor.view_reactor')
def view_reactor(request):
sorry if i misunderstood
Why don't you use User, Permission, Group Class which Django have as default?
models.py in exampleApp
class ExampleModel(models.Model):
somefield = models.CharField(max_length=4)
if you do 'makemigration' and 'migrate', It create 'add_examplemodel', 'change_examplemodel', 'delete_examplemodel' automatically. You can check auto_permission table in DB.
models.py in exampleApp
class ExampleModel2(models.Model):
somefield = models.CharField(max_length=4)
class Meta:
permissions = ( (permission_code, human_readable_permission_name), )
if you do 'makemigrations' and 'migrate' with that model, it doesn't create three default permissions but just one you named in Meta class. (It works when you create model, not when you edit)
You can just add permissions in Admin page.
It's just adding permission name in Permission class. You need to set permission for User.
you can give permission in User like this.
user = User.objects.get(id=someidnumber)
# User and Permissions Class have manytomany relationship.
user.permissions_set.add(permission, ... )
# you can set user 1 have one permission like view_reactor.
# you can set user 2 have two permission like view_reactor, find_reactor.
# you can give permissions to each user independently.
Then, you can use #permission_required decorator
if you want to user 1 have view_reactor permission. Just give permission user 1 by User.objects.get(id=user1_id).permissions_set.add(view_reactor permission). Then #permission_required decorator will check.
Please read manual below.
Adding Permission in Manual
permission_required decorator in manual

User with permission to modify only one field of the model in the Django Admin

I have a user named ExpertUser who should only be able to modify an attribute of the called model (money) of the users in the Django Admin.
I have tried adding permissions in the model using the Meta but when entering with that permission I can not modify anything since I do not have access to any user.
My model is this:
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
money = models.FloatField(default=1000)
def __str__(self):
return self.user.username
class Meta:
permissions = (("can_view_money", "Can view money"),)
Have a look at Django Guardian. That provides more flexibility in assigning permissions on various levels. Django only lets you set permissions at object level, so in your case you were only able to set permission to create/edit/delete Client objects.
http://django-guardian.readthedocs.io/en/v1.4.8/index.html
If that doesn't suffice, there are a few other packages with the desired functionality:
https://djangopackages.org/grids/g/perms/

Django membership/dashboard plugin

I want to create a membership website where users can log in to a control panel separated from the admin panel.
Inside the control panel users can edit their settings, view statistics and use paid services.
What are the plugins I need to build this kind of websites?
How I can improve the security and automate the workflow ?
Start with the basic User module that comes with Django. When adding more settings to a user, you must create another model UserProfile that is linked to the base User model.
class UserProfile(models.Model):
user = models.OneToOneField(User) # The base User model takes username, password and email
# For the "paid services" you could use a boolean field and evaluate in your template
premium = models.BooleanField()
# Alternatively, a field that links to the services, which you'll have to include in your models.py
account_type = models.ManyToManyField(Service)
Make sure you have 'django.contrib.auth' and 'registration' in your INSTALLED_APPS in your project's settings.py, and work using those apps if they suit you.
For security, check https://docs.djangoproject.com/en/1.10/topics/security/

Categories