Django user roles - django

I m building a website in which I have 2 types of users.
For each type of user I have a corresponding django application.
I would like when I am logging into the website as type A user or type B user, to be redirected to the appropriate django app and not to be able to access the other application. For logging each user will have a corresponding form.
What is the best approach for this case ?

Try to use Django Groups Model, so you gonna create two groups: type A and type B; Each user will be in one of these groups. On your index view, check which group the user belongs to and redirect for whatever you want.
def index(request):
if request.user.groups.filter(name='type A').exists():
return redirect('/url_type_A/')
elif request.user.groups.filter(name='type B').exists():
return redirect('/url_type_B/')
Now you can create permission for each group for accessing a certain view or do some specific action. I recommend to create two apps(python manage.py startapp typeA and python manage.py startapp typeB ) so you can redirect for an entire interface dedicate for the type of user.

Related

Django REST auth - users stored in external service

I've been wondering the best way to handle the case where a Django is used in a service-oriented architecture, so individual Django applications do not maintain their own user stores. One service maintains the user store, and others must call it in order to retrieve user information.
So far example, here is how I was thinking of building a custom authentication class in Django REST to handle this:
class SOAAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
token = request.get_token_from_auth_header()
if not remote_auth_service.is_token_valid(token):
raise AuthFailed('Token is invalid')
user_properties = remote_users_service.get_user(token):
# user_properties is a dict of properties
if not user_properties:
raise AuthFailed('User does not exist.')
user = MyCustomUserClass(**user_properties)
return (user, 'soa')
So no user info would get persisted in the Django application's database, and permission classes could interrogate the instance of MyCustomUserClass to figure out what groups a user belongs to.
Would this approach work for simple group-based authorization? My think is that I don't need object-level permissions, so there's no need to create rows for my users in the Django database.

Django Integrating Python Social Auth And The Default Auth With A Custom User Model:

I have a project I am working on that requires some users to be authenticated via facebook and others to sign up using a custom model. The facebook users will not have the same sign up credentials as the custom model. For example- there will be a restaurant owner sign up and a customer signup. The customer will not have to put a street address location, they can simply login.
My intentions were to have the restaurant owners sign up via the custom profile model and the facebook users to simply login via the defualt social auth, but whenever I combine the two, social auth starts to use the custom model because I define a custom user model within settings. Is there a way to distinguish to the python social auth backend to only use the default or a way to update my current custom user model to have a facebook segment. I have searched the web for a long time for this, but can not seem to find anything that can combine the two besides (1), but it did not work successfully. I can however get one or the other working successfully depending on if I specify a user model in my settings.py file or not.
It is quite simple, but I do not know of a way to get social auth to look at its default and djangos authentication to look at my custom model.
(1)-http://code.techandstartup.com/django/profiles/
In order to distinguish one type of user from another, you can do something like this:
First, in your settings file, store the following:
FIELDS_STORED_IN_SESSION = ['type']
This will be stored in strategy parameter in every function of pipeline
Then, change the pipeline wherever necessary. For example, in your create_user pipeline function, you can do this:
user_type = strategy.session_get('type')
if user_type != 'customuser':
return {
'is_new': True,
'user': strategy.create_user(**fields)
}
else:
return {
'is_new': True,
'user': create_restaurant(**fields)
}

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.

Django: Add multiple user to one group in admin interface

At the moment i'm settting up the permissions in my project and i assigned some permissions to one user group. Now i have to assign a large number of users to this group, so that they can us the permissions of the group.
Problem:
I have to click on every user in the admin interface, add them to the group and the same for the next ones. This takes a large amount of time. Is it possible to select anywhere all users that should belong to a group? That would be much faster...
If it's not possible with the standard admin interface, is there an app I can install and use for this (like "South" for database migration tasks)?
Use the django shell:
$ python manage.py shell
>>> from django.contrib.auth.models import User, Group
>>> the_group = Group.objects.get(name='the_name_in_admin')
>>> users = User.objects.exclude(groups__name='the_group_you_made_in_admin')
>>> for i in users:
... i.groups.add(the_group)
... i.save()
>>>
For more information on the api of the authentication system, have a read through the documentation

Django: how to store subdomain-based authentication usernames?

I need to create a subdomain based authentication system, like the one 37signals, freshbooks, codebase use. That is, each subdomain of my main application needs to have its own username namespace. I would like to keep as much as possible of the django authentication system.
What is a good way to store the username?
In particular, it should be possible for different users to have the same username as long as their account belongs to a different subdomain.
Some approaches I've considered, for which I can foresee shortcomings:
storing some prefix in the username field of the django auth user model.
extending the user model according to this.
customizing the source of auth to my needs
I have built this functionality for several sites in the past and have found that your first bullet point is the way to go.
It means that you don't have to make massive change to django auth. What I did was set up a custom authentication backend that abstracts away the way usernames are stored.
auth_backends.py
from django.contrib.auth.backends import ModelBackend
from Home.models import Account
class CustomUserModelBackend(ModelBackend):
def authenticate(self, subdomain, email, password):
try:
user = Account.objects.get(username=u'%s.%s' % (subdomain, email))
if user.check_password(password):
return user
except Account.DoesNotExist:
return None
def get_user(self, user_id):
try:
return Account.objects.get(pk=user_id)
except Account.DoesNotExist:
return None
For this particular project Account was the user model and it just inherited directly from User however you could replace Account with whatever you want.
You have to install the custom auth backend in your settings file:
AUTHENTICATION_BACKENDS = (
'auth_backends.CustomUserModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
Then when you call authenticate you need to pass in the subdomain, email and password.
You can also add some other helper functions or model methods that help with making sure that only the user's actual username is displayed, but that is all pretty trivial.
I think this may be a good use case for using django.contrib.sites in combination with the second bullet item you mentioned. You could create a CustomUser model like so:
from django.contrib.sites.models import Site
class CustomUser(User):
"""User with app settings."""
sites = models.ManyToManyField(Site)
Then you could write a custom auth backend to check that the user can sign in to the current subdomain using the supplied credentials. This allows you to have one username for multiple sites (subdomains) without having to hack the internal auth app or store multiple usernames with custom prefixes.
EDIT: you can get the current site by using Site.objects.get_current() and then check to see if the current site is in the user's sites.
You can read more about the sites framework here: http://docs.djangoproject.com/en/dev/ref/contrib/sites/