12 changed files with 224 additions and 15 deletions
@ -0,0 +1,16 @@ |
|||||
|
from rest_framework.permissions import BasePermission |
||||
|
|
||||
|
class IsDiveBaseAdmin(BasePermission): |
||||
|
""" |
||||
|
Allows access only to admins or superusers. |
||||
|
""" |
||||
|
def has_permission(self, request, view): |
||||
|
return bool(request.user and request.user.is_authenticated and request.user.role == "ADMIN" or request.user.is_superuser) |
||||
|
|
||||
|
|
||||
|
class IsSameDiveBase(BasePermission): |
||||
|
""" |
||||
|
Allows access only to objects in the same dive base as the user. |
||||
|
""" |
||||
|
def has_object_permission(self, request, view, obj): |
||||
|
return obj.dive_base == request.user.dive_base |
||||
@ -0,0 +1,9 @@ |
|||||
|
from rest_framework import viewsets |
||||
|
from .models import DiveBase |
||||
|
from .serializers import DiveBaseSerializer |
||||
|
from rest_framework.permissions import IsAuthenticated |
||||
|
|
||||
|
class DiveBaseViewSet(viewsets.ModelViewSet): |
||||
|
serializer_class = DiveBaseSerializer |
||||
|
permission_classes = [IsAuthenticated] |
||||
|
queryset = DiveBase.objects.all() |
||||
@ -0,0 +1,7 @@ |
|||||
|
from rest_framework import serializers |
||||
|
from .models import DiveBase |
||||
|
|
||||
|
class DiveBaseSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = DiveBase |
||||
|
fields = ['id', 'name', 'location'] |
||||
@ -1,7 +1,19 @@ |
|||||
|
|
||||
from django.contrib import admin |
from django.contrib import admin |
||||
from django.urls import path |
from django.urls import path, include |
||||
|
from rest_framework.routers import DefaultRouter |
||||
|
from users.api import UserViewSet |
||||
|
from divebases.api import DiveBaseViewSet |
||||
|
from events.api import EventViewSet, EventApplicationViewSet |
||||
|
from infos.api import InfoArticleViewSet |
||||
|
|
||||
|
router = DefaultRouter() |
||||
|
router.register(r'users', UserViewSet, basename='user') |
||||
|
router.register(r'divebases', DiveBaseViewSet, basename='divebase') |
||||
|
router.register(r'events', EventViewSet, basename='event') |
||||
|
router.register(r'event-applications', EventApplicationViewSet, basename='eventapplication') |
||||
|
router.register(r'infos', InfoArticleViewSet, basename='info') |
||||
|
|
||||
urlpatterns = [ |
urlpatterns = [ |
||||
path('admin/', admin.site.urls), |
path('admin/', admin.site.urls), |
||||
|
path('api/', include(router.urls)), |
||||
] |
] |
||||
|
|||||
@ -0,0 +1,27 @@ |
|||||
|
from rest_framework import viewsets |
||||
|
from rest_framework.permissions import IsAuthenticated |
||||
|
from .models import Event, EventApplication |
||||
|
from .serializers import EventSerializer, EventApplicationSerializer |
||||
|
from core.permissions import IsSameDiveBase, IsDiveBaseAdmin |
||||
|
|
||||
|
class EventViewSet(viewsets.ModelViewSet): |
||||
|
serializer_class = EventSerializer |
||||
|
permission_classes = [IsAuthenticated] |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
return Event.objects.filter(dive_base=self.request.user.dive_base, is_deleted=False) |
||||
|
|
||||
|
def perform_destroy(self, instance): |
||||
|
instance.is_deleted = True |
||||
|
instance.save() |
||||
|
|
||||
|
|
||||
|
class EventApplicationViewSet(viewsets.ModelViewSet): |
||||
|
serializer_class = EventApplicationSerializer |
||||
|
permission_classes = [IsAuthenticated] |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
return EventApplication.objects.filter(user=self.request.user) |
||||
|
|
||||
|
def perform_create(self, serializer): |
||||
|
serializer.save(user=self.request.user) |
||||
@ -0,0 +1,48 @@ |
|||||
|
# Generated by Django 5.2.9 on 2026-01-06 12:26 |
||||
|
|
||||
|
import django.db.models.deletion |
||||
|
from django.conf import settings |
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('events', '0002_initial'), |
||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='event', |
||||
|
name='description', |
||||
|
field=models.TextField(blank=True), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='event', |
||||
|
name='google_maps_link', |
||||
|
field=models.URLField(blank=True), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='event', |
||||
|
name='location', |
||||
|
field=models.CharField(blank=True, max_length=255), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='event', |
||||
|
name='payment_details', |
||||
|
field=models.TextField(blank=True), |
||||
|
), |
||||
|
migrations.CreateModel( |
||||
|
name='EventApplication', |
||||
|
fields=[ |
||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('paid', models.BooleanField(default=False)), |
||||
|
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='applications', to='events.event')), |
||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='event_applications', to=settings.AUTH_USER_MODEL)), |
||||
|
], |
||||
|
options={ |
||||
|
'unique_together': {('event', 'user')}, |
||||
|
}, |
||||
|
), |
||||
|
] |
||||
@ -1,26 +1,32 @@ |
|||||
from django.db import models |
from django.db import models |
||||
from django.conf import settings |
from django.conf import settings |
||||
|
from divebases.models import DiveBase |
||||
|
|
||||
User = settings.AUTH_USER_MODEL |
User = settings.AUTH_USER_MODEL |
||||
|
|
||||
|
|
||||
class Event(models.Model): |
class Event(models.Model): |
||||
title = models.CharField(max_length=255) |
title = models.CharField(max_length=255) |
||||
start_datetime = models.DateTimeField() |
start_datetime = models.DateTimeField() |
||||
|
location = models.CharField(max_length=255, blank=True) |
||||
|
google_maps_link = models.URLField(blank=True) |
||||
|
description = models.TextField(blank=True) |
||||
|
payment_details = models.TextField(blank=True) |
||||
|
|
||||
dive_base = models.ForeignKey( |
dive_base = models.ForeignKey(DiveBase, on_delete=models.CASCADE, related_name='events') |
||||
'divebases.DiveBase', |
created_by = models.ForeignKey(User, on_delete=models.PROTECT, related_name='created_events') |
||||
on_delete=models.CASCADE, |
|
||||
related_name='events' |
|
||||
) |
|
||||
|
|
||||
created_by = models.ForeignKey( |
|
||||
User, |
|
||||
on_delete=models.PROTECT, |
|
||||
related_name='created_events' |
|
||||
) |
|
||||
|
|
||||
is_deleted = models.BooleanField(default=False) |
is_deleted = models.BooleanField(default=False) |
||||
|
|
||||
def __str__(self): |
def __str__(self): |
||||
return self.title |
return self.title |
||||
|
|
||||
|
|
||||
|
class EventApplication(models.Model): |
||||
|
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='applications') |
||||
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='event_applications') |
||||
|
paid = models.BooleanField(default=False) |
||||
|
|
||||
|
class Meta: |
||||
|
unique_together = ('event', 'user') # prevent duplicate applications |
||||
|
|
||||
|
def __str__(self): |
||||
|
return f"{self.user} applied for {self.event}" |
||||
|
|||||
@ -0,0 +1,23 @@ |
|||||
|
from rest_framework import serializers |
||||
|
from .models import Event, EventApplication |
||||
|
from divebases.serializers import DiveBaseSerializer |
||||
|
from users.serializers import UserSerializer |
||||
|
|
||||
|
class EventSerializer(serializers.ModelSerializer): |
||||
|
dive_base = DiveBaseSerializer(read_only=True) |
||||
|
|
||||
|
class Meta: |
||||
|
model = Event |
||||
|
fields = ['id', 'title', 'start_datetime', 'location', 'google_maps_link', |
||||
|
'description', 'payment_details', 'dive_base', 'is_deleted'] |
||||
|
|
||||
|
class EventApplicationSerializer(serializers.ModelSerializer): |
||||
|
user = UserSerializer(read_only=True) |
||||
|
event_id = serializers.PrimaryKeyRelatedField( |
||||
|
source='event', queryset=Event.objects.all(), write_only=True |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
model = EventApplication |
||||
|
fields = ['id', 'event', 'event_id', 'user', 'paid'] |
||||
|
read_only_fields = ['id', 'user'] |
||||
@ -0,0 +1,15 @@ |
|||||
|
from rest_framework import viewsets |
||||
|
from rest_framework.permissions import IsAuthenticated |
||||
|
from .models import InfoArticle |
||||
|
from .serializers import InfoArticleSerializer |
||||
|
|
||||
|
class InfoArticleViewSet(viewsets.ModelViewSet): |
||||
|
serializer_class = InfoArticleSerializer |
||||
|
permission_classes = [IsAuthenticated] |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
return InfoArticle.objects.filter(dive_base=self.request.user.dive_base, is_deleted=False) |
||||
|
|
||||
|
def perform_destroy(self, instance): |
||||
|
instance.is_deleted = True |
||||
|
instance.save() |
||||
@ -0,0 +1,10 @@ |
|||||
|
from rest_framework import serializers |
||||
|
from .models import InfoArticle |
||||
|
from divebases.serializers import DiveBaseSerializer |
||||
|
|
||||
|
class InfoArticleSerializer(serializers.ModelSerializer): |
||||
|
dive_base = DiveBaseSerializer(read_only=True) |
||||
|
|
||||
|
class Meta: |
||||
|
model = InfoArticle |
||||
|
fields = ['id', 'title', 'short_description', 'content', 'dive_base', 'is_deleted'] |
||||
@ -0,0 +1,17 @@ |
|||||
|
from rest_framework import viewsets |
||||
|
from rest_framework.permissions import IsAuthenticated |
||||
|
from .models import User |
||||
|
from .serializers import UserSerializer |
||||
|
from core.permissions import IsDiveBaseAdmin |
||||
|
|
||||
|
class UserViewSet(viewsets.ModelViewSet): |
||||
|
serializer_class = UserSerializer |
||||
|
permission_classes = [IsAuthenticated] |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
user = self.request.user |
||||
|
if user.is_superuser: |
||||
|
return User.objects.all() |
||||
|
if user.role == "ADMIN": |
||||
|
return User.objects.filter(dive_base=user.dive_base) |
||||
|
return User.objects.filter(id=user.id) |
||||
@ -0,0 +1,19 @@ |
|||||
|
from rest_framework import serializers |
||||
|
from .models import User |
||||
|
from divebases.models import DiveBase |
||||
|
|
||||
|
class DiveBaseSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = DiveBase |
||||
|
fields = ['id', 'name', 'location'] |
||||
|
|
||||
|
class UserSerializer(serializers.ModelSerializer): |
||||
|
dive_base = DiveBaseSerializer(read_only=True) |
||||
|
dive_base_id = serializers.PrimaryKeyRelatedField( |
||||
|
source='dive_base', queryset=DiveBase.objects.all(), write_only=True, required=False |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
model = User |
||||
|
fields = ['id', 'username', 'email', 'role', 'dive_certificate', 'dive_base', 'dive_base_id'] |
||||
|
read_only_fields = ['id'] |
||||
Loading…
Reference in new issue