добавил авторизацию

This commit is contained in:
Mike0001-droid 2024-06-04 14:39:37 +05:00
parent 7475f8251e
commit 09b45bd1d4
29 changed files with 312 additions and 3 deletions

View File

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class AccountConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'account'

View File

@ -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')

View File

@ -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 = 'Пользователи'

View File

@ -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

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -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

View File

@ -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]

View File

@ -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': [

View File

@ -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'),