Skip to content

Commit

Permalink
Merge pull request #66 from Nuno-Jesus/jwtbug
Browse files Browse the repository at this point in the history
Password Validation
  • Loading branch information
Nuno-Jesus authored Nov 21, 2024
2 parents b88b177 + d305053 commit 544b702
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 4 deletions.
6 changes: 6 additions & 0 deletions backend/backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,19 @@
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
"OPTIONS": {
"min_length": 10,
},
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
{
'NAME': 'pong.validators.CustomPasswordValidator',
},
]

AUTH_USER_MODEL = 'pong.Users'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 5.1.3 on 2024-11-21 21:35

from django.db import migrations, models


class Migration(migrations.Migration):

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

operations = [
migrations.AlterField(
model_name='gamesstats',
name='average_ball_speed',
field=models.FloatField(default=0),
),
migrations.AlterField(
model_name='gamesstats',
name='max_ball_speed',
field=models.FloatField(default=0),
),
migrations.AlterField(
model_name='gamesstats',
name='min_ball_speed',
field=models.FloatField(default=0),
),
migrations.AlterField(
model_name='userstats',
name='max_ball_speed',
field=models.FloatField(default=0),
),
]
10 changes: 6 additions & 4 deletions backend/pong/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class UserManager(BaseUserManager):
def create_user(self, username, password=None, **extra_fields):
if not username:
raise ValueError('The Username field must be set')
if len(username) < 5:
raise ValueError('The Username needs to have more than 5 letters')
if not password:
raise ValueError('The Password field must be set')
user = self.model(username=username, **extra_fields)
Expand Down Expand Up @@ -162,7 +164,7 @@ class UserStats(models.Model):
nb_games_won = models.IntegerField(default=0)
nb_goals_scored = models.IntegerField(default=0)
nb_goals_suffered = models.IntegerField(default=0)
max_ball_speed = models.IntegerField(default=0)
max_ball_speed = models.FloatField(default=0)
date_max_ball_speed = models.DateTimeField(null=True)
max_rally_length = models.IntegerField(default=0)
date_max_rally_length = models.DateTimeField(null=True)
Expand Down Expand Up @@ -192,9 +194,9 @@ class GamesStats(models.Model):
longer_rally = models.IntegerField(default=0)
shorter_rally = models.IntegerField(default=0)
average_rally = models.IntegerField(default=0)
max_ball_speed = models.IntegerField(default=0)
min_ball_speed = models.IntegerField(default=0)
average_ball_speed = models.IntegerField(default=0)
max_ball_speed = models.FloatField(default=0)
min_ball_speed = models.FloatField(default=0)
average_ball_speed = models.FloatField(default=0)
greatest_deficit_overcome = models.IntegerField(default=0)
gdo_user = models.ForeignKey(Users, on_delete=models.SET_NULL, null=True, related_name='gdo_games')
most_consecutive_goals = models.IntegerField(default=0)
Expand Down
34 changes: 34 additions & 0 deletions backend/pong/validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import re
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _

class CustomPasswordValidator:

def validate(self, password, user):
if not re.search(r'[A-Z]', password):
raise ValidationError(
_("Password must contain at least one uppercase letter."),
code='password_no_upper',
)
if not re.search(r'[a-z]', password):
raise ValidationError(
_("Password must contain at least one lowercase letter."),
code='password_no_lower',
)
if not re.search(r'[0-9]', password):
raise ValidationError(
_("Password must contain at least one digit."),
code='password_no_digit',
)
if not re.search(r'[\W_]', password):
raise ValidationError(
_("Password must contain at least one special character."),
code='password_no_special',
)


def get_help_text(self):
return _(
"Your password must be at least 10 characters long and contain at least one "
"uppercase letter, one lowercase letter, one digit, and one special character."
)
34 changes: 34 additions & 0 deletions backend/pong/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from django.core.mail import send_mail

from django.contrib.auth.decorators import login_required
from django.contrib.auth.password_validation import validate_password
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from datetime import datetime
Expand Down Expand Up @@ -153,6 +154,25 @@ def send_code_verify_email(request):
)
return JsonResponse({'message': 'Code sent.'}, status=200)

class MockUser:
def __init__(self, username, email):
self.username = username
self.email = email
self._meta = self.MockMeta()

class MockMeta:
def get_field(self, field_name):
if field_name == 'username':
return self.MockField("Username")
elif field_name == 'email':
return self.MockField("Email")
raise AttributeError(f"Unknown field: {field_name}")

class MockField:
def __init__(self, verbose_name):
self.verbose_name = verbose_name


def user_create(request):
if request.method == 'POST':
try:
Expand All @@ -167,10 +187,19 @@ def user_create(request):

if not username or not email or not password1 or not password2:
return JsonResponse({'message': 'All fields are required.'}, status=400)

if len(username) < 5:
return JsonResponse({'message': 'The Username needs to have more than 5 letters.'}, status=400)

if Users.objects.filter(username=username).exists():
return JsonResponse({'message': 'Username already exists! Please try another username.'}, status=400)

try:
user_mock = MockUser(username=username, email=email)
validate_password(password1, user_mock)
except ValidationError as e:
return JsonResponse({'message': ' '.join(e)}, status=400)

try:
validate_email(email)
except ValidationError:
Expand Down Expand Up @@ -341,6 +370,11 @@ def user_password(request, pk):
if new_password1 != new_password2:
return JsonResponse({'message': 'Passwords did not match.', 'access_token': new_token}, status=400)

try:
validate_password(new_password1, user)
except ValidationError as e:
return JsonResponse({'message': ' '.join(e)}, status=400)

user.set_password(new_password1)
user.save()

Expand Down

0 comments on commit 544b702

Please sign in to comment.