# -*- coding: utf-8 -*- import hashlib from random import random from django.shortcuts import render, redirect, get_object_or_404 from django.core.urlresolvers import reverse from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_variables, sensitive_post_parameters from django.contrib import auth from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required from django.contrib import messages from django.conf import settings from project.customer.models import UserProfile, UserProfileFilters from . import forms, models, emails REGISTRATION_OPEN = getattr(settings, 'REGISTRATION_OPEN', True) @sensitive_variables() def _create_user(request, **kwargs): # создать юзера email, password = kwargs['email'], kwargs['password1'] # сгенерировать имя пользователя. на всякий случай, добавить к нему соль, чтобы снизить вероятность коллизий username = hashlib.sha1(u'%s%s' % (email, random())).hexdigest()[:30] user = User.objects.create_user(username=username, email=email, password=password) # создать пустой профиль profile_type = kwargs['profile_type'] UserProfile.objects.create_profile(user=user, profile_type=profile_type) # создать фильтры профиля UserProfileFilters.objects.create_filters(user=user) # создать запись, что email не подтверждён models.ConfirmEmail.objects.unconfirm(user) # аутентифицировать и залогинить new_user = auth.authenticate(username=username, password=password) auth.login(request, new_user) return new_user @sensitive_variables() @sensitive_post_parameters() @csrf_protect def register(request): """ Регистрация нового пользователя. Алгоритм регистрации такой: - юзер в форме вводит свой email, пароль и форму собственности; - форма сабмитится во вьюху и проверяется на валидность; - генерится хеш по юзерскому email - т.к. регистрация и логин по email, а поле User.username всего лишь 30 символов, то храню email не в нем, а в соответсвующем поле, ну а username генерирую "левый"; - создается юзер, пока с пустым профилем; - юзера аутентифицирует и логинит в систему; - после чего редиректит на страницу редактирования профиля. """ form_class = forms.RegistrationForm form_prefix = 'register' template_name = 'myauth/register.html' success_url = 'customer_profile_edit' registration_closed_url = 'myauth_registration_closed' if not REGISTRATION_OPEN: return redirect(registration_closed_url) if request.method == 'POST': form = form_class(data=request.POST, prefix=form_prefix) if form.is_valid(): new_user = _create_user(request, **form.cleaned_data) confirm_url = reverse('myauth_confirm_email', args=[new_user.username,]) emails.send_registration_email(new_user.email, confirm_url) return redirect(success_url) else: form = form_class(prefix=form_prefix) return render(request, template_name, {'form': form,}) @sensitive_variables() def confirm_registered_email(request, key): """Подтверждение зарегистрированного email.""" success_url = 'customer_profile_view' success_msg = u'E-mail подтверждён.' user = get_object_or_404(User, username__iexact = key) # ключ = имя пользователя models.ConfirmEmail.objects.confirm(user) messages.add_message(request, messages.INFO, success_msg) return redirect(success_url) @sensitive_variables() @sensitive_post_parameters() @csrf_protect def reset(request): """Запросить ключ восстановления пароля.""" form_class = forms.ResetPasswordForm form_prefix='reset' template_name = 'myauth/reset.html' success_url = 'myauth_reset_key_ready' if request.method == 'POST': form = form_class(data=request.POST, prefix=form_prefix) if form.is_valid(): user = form.get_user() key = models.ResetKey.objects.create_key(user) confirm_url = reverse('myauth_confirm_reset', args=[key.key,]) emails.send_reset_password_email(user.email, confirm_url) return redirect(success_url) else: form = form_class(prefix=form_prefix) return render(request, template_name, {'form': form,}) @sensitive_variables() def confirm_reset(request, key): """Подтверждение запроса на восстановление пароля. Генерирует новый пароль и отправляет его на почту пользователю. """ success_url = 'customer_profile_view' success_msg = u'Новый пароль выслан на ваш e-mail.' key = get_object_or_404(models.ResetKey, key__iexact = key) new_password = User.objects.make_random_password() # новый пароль key.user.set_password(new_password) key.user.save() emails.send_new_password_email(key.user.email, new_password) key.delete() # удалить ключ восстановления пароля messages.add_message(request, messages.INFO, success_msg) return redirect(success_url) @sensitive_variables() @sensitive_post_parameters() @login_required @csrf_protect def change_password(request): form_class = forms.ChangePasswordForm form_prefix = 'change_password' template_name = 'myauth/change_password.html' success_url = 'customer_profile_view' success_msg = u'Ваш пароль изменён на новый.' if request.method == 'POST': form = form_class(user=request.user, data=request.POST, prefix=form_prefix) if form.is_valid(): new_password = form.cleaned_data['password1'] request.user.set_password(new_password) request.user.save() messages.add_message(request, messages.INFO, success_msg) return redirect(success_url) else: form = form_class(user=request.user, prefix=form_prefix) return render(request, template_name, {'form': form,}) @sensitive_variables() @sensitive_post_parameters() @login_required @csrf_protect def change_email(request): form_class = forms.ChangeEmailForm form_prefix = 'change_email' template_name = 'myauth/change_email.html' success_url = 'customer_profile_view' success_msg = u'Ваш e-mail изменён на новый.' if request.method == 'POST': form = form_class(user=request.user, data=request.POST, prefix=form_prefix) if form.is_valid(): new_email = form.cleaned_data['email'] request.user.email = new_email request.user.save() models.ConfirmEmail.objects.unconfirm(request.user) messages.add_message(request, messages.INFO, success_msg) return redirect(success_url) else: form = form_class(user=request.user, prefix=form_prefix) return render(request, template_name, {'form': form,}) @sensitive_variables() @sensitive_post_parameters() @csrf_protect def login(request): """Вход в систему.""" form_class = forms.LoginForm form_prefix = 'login' template_name = 'myauth/login.html' success_url = 'customer_profile_view' if request.method == 'POST': form = form_class(data=request.POST, prefix=form_prefix) if form.is_valid(): auth.login(request, form.get_user()) return redirect(success_url) else: form = form_class(prefix=form_prefix) return render(request, template_name, {'form': form,})