Check if user is authenticated in urls.py - python

Is it possible to do something like this in urls.py?
urls.py: http://pastebin.com/raw.php?i=QVQ8BEvJ

This is not right way to implement it.
The best solution is to wrap your views with #login_requered decorator.
Example:
#login_required
def home_page(request):
...
You can specify in your settings.py LOGIN_URL where user will be redirected if not authorized.
Please read more at django documentation

Authentication checks should be performed in the view, that's where checks and security are ment to exist.
Apart from that you can decorate Class Based Views in urls to check for login, but the most common / sensible / usual approach is to make that check in the view.
If you are using Class Based Views then you could create a Mixin which checks if the user is authenticated, this combined with the tools Django Offers, allow you to redirect the user to the appropriate view (login, or if check is passed allow him to view the requested url).
If you are using function based views, then Django offers decorators for those functions to provide common "needs" of a web framework.
PS If you are using CBV's then django-braces has already a few wonderful mixins available for common tasks (Ajax, Security etc).

Related

Django Practice to organize views that have same permission

The login_required, user_passes_test and permission_required decorator only apply to specific functions, similar for the mixin. But is it a good practice to put #permission_required('polls.add_choice') to each and every view that require such permission?
I think it is quite common that multiple views have the same permission. For example, you have an employer and job seeker, only the employer can add company name/ address, post a job and check job application. It is also common that the website requires login for most of its pages.
So my question is what is the idioms/practice assigning the same permission to multiple views? The only recipe I can find is Beginning Django - Listing 10-8. Permission checks in urls. Pay for include () definitions. Another approach is to swap the view function inside a class (as static method) and do some trick the add permission to all methods.
Is there any better sulotion? Or any reason not to do that?
I think that in this case it is most ideal to use Django's groups system.
It's totally ok to use same permission for several views because in some cases there is more views than the 4 CRUD views and 2 views can be intended to same user/rule/groups.
It also depends on number of online users of your site.
It there are thousands of users online - try to cache that wrappers.
or rewrite all to api

Flask-Security override register view

Is there some convenient way to override register view in Flask-Security? I'm pretty happy with the built-in view for registration, but I need it to be accessible only after authentication and by certain roles.
I tried to override it like this (with SECURITY_REGISTER_URL='/register/') but that just takes the built-in function and mine is completely ignored:
#app.route('/register/')
#login_required
#roles_required('superuser')
def register():
"""View function which handles a registration request."""
...
So the question is - do I have to write my own register view from peak and disable the Flask-Security registration?
I thought also about checking the user login/role in register_user.html template and possibly redirecting back to home page, but I'm not sure if that's the correct way to achieve this...
After several hours I finally managed to get it working. I forgot to specify methods, while registering the route #app.route('/register/', methods=['GET', 'POST']). If you disable the original Flask-Security's register view (SECURITY_REGISTERABLE = False), it works like a charm!
Also, when you want to override some view from Flask-Security, that can't be disabled so easily, like login, you have to do the same thing as mentioned above, but also register your view/blueprint first!

Subclassing and overriding Django Class based views

I'm building a website using django-all auth for it's authentication and social authentication functions. The forms that come bundled with the app are hardly great to look at and hence I decided to create my own views.
The problem is: How do I create them while ensuring that the backend of Django all auth is still available to me? I've dug into the source code and found that it uses class based views for rendering and performing CRUD operations.
I want to know if I can subclass those views in my own app/views.py and just change their template_name field to my own templates. Any advice would be most helpful.
Thanks.
You can of course subclass the views, as long as you change your URLs to point to the overridden versions. However, there is no need to do this just to use your own templates; Django's template loader is specifically written with this use case in mind. Simply create your own directory inside your templates folder to match the one allauth is using, and create your own template files inside it; Django will find yours first and use them.

Django decorator to redirect based on user-type

Currently in my django app, I have two kind of users, say userTypeA and userTypeB.
At this point, I redirect both of the types to /usercheck/ which has a function to check the type of user, and redirect them accordingly. This is working out pretty well.
However, just for curiosity, if I were to write a decorator where would I put it ?
One place I can think of is settings.py where a decorator will output different LOGIN_REDIRECT_URL based on the user type.
It is just for learning. My current implementation is working out pretty good so far.
Thanks a lot.
settings.py is meant for global static configuration data, I would definitely not try dynamically changing the settings. There are many other places in Django where a login url can be set explicitly.
I'm not entirely clear on what you want to do, but it sounds like the user_passes_test decorator is what you're after. From the docs:
Limiting access to logged-in users that pass a test: The simple way is to run your test on request.user in the view directly.... As a shortcut, you can use the convenient user_passes_test decorator.

Multiple versions of django admin page for the same model

In my django admin section, I'd like to show different versions of the admin page depending on what kind of user is currently logged in. I can think of a couple ways this might work, but haven't figured out how to do any of them.
Perhaps I could put logic into the admin.ModelAdmin to look at the current user and change the 'exclude' field dynamically. Does that work? Or maybe run different custom templates based on who's logged in, and have the templates include / exclude the fields as appropriate.
I could register two versions of the admin.ModelAdmin class, one for each type of user, and maybe restrict access through permissions? But the permissions system seems to believe fairly deeply in one set of permissions per model class so I'm not sure how to change that.
I could grab a couple of the widgets that are used in rendering the admin page templates, and include them in my own page that does the one specific job I need powerful users to be able to do.
I could set up multiple AdminSites and restrict access to them through the url / view system. But then I'm not sure how to register different admin.ModelAdmin classes with the different AdminSites.
Any advice on this would be appreciated.
Answer
Thanks for the hint. Here's how I did it...
def get_form(self, request, obj=None, **kwargs):
"""This dynamically inserts the "owners" field into the exclude list
if the current user is not superuser.
"""
if not request.user.is_superuser:
if self.exclude:
self.exclude.append('owners')
else:
self.exclude = ['owners']
else:
# Necessary since Admin objects outlive requests
try:
self.exclude.remove('owners')
except:
pass
return super(OwnersModelAdmin,self).get_form(request, obj=None, **kwargs)
There are quite a few hooks provided in the ModelAdmin class for this sort of thing.
One possibility would be to override the get_form method. This takes the request, as well as the object being edited, so you could get the current user from there, and return different ModelForms dependent on the user.
It's worth looking at the source for ModelAdmin - it's in django.contrib.admin.options - to see if overriding this or any other other methods might meet your needs.

Categories