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

Email as permission #65

Merged
merged 7 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
140 changes: 139 additions & 1 deletion insalan/tournament/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from types import NoneType

from django.db.utils import IntegrityError
from django.contrib.auth.models import Permission
from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, TransactionTestCase
Expand Down Expand Up @@ -915,7 +916,6 @@ def test_example(self):
reverse("tournament/details-full", args=[tourneyobj_one.id]), format="json"
)
self.assertEqual(request.status_code, 200)
print(request.data)
self.assertEqual(
request.data,
{
Expand Down Expand Up @@ -1278,3 +1278,141 @@ def test_payment_status_set(self):
man_reg.payment_status = PaymentStatus.PAY_LATER

self.assertEqual(PaymentStatus.PAY_LATER, man_reg.payment_status)


class TournamentTeamEndpoints(TestCase):
"""Tournament Registration Endpoint Test Class"""

# TODO Test all endpoints

def setUp(self):
"""Setup method for Tournament Registrations Unit Tests"""

# Basic setup for a one-tournamnent game event
event = Event.objects.create(
name="InsaLan Test", year=2023, month=3, description=""
)
game = Game.objects.create(name="Test Game")
trnm = Tournament.objects.create(game=game, event=event)
team_one = Team.objects.create(name="La Team Test", tournament=trnm)

# user_one = User.objects.create_user(
# username="testplayer",
# email="[email protected]",
# password="^ThisIsAnAdminPassword42$",
# first_name="Iam",
# last_name="Staff",
# )

invalid_email_user: User = User.objects.create_user(
username="invalidemail",
email="[email protected]",
password="IUseAVerySecurePassword",
first_name="Random",
last_name="Player",
)

valid_email_user: User = User.objects.create_user(
username="validemail",
password="ThisIsPassword",
)

valid_email_user.set_email_active()

# Player.objects.create(team=team_one, user=user_one)
# Player.objects.create(team=team_one, user=another_player)
# Manager.objects.create(team=team_one, user=random_player)

def test_can_create_a_team_with_valid_email(self):
"""Try to create a team with a valid email"""
user: User = User.objects.get(username="validemail")
self.client.force_login(user=user)

event = Event.objects.get(name="InsaLan Test")
trnm = event.get_tournaments()[0]

request = self.client.post(
"/v1/tournament/team/",
{
"name": "Les emails valides",
"tournament": trnm.id,
},
format="json",
)

self.assertEquals(request.status_code, 201)

def test_cant_create_a_team_with_no_valid_email(self):
"""Try to create a team with email not validated"""
user: User = User.objects.get(username="invalidemail")
self.client.force_login(user=user)

event = Event.objects.get(name="InsaLan Test")
trnm = event.get_tournaments()[0]

request = self.client.post(
"/v1/tournament/team/",
{
"name": "Flemme de valider",
"tournament": trnm.id,
},
format="json",
)

self.assertEquals(request.status_code, 403)

def test_can_join_a_team_with_a_valid_email(self):
"""Try to join an existing team with a valid email"""
user: User = User.objects.get(username="validemail")
self.client.force_login(user=user)
team: Team = Team.objects.get(name="La Team Test")
event: Event = Event.objects.get(name="InsaLan Test")

trnm = event.get_tournaments()[0]

request = self.client.post(
f"/v1/tournament/player/",
{
"team": team.id,
},
format="json",
)
self.assertEquals(request.status_code, 201)

Player.objects.filter(user=user.id).delete()

request = self.client.post(
f"/v1/tournament/manager/",
{
"team": team.id,
},
format="json",
)
self.assertEquals(request.status_code, 201)

def test_cant_join_a_team_with_no_valid_email(self):
"""Try to join an existing team with no valid email"""
user: User = User.objects.get(username="invalidemail")
self.client.force_login(user=User.objects.get(username="invalidemail"))
team: Team = Team.objects.get(name="La Team Test")
event: Event = Event.objects.get(name="InsaLan Test")

trnm = event.get_tournaments()[0]

request = self.client.post(
f"/v1/tournament/player/",
{
"team": team.id,
},
format="json",
)
self.assertEquals(request.status_code, 403)

request = self.client.post(
f"/v1/tournament/manager/",
{
"team": user.id,
},
format="json",
)
self.assertEquals(request.status_code, 403)
120 changes: 106 additions & 14 deletions insalan/tournament/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
# "Too few public methods"
# pylint: disable=R0903

from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.utils.translation import gettext_lazy as _
from rest_framework import generics, permissions, status
from rest_framework.exceptions import NotFound
from rest_framework.permissions import BasePermission, SAFE_METHODS
Expand All @@ -15,7 +17,7 @@
from insalan.user.models import User
import insalan.tournament.serializers as serializers

from .models import Player, Manager, Event, Tournament, Game, Team
from .models import Player, Manager, Event, Tournament, Game, Team, PaymentStatus


class ReadOnly(BasePermission):
Expand Down Expand Up @@ -51,6 +53,7 @@ class EventDetails(generics.RetrieveUpdateDestroyAPIView):
queryset = Event.objects.all().order_by("id")
permission_classes = [permissions.IsAdminUser | ReadOnly]


class EventDetailsSomeDeref(APIView):
"""Details about an Event that dereferences tournaments, but nothing else"""

Expand All @@ -64,10 +67,14 @@ def get(self, request, primary_key: int):

event = candidates[0]

event_serialized = serializers.EventSerializer(event, context={"request": request}).data
event_serialized = serializers.EventSerializer(
event, context={"request": request}
).data

event_serialized["tournaments"] = [
serializers.TournamentSerializer(Tournament.objects.get(id=id), context={"request": request}).data
serializers.TournamentSerializer(
Tournament.objects.get(id=id), context={"request": request}
).data
for id in event_serialized["tournaments"]
]

Expand All @@ -76,15 +83,18 @@ def get(self, request, primary_key: int):

return Response(event_serialized, status=status.HTTP_200_OK)


class EventByYear(generics.ListAPIView):
"""Get all of the events of a year"""

pagination_class = None
serializer_class = serializers.EventSerializer

def get_queryset(self):
"""Return the queryset"""
return Event.objects.filter(year=int(self.kwargs["year"]))


# Games
class GameList(generics.ListCreateAPIView):
"""List all known games"""
Expand Down Expand Up @@ -136,30 +146,36 @@ def get(self, request, primary_key: int):

tourney = tourneys[0]

tourney_serialized = serializers.TournamentSerializer(tourney, context={"request": request}).data
tourney_serialized = serializers.TournamentSerializer(
tourney, context={"request": request}
).data

# Dereference the event
event = tourney.event
tourney_serialized["event"] = serializers.EventSerializer(event, context={"request": request}).data
tourney_serialized["event"] = serializers.EventSerializer(
event, context={"request": request}
).data
del tourney_serialized["event"]["tournaments"]

# Dereference the game
tourney_serialized["game"] = serializers.GameSerializer(tourney.game, context={"request": request}).data
tourney_serialized["game"] = serializers.GameSerializer(
tourney.game, context={"request": request}
).data

# Dereference the teams
teams_serialized = []
for team in tourney_serialized["teams"]:
team_preser = serializers.TeamSerializer(Team.objects.get(id=team), context={"request": request}).data
team_preser = serializers.TeamSerializer(
Team.objects.get(id=team), context={"request": request}
).data
del team_preser["tournament"]

# Dereference players/managers to users (username)
team_preser["players"] = [
User.objects.get(id=pid).username
for pid in team_preser["players"]
User.objects.get(id=pid).username for pid in team_preser["players"]
]
team_preser["managers"] = [
User.objects.get(id=pid).username
for pid in team_preser["managers"]
User.objects.get(id=pid).username for pid in team_preser["managers"]
]

teams_serialized.append(team_preser)
Expand All @@ -176,7 +192,30 @@ class TeamList(generics.ListCreateAPIView):

queryset = Team.objects.all().order_by("id")
serializer_class = serializers.TeamSerializer
permission_classes = [permissions.IsAdminUser | ReadOnly]
permission_classes = [permissions.IsAuthenticated | ReadOnly]

def post(this, request, *args, **kwargs):
user = request.user
data = request.data

if user is None or not user.is_authenticated or "name" not in data:
raise PermissionDenied()

if not user.is_email_active():
raise PermissionDenied(
{
"email": [
_(
"Veuillez activer votre courriel pour vous inscrire à un tournoi"
)
]
}
)
mut = data._mutable
data._mutable = True
# data["players"] = [user.id]
data._mutable = mut
return super().post(request, *args, **kwargs)


class TeamDetails(generics.RetrieveUpdateDestroyAPIView):
Expand All @@ -195,13 +234,42 @@ class PlayerRegistration(generics.RetrieveAPIView):
queryset = Player.objects.all().order_by("id")


class PlayerRegistrationList(generics.ListAPIView):
class PlayerRegistrationList(generics.ListCreateAPIView):
"""Get all player registrations"""

pagination_class = None
serializer_class = serializers.PlayerSerializer
queryset = Player.objects.all().order_by("id")

def post(this, request, *args, **kwargs):
user = request.user
data = request.data

if (
user is None
or not user.is_authenticated
or "team" not in data
or "payment" in data
):
raise PermissionDenied()

if not user.is_email_active():
raise PermissionDenied(
{
"email": [
_(
"Veuillez activer votre courriel pour vous inscrire à un tournoi"
)
]
}
)
mut = data._mutable
data._mutable = True
data["user"] = user.id
data["payment"] = PaymentStatus.NOT_PAID
data._mutable = mut
return super().post(request, *args, **kwargs)


class PlayerRegistrationListId(generics.ListAPIView):
"""Find all player registrations of a user from their ID"""
Expand Down Expand Up @@ -237,13 +305,37 @@ class ManagerRegistration(generics.RetrieveAPIView):
queryset = Manager.objects.all().order_by("id")


class ManagerRegistrationList(generics.ListAPIView):
class ManagerRegistrationList(generics.ListCreateAPIView):
"""Show all manager registrations"""

pagination_class = None
serializer_class = serializers.ManagerSerializer
queryset = Manager.objects.all().order_by("id")

def post(this, request, *args, **kwargs):
user = request.user
data = request.data

if user is None or "team" not in data or "payment" in data:
raise PermissionDenied()

if not user.is_email_active():
raise PermissionDenied(
{
"email": [
_(
"Veuillez activer votre courriel pour vous inscrire à un tournoi"
)
]
}
)
mut = data._mutable
data._mutable = True
data["user"] = user.id
data["payment"] = PaymentStatus.NOT_PAID
data._mutable = mut
return super().post(request, *args, **kwargs)


class ManagerRegistrationListId(generics.ListAPIView):
"""Find all player registrations of a user from their ID"""
Expand Down
3 changes: 2 additions & 1 deletion insalan/user/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Register our models in Django admin panel"""
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import Permission
from .models import User

class CustomUserAdmin(UserAdmin):
Expand All @@ -11,4 +12,4 @@ class CustomUserAdmin(UserAdmin):
)

admin.site.register(User, CustomUserAdmin)
# Register your models here.
admin.site.register(Permission)
Loading
Loading