mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-08-02 19:55:18 +02:00
feat: Implement disable password authentication for users with social accounts
This commit is contained in:
parent
189cd0ee69
commit
a38828eb45
14 changed files with 184 additions and 17 deletions
16
backend/server/users/backends.py
Normal file
16
backend/server/users/backends.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from django.contrib.auth.backends import ModelBackend
|
||||
from allauth.socialaccount.models import SocialAccount
|
||||
|
||||
class NoPasswordAuthBackend(ModelBackend):
|
||||
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||
print("NoPasswordAuthBackend")
|
||||
# First, attempt normal authentication
|
||||
user = super().authenticate(request, username=username, password=password, **kwargs)
|
||||
if user is None:
|
||||
return None
|
||||
|
||||
if SocialAccount.objects.filter(user=user).exists() and user.disable_password:
|
||||
# If yes, disable login via password
|
||||
return None
|
||||
|
||||
return user
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.0.8 on 2025-03-17 01:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0003_alter_customuser_email'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='disable_password',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -8,6 +8,7 @@ class CustomUser(AbstractUser):
|
|||
profile_pic = ResizedImageField(force_format="WEBP", quality=75, null=True, blank=True, upload_to='profile-pics/')
|
||||
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||
public_profile = models.BooleanField(default=False)
|
||||
disable_password = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.username
|
|
@ -64,9 +64,11 @@ class UserDetailsSerializer(serializers.ModelSerializer):
|
|||
extra_fields.append('date_joined')
|
||||
if hasattr(UserModel, 'is_staff'):
|
||||
extra_fields.append('is_staff')
|
||||
if hasattr(UserModel, 'disable_password'):
|
||||
extra_fields.append('disable_password')
|
||||
|
||||
fields = ['pk', *extra_fields]
|
||||
read_only_fields = ('email', 'date_joined', 'is_staff', 'is_superuser', 'is_active', 'pk')
|
||||
read_only_fields = ('email', 'date_joined', 'is_staff', 'is_superuser', 'is_active', 'pk', 'disable_password')
|
||||
|
||||
def handle_public_profile_change(self, instance, validated_data):
|
||||
"""
|
||||
|
@ -95,7 +97,7 @@ class CustomUserDetailsSerializer(UserDetailsSerializer):
|
|||
class Meta(UserDetailsSerializer.Meta):
|
||||
model = CustomUser
|
||||
fields = UserDetailsSerializer.Meta.fields + ['profile_pic', 'uuid', 'public_profile', 'has_password']
|
||||
read_only_fields = UserDetailsSerializer.Meta.read_only_fields + ('uuid', 'has_password')
|
||||
read_only_fields = UserDetailsSerializer.Meta.read_only_fields + ('uuid', 'has_password', 'disable_password')
|
||||
|
||||
@staticmethod
|
||||
def get_has_password(instance):
|
||||
|
|
|
@ -13,6 +13,7 @@ from .serializers import CustomUserDetailsSerializer as PublicUserSerializer
|
|||
from allauth.socialaccount.models import SocialApp
|
||||
from adventures.serializers import AdventureSerializer, CollectionSerializer
|
||||
from adventures.models import Adventure, Collection
|
||||
from allauth.socialaccount.models import SocialAccount
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
@ -171,4 +172,35 @@ class EnabledSocialProvidersView(APIView):
|
|||
'url': f"{getenv('PUBLIC_URL')}/accounts/{new_provider}/login/",
|
||||
'name': provider.name
|
||||
})
|
||||
return Response(providers, status=status.HTTP_200_OK)
|
||||
return Response(providers, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DisablePasswordAuthenticationView(APIView):
|
||||
"""
|
||||
Disable password authentication for a user. This is used when a user signs up with a social provider.
|
||||
"""
|
||||
|
||||
# Allows the user to set the disable_password field to True if they have a social account linked
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@swagger_auto_schema(
|
||||
responses={
|
||||
200: openapi.Response('Password authentication disabled'),
|
||||
400: 'Bad Request'
|
||||
},
|
||||
operation_description="Disable password authentication."
|
||||
)
|
||||
def post(self, request):
|
||||
user = request.user
|
||||
if SocialAccount.objects.filter(user=user).exists():
|
||||
user.disable_password = True
|
||||
user.save()
|
||||
return Response({"detail": "Password authentication disabled."}, status=status.HTTP_200_OK)
|
||||
return Response({"detail": "No social account linked."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def delete(self, request):
|
||||
user = request.user
|
||||
user.disable_password = False
|
||||
user.save()
|
||||
return Response({"detail": "Password authentication enabled."}, status=status.HTTP_200_OK)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue