work in progress

sync
Laurent 1 year ago
parent 3783477768
commit 415f70458c
  1. 7
      api/serializers.py
  2. 1
      api/urls.py
  3. 110
      api/views.py
  4. 7
      tournaments/admin.py
  5. 27
      tournaments/migrations/0092_dataaccess.py
  6. 1
      tournaments/models/__init__.py
  7. 4
      tournaments/models/base.py
  8. 41
      tournaments/models/data_access.py
  9. 2
      tournaments/models/model_log.py
  10. 472
      tournaments/models/views.py

@ -11,6 +11,7 @@ from django.core.mail import EmailMessage
from django.contrib.sites.shortcuts import get_current_site from django.contrib.sites.shortcuts import get_current_site
from api.tokens import account_activation_token from api.tokens import account_activation_token
from tournaments.models.data_access import DataAccess
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
@ -225,3 +226,9 @@ class DeviceTokenSerializer(serializers.ModelSerializer):
model = DeviceToken model = DeviceToken
fields = '__all__' fields = '__all__'
read_only_fields = ['user'] read_only_fields = ['user']
class DataAccessSerializer(serializers.ModelSerializer):
class Meta:
model = DataAccess
fields = '__all__'
read_only_fields = ['user']

@ -21,6 +21,7 @@ router.register(r'date-intervals', views.DateIntervalViewSet)
router.register(r'failed-api-calls', views.FailedApiCallViewSet) router.register(r'failed-api-calls', views.FailedApiCallViewSet)
router.register(r'logs', views.LogViewSet) router.register(r'logs', views.LogViewSet)
router.register(r'device-token', views.DeviceTokenViewSet) router.register(r'device-token', views.DeviceTokenViewSet)
router.register(r'data-access', views.DataAccessViewSet)
urlpatterns = [ urlpatterns = [
path('', include(router.urls)), path('', include(router.urls)),

@ -1,5 +1,5 @@
from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, TournamentSerializer, UserSerializer, ChangePasswordSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, LiveMatchSerializer, PurchaseSerializer, CustomUserSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, TournamentSerializer, UserSerializer, ChangePasswordSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, LiveMatchSerializer, PurchaseSerializer, CustomUserSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer, DataAccessSerializer
from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken, ModelLog from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken, ModelLog, DataAccess
from rest_framework import viewsets, permissions from rest_framework import viewsets, permissions
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
@ -32,6 +32,7 @@ class DataApi(APIView):
model_name = request.data.get('model_name') model_name = request.data.get('model_name')
data = request.data.get('data') data = request.data.get('data')
store_id = request.data.get('store_id') store_id = request.data.get('store_id')
print(f"DataApi post > {model_operation} {model_name}") print(f"DataApi post > {model_operation} {model_name}")
serializer_class = build_serializer_class(model_name) serializer_class = build_serializer_class(model_name)
@ -42,8 +43,9 @@ class DataApi(APIView):
instance = model.objects.get(id=data_id) instance = model.objects.get(id=data_id)
if model_operation == 'DELETE': if model_operation == 'DELETE':
return self.delete_and_save_log(request, data_id, model_operation, model_name, store_id) parent_model, parent_id = instance.get_parent_reference()
else: # POST/PUT return self.delete_and_save_log(request, data_id, model_operation, model_name, store_id, parent_id, parent_model)
else: # PUT
serializer = serializer_class(instance, data=data, context={'request': request}) serializer = serializer_class(instance, data=data, context={'request': request})
if serializer.is_valid(): if serializer.is_valid():
if instance.last_update <= serializer.validated_data.get('last_update'): if instance.last_update <= serializer.validated_data.get('last_update'):
@ -54,8 +56,7 @@ class DataApi(APIView):
return Response(serializer.data, status=status.HTTP_203_NON_AUTHORITATIVE_INFORMATION) return Response(serializer.data, status=status.HTTP_203_NON_AUTHORITATIVE_INFORMATION)
else: else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except model.DoesNotExist: except model.DoesNotExist: # POST
# If the instance doesn't exist, we should be in a POST situation
print('>>> insert') print('>>> insert')
serializer = serializer_class(data=data, context={'request': request}) serializer = serializer_class(data=data, context={'request': request})
if serializer.is_valid(): if serializer.is_valid():
@ -65,18 +66,21 @@ class DataApi(APIView):
def save_and_create_log(self, request, serializer, model_operation, model_name, store_id): def save_and_create_log(self, request, serializer, model_operation, model_name, store_id):
instance = serializer.save() instance = serializer.save()
parent_model, parent_id = instance.get_parent_reference()
self.create_and_save_model_log( self.create_and_save_model_log(
user=request.user, user=request.user,
model_operation=model_operation, model_operation=model_operation,
model_name=model_name, model_name=model_name,
model_id=instance.id, model_id=instance.id,
store_id=store_id store_id=store_id,
parent_id=parent_id,
parent_model=parent_model
) )
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
def delete_and_save_log(self, request, data_id, model_operation, model_name, store_id): def delete_and_save_log(self, request, data_id, model_operation, model_name, store_id, parent_id, parent_model):
model = apps.get_model(app_label='tournaments', model_name=model_name) model = apps.get_model(app_label='tournaments', model_name=model_name)
print(model) print(model)
@ -94,12 +98,14 @@ class DataApi(APIView):
model_operation=model_operation, model_operation=model_operation,
model_name=model_name, model_name=model_name,
model_id=data_id, model_id=data_id,
store_id=store_id store_id=store_id,
parent_id=parent_id,
parent_model=parent_model
) )
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
def create_and_save_model_log(self, user, model_operation, model_name, model_id, store_id): def create_and_save_model_log(self, user, model_operation, model_name, model_id, store_id, parent_id, parent_model):
model_log = ModelLog() model_log = ModelLog()
model_log.user = user model_log.user = user
model_log.operation = model_operation model_log.operation = model_operation
@ -107,6 +113,8 @@ class DataApi(APIView):
model_log.model_name = model_name model_log.model_name = model_name
model_log.model_id = model_id model_log.model_id = model_id
model_log.store_id = store_id model_log.store_id = store_id
model_log.parent_model_id = parent_id
model_log.parent_model_name = parent_model
model_log.save() model_log.save()
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
@ -123,7 +131,9 @@ class DataApi(APIView):
except ValueError: except ValueError:
return Response({"error": f"Invalid date format for last_update: {last_update}"}, status=status.HTTP_400_BAD_REQUEST) return Response({"error": f"Invalid date format for last_update: {last_update}"}, status=status.HTTP_400_BAD_REQUEST)
logs = ModelLog.objects.filter(date__gt=last_update).order_by('date') data_access = DataAccess.objects.filter(shared_with=request.user).values_list('model_id', flat=True)
log_query = Q(date__gt=last_update) & (Q(user=request.user) | Q(model_id__in=data_access) | Q(parent_model_id__in=data_access))
logs = ModelLog.objects.filter(log_query).order_by('date')
updates = defaultdict(dict) updates = defaultdict(dict)
deletions = defaultdict(list) deletions = defaultdict(list)
@ -133,15 +143,20 @@ class DataApi(APIView):
if log.operation in ['POST', 'PUT']: if log.operation in ['POST', 'PUT']:
try: try:
instance = model.objects.get(id=log.model_id) data = self.get_data(model, log)
serializer_class = build_serializer_class(log.model_name)
serializer = serializer_class(instance) # instance = model.objects.get(id=log.model_id)
updates[log.model_name][log.model_id] = serializer.data # serializer_class = build_serializer_class(log.model_name)
# serializer = serializer_class(instance)
updates[log.model_name][log.model_id] = data
except model.DoesNotExist: except model.DoesNotExist:
# If the instance doesn't exist, it might have been deleted after this log was created # If the instance doesn't exist, it might have been deleted after this log was created
pass pass
elif log.operation == 'DELETE': elif log.operation == 'DELETE':
deletions[log.model_name].append({'model_id': log.model_id, 'store_id': log.store_id}) deletions[log.model_name].append({'model_id': log.model_id, 'store_id': log.store_id})
elif log.operation == 'SHARE':
data = self.get_data(model, log)
updates[log.model_name][log.model_id] = data
# Convert updates dict to list for each model # Convert updates dict to list for each model
for model_name in updates: for model_name in updates:
@ -151,12 +166,7 @@ class DataApi(APIView):
for model_name in deletions: for model_name in deletions:
deletions[model_name] = deletions[model_name] deletions[model_name] = deletions[model_name]
# local_time = timezone.localtime(timezone.now())
# print(local_time.isoformat(timespec='seconds'))
date = logs.last().date.astimezone().isoformat(timespec='seconds') if logs else None date = logs.last().date.astimezone().isoformat(timespec='seconds') if logs else None
print(date)
response_data = { response_data = {
"updates": dict(updates), "updates": dict(updates),
@ -166,6 +176,12 @@ class DataApi(APIView):
return Response(response_data, status=status.HTTP_200_OK) return Response(response_data, status=status.HTTP_200_OK)
def get_data(self, model, log):
instance = model.objects.get(id=log.model_id)
serializer_class = build_serializer_class(log.model_name)
serializer = serializer_class(instance)
return serializer.data
class CustomAuthToken(APIView): class CustomAuthToken(APIView):
permission_classes = [] permission_classes = []
@ -245,16 +261,31 @@ class TournamentViewSet(viewsets.ModelViewSet):
def get_queryset(self): def get_queryset(self):
if self.request.user.is_anonymous: if self.request.user.is_anonymous:
return [] return []
return self.queryset.filter(event__creator=self.request.user)
return self.queryset.filter(
Q(event__creator=self.request.user) |
Q(id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
class PurchaseViewSet(viewsets.ModelViewSet): class PurchaseViewSet(viewsets.ModelViewSet):
queryset = Purchase.objects.all() queryset = Purchase.objects.all()
serializer_class = PurchaseSerializer serializer_class = PurchaseSerializer
def get_queryset(self): def get_queryset(self):
if self.request.user: if self.request.user.is_anonymous:
return self.queryset.filter(user=self.request.user) return []
return []
# return self.queryset.filter(user=self.request.user)
return self.queryset.filter(
Q(user=self.request.user) |
Q(id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
def put(self, request, pk): def put(self, request, pk):
raise MethodNotAllowed('PUT') raise MethodNotAllowed('PUT')
@ -290,7 +321,14 @@ class EventViewSet(viewsets.ModelViewSet):
def get_queryset(self): def get_queryset(self):
if self.request.user.is_anonymous: if self.request.user.is_anonymous:
return [] return []
return self.queryset.filter(creator=self.request.user) # return self.queryset.filter(creator=self.request.user)
return self.queryset.filter(
Q(creator=self.request.user) |
Q(id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
class RoundViewSet(viewsets.ModelViewSet): class RoundViewSet(viewsets.ModelViewSet):
queryset = Round.objects.all() queryset = Round.objects.all()
@ -373,9 +411,16 @@ class DateIntervalViewSet(viewsets.ModelViewSet):
serializer_class = DateIntervalSerializer serializer_class = DateIntervalSerializer
def get_queryset(self): def get_queryset(self):
if self.request.user: if self.request.user.is_anonymous:
return self.queryset.filter(event__creator=self.request.user) return []
return []
return self.queryset.filter(
Q(event__creator=self.request.user) |
Q(event__id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
class FailedApiCallViewSet(viewsets.ModelViewSet): class FailedApiCallViewSet(viewsets.ModelViewSet):
queryset = FailedApiCall.objects.all() queryset = FailedApiCall.objects.all()
@ -427,3 +472,12 @@ class DeviceTokenViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(user=self.request.user) serializer.save(user=self.request.user)
class DataAccessViewSet(viewsets.ModelViewSet):
queryset = DataAccess.objects.all()
serializer_class = DataAccessSerializer
def get_queryset(self):
if self.request.user:
return self.queryset.filter(owner=self.request.user)
return []

@ -1,6 +1,7 @@
from django.contrib import admin from django.contrib import admin
from tournaments.models import team_registration from tournaments.models import team_registration
from tournaments.models.data_access import DataAccess
from tournaments.models.device_token import DeviceToken from tournaments.models.device_token import DeviceToken
from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, Court, DateInterval, FailedApiCall, Log, ModelLog from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, Court, DateInterval, FailedApiCall, Log, ModelLog
@ -98,6 +99,11 @@ class ModelLogAdmin(admin.ModelAdmin):
list_filter = ['user'] list_filter = ['user']
ordering = ['-date'] ordering = ['-date']
class DataAccessAdmin(admin.ModelAdmin):
list_display = ['owner', 'shared_with', 'model_name', 'model_id', 'granted_at']
list_filter = ['owner', 'shared_with']
ordering = ['-granted_at']
admin.site.register(CustomUser, CustomUserAdmin) admin.site.register(CustomUser, CustomUserAdmin)
admin.site.register(Club, ClubAdmin) admin.site.register(Club, ClubAdmin)
admin.site.register(Event, EventAdmin) admin.site.register(Event, EventAdmin)
@ -115,3 +121,4 @@ admin.site.register(FailedApiCall, FailedApiCallAdmin)
admin.site.register(Log, LogAdmin) admin.site.register(Log, LogAdmin)
admin.site.register(DeviceToken, DeviceTokenAdmin) admin.site.register(DeviceToken, DeviceTokenAdmin)
admin.site.register(ModelLog, ModelLogAdmin) admin.site.register(ModelLog, ModelLogAdmin)
admin.site.register(DataAccess, DataAccessAdmin)

@ -0,0 +1,27 @@
# Generated by Django 5.1 on 2024-11-01 08:02
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0091_modellog_store_id'),
]
operations = [
migrations.CreateModel(
name='DataAccess',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('model_name', models.CharField(max_length=50)),
('model_id', models.UUIDField()),
('granted_at', models.DateTimeField(auto_now_add=True)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owned_data', to=settings.AUTH_USER_MODEL)),
('shared_with', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shared_data', to=settings.AUTH_USER_MODEL)),
],
),
]

@ -18,3 +18,4 @@ from .failed_api_call import FailedApiCall
from .log import Log from .log import Log
from .device_token import DeviceToken from .device_token import DeviceToken
from .model_log import ModelLog from .model_log import ModelLog
from .data_access import DataAccess

@ -8,6 +8,10 @@ class BaseModel(models.Model):
class Meta: class Meta:
abstract = True abstract = True
def get_parent_reference(self):
"""Override in child models to provide parent reference"""
return None, None
class SideStoreModel(BaseModel): class SideStoreModel(BaseModel):
store_id = models.CharField(max_length=100) store_id = models.CharField(max_length=100)

@ -0,0 +1,41 @@
from django.db import models
from django.utils import timezone
from django.apps import apps
import uuid
from . import ModelLog, SideStoreModel
class DataAccess(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
owner = models.ForeignKey('CustomUser', related_name='owned_data', on_delete=models.CASCADE)
shared_with = models.ForeignKey('CustomUser', related_name='shared_data', on_delete=models.CASCADE)
model_name = models.CharField(max_length=50)
model_id = models.UUIDField()
granted_at = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
is_new = self._state.adding # Check if this is a new DataAccess
super().save(*args, **kwargs)
if is_new:
self.create_initial_sync_logs()
def create_initial_sync_logs(self):
model_class = apps.get_model(self.model_name)
obj = model_class.objects.get(id=self.model_id)
parent_model, parent_id = obj.get_parent_reference()
store_id = None
if isinstance(obj, SideStoreModel):
store_id = obj.store_id
ModelLog.objects.create(
user=self.shared_with, # The user receiving access
model_id=self.model_id,
model_name=self.model_name,
operation='SHARE', # New operation type
date=timezone.now(),
store_id=store_id,
parent_model_id=parent_id,
parent_model_name=parent_model
)

@ -10,3 +10,5 @@ class ModelLog(models.Model):
date = models.DateTimeField() date = models.DateTimeField()
model_name = models.CharField(max_length=50) model_name = models.CharField(max_length=50)
store_id = models.CharField(max_length=200, blank=True, null=True) store_id = models.CharField(max_length=200, blank=True, null=True)
parent_model_id = models.UUIDField(null=True)
parent_model_name = models.CharField(max_length=50, null=True)

@ -0,0 +1,472 @@
from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, TournamentSerializer, UserSerializer, ChangePasswordSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, LiveMatchSerializer, PurchaseSerializer, CustomUserSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer, DataAccessSerializer
from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken, ModelLog, DataAccess
from rest_framework import viewsets, permissions
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from rest_framework.generics import UpdateAPIView
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from django.contrib.auth import authenticate
from django.db.models import Q
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from django.apps import apps
from collections import defaultdict
from .permissions import IsClubOwner
from .utils import is_valid_email, build_serializer_class
class DataApi(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
# unfold content
model_operation = request.data.get('operation')
model_name = request.data.get('model_name')
data = request.data.get('data')
store_id = request.data.get('store_id')
print(f"DataApi post > {model_operation} {model_name}")
serializer_class = build_serializer_class(model_name)
model = apps.get_model(app_label='tournaments', model_name=model_name)
try:
data_id = data.get('id')
instance = model.objects.get(id=data_id)
if model_operation == 'DELETE':
parent_model, parent_id = instance.get_parent_reference()
return self.delete_and_save_log(request, data_id, model_operation, model_name, store_id, parent_id, parent_model)
else: # PUT
serializer = serializer_class(instance, data=data, context={'request': request})
if serializer.is_valid():
if instance.last_update <= serializer.validated_data.get('last_update'):
print('>>> update')
return self.save_and_create_log(request, serializer, model_operation, model_name, store_id)
else:
print('>>> return 203')
return Response(serializer.data, status=status.HTTP_203_NON_AUTHORITATIVE_INFORMATION)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except model.DoesNotExist: # POST
print('>>> insert')
serializer = serializer_class(data=data, context={'request': request})
if serializer.is_valid():
return self.save_and_create_log(request, serializer, model_operation, model_name, store_id)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def save_and_create_log(self, request, serializer, model_operation, model_name, store_id):
instance = serializer.save()
parent_model, parent_id = instance.get_parent_reference()
self.create_and_save_model_log(
user=request.user,
model_operation=model_operation,
model_name=model_name,
model_id=instance.id,
store_id=store_id,
parent_id=parent_id,
parent_model=parent_model
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
def delete_and_save_log(self, request, data_id, model_operation, model_name, store_id, parent_id, parent_model):
model = apps.get_model(app_label='tournaments', model_name=model_name)
print(model)
try:
instance = model.objects.get(id=data_id)
instance.delete()
except model.DoesNotExist:
return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
# we delete all logs linked to the instance because they won't be needed anymore
ModelLog.objects.filter(model_id=data_id).delete()
self.create_and_save_model_log(
user=request.user,
model_operation=model_operation,
model_name=model_name,
model_id=data_id,
store_id=store_id,
parent_id=parent_id,
parent_model=parent_model
)
return Response(status=status.HTTP_204_NO_CONTENT)
def create_and_save_model_log(self, user, model_operation, model_name, model_id, store_id, parent_id, parent_model):
model_log = ModelLog()
model_log.user = user
model_log.operation = model_operation
model_log.date = timezone.localtime(timezone.now())
model_log.model_name = model_name
model_log.model_id = model_id
model_log.store_id = store_id
model_log.parent_model_id = parent_id
model_log.parent_model_name = parent_model
model_log.save()
def get(self, request, *args, **kwargs):
print('/data GET YEAH!')
last_update = request.query_params.get('last_update')
if not last_update:
return Response({"error": "last_update parameter is required"}, status=status.HTTP_400_BAD_REQUEST)
print(last_update)
try:
last_update = timezone.datetime.fromisoformat(last_update)
except ValueError:
return Response({"error": f"Invalid date format for last_update: {last_update}"}, status=status.HTTP_400_BAD_REQUEST)
data_access = DataAccess.objects.filter(shared_with=request.user).values_list('model_id', flat=True)
log_query = Q(date__gt=last_update) & (Q(user=request.user) | Q(model_id__in=data_access))
logs = ModelLog.objects.filter(log_query).order_by('date')
updates = defaultdict(dict)
deletions = defaultdict(list)
for log in logs:
model = apps.get_model(app_label='tournaments', model_name=log.model_name)
if log.operation in ['POST', 'PUT']:
try:
instance = model.objects.get(id=log.model_id)
serializer_class = build_serializer_class(log.model_name)
serializer = serializer_class(instance)
updates[log.model_name][log.model_id] = serializer.data
except model.DoesNotExist:
# If the instance doesn't exist, it might have been deleted after this log was created
pass
elif log.operation == 'DELETE':
deletions[log.model_name].append({'model_id': log.model_id, 'store_id': log.store_id})
# Convert updates dict to list for each model
for model_name in updates:
updates[model_name] = list(updates[model_name].values())
# Convert deletions set to list for each model
for model_name in deletions:
deletions[model_name] = deletions[model_name]
date = logs.last().date.astimezone().isoformat(timespec='seconds') if logs else None
response_data = {
"updates": dict(updates),
"deletions": dict(deletions),
"date": date
}
return Response(response_data, status=status.HTTP_200_OK)
class CustomAuthToken(APIView):
permission_classes = []
def post(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
device_id = request.data.get('device_id')
user = authenticate(username=username, password=password)
if user is None and is_valid_email(username) == True:
true_username = self.get_username_from_email(username)
user = authenticate(username=true_username, password=password)
if user is not None:
# if user.device_id is None or user.device_id == device_id or user.username == 'apple-test':
# if user.device_id is None or user.device_id == device_id or user.username == 'apple-test':
user.device_id = device_id
user.save()
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key})
# else:
# return Response({'error': 'Vous ne pouvez pour l\'instant vous connecter sur plusieurs appareils en même temps. Veuillez vous déconnecter du précédent appareil. Autrement, veuillez contacter le support.'}, status=status.HTTP_403_FORBIDDEN)
else:
return Response({'error': 'L\'utilisateur et le mot de passe de correspondent pas'}, status=status.HTTP_401_UNAUTHORIZED)
def get_username_from_email(self, email):
try:
user = CustomUser.objects.get(email=email)
return user.username
except ObjectDoesNotExist:
return None # or handle the case where the user doesn't exist
class Logout(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request, *args, **kwargs):
# request.user.auth_token.delete()
device_id = request.data.get('device_id')
if request.user.device_id == device_id:
request.user.device_id = None
request.user.save()
return Response(status=status.HTTP_200_OK)
@api_view(['GET'])
def user_by_token(request):
serializer = UserSerializer(request.user)
return Response(serializer.data, status=status.HTTP_200_OK)
class UserViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = CustomUserSerializer
permission_classes = [] # Users are public whereas the other requests are only for logged users
def get_serializer_class(self):
# Use UserSerializer for other actions (e.g., create, retrieve)
if self.action in ['create', 'retrieve']:
return UserSerializer
return self.serializer_class
class ClubViewSet(viewsets.ModelViewSet):
queryset = Club.objects.all()
serializer_class = ClubSerializer
permission_classes = [IsClubOwner] # Clubs are public whereas the other requests are only for logged users
def perform_create(self, serializer):
serializer.save(creator=self.request.user)
class TournamentViewSet(viewsets.ModelViewSet):
queryset = Tournament.objects.all()
serializer_class = TournamentSerializer
def get_queryset(self):
if self.request.user.is_anonymous:
return []
return self.queryset.filter(
Q(event__creator=self.request.user) |
Q(id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
class PurchaseViewSet(viewsets.ModelViewSet):
queryset = Purchase.objects.all()
serializer_class = PurchaseSerializer
def get_queryset(self):
if self.request.user.is_anonymous:
return []
# return self.queryset.filter(user=self.request.user)
return self.queryset.filter(
Q(user=self.request.user) |
Q(id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
def put(self, request, pk):
raise MethodNotAllowed('PUT')
def patch(self, request, pk):
raise MethodNotAllowed('PATCH')
def delete(self, request, pk):
raise MethodNotAllowed('DELETE')
# class ExpandedTournamentViewSet(viewsets.ModelViewSet):
# queryset = Tournament.objects.all()
# serializer_class = ExpandedTournamentSerializer
class ChangePasswordView(UpdateAPIView):
serializer_class = ChangePasswordSerializer
def update(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
# if using drf authtoken, create a new token
if hasattr(user, 'auth_token'):
user.auth_token.delete()
token, created = Token.objects.get_or_create(user=user)
# return new token
return Response({'token': token.key}, status=status.HTTP_200_OK)
class EventViewSet(viewsets.ModelViewSet):
queryset = Event.objects.all()
serializer_class = EventSerializer
def get_queryset(self):
if self.request.user.is_anonymous:
return []
# return self.queryset.filter(creator=self.request.user)
return self.queryset.filter(
Q(creator=self.request.user) |
Q(id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
class RoundViewSet(viewsets.ModelViewSet):
queryset = Round.objects.all()
serializer_class = RoundSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
return self.queryset.filter(tournament__event__creator=self.request.user)
return []
class GroupStageViewSet(viewsets.ModelViewSet):
queryset = GroupStage.objects.all()
serializer_class = GroupStageSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
return self.queryset.filter(tournament__event__creator=self.request.user)
return []
class MatchViewSet(viewsets.ModelViewSet):
queryset = Match.objects.all()
serializer_class = MatchSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(Q(group_stage__tournament=tournament_id) | Q(round__tournament=tournament_id))
if self.request.user:
return self.queryset.filter(Q(group_stage__tournament__event__creator=self.request.user) | Q(round__tournament__event__creator=self.request.user))
return []
class TeamScoreViewSet(viewsets.ModelViewSet):
queryset = TeamScore.objects.all()
serializer_class = TeamScoreSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(team_registration__tournament=tournament_id)
if self.request.user:
return self.queryset.filter(team_registration__tournament__event__creator=self.request.user)
return []
class TeamRegistrationViewSet(viewsets.ModelViewSet):
queryset = TeamRegistration.objects.all()
serializer_class = TeamRegistrationSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
return self.queryset.filter(tournament__event__creator=self.request.user)
return []
class PlayerRegistrationViewSet(viewsets.ModelViewSet):
queryset = PlayerRegistration.objects.all()
serializer_class = PlayerRegistrationSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(team_registration__tournament=tournament_id)
if self.request.user:
return self.queryset.filter(team_registration__tournament__event__creator=self.request.user)
return []
class CourtViewSet(viewsets.ModelViewSet):
queryset = Court.objects.all()
serializer_class = CourtSerializer
class DateIntervalViewSet(viewsets.ModelViewSet):
queryset = DateInterval.objects.all()
serializer_class = DateIntervalSerializer
def get_queryset(self):
if self.request.user.is_anonymous:
return []
return self.queryset.filter(
Q(event__creator=self.request.user) |
Q(event__id__in=DataAccess.objects.filter(
shared_with=self.request.user,
model_name=self.queryset.model.__name__
).values_list('model_id', flat=True))
)
class FailedApiCallViewSet(viewsets.ModelViewSet):
queryset = FailedApiCall.objects.all()
serializer_class = FailedApiCallSerializer
permission_classes = [] # FailedApiCall are public whereas the other requests are only for logged users
def get_queryset(self):
return []
def perform_create(self, serializer):
if self.request.user.is_anonymous == False:
serializer.save(user=self.request.user)
else:
serializer.save()
class LogViewSet(viewsets.ModelViewSet):
queryset = Log.objects.all()
serializer_class = LogSerializer
permission_classes = [] # Log are public whereas the other requests are only for logged users
def get_queryset(self):
return []
def perform_create(self, serializer):
if self.request.user.is_anonymous == False:
serializer.save(user=self.request.user)
else:
serializer.save()
class DeviceTokenViewSet(viewsets.ModelViewSet):
queryset = DeviceToken.objects.all()
serializer_class = DeviceTokenSerializer
def get_queryset(self):
if self.request.user:
return self.queryset.filter(user=self.request.user)
return []
def create(self, request, *args, **kwargs):
value = request.data.get('value')
if DeviceToken.objects.filter(value=value).exists():
return Response({"detail": "This device token is already registered."}, status=208)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class DataAccessViewSet(viewsets.ModelViewSet):
queryset = DataAccess.objects.all()
serializer_class = DataAccessSerializer
def get_queryset(self):
if self.request.user:
return self.queryset.filter(owner=self.request.user)
return []
Loading…
Cancel
Save