diff --git a/CHANGELOG.md b/CHANGELOG.md index 2288f591c..6201e6c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ --- ## Neste versjon + +## Versjon 2023.10.23 +- ⚡ **Brukere** HS kan styre medlemmer - ✨ **Bannere** Filtrering på bannere - ✨ **Spørreskjemaer** NOK medlemmer kan lage spørreskjema. - ⚡ **Bruker** Nå kan ikke HS lenger endre eller slette brukere. diff --git a/app/content/exceptions.py b/app/content/exceptions.py index ff83e3f28..07eae9f42 100644 --- a/app/content/exceptions.py +++ b/app/content/exceptions.py @@ -2,6 +2,11 @@ from rest_framework.exceptions import APIException +class APIPaidEventCantBeChangedToFreeEventException(APIException): + status_code = status.HTTP_400_BAD_REQUEST + default_detail = "Arrangementet er et betalt arrangement, og kan ikke endres til et gratis arrangement" + + class APIUserAlreadyAttendedEvent(APIException): status_code = status.HTTP_400_BAD_REQUEST default_detail = "Brukeren har allerede ankommet" diff --git a/app/content/models/registration.py b/app/content/models/registration.py index 0f3a249fb..5af2be1ad 100644 --- a/app/content/models/registration.py +++ b/app/content/models/registration.py @@ -109,7 +109,6 @@ def admin_unregister(self, *args, **kwargs): def save(self, *args, **kwargs): if not self.registration_id: self.create() - self.send_notification_and_mail() if ( self.event.is_full @@ -118,6 +117,7 @@ def save(self, *args, **kwargs): ): raise EventIsFullError + self.send_notification_and_mail() return super().save(*args, **kwargs) def create(self): diff --git a/app/content/models/user.py b/app/content/models/user.py index 57555e9f8..26e3a4b9a 100644 --- a/app/content/models/user.py +++ b/app/content/models/user.py @@ -56,7 +56,7 @@ def create_superuser(self, user_id, password): class User(AbstractBaseUser, PermissionsMixin, BaseModel, OptionalImage): - write_access = [AdminGroup.INDEX] + write_access = AdminGroup.admin() read_access = [Groups.TIHLDE] user_id = models.CharField(max_length=15, primary_key=True) @@ -161,7 +161,6 @@ def has_unanswered_evaluations_for(self, event): return self.get_unanswered_evaluations().filter(event=event).exists() def get_unanswered_evaluations(self): - from app.forms.models.forms import EventForm, EventFormType date_30_days_ago = now() - timedelta(days=30) diff --git a/app/content/serializers/event.py b/app/content/serializers/event.py index b18230a8e..a31c89dca 100644 --- a/app/content/serializers/event.py +++ b/app/content/serializers/event.py @@ -5,6 +5,7 @@ from app.common.enums import GroupType from app.common.serializers import BaseModelSerializer +from app.content.exceptions import APIPaidEventCantBeChangedToFreeEventException from app.content.models import Event, PriorityPool from app.content.serializers.priority_pool import ( PriorityPoolCreateSerializer, @@ -178,10 +179,7 @@ def update(self, instance, validated_data): ) if event.is_paid_event and not len(paid_information_data): - paid_event = PaidEvent.objects.get(event=event) - if paid_event: - paid_event.delete() - event.paid_information = None + raise APIPaidEventCantBeChangedToFreeEventException() if len(paid_information_data): self.update_paid_information(event, paid_information_data) diff --git a/app/content/views/registration.py b/app/content/views/registration.py index d899e2031..4dfd3437b 100644 --- a/app/content/views/registration.py +++ b/app/content/views/registration.py @@ -3,6 +3,8 @@ from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response +from sentry_sdk import capture_exception + from app.common.pagination import BasePagination from app.common.permissions import BasicViewPermission, is_admin_user from app.common.viewsets import BaseViewSet @@ -67,9 +69,15 @@ def create(self, request, *args, **kwargs): try: create_payment_order(event, request, registration) - except Exception as e: + except Exception as order_error: + capture_exception(order_error) registration.delete() - raise e + return Response( + { + "detail": "Det skjedde en feil med opprettelse av betalingsordre. Påmeldingen ble ikke fullført." + }, + status=status.HTTP_400_BAD_REQUEST, + ) registration_serializer = RegistrationSerializer( registration, context={"user": registration.user} diff --git a/app/settings.py b/app/settings.py index a6b0176ac..73ab2432e 100644 --- a/app/settings.py +++ b/app/settings.py @@ -282,6 +282,7 @@ DEFAULT_AUTO_FIELD = "django.db.models.AutoField" -CELERY_BROKER_URL = "amqp://guest:guest@rabbitmq:5672" +CELERY_BROKER_URL = os.environ.get("CELERY_BROKER_URL") or "amqp://guest:guest@rabbitmq:5672" + if ENVIRONMENT == EnvironmentOptions.LOCAL: CELERY_TASK_ALWAYS_EAGER = False diff --git a/app/tests/content/test_user_integration.py b/app/tests/content/test_user_integration.py index d572c2f4e..27930833c 100644 --- a/app/tests/content/test_user_integration.py +++ b/app/tests/content/test_user_integration.py @@ -182,7 +182,6 @@ def test_filter_only_users_with_active_strikes( ], ) def test_user_actions_self(url, status_code, member, api_client): - url = f"{API_USER_BASE_URL}me{url}" client = api_client(user=member) @@ -341,7 +340,7 @@ def test_update_other_user_as_hs_user(member, user, api_client): url = _get_user_detail_url(user) response = client.put(url, data) - assert response.status_code == status.HTTP_403_FORBIDDEN + assert response.status_code == status.HTTP_200_OK def test_update_other_user_as_index_user(member, user, api_client): @@ -459,7 +458,7 @@ def test_destroy_other_user_as_hs_user(member, user, api_client): url = _get_user_detail_url(user) response = client.delete(url) - assert response.status_code == status.HTTP_403_FORBIDDEN + assert response.status_code == status.HTTP_200_OK def test_destroy_other_user_as_index_user(member, user, api_client): diff --git a/app/tests/payment/test_paid_event_integration.py b/app/tests/payment/test_paid_event_integration.py index d33370828..a759cdfa5 100644 --- a/app/tests/payment/test_paid_event_integration.py +++ b/app/tests/payment/test_paid_event_integration.py @@ -28,6 +28,7 @@ def get_paid_event_data( organizer=None, price=100.00, paytime="01:00:00", + is_paid_event=True, ): start_date = timezone.now() + timedelta(days=10) end_date = timezone.now() + timedelta(days=11) @@ -36,7 +37,7 @@ def get_paid_event_data( "location": location, "start_date": start_date, "end_date": end_date, - "is_paid_event": True, + "is_paid_event": is_paid_event, "paid_information": {"price": price, "paytime": paytime}, } if organizer: @@ -52,7 +53,7 @@ def _get_registration_post_data(user, event): def get_paid_event_without_price_data( - title="New Title", location="New Location", organizer=None + title="New Title", location="New Location", organizer=None, is_paid_event=True ): start_date = timezone.now() + timedelta(days=10) end_date = timezone.now() + timedelta(days=11) @@ -61,7 +62,7 @@ def get_paid_event_without_price_data( "location": location, "start_date": start_date, "end_date": end_date, - "is_paid_event": True, + "is_paid_event": is_paid_event, } if organizer: data["organizer"] = organizer @@ -134,21 +135,24 @@ def test_update_paid_event_as_admin(admin_user): assert float(response.data["paid_information"]["price"]) == new_event_price -# @pytest.mark.django_db -# def test_delete_paid_event_as_admin(admin_user, paid_event): -# client = get_api_client(user=admin_user) -# event = paid_event.event +@pytest.mark.django_db +def test_update_paid_event_to_free_event_as_admin(admin_user): + """ + HS and Index members should not be able to update a paid event to a free event. + Other subgroup members can update paid events where event.organizer is their group or None. + Leaders of committees and interest groups should be able to + update events where event.organizer is their group or None. + """ -# url = _get_registration_url(event=event) -# data = _get_registration_post_data(admin_user, event) -# response = client.post(url, data=data) -# assert response.status_code == 201 + paid_event = PaidEventFactory(price=100.00) + event = paid_event.event + organizer = Group.objects.get_or_create(name="HS", type=GroupType.BOARD)[0] + client = get_api_client(user=admin_user) + url = get_events_url_detail(event) + data = get_paid_event_data(organizer=organizer.slug, is_paid_event=False) -# url = get_events_url_detail(event) -# event_response = client.delete(url) -# paid_events = PaidEvent.objects.all() -# orders = Order.objects.all() + response = client.put(url, data) + event.refresh_from_db() -# assert event_response.status_code == 200 -# assert len(paid_events) == 0 -# assert len(orders) == 0 + assert response.status_code == 400 + assert event.is_paid_event