You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
6.9 KiB
Python
193 lines
6.9 KiB
Python
from __future__ import unicode_literals
|
|
|
|
from random import choice, sample
|
|
import string
|
|
|
|
from django.utils.timezone import now as tznow
|
|
from django.conf import settings
|
|
from django.contrib import messages
|
|
from django.contrib.auth import authenticate, login
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.mail import send_mail
|
|
from django.http import HttpResponseRedirect
|
|
from django.shortcuts import get_object_or_404, render
|
|
from django.template.defaultfilters import slugify
|
|
try:
|
|
from django.urls import reverse
|
|
except ImportError: # Django < 1.10
|
|
from django.core.urlresolvers import reverse
|
|
|
|
from nano.tools import pop_error, get_profile_model, asciify
|
|
from nano.user.forms import SignupForm, PasswordChangeForm, PasswordResetForm
|
|
from nano.user import new_user_created
|
|
|
|
|
|
import logging
|
|
_LOG = logging.getLogger(__name__)
|
|
|
|
class NanoUserError(Exception):
|
|
pass
|
|
|
|
class NanoUserExistsError(NanoUserError):
|
|
pass
|
|
|
|
# def pop_error(request):
|
|
# error = request.session.get('error', None)
|
|
# if 'error' in request.session:
|
|
# del request.session['error']
|
|
# return error
|
|
|
|
def random_password():
|
|
sample_space = string.ascii_letters + string.digits + r'!#$%&()*+,-.:;=?_'
|
|
outlist = []
|
|
for i in range(1,8):
|
|
chars = sample(sample_space, 2)
|
|
outlist.extend(chars)
|
|
return ''.join(outlist)
|
|
|
|
def make_user(username, password, email=None, request=None):
|
|
User = get_user_model()
|
|
try:
|
|
User.objects.get(username=username)
|
|
except User.DoesNotExist:
|
|
# make user
|
|
user = User(username=username[:30])
|
|
user.set_password(password)
|
|
user.is_staff = False
|
|
user.is_superuser = False
|
|
user.is_active = True
|
|
if email:
|
|
user.email = email
|
|
user.save()
|
|
|
|
# Create profile
|
|
Profile = get_profile_model(raise_on_error=False)
|
|
if Profile:
|
|
profile = Profile(user=user, display_name=username)
|
|
profile.save()
|
|
|
|
# Don't signal creation of test users
|
|
test_users = getattr(settings, 'NANO_USER_TEST_USERS', ())
|
|
for test_user in test_users:
|
|
if user.username.startswith(test_user):
|
|
break
|
|
else:
|
|
new_user_created.send(sender=User, user=user)
|
|
if request is not None:
|
|
infomsg = 'You\'re now registered, as "%s"' % username
|
|
messages.info(request, infomsg)
|
|
_LOG.debug('Created user: %s/%s' % (user, user.check_password(password)))
|
|
return user
|
|
else:
|
|
raise NanoUserExistsError("The username '%s' is already in use by somebody else" % username)
|
|
|
|
def signup(request, template_name='signup.html', *args, **kwargs):
|
|
me = 'people'
|
|
error = pop_error(request)
|
|
data = {
|
|
'me': me,
|
|
'error': error,
|
|
'form': SignupForm()
|
|
}
|
|
if request.method == 'POST':
|
|
form = SignupForm(data=request.POST)
|
|
if form.is_valid():
|
|
username = asciify(form.cleaned_data['username'])
|
|
password = form.cleaned_data['password2']
|
|
email = form.cleaned_data['email'].strip() or ''
|
|
|
|
errormsg = 'Username "%s" is taken'
|
|
|
|
# check that username not taken
|
|
userslug = slugify(username)
|
|
Profile = get_profile_model(raise_on_error=False)
|
|
if Profile.objects.filter(slug=userslug).count():
|
|
# error!
|
|
safe_username = slugify('%s-%s' % (username, str(tznow())))
|
|
changed_warningmsg = errormsg + ", changed it to '%s'."
|
|
messages.warning(request, changed_warningmsg % (username, safe_username))
|
|
username = safe_username
|
|
|
|
# make user
|
|
try:
|
|
user = make_user(username, password, email=email, request=request)
|
|
except NanoUserExistsError:
|
|
next_profile = Profile.objects.get(user=user).get_absolute_url()
|
|
return HttpResponseRedirect(next_profile)
|
|
else:
|
|
# fake authentication, avoid a db-lookup/thread-trouble/
|
|
# race conditions
|
|
user.backend = 'django.contrib.auth.backends.ModelBackend'
|
|
_LOG.debug('Attempting login of: %s' % user)
|
|
login(request, user)
|
|
nexthop = getattr(settings, 'NANO_USER_SIGNUP_NEXT', reverse('nano_user_signup_done'))
|
|
try:
|
|
nexthop_profile = Profile.objects.get(user=user).get_absolute_url()
|
|
return HttpResponseRedirect(nexthop_profile)
|
|
except Profile.DoesNotExist:
|
|
pass
|
|
return HttpResponseRedirect(nexthop)
|
|
_LOG.debug('Should never end up here')
|
|
return render(request, template_name, data)
|
|
|
|
@login_required
|
|
def password_change(request, *args, **kwargs):
|
|
error = pop_error(request)
|
|
template_name = 'password_change_form.html'
|
|
if request.method == "POST":
|
|
form = PasswordChangeForm(request.POST)
|
|
if form.is_valid():
|
|
password = form.cleaned_data['password2']
|
|
user = request.user
|
|
user.set_password(password)
|
|
user.save()
|
|
request.session['error'] = None
|
|
return HttpResponseRedirect('/password/change/done/')
|
|
else:
|
|
form = PasswordChangeForm()
|
|
data = { 'form': form,
|
|
'error': error,}
|
|
return render(request, template_name, data)
|
|
|
|
def password_reset(request, project_name='Nano', *args, **kwargs):
|
|
User = get_user_model()
|
|
error = pop_error(request)
|
|
template = 'password_reset_form.html'
|
|
e_template = 'password_reset.txt'
|
|
help_message = None
|
|
e_subject = '%s password assistance' % project_name
|
|
e_message = """Your new password is:
|
|
|
|
%%s
|
|
|
|
It is long deliberately, so change it to
|
|
something you'll be able to remember.
|
|
|
|
|
|
%s' little password-bot
|
|
""" % project_name
|
|
e_from = getattr(settings, 'NANO_USER_EMAIL_SENDER', '')
|
|
form = PasswordResetForm()
|
|
if e_from and request.method == 'POST':
|
|
form = PasswordResetForm(request.POST)
|
|
if form.is_valid():
|
|
user = get_object_or_404(User, username=form.cleaned_data['username'])
|
|
if user.email:
|
|
tmp_pwd = random_password()
|
|
user.set_password(tmp_pwd)
|
|
result = send_mail(subject=e_subject, from_email=e_from, message=e_message % tmp_pwd, recipient_list=(user.email,))
|
|
user.save()
|
|
request.session['error'] = None
|
|
return HttpResponseRedirect('/password/reset/sent/')
|
|
else:
|
|
error = """There's no email-address registered for '%s',
|
|
the password can't be reset.""" % user.username
|
|
request.session['error'] = error
|
|
|
|
data = {'form': form,
|
|
'help_message': help_message,
|
|
'error':error}
|
|
return render(request, template, data)
|
|
|