mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-08-04 04:35:19 +02:00
Initial migration to new session based auth system with AllAuth
This commit is contained in:
parent
7defdac3a8
commit
9bc20be70e
24 changed files with 313 additions and 773 deletions
10
backend/server/users/adapters.py
Normal file
10
backend/server/users/adapters.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from allauth.account.adapter import DefaultAccountAdapter
|
||||
from django.conf import settings
|
||||
|
||||
class NoNewUsersAccountAdapter(DefaultAccountAdapter):
|
||||
"""
|
||||
Disable new user registration.
|
||||
"""
|
||||
def is_open_for_signup(self, request):
|
||||
is_disabled = getattr(settings, 'DISABLE_REGISTRATION', False)
|
||||
return not is_disabled
|
|
@ -1,3 +1,10 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here
|
||||
from django.contrib.sessions.models import Session
|
||||
|
||||
class SessionAdmin(admin.ModelAdmin):
|
||||
def _session_data(self, obj):
|
||||
return obj.get_decoded()
|
||||
list_display = ['session_key', '_session_data', 'expire_date']
|
||||
|
||||
admin.site.register(Session, SessionAdmin)
|
17
backend/server/users/form_overrides.py
Normal file
17
backend/server/users/form_overrides.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from django import forms
|
||||
|
||||
class CustomSignupForm(forms.Form):
|
||||
first_name = forms.CharField(max_length=30, required=True)
|
||||
last_name = forms.CharField(max_length=30, required=True)
|
||||
|
||||
def signup(self, request, user):
|
||||
# Delay the import to avoid circular import
|
||||
from allauth.account.forms import SignupForm
|
||||
|
||||
# No need to call super() from CustomSignupForm; use the SignupForm directly if needed
|
||||
user.first_name = self.cleaned_data['first_name']
|
||||
user.last_name = self.cleaned_data['last_name']
|
||||
|
||||
# Save the user instance
|
||||
user.save()
|
||||
return user
|
|
@ -1,55 +1,17 @@
|
|||
from allauth.account.utils import (filter_users_by_email, user_pk_to_url_str, user_username)
|
||||
from allauth.utils import build_absolute_uri
|
||||
from allauth.account.adapter import get_adapter
|
||||
from allauth.account.forms import default_token_generator
|
||||
from allauth.account import app_settings
|
||||
from django.conf import settings
|
||||
from django import forms
|
||||
|
||||
from allauth.account.forms import ResetPasswordForm as AllAuthPasswordResetForm
|
||||
class CustomSignupForm(forms.Form):
|
||||
first_name = forms.CharField(max_length=30, required=True)
|
||||
last_name = forms.CharField(max_length=30, required=True)
|
||||
|
||||
class CustomAllAuthPasswordResetForm(AllAuthPasswordResetForm):
|
||||
|
||||
def clean_email(self):
|
||||
"""
|
||||
Invalid email should not raise error, as this would leak users
|
||||
for unit test: test_password_reset_with_invalid_email
|
||||
"""
|
||||
email = self.cleaned_data["email"]
|
||||
email = get_adapter().clean_email(email)
|
||||
self.users = filter_users_by_email(email, is_active=True)
|
||||
return self.cleaned_data["email"]
|
||||
|
||||
def save(self, request, **kwargs):
|
||||
email = self.cleaned_data['email']
|
||||
token_generator = kwargs.get('token_generator', default_token_generator)
|
||||
|
||||
for user in self.users:
|
||||
temp_key = token_generator.make_token(user)
|
||||
|
||||
path = f"custom_password_reset_url/{user_pk_to_url_str(user)}/{temp_key}/"
|
||||
url = build_absolute_uri(request, path)
|
||||
|
||||
frontend_url = settings.FRONTEND_URL
|
||||
# remove ' from frontend_url
|
||||
frontend_url = frontend_url.replace("'", "")
|
||||
|
||||
#Values which are passed to password_reset_key_message.txt
|
||||
context = {
|
||||
"frontend_url": frontend_url,
|
||||
"user": user,
|
||||
"password_reset_url": url,
|
||||
"request": request,
|
||||
"path": path,
|
||||
"temp_key": temp_key,
|
||||
'user_pk': user_pk_to_url_str(user),
|
||||
}
|
||||
|
||||
if app_settings.AUTHENTICATION_METHOD != app_settings.AuthenticationMethod.EMAIL:
|
||||
context['username'] = user_username(user)
|
||||
get_adapter(request).send_mail(
|
||||
'account/email/password_reset_key', email, context
|
||||
)
|
||||
|
||||
return self.cleaned_data['email']
|
||||
|
||||
def signup(self, request, user):
|
||||
# Delay the import to avoid circular import
|
||||
from allauth.account.forms import SignupForm
|
||||
|
||||
# No need to call super() from CustomSignupForm; use the SignupForm directly if needed
|
||||
user.first_name = self.cleaned_data['first_name']
|
||||
user.last_name = self.cleaned_data['last_name']
|
||||
|
||||
# Save the user instance
|
||||
user.save()
|
||||
return user
|
|
@ -1,10 +1,8 @@
|
|||
from rest_framework import serializers
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from adventures.models import Adventure, Collection
|
||||
from users.forms import CustomAllAuthPasswordResetForm
|
||||
from adventures.models import Collection
|
||||
from dj_rest_auth.serializers import PasswordResetSerializer
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
@ -32,77 +30,7 @@ class ChangeEmailSerializer(serializers.Serializer):
|
|||
return value
|
||||
|
||||
|
||||
class RegisterSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(
|
||||
max_length=get_username_max_length(),
|
||||
min_length=allauth_account_settings.USERNAME_MIN_LENGTH,
|
||||
required=allauth_account_settings.USERNAME_REQUIRED,
|
||||
)
|
||||
email = serializers.EmailField(required=allauth_account_settings.EMAIL_REQUIRED)
|
||||
password1 = serializers.CharField(write_only=True)
|
||||
password2 = serializers.CharField(write_only=True)
|
||||
first_name = serializers.CharField(required=False)
|
||||
last_name = serializers.CharField(required=False)
|
||||
|
||||
def validate_username(self, username):
|
||||
username = get_adapter().clean_username(username)
|
||||
return username
|
||||
|
||||
def validate_email(self, email):
|
||||
email = get_adapter().clean_email(email)
|
||||
if allauth_account_settings.UNIQUE_EMAIL:
|
||||
if email and EmailAddress.objects.is_verified(email):
|
||||
raise serializers.ValidationError(
|
||||
_('A user is already registered with this e-mail address.'),
|
||||
)
|
||||
return email
|
||||
|
||||
def validate_password1(self, password):
|
||||
return get_adapter().clean_password(password)
|
||||
|
||||
def validate(self, data):
|
||||
if data['password1'] != data['password2']:
|
||||
raise serializers.ValidationError(_("The two password fields didn't match."))
|
||||
|
||||
# check if a user with the same email already exists
|
||||
if User.objects.filter(email=data['email']).exists():
|
||||
raise serializers.ValidationError("This email is already in use.")
|
||||
|
||||
return data
|
||||
|
||||
def custom_signup(self, request, user):
|
||||
pass
|
||||
|
||||
def get_cleaned_data(self):
|
||||
return {
|
||||
'username': self.validated_data.get('username', ''),
|
||||
'password1': self.validated_data.get('password1', ''),
|
||||
'email': self.validated_data.get('email', ''),
|
||||
'first_name': self.validated_data.get('first_name', ''),
|
||||
'last_name': self.validated_data.get('last_name', ''),
|
||||
}
|
||||
|
||||
def save(self, request):
|
||||
# Check if registration is disabled
|
||||
if getattr(settings, 'DISABLE_REGISTRATION', False):
|
||||
raise PermissionDenied("Registration is currently disabled.")
|
||||
|
||||
# If registration is not disabled, proceed with the original logic
|
||||
adapter = get_adapter()
|
||||
user = adapter.new_user(request)
|
||||
self.cleaned_data = self.get_cleaned_data()
|
||||
user = adapter.save_user(request, user, self, commit=False)
|
||||
if "password1" in self.cleaned_data:
|
||||
try:
|
||||
adapter.clean_password(self.cleaned_data['password1'], user=user)
|
||||
except DjangoValidationError as exc:
|
||||
raise serializers.ValidationError(
|
||||
detail=serializers.as_serializer_error(exc)
|
||||
)
|
||||
user.save()
|
||||
self.custom_signup(request, user)
|
||||
setup_user_email(request, user, [])
|
||||
return user
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
|
@ -116,20 +44,6 @@ from rest_framework import serializers
|
|||
from django.conf import settings
|
||||
import os
|
||||
|
||||
# class AdventureSerializer(serializers.ModelSerializer):
|
||||
# image = serializers.SerializerMethodField()
|
||||
|
||||
# class Meta:
|
||||
# model = Adventure
|
||||
# fields = ['id', 'user_id', 'type', 'name', 'location', 'activity_types', 'description',
|
||||
# 'rating', 'link', 'image', 'date', 'trip_id', 'is_public', 'longitude', 'latitude']
|
||||
|
||||
# def get_image(self, obj):
|
||||
# if obj.image:
|
||||
# public_url = os.environ.get('PUBLIC_URL', '')
|
||||
# return f'{public_url}/media/{obj.image.name}'
|
||||
# return None
|
||||
|
||||
class UserDetailsSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
User model w/o password
|
||||
|
@ -203,13 +117,3 @@ class CustomUserDetailsSerializer(UserDetailsSerializer):
|
|||
representation['profile_pic'] = f"{public_url}/media/{instance.profile_pic.name}"
|
||||
del representation['pk'] # remove the pk field from the response
|
||||
return representation
|
||||
|
||||
class MyPasswordResetSerializer(PasswordResetSerializer):
|
||||
|
||||
def validate_email(self, value):
|
||||
# use the custom reset form
|
||||
self.reset_form = CustomAllAuthPasswordResetForm(data=self.initial_data)
|
||||
if not self.reset_form.is_valid():
|
||||
raise serializers.ValidationError(self.reset_form.errors)
|
||||
|
||||
return value
|
|
@ -83,3 +83,18 @@ class PublicUserDetailView(APIView):
|
|||
user.email = None
|
||||
serializer = PublicUserSerializer(user)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
class UserMetadataView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@swagger_auto_schema(
|
||||
responses={
|
||||
200: openapi.Response('User metadata'),
|
||||
400: 'Bad Request'
|
||||
},
|
||||
operation_description="Get user metadata."
|
||||
)
|
||||
def get(self, request):
|
||||
user = request.user
|
||||
serializer = PublicUserSerializer(user)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
Loading…
Add table
Add a link
Reference in a new issue