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.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 = [ |
|||
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.conf import settings |
|||
from divebases.models import DiveBase |
|||
|
|||
User = settings.AUTH_USER_MODEL |
|||
|
|||
|
|||
class Event(models.Model): |
|||
title = models.CharField(max_length=255) |
|||
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( |
|||
'divebases.DiveBase', |
|||
on_delete=models.CASCADE, |
|||
related_name='events' |
|||
) |
|||
|
|||
created_by = models.ForeignKey( |
|||
User, |
|||
on_delete=models.PROTECT, |
|||
related_name='created_events' |
|||
) |
|||
|
|||
dive_base = models.ForeignKey(DiveBase, 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) |
|||
|
|||
def __str__(self): |
|||
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