Skip to content

Commit

Permalink
🚨 Linting score is getting dangerously close 9
Browse files Browse the repository at this point in the history
Fixed a few warnings, mostly by adding docstrings
  • Loading branch information
Lugrim committed Oct 7, 2023
1 parent c04b30f commit eeaba7a
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
4 changes: 4 additions & 0 deletions insalan/user/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ def create_user(
return user

def create_superuser(self, email, username, password, **extra_fields):
"""
Check that all required fields are present and create a superuser
"""
if password is None:
raise TypeError(_("Les superutilisateur·rices requièrent un mot de passe"))
user = self.create_user(email, username, password, **extra_fields)
Expand Down Expand Up @@ -132,6 +135,7 @@ def send_email_confirmation(user_object: User):
fail_silently=False,
)

@staticmethod
def send_password_reset(user_object: User):
"""
Send a password reset token.
Expand Down
85 changes: 85 additions & 0 deletions insalan/user/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@


class UserTestCase(TestCase):
"""
Tests of the User model
"""

def setUp(self):
"""
Create some base users to do operations on
"""
u: User = User.objects.create_user(
username="staffplayer",
email="[email protected]",
Expand Down Expand Up @@ -43,6 +50,9 @@ def setUp(self):
)

def test_get_existing_full_user(self):
"""
Test getting all the fields of an already created user
"""
u: User = User.objects.get(username="randomplayer")
self.assertEquals(u.get_username(), "randomplayer")
self.assertEquals(u.get_short_name(), "Random")
Expand All @@ -54,6 +64,9 @@ def test_get_existing_full_user(self):
self.assertFalse(u.is_staff)

def test_get_existing_minimal_user(self):
"""
Test getting all the fields of an user created with only the required fields
"""
u: User = User.objects.get(username="anotherplayer")
self.assertEquals(u.get_username(), "anotherplayer")
self.assertEquals(u.get_short_name(), "")
Expand All @@ -65,14 +78,24 @@ def test_get_existing_minimal_user(self):
self.assertFalse(u.is_staff)

def test_get_non_existing_user(self):
"""
Test that getting an user which does not exist throws an `User.DoesNotExist` error
"""
with self.assertRaises(User.DoesNotExist):
User.objects.get(username="idontexist")


class UserEndToEndTestCase(TestCase):
"""
Test cases of the API endpoints and workflows related to user model
"""

client: APIClient

def setUp(self):
"""
Create a player to test getters
"""
self.client = APIClient()
User.objects.create_user(
username="randomplayer",
Expand All @@ -85,6 +108,10 @@ def setUp(self):
)

def test_register_invalid_data(self):
"""
Test trying to register a few invalid users
"""

def send_invalid_data(data):
request = self.client.post("/v1/user/register/", data, format="json")
self.assertEquals(request.status_code, 400)
Expand All @@ -95,7 +122,14 @@ def send_invalid_data(data):
send_invalid_data({"username": "newuser", "email": "[email protected]"})

def test_register_valid_account(self):
"""
Test registering valid users
"""

def send_valid_data(data, check_fields=[]):
"""
Helper function that will request a register and check its output
"""
request = self.client.post("/v1/user/register/", data, format="json")

self.assertEquals(request.status_code, 201)
Expand Down Expand Up @@ -144,6 +178,10 @@ def send_valid_data(data, check_fields=[]):
)

def test_register_read_only_fields(self):
"""
Test that the read-only register fields are indeed read-only
"""

def send_valid_data(data, check_fields=[]):
request = self.client.post("/v1/user/register/", data, format="json")

Expand Down Expand Up @@ -197,6 +235,9 @@ def send_valid_data(data, check_fields=[]):
)

def test_register_email_is_sent(self):
"""
Test that an email is sent upon registration
"""
data = {
"username": "ILoveMail",
"password": "1111qwer!",
Expand All @@ -212,6 +253,9 @@ def test_register_email_is_sent(self):
self.assertEqual(mail.outbox[0].to, ["[email protected]"])

def test_register_can_confirm_email(self):
"""
Test that an user can confirm their email with the link they received
"""
data = {
"username": "ILoveEmail",
"password": "1111qwer!",
Expand Down Expand Up @@ -241,6 +285,9 @@ def test_register_can_confirm_email(self):
self.assertTrue(User.objects.get(username=data["username"]).email_active)

def test_can_confirm_email_only_once(self):
"""
Test that an user can confirm their email only once
"""
data = {
"username": "ILoveEmail",
"password": "1111qwer!",
Expand All @@ -266,6 +313,9 @@ def test_can_confirm_email_only_once(self):
self.assertEquals(request.status_code, 400)

def test_confirmation_email_is_token_checked(self):
"""
Test that the token sent to an user for their email confirmation is really checked
"""
data = {
"username": "ILoveEmail",
"password": "1111qwer!",
Expand All @@ -292,6 +342,10 @@ def test_confirmation_email_is_token_checked(self):
self.assertEquals(request.status_code, 400)

def test_login_invalid_account(self):
"""
Try to login with invalid requests
"""

def send_valid_data(data):
request = self.client.post("/v1/user/login/", data, format="json")

Expand All @@ -309,6 +363,9 @@ def send_valid_data(data):
)

def test_login_not_active_account(self):
"""
Test trying to login to an account which email is not already activated
"""
User.objects.create_user(
username="newplayer", email="[email protected]", password="1111qwer!"
)
Expand All @@ -326,6 +383,9 @@ def send_valid_data(data):
)

def test_login_account(self):
"""
Test that when everything is ok, an user is able to login
"""
User.objects.create_user(
username="newplayer",
email="[email protected]",
Expand All @@ -347,6 +407,10 @@ def send_valid_data(data):
)

def can_resend_confirmation_email(self):
"""
Test that an user can request another confirmation email when
requesting the right route
"""
data = {
"username": "ILoveEmail",
"password": "1111qwer!",
Expand All @@ -373,6 +437,10 @@ def can_resend_confirmation_email(self):
self.assertEqual(mail.outbox, 3)

def cant_resend_confirmation_if_already_valid(self):
"""
Test that an user cannot resend a confirmation email if they already
confirmed their email
"""
User.objects.create_user(
username="newplayer",
email="[email protected]",
Expand All @@ -387,18 +455,29 @@ def cant_resend_confirmation_if_already_valid(self):
self.assertEqual(request.status_code, 400)

def cant_resend_confirmation_if_nonexisting_user(self):
"""
Test that we cannot resend a confirmation email for a non existing user
without crashing the server
"""
request = self.client.post(
"/v1/user/resend-email/", {"username": "IDontExistLol"}, format="json"
)

self.assertEqual(request.status_code, 400)

def dont_crash_resend_confirmation_if_empty(self):
"""
Test that server doesn't crash if ask to resend an email without any
valid data in request
"""
request = self.client.post("/v1/user/resend-email/", {}, format="json")

self.assertEqual(request.status_code, 400)

def test_can_reset_password(self):
"""
Test that an user can reset their password (full workflow)
"""
data = {
"email": "[email protected]",
}
Expand Down Expand Up @@ -446,6 +525,9 @@ def test_can_reset_password(self):
self.assertEquals(request.status_code, 404)

def test_can_reset_password_only_once(self):
"""
Test that an user can reset their password only once with a token
"""
data = {
"email": "[email protected]",
}
Expand Down Expand Up @@ -486,6 +568,9 @@ def test_can_reset_password_only_once(self):
self.assertEquals(request.status_code, 400)

def test_password_reset_is_token_checked(self):
"""
Test that the password reset token is actually checked
"""
data = {
"email": "[email protected]",
}
Expand Down
38 changes: 37 additions & 1 deletion insalan/user/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,37 @@ def get(self, request):

# TODO: change permission
class PermissionViewSet(generics.ListCreateAPIView):
"""
Django's `Permission` ViewSet to be able to add them to the admin panel
"""

queryset = Permission.objects.all().order_by("name")
serializer_class = PermissionSerializer
permission_classes = [permissions.IsAdminUser]


class GroupViewSet(generics.ListCreateAPIView):
"""
Django's `Group` ViewSet to be able to add them to the admin panel
"""

queryset = Group.objects.all().order_by("name")
serializer_class = GroupSerializer
permission_classes = [permissions.IsAdminUser]


class EmailConfirmView(APIView):
"""
Email confirmation user API Endpoint
"""

permissions_classes = [permissions.AllowAny]
authentication_classes = [SessionAuthentication]

def get(self, request, user=None, token=None):
"""
If requested with valid parameters, will validate an user's email
"""
error_text = _("Utilisateur ou jeton invalide (ou adresse déjà confirmée)")

if user and token:
Expand All @@ -100,10 +115,18 @@ def get(self, request, user=None, token=None):


class AskForPasswordReset(APIView):
"""
Asking for a password reset API Endpoint
"""

permissions_classes = [permissions.AllowAny]
authentication_classes = [SessionAuthentication]

def post(self, request):
"""
If requested with valid parameters, will send a password reset email to
an user given their email address
"""
try:
user_object: User = User.objects.get(email=request.data["email"])
UserMailer.send_password_reset(user_object)
Expand All @@ -114,10 +137,17 @@ def post(self, request):


class ResetPassword(APIView):
"""
Password Reset API Endpoint
"""

permissions_classes = [permissions.AllowAny]
authentication_classes = [SessionAuthentication]

def post(self, request):
"""
If requested with valid parameters, will reset an user password
"""
data = request.data
if not (
"user" in data
Expand Down Expand Up @@ -170,13 +200,16 @@ def post(self, request):

class ResendEmailConfirmView(APIView):
"""
API endpoint to re-send
API endpoint to re-send a confirmation email
"""

permissions_classes = [permissions.AllowAny]
authentication_classes = [SessionAuthentication]

def post(self, request):
"""
If the user is found, will send again a confirmation email
"""
error_text = _("Impossible de renvoyer le courriel de confirmation")

username = request.data.get("username")
Expand Down Expand Up @@ -250,5 +283,8 @@ class UserLogout(APIView):
authentication_classes = []

def post(self, request):
"""
Will logout an user.
"""
logout(request)
return Response(status=status.HTTP_200_OK)

0 comments on commit eeaba7a

Please sign in to comment.