Django password required views - django

I have an edit view for editing models objects. I want to make it password protected with a password I generate and put in my model. I don't want to use django Users
Let's say I have something like this:
models.py
class Job(models.Model):
......
job_uuid = models.CharField("UUID", max_length=36, default=make_uuid)
password = models.CharField("password", max_length=36)
views.py
def edit_job(request, job_uuid):
job = get_object_or_404(Job, job_uuid=job_uuid)
job_form = EditJobForm(instance=job)
c = {'job_form': job_form,
}
c.update(csrf(request))
return render_to_response('jobs/edit_job.html', c, context_instance=RequestContext(request))
I wanted to protect this URL with the password from the object. I found this app django-password-required but this app uses one password you set in the settings.py
Any easy package or way to do this?

You can write a decorator that will check if password access is required for edit_job view.
Then decorator can use password from session/cookies to verify the access.
If password does not match or not present, you can redirect to different view to show password form, and store it in session.
Hope this helps.

Related

how to generate token using username and pin field in django auth toolkit for a phone app while keeping username and password for the web application?

I am using DRF with auth toolkit and it is working fine. However, I want to have a second login api so a user can log in using username and pin number. It is cos we have a USSD application and it is easier to give them a pin based login system.
Currently, I have the following URL that, when called, generates token:
url(r'^signin/', include('oauth2_provider.urls', namespace='oauth2_provider')),
For the ussd app, I want something like that but the auth2 should check pin field, defined in a separate model defined as follows:
class Members(models.Model):
pin=models.IntegerField()
user=models.ForeignKey(User)
I am a little lost where to start.
Using this answer as a base to answer this question, and Django's documentation.
I would say you'd want to create a custom authentication backend, and you'd want a custom user model with two passwords, or using a one-to-one relationship to add the additional password field, something like so:
from django.contrib.auth.models import AbstractBaseUser
class UserExtension(AbstractBaseUser):
user = models.OneToOneField(User)
...
Inheriting from the AbstractBaseUser should add a password field like the user model, (although I haven't tried this). If you prefer the custom user approach, I actually have a github repo that has a custom user app, so if you'd like to get any ideas of how to achieve this check it out.
Or have a look through the documentation.
Either way, once you've got your two passwords, you need to decide which one to use as the pin. If you're using oauth for the pin field and the web applicaiton with the password, I would probably use the standard user password for the pin login, as that way you don't need to change the oauth package to work with your new password. Then for your web application build a custom login. To do this create a custom authentication backend along the lines of:
from django.contrib.auth.models import User
from django.contrib.auth.hashers import check_password
class AuthBackend(object):
supports_object_permissions = True
supports_anonymous_user = False
supports_inactive_user = False
def get_user(self, user_id):
return User.objects.filter(pk=user_id).first()
def authenticate(self, username, password):
user = User.objects.filter(username=username).first()
if not user:
return None
# this is checking the password provided against the secondary password field
return user if check_password(password, user.userextension.password) else None
Then you need to add this authentication backend to your settings:
AUTHENTICATION_BACKENDS = ('myapp.backends.AuthBackend',)
Then create the web application login (as per the stackoverflow answer above):
from django.contrib.auth import authenticate, login
def my_login_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
# Redirect to a success page.
else:
# Return a 'disabled account' error message
...
else:
# Return an 'invalid login' error message.
...
You should now have a custom authentication login for the web application using your password2 field, and you can use the oauth authentication to work with the standard Django password in which you're going to store the pin. Which I think is what you're trying to do?
NOTE: All of the above I haven't tested, so this may not work perfectly, but it should hopefully be able to at least point you in the right direction and give you a few ideas. If I'm understanding your problem correctly, this is the sort of approach that I would take to tackle the problem.

django User registration and authentication by email

I want to make users active by sending them an activation email to click. I guess it is currently not incorporated in Django 1.6.The user-registration app coded in Django seems to serve this purpose. But I have some doubts with regard to the DefaultForm it provides in forms.py. I want to have more fields included in it. How can I achieve that in class RegistrationForm(forms.Form) implemented there. If I install this app, is it a good idea to change include more fields directly there, is there a better way to achieve the same.
In the views.py, I see some methods such as the following are not implemented. I dont have a clear picture of what these methods need to do. should I redirect the url here to the pages?
def register(self, request, **cleaned_data):
raise NotImplementedError
def activate(self, request, *args, **kwargs):
raise NotImplementedError
def get_success_url(self, request, user):
raise NotImplementedError
You need to first let them sign up and mark them as is_active=False for the time being. Something like this:
from django.contrib.auth.models import User
from django.core.mail import send_mail
from django.http import HttpResponseRedirect
def signup(request):
# form to sign up is valid
user = User.objects.create_user('username', 'email', 'password')
user.is_active=False
user.save()
# now send them an email with a link in order to activate their user account
# you can also use an html django email template to send the email instead
# if you want
send_mail('subject', 'msg [include activation link to View here to activate account]', 'from_email', ['to_email'], fail_silently=False)
return HttpResponseRedirect('register_success_view')
Then once they click the link in the email it takes them to the next view (note: you need to put a link in the email so that you know which user it is. This may be 16-digit salt or something. The below view uses the user.pk:
def activate_view(request, pk):
user = User.objects.get(pk=pk)
user.is_active=True
user.save()
return HttpResponseRedirect('activation_success_view')
Hope that helps. Good Luck!
Basically you can use django's user model(https://docs.djangoproject.com/en/1.9/ref/contrib/auth/). However, in user model email is not a required field. You need to modify the model to make email an required field.
In your views, you might need the following method:
1) Sign up: after sign up, set user.is_active=False and call function send_email to include an activation link in the email. In the link, you might want to include the user's information (for example, user.id) so when the user click the link, you know which user to activate.
2) send_email: send a link to user's email address for verification. The link includes user's id. For example:
http://127.0.0.1:8000/activation/?id=4
3) Activate: get the id information from the URL using id=request.GET.get('id'). Query user=user whose id is id. set user.is_active=True.
Actually I implemented an reusable application like your request, check this(https://github.com/JunyiJ/django-register-activate) if you are interested.
Hope that helps. Good luck!
check this out... i Hope it helps out with not only the solution u need but also the explanation.. Because i think django-registration app is meant for default Django User. So if u want to have extra fields in your registration form, Start thinking of customizing ur Django User and Its authentication yourself. You dont need the django-registration app here..
Here are some tutorials thats will help
http://www.caktusgroup.com/blog/2013/08/07/migrating-custom-user-model-django/
and many more...

Getting user defined urls in django

I would like to add to my app a way for users to create their own url. So, what I mean by this, is that if a user wants to go to their webpage, they could go to http://www.projectdomain.com/JimmyJohn
In my model I have
class Person(models.Model):
username = models.CharField(max_length=30) #username = JimmyJohn
....
Is the best way to do this by just adding a method that catches everything after / in urls.py? Or is there a way to more tightly integrate my models with the urls.py?
Just add a url to your main urls.py accepting a first alphabetic argument (consider adding any other urls of your app above this, and validating usernames so your urls are not valid usernames):
urlpatterns = patterns('',
# ... other fixed urls before
url(r'^(\w+)/$', 'website.views.user_page', name='user_page'),
)
Then query for a User in your view matching the given username:
def user_page(request, username):
user = get_object_or_404(User, username=username)
return render(...)

Django: How can I implement a low level login using a md5 password column since I'm porting over my users table from an old site?

Basically, I currently have login/ in urls.py redirect to the django.contrib.auth.views.login and that seems to work out fine.
However I'm porting over passwords from a legacy mysql/php site and I believe I should just create a new model profile per http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users. This new model/table will have the old md5 password column, and I'll port over the usernames to the main users table.
How could I change the login method such that I first check if the user has a password in the auth_user table, and if not then md5 the POST password field and attempt to match it to my new profile password column, if so save the password in the new auth_user table by SHA1 encrypting like how the admin does it?
I would create a new view that does something along the following:
from django.contrib.auth.models import User, check_password
import hashlib
def login_with_lookup(request):
if request.POST: # If you want to restrict to POST
username = request.POST['username']
password = request.POST['password']
user = User.objects.get(username=username)
profile = user.get_profile()
if profile.old_password != '' and profile.old_password == hashlib.md5(password).hexdigest():
user.set_password(password)
profile.old_password = ''
user.save() # Might need to save profile as well, not sure how it works
if check_password(password, user.password):
login(request, user)
#Whatever else you want to do, followed by a render to template or redirect
This is un-tested, so it will need a bit of clean-up. It will also need error checking at different points to handle failure cases (this example assumes success).
Write a custom authentication backend:
http://docs.djangoproject.com/en/1.1/topics/auth/#writing-an-authentication-backend

How to disable email activation in django-registration app?

How to disable email activation in django-registration app?
In the current tip versions of django-registration there is a simple backend with no email and you can write your own backend to specify the workflow you want. See here https://bitbucket.org/ubernostrum/django-registration/src/fad7080fe769/docs/backend-api.rst for documentation.
To use the simple one without email, just change your urls.py to point to this backend, eg.
(r'^accounts/', include('registration.backends.simple.urls')),
Why not use this method and just use the simple backend that comes with django-registration instead of the default backend?
The new work flow would be...
1. A user signs up by filling out a registration form.
2. The user’s account is created and is active immediately, with no intermediate confirmation or activation step.
3. The new user is logged in immediately.
so on your main urls.py you would change:
url(r'^accounts/', include('registration.backends.default.urls')),
to
url(r'^accounts/', include('registration.backends.simple.urls')),
Better to fix the problem at the root than bandage it by calling commands to automatically activate the user.
Add this method to registration models.py:
def create_active_user(self, username, email, password,
site):
"""
Create a new, active ``User``, generate a
``RegistrationProfile`` and email its activation key to the
``User``, returning the new ``User``.
"""
new_user = User.objects.create_user(username, email, password)
new_user.is_active = True
new_user.save()
registration_profile = self.create_profile(new_user)
return new_user
create_active_user = transaction.commit_on_success(create_active_user)
Then, edit registration/backend/defaults/init.py and find the register() method.
Change the following to call your new method:
#new_user = RegistrationProfile.objects.create_inactive_user(username, email,
#password, site)
new_user = RegistrationProfile.objects.create_active_user(username, email,
password, site)
You could always modify this line to:
new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'],
password=self.cleaned_data['password1'],
email=self.cleaned_data['email'],
profile_callback=profile_callback,
send_email = False)
Or you could change this line to:
def create_inactive_user(self, username, password, email,
send_email=False, profile_callback=None):
Rather than modifying the registration app, why not just activate the user the same way django-registration does:
user.is_active = True
user.save()
profile.activation_key = "ALREADY_ACTIVATED"
profile.save()
After looking at it even more... I think what you want is to use both solutions. Probably add the above code, just after the change suggested by Dominic (though I would suggest using signals, or subclassing the form if possible)
OK final Answer:
new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'],
password=self.cleaned_data['password1'],
email=self.cleaned_data['email'],
profile_callback=profile_callback,
send_email = False)
RegistrationProfile.objects.activate_user(new_user.activation_key)