object-level permissions django - django

How do you ensure that a User can only edit objects they've created? What's the best way to set this up?
I'm using django-rest-framework and wondering if there's a way I can restrict users from viewing/ editing objects they don't 'own'.
class Video(models.Model):
owner = models.ForeignKey(User)
...
So User 'x' should only be able to edit videos in their owner_set.

Presumably you have sessions and the auth model turned on.
You must be sure that all views (REST and non-REST) require authentication.
For non-REST, it's easy. You simply use a basic #login-required decorator everywhere.
For the Django-REST Framework, read this: http://django-rest-framework.org/library/authentication.html#module-authentication.
You have to use the authentication mixin to be sure that authentication actually happened.
The framework supports BASIC Authentication, which requires an SSL connection to be secure. It's not too difficult to implement DIGEST authentication, which doesn't require SSL.
Avoid sessions. It violates a principle of REST to login and logout. The framework supports sessions, but it's less than ideal.
Once you have all requests authenticated, you'll know the user.
If you know the user, then user.video_set works perfectly. You can also use Video.objects.filter(...) to be sure that you're querying the user, but it's easier to confirm the code is correct if you work with user.video_set.get(...) or user.video_set.filter() or whatever.
All the relevant authorization checking is done in Views. You're providing Views for your ModelResources.
These are "class-based views". Documentation is here: https://docs.djangoproject.com/en/dev/topics/class-based-views/#viewing-subsets-of-objects
The trick is to pick all the right mixing and serializers.
For example, you can mixing get processing this way:
http://django-rest-framework.org/howto/mixin.html
You'll implement the filter in the get method

Related

Object level permission at ORM level in Django

I have a Django application (mainly a rest API) with a completely custom User model (not inhered from Django). My authentication is based on JWT tokens.
I would like to make sure a user cannot access to data of another user. I have checked the django-guardian and django-rules. It provides stuff to call a has_perm function. However, in the case the developer does not perform the check and makes a mistake (for example hardcoding the user id in a query), a user might be able to access someone else data
Is there any way to enforce some kind of rule at the ORM level?

How can I allow users to register with an email using django-rest-framework-social-oauth2?

I'd like users to be able to register without using a 3rd party if they so choose. Few sites require a username to login anymore, so I'd like to use emails instead of usernames.
django-rest-framework-social-oauth2 combines python-social-auth and django-oauth-toolkit.
python-social-auth includes an EmailAuth backend that should let users register with an email and password. However, I don't understand the implications around using this instead of a Django-specific auth backend, and the docs label it as 'legacy', which sounds a little scary.
In fact, I have no idea how creating accounts, including from 3rd parties, works regarding the Django User Model as it requires a username.
What will I lose using EmailAuth? Is that the ideal way to go here, or is there an alternative?
For reasons I don't understand, Django still doesn't support emails instead of usernames without a custom user model, so regardless I need to use something bespoke or open-source for email-based accounts.
EDIT: python-social-auth just fills the username field with username = email.split('#', 1)[0] as shown here. I think I may need to make a custom Django User model and point python-social-auth to it, but I'm not sure how, and I'm not sure if this should still be used via EmailAuth or independantly of python-social-auth.

Multiple User Types For Auth in Django

My web features two user types, Client and Professional. There are also two 'main modules', one for clients to buy stuff and so on (the main site), and the other for professionals to manage operations. For auth, I would like to have:
A single 'sign in' form, which detects whether the user is a client or a professional and forwards her to the right module (main site or management site).
Two 'sign up' forms, one for clients and other for professionals. Probably, the site will ask the user whether she wants to register as a professional or as a client, to trigger the right registration flow for each case.
Clients will use the 'main site' and should not be authorized to use the 'management site'.
Professionals will use the 'management site' but should not be authorized to sign in to the main site.
Both professionals and clients are registered as Users, and share common fields, such as username, phone, email, etc...
Since Django won't let me use two models for authentication. I've created custom model subclassing AbstractBaseUser and which serves me as a base auth class for Client and Professional.
class BaseUser(AbstractBaseUser):
...
class Client(BaseUser):
...
class Professional(BaseUser):
...
I've also changed the AUTH_USER_MODEL setting to:
AUTH_USER_MODEL = 'myapp.BaseUser'
I've also included django-allauth to manage user registration and authentication. But now I'm stuck. I just began playing with Django/Python and I'm not sure how to solve this.
It seems there is no official recommended way for doing this (Implementing multiple user types with Django 1.5). Should I stick to the subclassing approach, or should I do the OnetoOne relationship pointed out in the docs ?
Once I have the models properly setup, how should I proceed with the two registration forms? Is it possible to accomplish this with django-allauth, or do I need to do it manually?
As far as I know, when a new user is registered, a new base user is created in the User table. But since I will be creating user specializations (Client or Professional), how should I specify that I also want to create the client-related data or professional-related data in the corresponding table?
I'm pretty new to Django, so any advise will help
I think the easiest way for you to do what you are talking about is going to be to have 3 apps in your project: your top level app, a "professional" app and a "client" app. At the top level app, all you really need to do is give the users a login form, and 2 links, one for registering as a Professional and one for registering as a Client.
In this case, I believe it will be easiest for you to use Django's built in Permissions system, and assign each type of user to a corresponding group (eg. professionals and clients). You can use a decorator on your views to ensure that only members of a particular group can access that view (since you have 2 separate apps for each group, you can add a decorator to all views in each of them, or you can import Django's authorization functions into your urls.py and check it there, although that is beyond the scope of this answer).
Registration is easy enough, use your urls.py file to forward the user that wants to register to the correct app. Once you do that, you should be able to use django-allauth registration on each app, allowing you to create 2 different kinds of users. Make sure when the register, you assign them to the correct group membership.
As for the login redirection, once you receive the POST data, I would check for which type of user logged in, and use that to forward the user to the correct URL that goes with the Professional or Client app. You can see the below link for an idea of redirecting a user after login.
Django - after login, redirect user to his custom page --> mysite.com/username

Adding Pushover integration in Django

I've recently started using Pushover.net, I've done some searching and can't find any examples of it being integrated with a django project.
Since i can't find any examples I've decided it would be fun to try myself. What I'm interested in is how you would suggest I do it. I want the actual pushover part as decoupled a possible, hence doing it asas an app.
What I'm not entirely sure on how to approach is the user authorization. The idea being a user enters their pushover user key and its saved in a user profile model using django's AUTH_PROFILE_MODULE with some functions such as has_pushover but obviously I'd like some security so the user keys aren't stored in plaintext. What do people suggest for this?
Is there some inbuilt django security I can use?
In the past when I've needed to encrypt Django fields I used the encrypted fields available in django-fields. You could use one of these on your UserProfile model and define a has_pushover() method on the model which basically returns whether the pushover token field is None or not.
I'm guessing because you're talking about storing each user's Pushover token you are wanting to build an app for pushing arbitrary notifications to your website's users? This is in contrast to having the website just push notifications to yourself for site events.

Going about Implementing Authentication/Authorization using CouchDb as backend in Django

I need to store both authentication and authorization information in couchdb. I've used a similar method to this for implementing authentication. However, what do I need to implement authorization for users. I need that certain actions be called only by specific users. Will using the user_passes_test decorator be a good idea for this?
I am also looking to move the session store to a separate couchdb instance. Will this be a good idea? Can anyone give me pointers/examples on how to go about this.
I am new to both Python and Django.
To answer the first part of your question, all you need to implement is the "authenticate" method of your custom authentication backend. The Django docs have some decent examples of how you could implement an authentication backend.
In regard to your permissions question, it depends on the exact details of what types of permission checks you need. If your permissions model fits well with Django's existing permissions system, you can make make authorizations decisions based on data in couchdb by implementing the optional permission bits in your custom authentication backend. Again, the Django docs have details on how exactly to do this.
As far as the session store, I don't know enough about CouchDB's performance characteristics to say if you need to store session data in a separate instance or not. What I can tell you however is either way, the way you use a CouchDB instance as your session store is to use a custom session engine. With a quick look around, it looks like django-couchdb-utils can provide you with a session engine that you could drop in without too much work (might also have some other useful bits for you).