Skip to content

Commit

Permalink
Merge branch 'dev' into fix(registration)/allow-registration-for-grou…
Browse files Browse the repository at this point in the history
…p-members
  • Loading branch information
MadsNyl authored Nov 11, 2024
2 parents 5993079 + 0a177b0 commit cd9c34b
Show file tree
Hide file tree
Showing 44 changed files with 925 additions and 7 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@
---

## Neste versjon

## Versjon 2024.11.04
- 🎨**Overordnet**. Endret variabel og funksjonsnavn til å følge konvensjoner og andre små endringer.
-**Filtrering**. Admin kan nå filtere deltakere av et arrangement på studie, studieår, om deltakere har allergier, (om deltakere godtar å bli tatt bilde av, om deltakere har ankommet), i tillegg til søk på fornavn og etternavn.

-**Filopplasting**. Det er nå mulig for admin brukere å laste opp- og slette filer.
-**Mail endepunkt**. Det er nå laget et endepunkt for å sende mailer.

## Versjon 2024.10.11
-**Tilbakemelding-funksjon**. Man kan nå opprette tilbakemeldinger for bugs og idé.
- 🦟 **Påmelding**. Det vil nå ikke være mulig med flere påmeldinger på et arrangement enn maksgrensen.
Expand Down
2 changes: 2 additions & 0 deletions app/common/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ class BaseModelSerializer(serializers.ModelSerializer):
def update(self, instance, validated_data):
if hasattr(instance, "image") and "image" in validated_data:
replace_file(instance.image, validated_data.get("image", None))
if hasattr(instance, "file") and "file" in validated_data:
replace_file(instance.file, validated_data.get("file", None))
return super().update(instance, validated_data)
2 changes: 2 additions & 0 deletions app/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@
SLACK_BEDPRES_OG_KURS_CHANNEL_ID = "C01DCSJ8X2Q"
SLACK_ARRANGEMENTER_CHANNEL_ID = "C01LFEFJFV3"

MAX_GALLERY_SIZE = 50

# TODO: Create api-urls as constants which then can be used in for example tests and urls.py files
4 changes: 0 additions & 4 deletions app/content/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@
UserCalendarEvents,
UserViewSet,
accept_form,
delete,
register_with_feide,
send_email,
upload,
)

router = routers.DefaultRouter()
Expand Down Expand Up @@ -53,9 +51,7 @@
urlpatterns = [
re_path(r"", include(router.urls)),
path("accept-form/", accept_form),
path("upload/", upload),
path("send-email/", send_email),
path("delete-file/<str:container_name>/<str:blob_name>/", delete),
path("feide/", register_with_feide),
re_path(r"users/(?P<user_id>[^/.]+)/events.ics", UserCalendarEvents()),
]
1 change: 0 additions & 1 deletion app/content/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from app.content.views.news import NewsViewSet
from app.content.views.page import PageViewSet
from app.content.views.short_link import ShortLinkViewSet
from app.content.views.upload import upload, delete
from app.content.views.strike import StrikeViewSet
from app.content.views.toddel import ToddelViewSet
from app.content.views.qr_code import QRCodeViewSet
Expand Down
Empty file added app/files/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions app/files/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.contrib import admin

from app.files import models

admin.site.register(models.UserGallery)
admin.site.register(models.File)
5 changes: 5 additions & 0 deletions app/files/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class FilesConfig(AppConfig):
name = "app.files"
Empty file added app/files/enums.py
Empty file.
22 changes: 22 additions & 0 deletions app/files/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from rest_framework import status
from rest_framework.exceptions import APIException, ValidationError

from app.constants import MAX_GALLERY_SIZE


class APINoGalleryFoundForUser(APIException):
status_code = status.HTTP_400_BAD_REQUEST
default_detail = "Ingen galleri ble funnet for brukeren."


class NoGalleryFoundForUser(ValidationError):
default_detail = "Ingen galleri ble funnet for brukeren."


class APIGalleryIsFull(APIException):
status_code = status.HTTP_400_BAD_REQUEST
default_detail = f"Galleriet er fullt med {MAX_GALLERY_SIZE} filer."


class GalleryIsFull(ValidationError):
default_detail = f"Galleriet er fullt med {MAX_GALLERY_SIZE} filer."
Empty file added app/files/factories/__init__.py
Empty file.
Empty file added app/files/filters/__init__.py
Empty file.
68 changes: 68 additions & 0 deletions app/files/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Generated by Django 4.2.16 on 2024-10-07 16:45

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="UserGallery",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"author",
models.OneToOneField(
on_delete=django.db.models.deletion.PROTECT,
related_name="user_galleries",
to=settings.AUTH_USER_MODEL,
),
),
],
),
migrations.CreateModel(
name="File",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("title", models.CharField(max_length=80)),
("url", models.URLField()),
("description", models.TextField(blank=True)),
(
"gallery",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="files",
to="files.usergallery",
),
),
],
),
]
22 changes: 22 additions & 0 deletions app/files/migrations/0002_remove_file_url_file_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 5.1.1 on 2024-10-31 15:22

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("files", "0001_initial"),
]

operations = [
migrations.RemoveField(
model_name="file",
name="url",
),
migrations.AddField(
model_name="file",
name="file",
field=models.URLField(blank=True, max_length=600, null=True),
),
]
Empty file.
17 changes: 17 additions & 0 deletions app/files/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from app.files.exceptions import (
APIGalleryIsFull,
APINoGalleryFoundForUser,
GalleryIsFull,
NoGalleryFoundForUser,
)
from app.util.mixins import APIErrorsMixin


class FileErrorMixin(APIErrorsMixin):
@property
def expected_exceptions(self):
return {
**super().expected_exceptions,
NoGalleryFoundForUser: APINoGalleryFoundForUser,
GalleryIsFull: APIGalleryIsFull,
}
2 changes: 2 additions & 0 deletions app/files/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from app.files.models.user_gallery import UserGallery
from app.files.models.file import File
68 changes: 68 additions & 0 deletions app/files/models/file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from django.db import models
from django.db.models import PROTECT

from app.common.enums import AdminGroup, Groups
from app.common.permissions import BasePermissionModel, check_has_access
from app.files.models.user_gallery import UserGallery
from app.util.models import BaseModel, OptionalFile


class File(BaseModel, BasePermissionModel, OptionalFile):
read_access = AdminGroup.admin()
write_access = AdminGroup.admin()

title = models.CharField(max_length=80)

description = models.TextField(blank=True)
gallery = models.ForeignKey(
UserGallery, on_delete=PROTECT, related_name="files", blank=False
)

class Meta:
pass

def __str__(self):
return self.title

@classmethod
def has_read_permission(cls, request):
return super().has_read_permission(request)

@classmethod
def has_write_permission(cls, request):
return check_has_access(Groups.TIHLDE, request)

@classmethod
def has_retrieve_permission(cls, request):
return cls.has_read_permission(request)

@classmethod
def has_create_permission(cls, request):
return check_has_access(cls.write_access, request)

@classmethod
def has_update_permission(cls, request):
return check_has_access(cls.write_access, request)

@classmethod
def has_destroy_permission(cls, request):
return check_has_access(Groups.TIHLDE, request)

@classmethod
def has_list_permission(cls, request):
return cls.has_read_permission(request)

def has_object_read_permission(self, request):
return self.has_read_permission(request)

def has_object_write_permission(self, request):
return self.has_write_permission(request)

def has_object_retrieve_permission(self, request):
return self.has_object_read_permission(request)

def has_object_update_permission(self, request):
return self.gallery.author == request.user

def has_object_destroy_permission(self, request):
return self.gallery.author == request.user
77 changes: 77 additions & 0 deletions app/files/models/user_gallery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from django.db import models
from django.db.models import PROTECT

from app.common.enums import AdminGroup
from app.common.permissions import BasePermissionModel
from app.content.models.user import User
from app.util.models import BaseModel


class UserGallery(BaseModel, BasePermissionModel):
read_access = AdminGroup.admin()
write_access = AdminGroup.admin()

author = models.OneToOneField(
User, on_delete=PROTECT, related_name="user_galleries"
)

class Meta:
pass

def __str__(self):
return f"Gallery by {self.author.first_name} {self.author.last_name}"

@classmethod
def has_read_permission(cls, request):
return super().has_read_permission(request)

@classmethod
def has_write_permission(cls, request):
return super().has_write_permission(request)

@classmethod
def has_retrieve_permission(cls, request):
return cls.has_read_permission(request)

@classmethod
def has_create_permission(cls, request):
return cls.has_write_permission(request)

@classmethod
def has_update_permission(cls, request):
return cls.has_write_permission(request)

@classmethod
def has_destroy_permission(cls, request):
return cls.has_write_permission(request)

@classmethod
def has_list_permission(cls, request):
return cls.has_read_permission(request)

def has_object_read_permission(self, request):
return self.has_read_permission(request)

def has_object_write_permission(self, request):
return self.has_write_permission(request)

def has_object_retrieve_permission(self, request):
return self.has_object_read_permission(request)

def has_object_update_permission(self, request):
return self.author == request.user

def has_object_destroy_permission(self, request):
return self.author == request.user

@classmethod
def get_all_files(cls, user):
return cls.objects.get(author=user).files.all()

@classmethod
def has_gallery(cls, user):
return cls.objects.filter(author=user).exists()

@classmethod
def create_gallery(cls, user):
return cls.objects.create(author=user)
6 changes: 6 additions & 0 deletions app/files/serializers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from app.files.serializers.user_gallery import UserGallerySerializer
from app.files.serializers.file import (
FileSerializer,
CreateFileSerializer,
DeleteFileSerializer,
)
Loading

0 comments on commit cd9c34b

Please sign in to comment.