Add JWT auth with per-user data isolation and account settings.
Users can register, log in, and manage profile/password in a personal account page; server data is scoped by owner across contacts, maps, tags, and import. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.password_validation import validate_password
|
||||
from rest_framework import serializers
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class RegisterSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(max_length=150)
|
||||
email = serializers.EmailField(required=False, allow_blank=True)
|
||||
password = serializers.CharField(write_only=True, min_length=8)
|
||||
|
||||
def validate_username(self, value):
|
||||
username = value.strip()
|
||||
if not username:
|
||||
raise serializers.ValidationError('Укажите имя пользователя.')
|
||||
if User.objects.filter(username__iexact=username).exists():
|
||||
raise serializers.ValidationError('Это имя пользователя уже занято.')
|
||||
return username
|
||||
|
||||
def validate_password(self, value):
|
||||
validate_password(value)
|
||||
return value
|
||||
|
||||
def create(self, validated_data):
|
||||
email = (validated_data.get('email') or '').strip()
|
||||
return User.objects.create_user(
|
||||
username=validated_data['username'],
|
||||
email=email,
|
||||
password=validated_data['password'],
|
||||
)
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['id', 'username', 'email']
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
class UpdateProfileSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(max_length=150, required=False)
|
||||
email = serializers.EmailField(required=False, allow_blank=True)
|
||||
current_password = serializers.CharField(write_only=True)
|
||||
|
||||
def validate_current_password(self, value):
|
||||
user = self.context['request'].user
|
||||
if not user.check_password(value):
|
||||
raise serializers.ValidationError('Неверный текущий пароль.')
|
||||
return value
|
||||
|
||||
def validate_username(self, value):
|
||||
username = value.strip()
|
||||
if not username:
|
||||
raise serializers.ValidationError('Укажите имя пользователя.')
|
||||
user = self.context['request'].user
|
||||
if User.objects.filter(username__iexact=username).exclude(pk=user.pk).exists():
|
||||
raise serializers.ValidationError('Это имя пользователя уже занято.')
|
||||
return username
|
||||
|
||||
def validate(self, data):
|
||||
if 'username' not in data and 'email' not in data:
|
||||
raise serializers.ValidationError('Укажите новое имя пользователя или email.')
|
||||
return data
|
||||
|
||||
def save(self):
|
||||
user = self.context['request'].user
|
||||
if 'username' in self.validated_data:
|
||||
user.username = self.validated_data['username']
|
||||
if 'email' in self.validated_data:
|
||||
user.email = (self.validated_data.get('email') or '').strip()
|
||||
user.save(update_fields=['username', 'email'])
|
||||
return user
|
||||
|
||||
|
||||
class ChangePasswordSerializer(serializers.Serializer):
|
||||
current_password = serializers.CharField(write_only=True)
|
||||
new_password = serializers.CharField(write_only=True, min_length=8)
|
||||
|
||||
def validate_current_password(self, value):
|
||||
user = self.context['request'].user
|
||||
if not user.check_password(value):
|
||||
raise serializers.ValidationError('Неверный текущий пароль.')
|
||||
return value
|
||||
|
||||
def validate_new_password(self, value):
|
||||
validate_password(value, self.context['request'].user)
|
||||
return value
|
||||
|
||||
def save(self):
|
||||
user = self.context['request'].user
|
||||
user.set_password(self.validated_data['new_password'])
|
||||
user.save(update_fields=['password'])
|
||||
return user
|
||||
Reference in New Issue
Block a user