Commit c59ab62f authored by Hamza Dely's avatar Hamza Dely

[activites/api] Premier jet de l'API de gestion des activités

parent 4fcc3899
"""
Vues de l'API de l'application « Comptes »
"""
from rest_framework import routers
from activites.views import ActiviteViewSet #, InviteViewSet
router = routers.DefaultRouter()
router.register(r'activites', ActiviteViewSet)
#router.register(r'invites', InviteViewSet)
urlpatterns = router.urls
"""
Sérialiseurs de l'app « Activités »
"""
from rest_framework import serializers
from note_kfet.serializers import mixins
from activites.models import Activite, Invite
class ActiviteSerializer(mixins.DynamicFieldsMixin, serializers.ModelSerializer):
"""
Sérialiseur pour le modèle Activite
"""
class Meta:
model = Activite
fields = [
'intitule', 'description', 'debut', 'fin',
'liste_invitation', 'organisateur', 'valide_par',
]
default_empty = False
class InviteSerializer(serializers.ModelSerializer):
"""
Sérialiseur pour le modèle Invite
"""
class Meta:
model = Invite
fields = ['nom', 'prenom', 'naissance', 'activite', 'invite_par', 'present',]
......@@ -18,6 +18,11 @@ from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMix
from django_filters.views import FilterView
from rest_framework import status
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import detail_route
from note_kfet.droits import D, Acl
from note_kfet.views.mixins import NoteMixin
......@@ -25,6 +30,11 @@ from comptes.models import Adherent
from activites.models import Activite, Invite
from activites.filters import ActiviteRechercheFilter
from activites.serializers import ActiviteSerializer
################################################################################
## Vues concernant le site Web ##
################################################################################
### Vues concernant les activités
......@@ -348,3 +358,178 @@ class ActiviteInviteRetraitView(PermissionRequiredMixin, LoginRequiredMixin, Red
kwargs.update(pk=invite.activite.id)
invite.delete()
return super().get_redirect_url(*args, **kwargs)
################################################################################
## Vues concernant l'API ##
################################################################################
class ActiviteViewSet(viewsets.GenericViewSet):
"""
Un ensemble de vues pour gérer les activités
"""
queryset = Activite.objects.all()
serializer_class = ActiviteSerializer
def get_queryset(self):
qs = super().get_queryset().filter()
if not self.request.user.has_perm("activites.activite_gerer", Acl.BASIQUE):
return qs.filter(Q(organisateur=self.request.user) | Q(valide_par__isnull=False))
else:
return qs
def list(self, request):
"""
Renvoie la liste des activités enregistrées.
Le paramètre 'show' peut prendre deux valeurs : 'normal' pour
afficher seulement les activités en cours ou à venir, ou 'all' pour
afficher toutes les activités. La valeur par défaut est 'normal'.
Les données doivent:
- être envoyées via un requête GET
- contenir dans la querystring le paramètre 'show'
"""
show = self.request.query_params.get('show', 'normal')
if show not in ['normal', 'all']:
return Response(
{"detail" : "Paramètre 'show' incorrect"},
status=status.HTTP_400_BAD_REQUEST,
)
lookup_args = {'fin__gte' : timezone.now()} if show == "normal" else {}
qs = super().get_queryset().filter(**lookup_args)
serializer = self.get_serializer(
qs,
many=True,
fields=['intitule', 'description', 'debut', 'fin', 'liste_invitation'],
)
return Response(serializer.data, status=status.HTTP_200_OK)
def retrieve(self, request, pk=None):
"""
Renvoie les détails sur une activité donnée.
Les données doivent:
- être envoyées via une requête GET
"""
fields = ['intitule', 'description', 'debut', 'fin', 'liste_invitation']
if self.request.user.has_perm("activites.activite_gerer", Acl.LIMITE):
fields += ['organisateur', 'valide_par']
serializer = self.get_serializer(self.get_object(), fields=fields)
return Response(serializer.data)
def create(self, request):
"""
Ajoute une nouvelle activité.
Les données doivent:
- être envoyées via une requête POST
-
"""
if not request.user.has_perm("activites.activite_ajouter", Acl.LIMITE):
return Response({}, status=status.HTTP_403_FORBIDDEN)
if ('organisateur' in request.data
and request.user.has_perm("activites.activite_ajouter", Acl.ETENDU)):
pass
elif 'organisateur' in request.data.dict():
return Response(
{
"detail" : "Vous ne pouvez pas indiquer d'organisateur",
},
status=status.HTTP_403_FORBIDDEN
)
else:
# L'organisateur n'a pas été spécifié, mais de toute façon l'utilisateur n'a
# pas le droit de le faire
request.data['organisateur'] = request.user
serializer = self.get_serializer(data=request.data)
if not serializer.is_valid():
return Response({}, status=status.HTTP_400_BAD_REQUEST)
activite = serializer.save()
return Response({"id" : activite.id}, status=status.HTTP_200_OK)
def partial_update(self, request, pk=None):
"""
Modifie une activité donnée. Il n'est pas possible de valider ou dévalider
une proposition d'activité avec cette vue de l'API.
Les données doivent :
- être envoyées via une requête PATCH
"""
if not request.user.has_perm("activites.activite_modifier", Acl.LIMITE):
return Response({}, status=status.HTTP_403_FORBIDDEN)
if 'valide_par' in request.data:
return Response(
{"detail" : "Impossible de valider/dévalider une activité"}, # XXX: C'est pas très clair
status=status.HTTP_400_BAD_REQUEST,
)
fields = ['intitule', 'description', 'debut', 'fin', 'liste_invitation', 'organisateur']
activite = self.get_object()
serializer = self.get_serializer(activite, data=request.data, partial=True, fields=fields)
serializer.is_valid(raise_exception=True)
if ('organisateur' in serializer.validated_data
and not request.user.has_perm("activites.activite_modifier", Acl.ETENDU)):
return Response(
{"detail" : "Vous ne pouvez pas changer l'organisateur d'une activité"},
status=status.HTTP_403_FORBIDDEN,
)
serializer.save()
return Response({}, status=status.HTTP_200_OK)
@detail_route(methods=['patch'])
def status(self, request, pk=None):
"""
Valide ou dévalide une activité.
Les données doivent :
- être envoyées via une requête PATCH
- contenir un unique paramètre 'action' pouvant valoir 'valider' ou 'devalider'
"""
if not request.user.has_perm("activites.activite_gerer", Acl.ETENDU):
return Response({}, status=status.HTTP_403_FORBIDDEN)
action = request.data.get('action', None)
if action not in ['valider', 'devalider']:
return Response({"detail" : "Paramètre 'action' invalide"}, status=status.HTTP_400_BAD_REQUEST)
activite = self.get_object()
if activite.valide_par is None and action == 'devalider':
# L'activité est dévalidée, mais on demande de nouveau une dévalidation
return Response({"detail" : "L'activité est déjà dévalidée"}, status=status.HTTP_409_CONFLICT)
elif action == 'devalider':
# L'activité est validée, et on demande sa dévalidation
activite.valide_par = None
elif activite.valide_par is None:
# L'activité est dévalidée, et on demande sa validation
activite.valide_par = request.user
else:
# L'activité est validée, mais on demande de nouveau sa validation
return Response({"detail" : "L'activité est déjà validée"}, status=status.HTTP_409_CONFLICT)
activite.save()
return Response({}, status=status.HTTP_200_OK)
def destroy(self, request, pk=None):
"""
Supprime une activité.
Les données doivent :
- être envoyées via une requête DELETE
"""
if not request.user.has_perm("activites.activite_modifier", Acl.LIMITE):
return Response({}, status=status.HTTP_403_FORBIDDEN)
activite = self.get_object()
if (activite.organisateur != request.user
and not request.user.has_perm("activites.activite_modifier", Acl.ETENDU)):
return Response(
{
"detail" : "Vous n'avez pas l'accréditation necéssaire pour "
"supprimer cette activité"
},
status=status.HTTP_403_FORBIDDEN,
)
activite.delete()
return Response({}, status=status.HTTP_204_NO_CONTENT)
......@@ -7,4 +7,5 @@ from django.conf.urls import url, include
urlpatterns = [
# TODO : Faire une vue API Root
url('^comptes/', include('comptes.api', namespace="comptes")),
url('^activites/', include('activites.api', namespace="activites")),
]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment