How to make Django REST User API with complex permissions - django

I want to make a Django REST User API with complex permissions as follows:
GET
Only Admin should be able to get all User data
Logged in User should be to get himself and the names of other Users
PUT
Only Admin and Self should be able to PUT
Except for is_staff and is_superuser only is_superuser should be able to change the status of a user
Password changes by a User should require the old password
if User is !is_staff password reset should be possible
POST / DELETE
Only Admin should be able POST/DELETE User
User should be able to update his own Profile
Unfortunately, I have no idea how to control the view or serializer to allow such permissions. Is there a template how I can exactly control the permissions?

You can write your custom permission according to DRF docs.
And add YourCustomPermission in your view:
class ExampleView(APIView):
permission_classes = (YourCustomPermission,)

Related

User registration with admin authorization

I was wonder if it is possible to include a way that when someone fill the user registration form to register, can the details be sent to an admin email for authorization before the user can login in django?
Since you did not provide any code I will guide you the process, you can later come back more specific question if you are stuck :
Use the field is_active provided by Django from the User model to authorised access within your website.
Extends the field is_active to set the default to False or set it to false in the begging of your user view
Create a link with the ID of the user and a path to the Django Admin where you can update the user and active to True
In short yes, possible and pretty easy if you know a bit of Django.

How to check if a user is logged in, in django token authentication?

Hi there I am currently starting a new rest api project with django. Normally when I start a new project I do a lot of planning and get a idea of how I want to build my app. For this app I want to use token authentication but can't find enough resources for this topic.
Can anyone tell me these two things, how to check if a user is logged in/authenticated and how to check which user is logged in(of course with token authentication in django). Thank you in advance.
Extra info(you don't need to read this):
The reason I want to use this kind of authentication is because I don't want to use the built in django models for my user model because my User model has to have some specific fields for this web app, obviously I can work my way around this but its not very efficient so I figured I'd use token authentication.
If you will use rest_framework.authtoken https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication you can set in each view to check whether the user is authenticated for admission or not. For example:
class UserList(generics.ListAPIView):
"""List all users"""
permission_classes = [IsAuthenticated] # allowed only by authenticated
serializer_class = UserCreateSerializer
queryset = CustomUser.objects.all()
To check which user is logged in, rest_framework.authtoken creates a table in the database that contains the token, the user and the time the token was created

Custom model for authentication in django restframework instead of default user model

I want to do some custom auth for my users with username or email with password. At the first time of logging with email and password the api should return me the respective user token. For all other operations with the api I need to make use of token, which I get at time of login.
And I need a custom model to store all user info like username, password, phone, email, token etc.
How to achieve this in django restframework.
Please guide me to achieve this. Thanks in advance.
Django rest-framework has a built in token system which can be used to distribute and authenticate tokens. Below is a sample of how to use it.
Create TOKEN
from rest_framework.authtoken.models import Token
user = User.objects.get(pk=some_pk)
token = Token.objects.create(user=user)
Authenticate token
if Token.ojects.get(key=token) # token is sent by client side
# do some task as auth is successful
If you want to extend the default User model then create a new model and put a onetoone field in your custom model which references default User model.
class AppUserProfile(models.Model):
user = models.OneToOneField(User)
... # add other custom fields like address or phone

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):

Change username for authenticated user in django User model

After authentification with social auth plugin, plugin create new user with not beauty usernames like sergey.kostin.345, I know that some users has a nice shorturls on the social media platforms and its ok for default behavior but I want to give user ability to change user names. As far as I understand django auth system does not let me to change User.username field by using methods. I also tried to change this field by using this code, but it seems to be ignoring in django.
owner = User.objects.get (id=request.user.id)
owner.username = newusername
owner.save()
owner is authenticated user
That would work, but there's no need to get the user again. request.user is already the user object.
owner = request.user
owner.username = newusername
owner.save()