parent
bb67cd3461
commit
b962c7973e
11 changed files with 750 additions and 0 deletions
@ -0,0 +1,26 @@ |
|||||||
|
from django.contrib import admin |
||||||
|
from .models import Profile |
||||||
|
|
||||||
|
# def delete_model(modeladmin, request, queryset): |
||||||
|
# for obj in queryset: |
||||||
|
# user_profile = obj.user.profile |
||||||
|
# if user_profile.user_points >= obj.points: |
||||||
|
# user_profile.user_points -= obj.points |
||||||
|
# user_profile.save() |
||||||
|
# obj.delete() |
||||||
|
# |
||||||
|
# delete_model.short_description = "Удалить как исполненный" |
||||||
|
|
||||||
|
# class PickUpRequestAdmin(admin.ModelAdmin): |
||||||
|
# list_display = [field.name for field in PickUpRequest._meta.fields] |
||||||
|
# actions = [delete_model] |
||||||
|
# class Meta: |
||||||
|
# model = PickUpRequest |
||||||
|
# |
||||||
|
# class UserProfileAdmin(admin.ModelAdmin): |
||||||
|
# list_display = [field.name for field in Profile._meta.fields] |
||||||
|
# class Meta: |
||||||
|
# model = Profile |
||||||
|
|
||||||
|
# admin.site.register(Profile, UserProfileAdmin) |
||||||
|
# admin.site.register(PickUpRequest, PickUpRequestAdmin) |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
from django.apps import AppConfig |
||||||
|
from django.utils.translation import ugettext_lazy as _ |
||||||
|
|
||||||
|
|
||||||
|
class AccountsExtConfig(AppConfig): |
||||||
|
name = 'accounts_ext' |
||||||
|
verbose_name = _("Authentication and Authorization") |
||||||
@ -0,0 +1,298 @@ |
|||||||
|
import logging |
||||||
|
from captcha.fields import CaptchaField |
||||||
|
from crispy_forms.helper import FormHelper |
||||||
|
from crispy_forms.layout import Layout, Field, Div, Submit, HTML |
||||||
|
from django import forms |
||||||
|
from django.conf import settings |
||||||
|
from django.contrib.auth import get_user_model, password_validation |
||||||
|
from django.core.exceptions import ObjectDoesNotExist |
||||||
|
from django.forms import inlineformset_factory |
||||||
|
from django.urls import reverse, reverse_lazy |
||||||
|
from django.utils.translation import ugettext_lazy as _ |
||||||
|
from registration.forms import RegistrationFormUniqueEmail |
||||||
|
from django.contrib.auth.forms import ( |
||||||
|
AuthenticationForm as AuthenticationFormBase, |
||||||
|
PasswordResetForm as PasswordResetFormBase, |
||||||
|
PasswordChangeForm as PasswordChangeFormBase |
||||||
|
) |
||||||
|
|
||||||
|
from core.models import STATUS_ACTIVE |
||||||
|
from .models import User, Profile, Company |
||||||
|
|
||||||
|
logger = logging.getLogger(__name__) |
||||||
|
|
||||||
|
|
||||||
|
# class PickUpPointsForm(layout.ModelForm): |
||||||
|
# class Meta:' |
||||||
|
# model = PickUpRequest |
||||||
|
# fields = ('requisites',) |
||||||
|
|
||||||
|
|
||||||
|
class RegistrationForm(RegistrationFormUniqueEmail): |
||||||
|
email = forms.EmailField(label=_("E-mail"), widget=forms.EmailInput(attrs={'class': 'reg__text'})) |
||||||
|
password1 = forms.CharField( |
||||||
|
label=_('Пароль'), |
||||||
|
strip=False, |
||||||
|
widget=forms.PasswordInput(attrs={'class': 'reg__text-label'}), |
||||||
|
help_text=password_validation.password_validators_help_text_html(), |
||||||
|
) |
||||||
|
password2 = forms.CharField( |
||||||
|
label=_('Подтверждение пароля'), |
||||||
|
widget=forms.PasswordInput(attrs={'class': 'reg__text-label'}), |
||||||
|
strip=False, |
||||||
|
help_text=_('Для потверждения пароля введите его еще раз'), |
||||||
|
) |
||||||
|
first_name = forms.CharField(label=_("Имя"), max_length=255, widget=forms.TextInput(attrs={'class': 'reg__text'})) |
||||||
|
last_name = forms.CharField(label=_("Фамилия"), max_length=255, |
||||||
|
widget=forms.TextInput(attrs={'class': 'reg__text'})) |
||||||
|
patronymic = forms.CharField(label=_("Отчество"), max_length=255, |
||||||
|
widget=forms.TextInput(attrs={'class': 'reg__text'})) |
||||||
|
agreement = forms.BooleanField() |
||||||
|
|
||||||
|
captcha = CaptchaField(required=not settings.DEBUG) |
||||||
|
|
||||||
|
title = _('Регистрация') |
||||||
|
|
||||||
|
def save(self, commit=True): |
||||||
|
user = super().save(commit) |
||||||
|
profile = Profile.objects.filter(user=user).first() |
||||||
|
if profile: |
||||||
|
profile.first_name = self.cleaned_data.get('first_name') |
||||||
|
profile.last_name = self.cleaned_data.get('last_name') |
||||||
|
profile.patronymic = self.cleaned_data.get('patronymic') |
||||||
|
profile.save() |
||||||
|
else: |
||||||
|
logger.error( |
||||||
|
msg="User {user_email} missing profile object".format({'user_email': user.email}) |
||||||
|
) |
||||||
|
return user |
||||||
|
|
||||||
|
class Meta: |
||||||
|
model = User |
||||||
|
fields = ('username',) |
||||||
|
labels = { |
||||||
|
'username': _('Логин'), |
||||||
|
} |
||||||
|
help_texts = { |
||||||
|
'username': _('Не менее 5х символов'), |
||||||
|
} |
||||||
|
widgets = { |
||||||
|
'username': forms.TextInput(attrs={'class': 'reg__text-label'}), |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
class RegistrationCompanyForm(forms.ModelForm): |
||||||
|
is_individual = forms.BooleanField(label=_('Я физическое лицо'), required=False) |
||||||
|
|
||||||
|
def save(self, user, commit=True): |
||||||
|
self.instance.user = user |
||||||
|
return super().save(commit) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
model = Company |
||||||
|
fields = ('company_name', 'address', 'inn', 'ogrn') |
||||||
|
labels = { |
||||||
|
'company_name': _('Наименование'), |
||||||
|
'inn': _('ИНН'), |
||||||
|
'ogrn': _('ОГРН'), |
||||||
|
'address': _('Юридический адрес') |
||||||
|
} |
||||||
|
widgets = { |
||||||
|
'company_name': forms.TextInput(attrs={'class': 'reg__text'}), |
||||||
|
'inn': forms.TextInput(attrs={'class': 'reg__text'}), |
||||||
|
'ogrn': forms.TextInput(attrs={'class': 'reg__text'}), |
||||||
|
'address': forms.Textarea(attrs={'class': 'reg__text', 'rows': 5, 'cols': 40}) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
class AuthenticationForm(AuthenticationFormBase): |
||||||
|
username = forms.CharField(max_length=255, widget=forms.TextInput(attrs={ |
||||||
|
'class': 'reg__text', |
||||||
|
'style': 'text-align:center', |
||||||
|
'placeholder': _('Логин') |
||||||
|
})) |
||||||
|
password = forms.CharField(max_length=255, widget=forms.PasswordInput(attrs={ |
||||||
|
'class': 'reg__text', |
||||||
|
'style': 'text-align:center', |
||||||
|
'placeholder': _('Пароль') |
||||||
|
})) |
||||||
|
|
||||||
|
field_template = 'bootstrap/forms/authentication.html' |
||||||
|
title = _('Вход') |
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs): |
||||||
|
self.helper = FormHelper() |
||||||
|
self.helper.layout = Layout( |
||||||
|
Field('username', template=self.field_template), |
||||||
|
Field('password', template=self.field_template), |
||||||
|
Div( |
||||||
|
HTML('<a class="header__link" href="{}">{}</a>'.format( |
||||||
|
reverse_lazy('accounts_ext:reset_password'), |
||||||
|
_('Забыли пароль ?')) |
||||||
|
), |
||||||
|
css_class="text-right" |
||||||
|
), |
||||||
|
Div( |
||||||
|
Div( |
||||||
|
Submit('submit', _('Войти'), css_class='btn-danger'), |
||||||
|
css_class='col-lg-12 text-center' |
||||||
|
), |
||||||
|
css_class='row' |
||||||
|
), |
||||||
|
) |
||||||
|
super().__init__(*args, **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetRequestForm(PasswordResetFormBase): |
||||||
|
field_template = 'bootstrap/forms/authentication.html' |
||||||
|
|
||||||
|
email_slug = 'reset_password' |
||||||
|
title = _('Сброс пароля') |
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs): |
||||||
|
self.helper = FormHelper() |
||||||
|
self.helper.form_action = reverse_lazy('accounts_ext:reset_password') |
||||||
|
self.helper.layout = Layout( |
||||||
|
Field('email', css_class='reg__text', template=self.field_template, placeholder="example@email.com"), |
||||||
|
Div( |
||||||
|
Div( |
||||||
|
Submit('submit', _('Сбросить'), css_class='btn-danger'), |
||||||
|
css_class='col-lg-12 text-center' |
||||||
|
), |
||||||
|
css_class="row" |
||||||
|
), |
||||||
|
) |
||||||
|
super().__init__(*args, **kwargs) |
||||||
|
|
||||||
|
def get_users(self, email): |
||||||
|
active_users = get_user_model()._default_manager.filter(**{ |
||||||
|
'%s__iexact' % get_user_model().get_email_field_name(): email, |
||||||
|
'status': STATUS_ACTIVE, |
||||||
|
}) |
||||||
|
return (u for u in active_users if u.has_usable_password()) |
||||||
|
|
||||||
|
def send_mail(self, subject_template_name, email_template_name, context, from_email, to_email, |
||||||
|
html_email_template_name=None): |
||||||
|
try: |
||||||
|
# mail_template = MailTemplate.objects.filter(slug=self.email_slug).first() |
||||||
|
kwargs = { |
||||||
|
'subject': subject_template_name, |
||||||
|
# 'message': get_template(html_email_template_name).templatetags.source |
||||||
|
} |
||||||
|
if not kwargs: |
||||||
|
kwargs = { |
||||||
|
'slug': self.email_slug, |
||||||
|
'name': email_template_name, |
||||||
|
'num_of_retries': 3, |
||||||
|
'is_html': True |
||||||
|
} |
||||||
|
# MailTemplate.objects.create(**kwargs) |
||||||
|
else: |
||||||
|
pass |
||||||
|
# mail_template.subject = kwargs.get('subject', mail_template.subject) |
||||||
|
# mail_template.message = kwargs.get('message', mail_template.message) |
||||||
|
# mail_template.save() |
||||||
|
user = User.active.filter(email__iexact=to_email).first() |
||||||
|
first_name = user.profile.first_name or "" |
||||||
|
last_name = user.profile.last_name or "" |
||||||
|
full_name = first_name + ' ' + last_name |
||||||
|
if len(full_name.strip()) != 0: |
||||||
|
context.update({'username': full_name}) |
||||||
|
# send_db_mail( |
||||||
|
# self.email_slug, |
||||||
|
# to_email, |
||||||
|
# subject_template_name, |
||||||
|
# context, |
||||||
|
# from_email=from_email, |
||||||
|
# retry=True, |
||||||
|
# retry_delay=300, |
||||||
|
# max_retries=3, |
||||||
|
# send_at_date=datetime.now(), |
||||||
|
# use_celery=celery_supported() |
||||||
|
# ) |
||||||
|
except ObjectDoesNotExist as e: |
||||||
|
logger.critical(e) |
||||||
|
|
||||||
|
def clean(self): |
||||||
|
return super().clean() |
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetForm(PasswordChangeFormBase): |
||||||
|
field_template = 'bootstrap/field.html' |
||||||
|
|
||||||
|
field_order = ['new_password1', 'new_password2'] |
||||||
|
|
||||||
|
title = _('Сброс пароля') |
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs): |
||||||
|
self.request = kwargs.pop('request') |
||||||
|
|
||||||
|
self.helper = FormHelper() |
||||||
|
self.helper.form_action = self.request.path |
||||||
|
self.helper.layout = Layout( |
||||||
|
Field('new_password1', template=self.field_template), |
||||||
|
Field('new_password2', template=self.field_template), |
||||||
|
Div( |
||||||
|
Div( |
||||||
|
Submit('submit', _('Сброс'), css_class='btn-danger'), |
||||||
|
css_class='col-lg-12 text-center' |
||||||
|
), |
||||||
|
css_class="row" |
||||||
|
), |
||||||
|
) |
||||||
|
|
||||||
|
super().__init__(kwargs.pop('user'), *args, **kwargs) |
||||||
|
self.fields['new_password1'].help_text = self.fields['new_password1'].help_text.replace('<ul>', |
||||||
|
'<ul class="required-list">') |
||||||
|
|
||||||
|
def is_valid(self): |
||||||
|
valid = super().is_valid() |
||||||
|
if not valid: |
||||||
|
if 'old_password' in self.errors: |
||||||
|
self.errors.pop('old_password') |
||||||
|
valid = super().is_valid() |
||||||
|
return valid |
||||||
|
|
||||||
|
|
||||||
|
class ProfileForm(forms.Form): |
||||||
|
email = forms.CharField(required=False) |
||||||
|
field_template = 'bootstrap/field_admin.html' |
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs): |
||||||
|
super().__init__(*args, **kwargs) |
||||||
|
|
||||||
|
self.helper = FormHelper() |
||||||
|
self.helper.form_action = reverse('accounts_ext:update') |
||||||
|
self.helper.form_class = 'formajax form-replace-block' |
||||||
|
self.helper.layout = Layout( |
||||||
|
Div( |
||||||
|
Field('email', template=self.field_template), |
||||||
|
Field('first_name', template=self.field_template), |
||||||
|
Field('last_name', template=self.field_template), |
||||||
|
Field('patronymic', template=self.field_template), |
||||||
|
Field('birthday', template=self.field_template), |
||||||
|
Field('company_name', template=self.field_template), |
||||||
|
Field('inn', template=self.field_template), |
||||||
|
Field('ogrn', template=self.field_template), |
||||||
|
Field('legal_address', template=self.field_template), |
||||||
|
css_class="setProfile" |
||||||
|
), |
||||||
|
Div( |
||||||
|
Submit('submit', _('Save'), css_class='button button--bigOrange'), |
||||||
|
css_class="settings-button" |
||||||
|
), |
||||||
|
) |
||||||
|
self.initial['email'] = self.instance.user.email |
||||||
|
self.fields['email'].widget.attrs['readonly'] = True |
||||||
|
self.fields['birthday'].widget.attrs['class'] = 'date inputText' |
||||||
|
|
||||||
|
def clean_email(self): |
||||||
|
instance = getattr(self, 'instance', None) |
||||||
|
if instance and instance.pk: |
||||||
|
return instance.user.email |
||||||
|
else: |
||||||
|
return self.cleaned_data['email'] |
||||||
|
|
||||||
|
class Meta: |
||||||
|
model = Profile |
||||||
|
exclude = ('user', 'create_at', 'updated_at', 'status',) |
||||||
@ -0,0 +1,172 @@ |
|||||||
|
from django.contrib.auth import get_user_model |
||||||
|
from django.contrib.auth.models import ( |
||||||
|
Group as GroupBase, AbstractBaseUser, BaseUserManager, PermissionsMixin |
||||||
|
) |
||||||
|
from django.core.exceptions import ObjectDoesNotExist |
||||||
|
from django.core.validators import RegexValidator |
||||||
|
from django.db import models, transaction |
||||||
|
from django.db.models.signals import post_save |
||||||
|
from django.dispatch import receiver |
||||||
|
from django.utils.translation import ugettext_lazy as _ |
||||||
|
from django.utils.timezone import now as datetime_now |
||||||
|
|
||||||
|
from registration.signals import user_activated |
||||||
|
|
||||||
|
from core.models import AbstractStatusModel, ActualOnlyManager, STATUS_ACTIVE |
||||||
|
|
||||||
|
|
||||||
|
# Create your models here. |
||||||
|
|
||||||
|
class CaseInsensitiveQuerySet(models.QuerySet): |
||||||
|
CASE_INSENSITIVE_FIELDS = ('email',) |
||||||
|
|
||||||
|
def _filter_or_exclude(self, negate, *args, **kwargs): |
||||||
|
for field in self.CASE_INSENSITIVE_FIELDS: |
||||||
|
if field in kwargs: |
||||||
|
kwargs[field + '__iexact'] = kwargs[field] |
||||||
|
del kwargs[field] |
||||||
|
return super()._filter_or_exclude(negate, *args, **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
class UserManager(ActualOnlyManager, BaseUserManager): |
||||||
|
def create_superuser(self, email, password): |
||||||
|
user = self.model( |
||||||
|
email=email, |
||||||
|
is_superuser=True, |
||||||
|
status=STATUS_ACTIVE, |
||||||
|
) |
||||||
|
user.set_password(password) |
||||||
|
user.save(using=self._db) |
||||||
|
return user |
||||||
|
|
||||||
|
def get_queryset(self): |
||||||
|
return CaseInsensitiveQuerySet(self.model) |
||||||
|
|
||||||
|
|
||||||
|
class User(AbstractStatusModel, PermissionsMixin, AbstractBaseUser): |
||||||
|
username = models.CharField(_('username'),max_length=255, blank=False, null=False) |
||||||
|
email = models.EmailField( |
||||||
|
_('email'), |
||||||
|
unique=True, |
||||||
|
error_messages={ |
||||||
|
'unique': _("A user with that email already exists."), |
||||||
|
}, |
||||||
|
) |
||||||
|
# referral = models.ForeignKey('referral.Referral', |
||||||
|
# verbose_name=_('Referral code'), |
||||||
|
# on_delete=models.DO_NOTHING, |
||||||
|
# blank=True, null=True, |
||||||
|
# related_name='ref_code') |
||||||
|
referral_user = models.ForeignKey('self', |
||||||
|
verbose_name=_('Referral user'), |
||||||
|
on_delete=models.DO_NOTHING, |
||||||
|
blank=True, null=True, |
||||||
|
related_name='ref_user') |
||||||
|
|
||||||
|
confirmed_at = models.DateTimeField(_('email confirmed at'), blank=True, null=True) |
||||||
|
|
||||||
|
USERNAME_FIELD = 'email' |
||||||
|
|
||||||
|
objects = UserManager() |
||||||
|
|
||||||
|
@property |
||||||
|
def is_staff(self): |
||||||
|
return self.is_superuser |
||||||
|
|
||||||
|
@property |
||||||
|
def date_joined(self): |
||||||
|
return self.create_at |
||||||
|
|
||||||
|
@date_joined.setter |
||||||
|
def date_joined(self, value): |
||||||
|
self.create_at = value |
||||||
|
|
||||||
|
def get_short_name(self): |
||||||
|
return self.email |
||||||
|
|
||||||
|
|
||||||
|
class Group(GroupBase): |
||||||
|
class Meta: |
||||||
|
proxy = True |
||||||
|
verbose_name = GroupBase._meta.verbose_name |
||||||
|
verbose_name_plural = GroupBase._meta.verbose_name_plural |
||||||
|
|
||||||
|
|
||||||
|
class Profile(AbstractStatusModel): |
||||||
|
user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE) |
||||||
|
first_name = models.CharField(_('first name'), max_length=100, blank=True, null=True) |
||||||
|
last_name = models.CharField(_('last name'), max_length=100, blank=True, null=True) |
||||||
|
patronymic = models.CharField(_('patronymic'), max_length=100, blank=True, null=True) |
||||||
|
birthday = models.DateField(_('birthday'), null=True, blank=True) |
||||||
|
|
||||||
|
phone_regex = RegexValidator(regex=r'^\((+7)|8)?\d{10}$', |
||||||
|
message="Phone number must be entered in the format: '+99999999999'. Up to 12 digits allowed.") |
||||||
|
phone = models.CharField(validators=[phone_regex], max_length=12, blank=True, null=True) |
||||||
|
|
||||||
|
@property |
||||||
|
def is_valid(self): |
||||||
|
return self.first_name and self.last_name and self.patronymic |
||||||
|
|
||||||
|
@property |
||||||
|
def is_complete(self): |
||||||
|
return self.first_name and self.last_name and self.patronymic and self.birthday |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = _('profile') |
||||||
|
verbose_name_plural = _('profiles') |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return str(self.user) |
||||||
|
|
||||||
|
|
||||||
|
COMPANY_STATUS_LEGAL = 25 |
||||||
|
COMPANY_STATUS_INDIVIDUAL = 50 |
||||||
|
COMPANY_STATUS_LIST = ( |
||||||
|
(COMPANY_STATUS_INDIVIDUAL, _("Legal")), |
||||||
|
(COMPANY_STATUS_INDIVIDUAL, _("Individual")) |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
class Company(AbstractStatusModel): |
||||||
|
user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE) |
||||||
|
company_name = models.CharField(max_length=255, blank=True, null=True) |
||||||
|
address = models.TextField(blank=True,null=True) |
||||||
|
inn = models.CharField(max_length=12, blank=True, null=True) |
||||||
|
ogrn = models.CharField(max_length=13, blank=True, null=True) |
||||||
|
status = models.SmallIntegerField(choices=COMPANY_STATUS_LIST, blank=True, null=True) |
||||||
|
|
||||||
|
@property |
||||||
|
def is_individual(self): |
||||||
|
return self.status == COMPANY_STATUS_INDIVIDUAL |
||||||
|
|
||||||
|
@property |
||||||
|
def is_legal(self): |
||||||
|
return self.status == COMPANY_STATUS_LEGAL |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return self.company_name |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = _('company') |
||||||
|
verbose_name_plural = _('companies') |
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=get_user_model()) |
||||||
|
def create_user_profile(sender, instance, created, **kwargs): |
||||||
|
if created: |
||||||
|
Profile.objects.create(user=instance) |
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=get_user_model()) |
||||||
|
def save_user_profile(sender, instance, **kwargs): |
||||||
|
try: |
||||||
|
instance.profile.save() |
||||||
|
except ObjectDoesNotExist: |
||||||
|
Profile.objects.create(user=instance) |
||||||
|
|
||||||
|
|
||||||
|
@receiver(user_activated) |
||||||
|
def save_activation_date(sender, user, request, **kwargs): |
||||||
|
user.confirmed_at = datetime_now() |
||||||
|
user.is_active = user.status == STATUS_ACTIVE |
||||||
|
user.save() |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
from django.template import Library |
||||||
|
|
||||||
|
register = Library() |
||||||
|
|
||||||
|
@register.filter(name='get_by_key') |
||||||
|
def get_by_key(dict, key): |
||||||
|
return getattr(dict,key,None) |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.test import TestCase |
||||||
|
|
||||||
|
# Create your tests here. |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
from django.urls import re_path |
||||||
|
from . import views |
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [ |
||||||
|
re_path(r'^login/$', views.LoginView.as_view(), name='login'), |
||||||
|
re_path(r'^logout/$', views.LogoutView.as_view(), name='logout'), |
||||||
|
re_path(r'^register/$', views.RegistrationView.as_view(), name='register'), |
||||||
|
re_path(r'^password/reset/$', views.ResetPasswordView.as_view(), name='reset_password'), |
||||||
|
re_path(r'^password/reset/done/$', views.ResetPasswordDoneView.as_view(), name='reset_password_done'), |
||||||
|
re_path(r'^password/change/$', views.ChangePasswordForm.as_view(), name='change_password'), |
||||||
|
re_path(r'^password/change/done/$', views.PasswordChangeViewBase.as_view(), name='change_password_done'), |
||||||
|
re_path(r'^password/reset/complete/$', views.ResetPasswordCompleteView.as_view(), name='reset_password_complete') |
||||||
|
] |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
|
||||||
|
def get_ballances(user): |
||||||
|
res = {} |
||||||
|
if user: |
||||||
|
for wallet in user.wallet_set.all(): |
||||||
|
info = '%.8f' % wallet.amount |
||||||
|
if wallet.amount_blocked: |
||||||
|
info += ' (%.8f)' % wallet.amount_blocked |
||||||
|
res[wallet.currency.iso] = info |
||||||
|
return res |
||||||
|
|
||||||
|
|
||||||
|
def get_ballances_decimal(user): |
||||||
|
res = {} |
||||||
|
if user: |
||||||
|
for wallet in user.wallet_set.all(): |
||||||
|
info = wallet.amount |
||||||
|
blocked = wallet.amount_blocked |
||||||
|
res[wallet.currency.iso] = (info, blocked) |
||||||
|
return res |
||||||
@ -0,0 +1,203 @@ |
|||||||
|
import logging |
||||||
|
from django.conf import settings |
||||||
|
from django.contrib.auth.views import ( |
||||||
|
LoginView as LoginViewBase, |
||||||
|
LogoutView, |
||||||
|
PasswordResetView as PasswordResetViewBase, |
||||||
|
PasswordResetDoneView as PasswordResetDoneViewBase, |
||||||
|
PasswordResetConfirmView as PasswordResetConfirmViewBase, |
||||||
|
PasswordResetCompleteView as PasswordResetCompleteViewBase, |
||||||
|
PasswordChangeView as PasswordChangeViewBase, |
||||||
|
PasswordChangeDoneView as PasswordChangeDoneViewBase |
||||||
|
) |
||||||
|
from django.views.generic import TemplateView |
||||||
|
|
||||||
|
from registration.backends.default.views import ( |
||||||
|
RegistrationView as RegistrationViewBase, |
||||||
|
ResendActivationView as ResendActivationViewBase |
||||||
|
) |
||||||
|
from django.contrib.messages.views import SuccessMessageMixin |
||||||
|
from django.http import JsonResponse |
||||||
|
from django.shortcuts import redirect, resolve_url |
||||||
|
from django.urls import reverse, reverse_lazy |
||||||
|
from django.utils.http import is_safe_url |
||||||
|
from django.utils.translation import ugettext_lazy as _ |
||||||
|
|
||||||
|
from core.views import ProtectedView |
||||||
|
from .forms import ( |
||||||
|
PasswordResetRequestForm, PasswordResetForm, RegistrationCompanyForm, |
||||||
|
AuthenticationForm, |
||||||
|
RegistrationForm) |
||||||
|
|
||||||
|
logger = logging.getLogger(__name__) |
||||||
|
|
||||||
|
|
||||||
|
# Create your views here. |
||||||
|
|
||||||
|
class LoginView(LoginViewBase): |
||||||
|
redirect_field_name = 'next' |
||||||
|
form_class = AuthenticationForm |
||||||
|
redirect_authenticated_user = True |
||||||
|
template_name = 'accounts_ext/authentication.html' |
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs): |
||||||
|
if self.request.user.is_authenticated: |
||||||
|
redirect_to = self.request.POST.get( |
||||||
|
self.redirect_field_name, |
||||||
|
self.request.GET.get(self.redirect_field_name, '') |
||||||
|
) |
||||||
|
if not is_safe_url(url=redirect_to, host=self.request.get_host()): |
||||||
|
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL) |
||||||
|
if redirect_to == self.request.path: |
||||||
|
raise ValueError( |
||||||
|
"Redirection loop for authenticated user detected. Check that " |
||||||
|
"your LOGIN_REDIRECT_URL doesn't point to a login page." |
||||||
|
) |
||||||
|
return redirect(redirect_to) |
||||||
|
return super().dispatch(request, *args, **kwargs) |
||||||
|
|
||||||
|
def render_done(self, form, **kwargs): |
||||||
|
""" |
||||||
|
This method gets called when all forms passed. The method should also |
||||||
|
re-validate all steps to prevent manipulation. If any form don't |
||||||
|
validate, `render_revalidation_failure` should get called. |
||||||
|
If everything is fine call `done`. |
||||||
|
""" |
||||||
|
final_form_list = [] |
||||||
|
# walk through the form list and try to validate the data again. |
||||||
|
for form_key in self.get_form_list(): |
||||||
|
form_obj = self.get_form(step=form_key, |
||||||
|
data=self.storage.get_step_data(form_key), |
||||||
|
files=self.storage.get_step_files( |
||||||
|
form_key)) |
||||||
|
form_obj.exclude_second_captcha_validation = True |
||||||
|
if not (form_key in self.idempotent_dict or form_obj.is_valid()): |
||||||
|
return self.render_revalidation_failure(form_key, form_obj, |
||||||
|
**kwargs) |
||||||
|
final_form_list.append(form_obj) |
||||||
|
|
||||||
|
# render the done view and reset the wizard before returning the |
||||||
|
# response. This is needed to prevent from rendering done with the |
||||||
|
# same data twice. |
||||||
|
done_response = self.done(final_form_list, **kwargs) |
||||||
|
self.storage.reset() |
||||||
|
return done_response |
||||||
|
|
||||||
|
def get_user(self): |
||||||
|
""" |
||||||
|
Returns the user authenticated by the AuthenticationForm. Returns False |
||||||
|
if not a valid user; see also issue #65. |
||||||
|
""" |
||||||
|
if not self.user_cache: |
||||||
|
form_obj = self.get_form(step='auth', |
||||||
|
data=self.storage.get_step_data('auth')) |
||||||
|
form_obj.exclude_second_captcha_validation = True |
||||||
|
self.user_cache = form_obj.is_valid() and form_obj.user_cache |
||||||
|
return self.user_cache |
||||||
|
|
||||||
|
def get_context_data(self, **kwargs): |
||||||
|
context = super().get_context_data(**kwargs) |
||||||
|
context['title'] = AuthenticationForm.title |
||||||
|
return context |
||||||
|
|
||||||
|
class ResetPasswordView(PasswordResetViewBase): |
||||||
|
form_class = PasswordResetRequestForm |
||||||
|
template_name = 'accounts_ext/reset_password.html' |
||||||
|
email_template_name = 'Reset password email' |
||||||
|
html_email_template_name = 'emails/reset_password_email.html' |
||||||
|
success_url = reverse_lazy('accounts_ext:reset_password_done') |
||||||
|
from_email = settings.DEFAULT_FROM_EMAIL |
||||||
|
subject_template_name = _('Сброс пароля') |
||||||
|
|
||||||
|
def get_context_data(self, **kwargs): |
||||||
|
context = super().get_context_data(**kwargs) |
||||||
|
context['title'] = PasswordResetForm.title |
||||||
|
return context |
||||||
|
|
||||||
|
|
||||||
|
class ResetPasswordDoneView(PasswordResetDoneViewBase): |
||||||
|
template_name = 'accounts_ext/reset_password_done.html' |
||||||
|
|
||||||
|
|
||||||
|
class ResetPasswordConfirmView(PasswordResetConfirmViewBase): |
||||||
|
form_class = PasswordResetForm |
||||||
|
template_name = 'accounts_ext/reset_password_confirm.html' |
||||||
|
success_url = reverse_lazy('accounts_ext:reset_password_complete') |
||||||
|
|
||||||
|
def get_form_kwargs(self): |
||||||
|
kwargs = super().get_form_kwargs() |
||||||
|
kwargs['request'] = self.request |
||||||
|
return kwargs |
||||||
|
|
||||||
|
|
||||||
|
class ResetPasswordCompleteView(PasswordResetCompleteViewBase): |
||||||
|
template_name = 'accounts_ext/reset_password_complete.html' |
||||||
|
title = _('Password reset complete') |
||||||
|
|
||||||
|
|
||||||
|
class RegistrationView(RegistrationViewBase): |
||||||
|
http_method_names = ['get', 'post'] |
||||||
|
template_name = 'registration/registration.html' |
||||||
|
|
||||||
|
def get_context_data(self, **kwargs): |
||||||
|
context = super().get_context_data(**kwargs) |
||||||
|
if self.request.POST: |
||||||
|
context['company_form'] = RegistrationCompanyForm(self.request.POST) |
||||||
|
else: |
||||||
|
context['company_form'] = RegistrationCompanyForm() |
||||||
|
context['title'] = RegistrationForm.title |
||||||
|
return context |
||||||
|
|
||||||
|
def form_valid(self, form): |
||||||
|
context = self.get_context_data() |
||||||
|
company_form = context.get('company_form') |
||||||
|
try: |
||||||
|
user = form.save() |
||||||
|
if company_form.is_valid(): |
||||||
|
company_form.save(user=user) |
||||||
|
else: |
||||||
|
logger.error("User {email} company has invalid data during registration") |
||||||
|
except Exception as e: |
||||||
|
logger.error(e) |
||||||
|
return self.form_invalid(form=form) |
||||||
|
return super().form_valid(form) |
||||||
|
|
||||||
|
|
||||||
|
class RegistrationDoneView(TemplateView): |
||||||
|
template_name = 'registration/registration_done.html' |
||||||
|
|
||||||
|
def get_context_data(self, **kwargs): |
||||||
|
context = super().get_context_data(**kwargs) |
||||||
|
context['title'] = _('Отправка письма активации') |
||||||
|
return context |
||||||
|
|
||||||
|
|
||||||
|
class ResendActivationView(ResendActivationViewBase): |
||||||
|
template_name = 'registration/resend_activation.tml' |
||||||
|
|
||||||
|
def get_context_data(self, **kwargs): |
||||||
|
context = super().get_context_data(**kwargs) |
||||||
|
context['title'] = _('Отправка письма активации') |
||||||
|
return context |
||||||
|
|
||||||
|
|
||||||
|
class ChangePasswordForm(PasswordChangeViewBase): |
||||||
|
template_name = 'accounts_ext/password_reset_change.html' |
||||||
|
|
||||||
|
def get_context_data(self, **kwargs): |
||||||
|
context = super().get_context_data(**kwargs) |
||||||
|
context['title'] = _('Введение нового пароля') |
||||||
|
return context |
||||||
|
|
||||||
|
|
||||||
|
class ChangePasswordDoneForm(PasswordChangeDoneViewBase): |
||||||
|
template_name = 'accounts_ext/password_reset_change_done.html' |
||||||
|
|
||||||
|
def get_context_data(self, **kwargs): |
||||||
|
context = super().get_context_data(**kwargs) |
||||||
|
context['title'] = _('Сброс пароля') |
||||||
|
return context |
||||||
|
|
||||||
|
|
||||||
|
class ProfileView(ProtectedView): |
||||||
|
template_name = 'accounts_ext/index.html' |
||||||
Loading…
Reference in new issue