Django - Granting custom permissions to a user - django

I have a user profile model with a custom permission defined as follows:
class Profile(models.Model):
# A few profile fields here...
class Meta:
permissions = (
('can_approve', _(u'Can review and approve new accounts')),
)
When I actually look at Profile objects in the Django admin site though, I don't see any way to actually grant this permission to users.
What's the easiest way to do this? (e.g. give user Joe the 'can_approve' permission?)

Adding a permission to Meta is not enough to see it in the admin panel. Permissions defined in Meta are only used to create a Permission in auth_permission table when you run manage.py syncdb.
Try running syncdb, or add the permission manually to database or create the permission from code. After it is added to db it will be visible in admin panel.
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get(app_label='myapp', model='Profile')
permission = Permission.objects.create(codename='can_approve',
name=_(u'Can review and approve new accounts'),
content_type=content_type)

Related

Rename django custom permissions

I'm working with django 2.0 app and going to update django version to 3.0.
But in my project there are few custom permissions named like view_modelname.
class MyConcreteModel(models.Model):
model_field_1 = models.CharField(max_length=100, blank=False)
# other fields
class Meta:
permissions = (
("view_myconcretemodel", "Can see available device interfaces"),
)
In django 3 (since v 2.1) such kind of permissions are default. So I got conflict with permission names.
Now I'm trying to rename custom permissions before updating django version.
class MyConcreteModel(models.Model):
model_field_1 = models.CharField(max_length=100, blank=False)
# other fields
class Meta:
permissions = (
("user_view_myconcretemodel", "User can see available device interfaces"),
)
After migration 'new' (with new names) permissions were created in DB. But old permissions still there and all users have old permissions (with old names like view_myconcretemodel). Obviously I need 'new' permissions for all users.
Is there possibility simple to rename permissions or give 'new' permissions to relevant users (according to 'old' permissions), and do it automatically?
After reading how to Programmatically creating permissions https://docs.djangoproject.com/en/3.2/topics/auth/default/#programmatically-creating-permissions
My solution is to modify codename in Permission model. i.e.
from django.contrib.auth.models import Permission
perm = Permission.objects.get(codename="view_myconcretemodel") #old name
perm.codename = "user_view_myconcretemodel" #new name
perm.save()

How to get user permissions for non supervisor user by using request user attribute

I developed an django app which register user and give resources based on resource level permissionIn this I am using django basic level permissions on my model and templates, there for view permission I set permission tuple in my model like:
class Model(AbstractUser):
group = models.ForeignKey(AppGroup)
class Meta:
permissions = ( ('view_app', 'user can view app'), )
and I migrate my model after create my model like above.
Now for permissions, I created a group from admin and including all app view/change/delete permissions, using that group I generated a drop down in form class. Now user(admin) can create other users based on selected permissions and after register successfully the new user able to login successfully and access all resources but when I am trying to access user permissions which is a many-to-many relationship using like
class UserListView(ListView):
def get_queryset(self):
print(self.request.user.user_permissions.all())
return super(UserListView, self).get_queryset()
When I list my view, it gives me a relation error (500 error):
relation views_list_user_permission does not exist
Now when I access the same view by superuser it gives me all permissions, but from a user which is neither superuser nor staff it spit out the above error. By reviewing djancgo.contrib.auth.models PermissionMixin class code it seems like to me the user_permissions m2m field can only access by superuser but I doubt it. So this is what I am doing and got the issue, please correct me if I take this in wrong way
The superuser has all the set of permissions granted. Therefore you are able to see all the permissions. But when a new user is created he will not have any of the permissions set therefore there is no relation between the user and permissions so you are getting the above error.
Note:-
You can check for the available permissions for the logged in user inside template by using
{{ perms }}
For a specific app:-
{{ perms.app_name }}
For a specific model:-
{{ perms.app_name.model_name }}
Suppose you want to grant access to a user with specific permission to a particular model for a view you can use the permission required decorator like this:-
from django.contrib.auth.decorators import permission_required
#permission_required('polls.can_vote')
def my_view(request):
...
Now here the user with the permission can_vote on "polls" will be allowed the access grant.
For further detailed use you can refer:-
Django documentation on permissions.
The authentication back-end is responsible for user permissions. I guess you are using your own custom authentication back-end. However if you are doing so you may have forgot to import ModelBackend.
from django.contrib.auth.backends import ModelBackend
Now make sure to extend this back-end into your own custom back-end
class EmailBackend(ModelBackend):

Django restrict views by User permissions which are editable in the Admin

I have a Django application where I need to restrict specific Views to subset of Users. I also want to be bale to edit which Users have this permission via the Django Admin. So in the admin I would like to be able to see all users and have a check box which can be checked to give permission to see this specific Views.
I believe the way to approach to this is to a permissions decorator on the Views in question:
from django.contrib.auth.decorators import permission_required
#login_required
#permission_required('user.can_view_restricted', login_url='/accounts/login/')
def Restrictedview(request, template_name='restricted.html'):
...
# restricted stuff
Now I know I need to define this permission (in permissions.py?), and register it with the Admin. I am unsure of how to do this and how to properly associate the permission with a specific User instance. Should this be an extra field on 'User', or a separate model to hold model to hole Users and Permissions?
You can read in details about django permissions in the docs
https://docs.djangoproject.com/en/dev/topics/auth/default/#permissions-and-authorization
Basically Django permissions use the Permission model, which is found at django.contrib.auth.models, but for most applications you don't need to directly import or use that model.
By default Django creates 3 default permissions for any model you have in your app. If you have a model named MyModel in an app named myapp, then Django will create create_mymodel, change_mymodel, and delete_mymodel permissions by default.
You can check if the user has a certain permission by calling
user.has_perm('myapp.create_mymodel')
if you're checking for the create permission for example. Or, like you did, you can use the decorator
permission_required('myapp.create_mymodel')
In addition to the default permissions provided by django, you can define custom permissions on your models by specifying the permissions attribute in the Meta class of your model like this:
class MyModel(models.Model):
[...]
class Meta:
permissions = (
("can_deliver_pizzas", "Can deliver pizzas"),
)
More on defining custom permissions here: https://docs.djangoproject.com/en/dev/ref/models/options/#permissions
By default, permissions can be easily edited for every user using the admin interface. Just visit a certain user's page and there will be a field named User Permissions with a list of all permissions in your project, from which you can add or remove permissions for your particular user.

Creating and setting permissions in Django

Let's say I have an app called Blog which contains Posts. I want a user to be able to add and change posts, but not delete them.
The Django docs have this example
from myapp.models import BlogPost
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(codename='can_publish',
name='Can Publish Posts',
content_type=content_type)
I don't see how it's actually defining anything here, it just gives it a name and content type.
Django also has basic permission checking
Assuming you have an application with an app_label foo and a model named Bar, to test for basic permissions you should use:
add: user.has_perm('foo.add_bar')
change: user.has_perm('foo.change_bar')
delete: user.has_perm('foo.delete_bar')
In my app they would become:
add: user.has_perm('blog.add_post')
change: user.has_perm('blog.change_post')
delete: user.has_perm('blog.delete_post')
How do I create and add such permissions to a user (in code, not the admin)?
Defining custom permissions in code can be done via a model's meta (see duplicate):
class BlogPost(models.Model):
class Meta:
permissions = (('can_publish', 'Can Publish Posts'),)
Per user permissions should not be added in code for the most part, but may however be added as part of a migration if using south or the built-in django migrations if your version is high enough.
python manage.py schemamigration $appname $migration_description --empty
class Migration(SchemaMigration):
def forwards(self, orm):
daemon = orm.User.objects.get(username='daemon')
daemon.user_permissions.add($permission)
daemon.save()
def backwards(self, orm):
daemon = orm.User.objects.get(username='daemon')
daemon.user_permissions.remove($permission)
daemon.save()

Extending Django User for Permission

I just want List user to be under permission , so i just made one custom model like below
from django.db import models
from django.contrib.auth.models import Permission,User
class Mycustomuser(User):
class Meta:
permissions = (
('users','users'),
('view_user', 'View user'),
)
In views i simply called
items=Mycustomuser.objects.all()
It is returning user id with 4 only.
I did so because i made following permission using django guardian
task = MyCustomuser.objects.create()
joe = User.objects.get(username__exact='admin')
assign('view_category', joe, task)
Now i want to check that permission whenever MyCustomuser is called.
It is not necessary and also not recommended to extend User model. See Storing additional information about users.
That said, you can create Permissions without setting permissions model Meta attribute, see Programmatically creating permissions.