Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Password resetting #74

Merged
merged 47 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
5fe0244
god help me
MaxIsJoe Jan 13, 2024
e7607bf
Update src/accounts/api/views.py
MaxIsJoe Jan 13, 2024
4b83cfa
fix save error
MaxIsJoe Jan 17, 2024
8d95ffb
remove account identifier from url
MaxIsJoe Jan 17, 2024
1234969
Update views.py
MaxIsJoe Jan 17, 2024
105cddf
fixes multiple arguments error
MaxIsJoe Jan 17, 2024
f20604b
random token
MaxIsJoe Jan 17, 2024
6264445
cacwka
MaxIsJoe Jan 17, 2024
c06af96
password resting works, woohoo!
MaxIsJoe Jan 17, 2024
833e69e
Update views.py
MaxIsJoe Jan 17, 2024
88614c8
token time lifespan
MaxIsJoe Jan 18, 2024
cab7dff
Update serializers.py
MaxIsJoe Jan 18, 2024
42b6a81
Update serializers.py
MaxIsJoe Jan 18, 2024
ad6fef7
Update models.py
MaxIsJoe Jan 18, 2024
edffbae
Update models.py
MaxIsJoe Jan 18, 2024
fd41b67
hour
MaxIsJoe Jan 18, 2024
395f686
view request changes
MaxIsJoe Jan 18, 2024
e9feb9f
name changes
MaxIsJoe Jan 18, 2024
498df54
remove some logs
MaxIsJoe Jan 18, 2024
4b60944
Update urls.py
MaxIsJoe Jan 18, 2024
eead438
Update urls.py
MaxIsJoe Jan 18, 2024
9c59243
Update urls.py
MaxIsJoe Jan 18, 2024
d8faa5e
precommit
MaxIsJoe Jan 18, 2024
69b8684
Update urls.py
MaxIsJoe Jan 18, 2024
34743a4
Update serializers.py
MaxIsJoe Jan 18, 2024
bde9f50
Update models.py
MaxIsJoe Jan 18, 2024
d32bef7
Update models.py
MaxIsJoe Jan 19, 2024
647c29a
e
MaxIsJoe Jan 19, 2024
ab501dc
email
MaxIsJoe Jan 21, 2024
7cb9285
Update views.py
MaxIsJoe Jan 21, 2024
6d03d36
Update views.py
MaxIsJoe Jan 21, 2024
341bf19
Update serializers.py
MaxIsJoe Jan 21, 2024
d83f73a
ee
MaxIsJoe Jan 21, 2024
95e1694
Update views.py
MaxIsJoe Jan 21, 2024
e0b3115
link correct
MaxIsJoe Jan 21, 2024
ada8c01
get email
MaxIsJoe Jan 21, 2024
27027ce
Update serializers.py
MaxIsJoe Jan 21, 2024
010ce67
password request
MaxIsJoe Jan 21, 2024
eed561a
Update views.py
MaxIsJoe Jan 21, 2024
c16d236
Update views.py
MaxIsJoe Jan 21, 2024
1cdbe5d
fixes an error with subscriptables
MaxIsJoe Jan 21, 2024
07fc838
Update src/accounts/api/serializers.py
MaxIsJoe Jan 22, 2024
1ccc17e
Merge remote-tracking branch 'upstream/develop' into forgetmepassword…
MaxIsJoe Jan 22, 2024
da3cef4
email working
MaxIsJoe Jan 22, 2024
9fcc842
Update serializers.py
MaxIsJoe Jan 22, 2024
7a04f96
Create 0001_squashed_0002_passwordresetrequest.py
MaxIsJoe Jan 23, 2024
f89154c
chore: make a single migration for the new model
corp-0 Jan 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/accounts/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django_email_verification import sendConfirm
from rest_framework import serializers

from ..models import Account
from ..models import (Account, PasswordResetRequestModel)


class PublicAccountDataSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -81,3 +81,35 @@ def validate(self, data):
"Verification token seems invalid or maybe outdated. Try requesting a new one."
)
return account

class ChangePasswordSerializer(serializers.ModelSerializer):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class ChangePasswordSerializer(serializers.ModelSerializer):
class ResetPasswordSerializer(serializers.ModelSerializer):

class Meta:
model = Account
fields = ("password")
MaxIsJoe marked this conversation as resolved.
Show resolved Hide resolved
extra_kwargs = {"password": {"write_only": True}}

def update(self, instance, validated_data):
instance.set_password(validated_data.get("password", instance.password))
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
instance.save()
return instance


class ChangePasswordRequestSerializer(serializers.ModelSerializer):
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
class Meta:
model = PasswordResetRequestModel
fields = ["email"]
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
MaxIsJoe marked this conversation as resolved.
Show resolved Hide resolved
corp-0 marked this conversation as resolved.
Show resolved Hide resolved

email = serializers.EmailField()

def validate(self, data):
account = Account.objects.filter(email=data["email"]).first()
#note: make this silently fail later, users dont need to know about this.
if account is None:
raise serializers.ValidationError("Account with this email doesn't exist.")
newModel = PasswordResetRequestModel(token=account.verification_token, account=account)
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
return newModel

def create(self, validated_data):
print(validated_data)
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
reset_request = PasswordResetRequestModel.objects.create(token=validated_data.token, account=validated_data.account)
return reset_request
4 changes: 4 additions & 0 deletions src/accounts/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
RequestVerificationTokenView,
UpdateAccountView,
VerifyAccountView,
ChangePasswordView,
RequestPasswordResetView,
)

app_name = "account"
Expand All @@ -32,4 +34,6 @@
name="request-verification-token",
),
path("verify-account", VerifyAccountView.as_view(), name="verify-account"),
path("change-password/<str:unique_identifier>/<str:token>", ChangePasswordView.as_view(), name="change-passwordd"),
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
path("change-password/", RequestPasswordResetView.as_view(), name="change-password"),
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
]
41 changes: 41 additions & 0 deletions src/accounts/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.serializers import ValidationError
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from django.contrib.auth.models import User
from .accounts.models import Account

use our Account class instead of the base User class.

from django.contrib.auth.tokens import default_token_generator
from django.utils.encoding import force_text
from django.utils.http import urlsafe_base64_decode
from django.contrib.auth.views import PasswordResetConfirmView
from django.contrib.auth.forms import SetPasswordForm
from django.http import HttpResponse

from ..exceptions import MissingMailConfirmationError
from ..models import Account
Expand All @@ -17,6 +25,8 @@
RegisterAccountSerializer,
UpdateAccountSerializer,
VerifyAccountSerializer,
ChangePasswordSerializer,
ChangePasswordRequestSerializer,
)


Expand Down Expand Up @@ -181,3 +191,34 @@ def post(self, request):
public_data = PublicAccountDataSerializer(account).data

return Response(public_data, status=status.HTTP_200_OK)

class ChangePasswordView(GenericAPIView):
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
permission_classes = (AllowAny,)
serializer_class = ChangePasswordSerializer

def get(self, unique_identifier, token):
try:
account = Account.objects.get(unique_identifier)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
return Response({'detail': 'Invalid link or expired.'}, status=status.HTTP_400_BAD_REQUEST)

if account is not None and default_token_generator.check_token(account, token):
return Response({'detail': 'Password reset successfully.'}, status=status.HTTP_200_OK)
else:
return Response({'detail': 'Invalid link or expired.'}, status=status.HTTP_400_BAD_REQUEST)

class RequestPasswordResetView(GenericAPIView):
permission_classes = (AllowAny,)
serializer_class = ChangePasswordRequestSerializer

def post(self, request):
serializer = self.serializer_class(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except ValidationError as e:
return Response(data={"error V": str(e)}, status=e.status_code)
corp-0 marked this conversation as resolved.
Show resolved Hide resolved
except Exception as e:
return Response(data={"error E": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
serializer.create(serializer.validated_data)
MaxIsJoe marked this conversation as resolved.
Show resolved Hide resolved
#return Response(data={"sucess test" : "soup"}, status=status.HTTP_200_OK)
return Response(data={"sucess" : str(serializer)}, status=status.HTTP_200_OK)
MaxIsJoe marked this conversation as resolved.
Show resolved Hide resolved
23 changes: 23 additions & 0 deletions src/accounts/migrations/0002_passwordresetrequest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.22 on 2024-01-13 17:03

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('accounts', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='PasswordResetRequest',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.UUIDField()),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
26 changes: 26 additions & 0 deletions src/accounts/migrations/0003_auto_20240113_1858.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 3.2.22 on 2024-01-13 18:58

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('accounts', '0002_passwordresetrequest'),
]

operations = [
migrations.CreateModel(
name='PasswordResetRequestModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.UUIDField()),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.DeleteModel(
name='PasswordResetRequest',
),
]
4 changes: 4 additions & 0 deletions src/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,7 @@ def save(self, *args, **kwargs):

def __str__(self):
return f"{self.unique_identifier} as {self.username}"

class PasswordResetRequestModel(models.Model):
token = models.UUIDField()
account = models.ForeignKey(Account, on_delete=models.CASCADE)
MaxIsJoe marked this conversation as resolved.
Show resolved Hide resolved
Loading