добавил авторизацию
This commit is contained in:
parent
7475f8251e
commit
09b45bd1d4
|
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AccountConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'account'
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.forms import ReadOnlyPasswordHashField
|
||||
from django.contrib.auth.forms import ReadOnlyPasswordHashField
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from account.models import MyUser
|
||||
|
||||
|
||||
class UserCreationForm(forms.ModelForm):
|
||||
"""A form for creating new users. Includes all the required
|
||||
fields, plus a repeated password."""
|
||||
password1 = forms.CharField(label='Пароль', widget=forms.PasswordInput)
|
||||
password2 = forms.CharField(label='Пароль ещё раз', widget=forms.PasswordInput)
|
||||
|
||||
class Meta:
|
||||
model = MyUser
|
||||
fields = ('email',)
|
||||
|
||||
def clean_password2(self):
|
||||
# Check that the two password entries match
|
||||
password1 = self.cleaned_data.get("password1")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password1 and password2 and password1 != password2:
|
||||
raise ValidationError("Пароли не совпадают")
|
||||
return password2
|
||||
|
||||
def save(self, commit=True):
|
||||
# Save the provided password in hashed format
|
||||
user = super().save(commit=False)
|
||||
user.set_password(self.cleaned_data["password1"])
|
||||
if commit:
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
class UserChangeForm(forms.ModelForm):
|
||||
"""A form for updating users. Includes all the fields on
|
||||
the user, but replaces the password field with admin's
|
||||
disabled password hash display field.
|
||||
"""
|
||||
password = ReadOnlyPasswordHashField(
|
||||
label='Пароль',
|
||||
help_text='Пароли не хранятся в открытом виде, поэтому нет возможности увидеть пароль этого пользователя, '
|
||||
'но вы можете изменить пароль, воспользовавшись '
|
||||
'<a href="{}">этой формой</a>.',
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = MyUser
|
||||
fields = ('email', 'password', 'is_active', 'is_staff', 'is_superuser')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
password = self.fields.get('password')
|
||||
if password:
|
||||
password.help_text = password.help_text.format('../password/')
|
||||
user_permissions = self.fields.get('user_permissions')
|
||||
if user_permissions:
|
||||
user_permissions.queryset = user_permissions.queryset.select_related('content_type')
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.core.mail import send_mail
|
||||
from django.contrib.auth.models import (
|
||||
BaseUserManager, AbstractBaseUser, PermissionsMixin
|
||||
)
|
||||
|
||||
|
||||
class MyUserManager(BaseUserManager):
|
||||
def create_user(self, email, phone, password=None):
|
||||
"""
|
||||
Creates and saves a User with the given email, date of
|
||||
birth and password.
|
||||
"""
|
||||
if not email:
|
||||
raise ValueError('Users must have an email address')
|
||||
|
||||
user = self.model(
|
||||
email=self.normalize_email(email),
|
||||
phone=phone
|
||||
)
|
||||
|
||||
user.set_password(password)
|
||||
user.save(using=self._db)
|
||||
return user
|
||||
|
||||
def create_superuser(self, email, password=None):
|
||||
"""
|
||||
Creates and saves a superuser with the given email, date of
|
||||
birth and password.
|
||||
"""
|
||||
user = self.create_user(
|
||||
email,
|
||||
password=password,
|
||||
)
|
||||
user.is_staff = True
|
||||
user.is_superuser = True
|
||||
user.set_password(password)
|
||||
user.save(using=self._db)
|
||||
return user
|
||||
|
||||
|
||||
class MyUser(AbstractBaseUser, PermissionsMixin):
|
||||
email = models.EmailField(
|
||||
verbose_name='Емайл',
|
||||
max_length=255,
|
||||
unique=True,
|
||||
)
|
||||
first_name = models.CharField('Имя', max_length=150, blank=True)
|
||||
last_name = models.CharField('Фамилия', max_length=150, blank=True)
|
||||
phone = models.CharField('Телефон', max_length=15, blank=True, null=True, unique=True)
|
||||
is_active = models.BooleanField('Активный', help_text='Отметьте, если пользователь должен считаться активным. '
|
||||
'Уберите эту отметку вместо удаления учётной записи.', default=True)
|
||||
is_staff = models.BooleanField('Статус персонала', help_text='Отметьте, если пользователь может входить в '
|
||||
'административную часть сайта.', default=False)
|
||||
date_joined = models.DateTimeField('Дата регистрации', default=timezone.now)
|
||||
organization = models.CharField('Название организаци', max_length=200, null=True)
|
||||
INN_us = models.CharField('ИНН', max_length=12, null=True)
|
||||
urid_adress = models.CharField('Юридический адрес', max_length=200, null=True)
|
||||
number = models.CharField('Номер телефона', max_length=20, null=True)
|
||||
|
||||
objects = MyUserManager()
|
||||
|
||||
USERNAME_FIELD = 'email'
|
||||
|
||||
def __str__(self):
|
||||
return self.email
|
||||
|
||||
def full_name(self):
|
||||
return f'{self.first_name} {self.last_name}' if self.first_name and self.last_name else self.email
|
||||
|
||||
def has_perm(self, perm, obj=None):
|
||||
"""Does the user have a specific permission?"""
|
||||
# Simplest possible answer: Yes, always
|
||||
return True
|
||||
|
||||
def has_module_perms(self, app_label):
|
||||
"""Does the user have permissions to view the app `app_label`?"""
|
||||
# Simplest possible answer: Yes, always
|
||||
return True
|
||||
|
||||
def email_user(self, subject, message, from_email=None, **kwargs):
|
||||
"""Send an email to this user."""
|
||||
send_mail(subject, message, from_email, [self.email], **kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Пользователь'
|
||||
verbose_name_plural = 'Пользователи'
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
from rest_framework.serializers import ModelSerializer, CharField, SerializerMethodField, ListField, IntegerField
|
||||
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
||||
from account.models import MyUser
|
||||
|
||||
|
||||
class MyUserSerializer(ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
user = MyUser.objects.create_user(**validated_data)
|
||||
return user
|
||||
|
||||
class Meta:
|
||||
model = MyUser
|
||||
fields = ('id', 'email', 'password',
|
||||
'first_name', 'last_name',
|
||||
'phone', 'date_joined',
|
||||
'last_login', 'INN_us',
|
||||
'urid_adress', 'organization'
|
||||
)
|
||||
extra_kwargs = {
|
||||
'password': {'write_only': True},
|
||||
}
|
||||
|
||||
|
||||
|
||||
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
|
||||
|
||||
@classmethod
|
||||
def get_token(cls, user):
|
||||
token = super().get_token(user)
|
||||
token['email'] = user.email
|
||||
token['first_name'] = user.first_name
|
||||
token['last_name'] = user.last_name
|
||||
|
||||
return token
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from rest_framework import routers
|
||||
from account import views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
|
||||
router.register(r'', views.MyUserViewSet, basename='users')
|
||||
|
||||
app_name = 'account'
|
||||
urlpatterns = router.urls
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
from rest_framework.viewsets import ViewSet
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.permissions import IsAdminUser, IsAuthenticated, AllowAny
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework import status
|
||||
from django.core.mail import send_mail
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from conf import settings
|
||||
from account.serializers import MyUserSerializer, MyTokenObtainPairSerializer
|
||||
from account.models import MyUser
|
||||
PermissionClass = IsAuthenticated if not settings.DEBUG else AllowAny
|
||||
|
||||
class MyTokenObtainPairView(TokenObtainPairView):
|
||||
permission_classes = [AllowAny]
|
||||
serializer_class = MyTokenObtainPairSerializer
|
||||
|
||||
|
||||
class MyUserViewSet(ViewSet):
|
||||
"""
|
||||
list:
|
||||
Авторизированный пользователь
|
||||
create_user:
|
||||
Создание пользователя
|
||||
update_user:
|
||||
Обновление пользователей
|
||||
"""
|
||||
|
||||
def list(self, request):
|
||||
serializer = MyUserSerializer(request.user, many=False)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
@action(detail=False, methods=['post'])
|
||||
def create_user(self, request):
|
||||
serializer = MyUserSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
else:
|
||||
text_error = ''
|
||||
error_dict = {}
|
||||
for error in serializer.errors:
|
||||
elm_error = serializer.errors.get(error)
|
||||
if len(elm_error) > 0:
|
||||
text_error += "{} \n".format(elm_error[0])
|
||||
error_dict.update({error: elm_error[0]})
|
||||
return Response({"detail": text_error, "error": error_dict}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
token_data = {
|
||||
"email": request.data["email"],
|
||||
"password": request.data["password"]
|
||||
}
|
||||
token_serializer = MyTokenObtainPairSerializer(data=token_data)
|
||||
token_serializer.is_valid(raise_exception=True)
|
||||
return Response(token_serializer.validated_data, status=status.HTTP_201_CREATED)
|
||||
|
||||
@action(detail=False, methods=['post'])
|
||||
def update_user(self, request):
|
||||
if 'email' in request.data:
|
||||
del request.data['email']
|
||||
if 'password' in request.data:
|
||||
request.data['password'] = make_password(request.data['password'])
|
||||
serializer = MyUserSerializer(request.user, data=request.data, partial=True)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(detail=False, methods=['post'])
|
||||
def password_reset_user(self, request):
|
||||
if 'email' in request.data:
|
||||
email = request.data.get('email')
|
||||
try:
|
||||
user = MyUser.objects.get(email=email)
|
||||
password = MyUser.objects.make_random_password()
|
||||
user.set_password(password)
|
||||
user.save(update_fields=['password'])
|
||||
message = "Запрос на восстановление пароля \nНовый пароль сгенерирован: {password}".format(password=password)
|
||||
send_mail('Смена пароля', message, settings.EMAIL_HOST_USER, [email])
|
||||
return Response({'detail': 'Новый пароль отправлен на емайл: {}'.format(email)}, status=status.HTTP_200_OK)
|
||||
except MyUser.DoesNotExist:
|
||||
text = 'Пользователь с емайлом {}, не найден'.format(email)
|
||||
return Response({'detail': text, 'error': {'email': text}}, status=status.HTTP_400_BAD_REQUEST)
|
||||
except:
|
||||
return Response(
|
||||
{'detail': 'Произошла неизвестная ошибка', 'error': {'email': 'Произошла неизвестная ошибка'}},
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response({'detail': 'Не передан емайл', 'error': {'email': 'Не передан емайл'}},
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def get_permissions(self):
|
||||
if self.action == "list":
|
||||
permission_classes = [IsAuthenticated]
|
||||
elif self.action == "create_user":
|
||||
permission_classes = [AllowAny]
|
||||
elif self.action == "update_user":
|
||||
permission_classes = [IsAuthenticated]
|
||||
elif self.action == "password_reset_user":
|
||||
permission_classes = [AllowAny]
|
||||
else:
|
||||
permission_classes = [IsAdminUser]
|
||||
return [permission() for permission in permission_classes]
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -110,7 +110,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|||
ROTATE_LOG_SIZE = 15 * 1024 * 1024
|
||||
ROTATE_LOG_COUNT = 10
|
||||
|
||||
LOGGING = {
|
||||
""" LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
|
|
@ -159,7 +159,7 @@ LOGGING = {
|
|||
'propagate': False,
|
||||
},
|
||||
},
|
||||
}
|
||||
} """
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ urlpatterns = [
|
|||
path('api/', include_docs_urls(title='API docs')),
|
||||
path('api/radio/', include(router.urls)),
|
||||
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
|
||||
path('api/user/', include('account.urls', namespace='user')),
|
||||
# path('webhook/', AzuraNowPlayingWebhookView.as_view(), name='webhook-receiver'),
|
||||
path('api/login/', login, name='login'),
|
||||
path('api/register/', register, name='register'),
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue