diff --git a/server/config/urls.py b/server/config/urls.py index 67e968c7..da7ff21d 100644 --- a/server/config/urls.py +++ b/server/config/urls.py @@ -10,6 +10,8 @@ from django.views import defaults as default_views from django.views.decorators.csrf import csrf_exempt from django_ratelimit.exceptions import Ratelimited from graphene_django.views import GraphQLView +from wagtail import urls as wagtail_urls +from wagtail.admin import urls as wagtailadmin_urls from vbv_lernwelt.assignment.views import request_assignment_completion_status from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt @@ -24,6 +26,7 @@ from vbv_lernwelt.core.views import ( vue_home, vue_login, vue_logout, + list_organisations, ) from vbv_lernwelt.course.views import ( course_page_api_view, @@ -54,9 +57,6 @@ from vbv_lernwelt.importer.views import ( t2l_sync, ) from vbv_lernwelt.notify.views import email_notification_settings -from wagtail import urls as wagtail_urls -from wagtail.admin import urls as wagtailadmin_urls -from wagtail.documents import urls as media_library_urls class SignedIntConverter(IntConverter): @@ -98,6 +98,8 @@ urlpatterns = [ # user management path("sso/", include("vbv_lernwelt.sso.urls")), re_path(r'api/core/me/$', me_user_view, name='me_user_view'), + re_path(r'api/core/organisations/$', list_organisations, name='list_organisations'), + re_path(r'api/core/login/$', django_view_authentication_exempt(vue_login), name='vue_login'), re_path(r'api/core/logout/$', vue_logout, name='vue_logout'), diff --git a/server/vbv_lernwelt/core/migrations/0003_user_organisation.py b/server/vbv_lernwelt/core/migrations/0003_user_organisation.py new file mode 100644 index 00000000..cb5f02d7 --- /dev/null +++ b/server/vbv_lernwelt/core/migrations/0003_user_organisation.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.20 on 2023-11-13 13:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0002_joblog'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='organisation', + field=models.CharField(blank=True, choices=[('1', 'Andere Broker'), ('2', 'Andere Krankenversicherer'), ('3', 'Andere Privatversicherer'), ('4', 'Allianz Suisse'), ('5', 'AON'), ('6', 'AXA Winterthur'), ('7', 'Baloise'), ('8', 'CAP Rechtsschutz'), ('9', 'Coop Rechtsschutz'), ('10', 'CSS'), ('11', 'Die Mobiliar'), ('12', 'Emmental Versicherung'), ('13', 'GENERALI Versicherungen'), ('14', 'Groupe Mutuel'), ('15', 'Helsana'), ('16', 'Helvetia'), ('17', 'Kessler & Co AG'), ('18', 'Orion Rechtsschutz Versicherung'), ('19', 'PAX'), ('20', 'Sanitas'), ('21', 'SUVA'), ('22', 'Swica'), ('23', 'Swiss Life'), ('24', 'Swiss Re'), ('25', 'Visana Services AG'), ('26', 'VZ VermögensZentrum AG'), ('27', 'Würth Financial Services AG'), ('28', 'Zürich'), ('29', 'VBV'), ('30', 'Vaudoise'), ('31', 'Keine Firmenzugehörigkeit')], max_length=255), + ), + ] diff --git a/server/vbv_lernwelt/core/models.py b/server/vbv_lernwelt/core/models.py index 524a2133..842a4a4f 100644 --- a/server/vbv_lernwelt/core/models.py +++ b/server/vbv_lernwelt/core/models.py @@ -4,6 +4,8 @@ from django.contrib.auth.models import AbstractUser from django.db import models from django.db.models import JSONField +from vbv_lernwelt.core.organisations import ORGANISATIONS + class User(AbstractUser): """ @@ -29,6 +31,12 @@ class User(AbstractUser): additional_json_data = JSONField(default=dict, blank=True) language = models.CharField(max_length=2, choices=LANGUAGE_CHOICES, default="de") + organisation = models.CharField( + max_length=255, + choices=ORGANISATIONS, + blank=True, + ) + class SecurityRequestResponseLog(models.Model): label = models.CharField(max_length=255, blank=True, default="") diff --git a/server/vbv_lernwelt/core/organisations.py b/server/vbv_lernwelt/core/organisations.py new file mode 100644 index 00000000..6bc80d38 --- /dev/null +++ b/server/vbv_lernwelt/core/organisations.py @@ -0,0 +1,33 @@ +ORGANISATIONS = [ + ("1", "Andere Broker"), + ("2", "Andere Krankenversicherer"), + ("3", "Andere Privatversicherer"), + ("4", "Allianz Suisse"), + ("5", "AON"), + ("6", "AXA Winterthur"), + ("7", "Baloise"), + ("8", "CAP Rechtsschutz"), + ("9", "Coop Rechtsschutz"), + ("10", "CSS"), + ("11", "Die Mobiliar"), + ("12", "Emmental Versicherung"), + ("13", "GENERALI Versicherungen"), + ("14", "Groupe Mutuel"), + ("15", "Helsana"), + ("16", "Helvetia"), + ("17", "Kessler & Co AG"), + ("18", "Orion Rechtsschutz Versicherung"), + ("19", "PAX"), + ("20", "Sanitas"), + ("21", "SUVA"), + ("22", "Swica"), + ("23", "Swiss Life"), + ("24", "Swiss Re"), + ("25", "Visana Services AG"), + ("26", "VZ VermögensZentrum AG"), + ("27", "Würth Financial Services AG"), + ("28", "Zürich"), + ("29", "VBV"), + ("30", "Vaudoise"), + ("31", "Keine Firmenzugehörigkeit"), +] diff --git a/server/vbv_lernwelt/core/serializers.py b/server/vbv_lernwelt/core/serializers.py index 523d70ec..3e910b80 100644 --- a/server/vbv_lernwelt/core/serializers.py +++ b/server/vbv_lernwelt/core/serializers.py @@ -25,6 +25,7 @@ class UserSerializer(serializers.ModelSerializer): "email", "username", "avatar_url", + "organisation", "is_superuser", "course_session_experts", "language", diff --git a/server/vbv_lernwelt/core/tests/test_me_api.py b/server/vbv_lernwelt/core/tests/test_me_api.py index 04fbc012..44981678 100644 --- a/server/vbv_lernwelt/core/tests/test_me_api.py +++ b/server/vbv_lernwelt/core/tests/test_me_api.py @@ -14,7 +14,7 @@ class MeUserViewTest(APITestCase): def test_user_can_update_language(self) -> None: # GIVEN - url = reverse("me_user_view") # replace with your actual URL name + url = reverse("me_user_view") # WHEN response = self.client.put(url, {"language": "it"}) @@ -24,3 +24,16 @@ class MeUserViewTest(APITestCase): updated_user = User.objects.get(username="testuser") self.assertEquals(updated_user.language, "it") + + def test_user_can_update_org(self) -> None: + # GIVEN + url = reverse("me_user_view") # replace with your actual URL name + + # WHEN + response = self.client.put(url, {"organisation": "6"}) + + # THEN + self.assertEqual(response.status_code, status.HTTP_200_OK) + + updated_user = User.objects.get(username="testuser") + self.assertEquals(updated_user.organisation, "6") diff --git a/server/vbv_lernwelt/core/tests/test_organisation_api.py b/server/vbv_lernwelt/core/tests/test_organisation_api.py new file mode 100644 index 00000000..ec34a0b2 --- /dev/null +++ b/server/vbv_lernwelt/core/tests/test_organisation_api.py @@ -0,0 +1,27 @@ +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APITestCase + +from vbv_lernwelt.core.models import User +from vbv_lernwelt.core.organisations import ORGANISATIONS + + +class OrganisationViewTest(APITestCase): + def setUp(self) -> None: + self.user = User.objects.create_user( + "testuser", "test@example.com", "testpassword" + ) + self.client.login(username="testuser", password="testpassword") + + def test_list_organisations(self) -> None: + # GIVEN + url = reverse("list_organisations") + + # WHEN + response = self.client.get(url) + + # THEN + self.assertEqual(response.status_code, status.HTTP_200_OK) + + _id, name = ORGANISATIONS[0] + self.assertEqual(response.data[0], {"id": _id, "name": name}) diff --git a/server/vbv_lernwelt/core/views.py b/server/vbv_lernwelt/core/views.py index 64bb11c4..8101e5cf 100644 --- a/server/vbv_lernwelt/core/views.py +++ b/server/vbv_lernwelt/core/views.py @@ -22,6 +22,7 @@ from rest_framework.permissions import IsAdminUser from rest_framework.response import Response from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt +from vbv_lernwelt.core.organisations import ORGANISATIONS from vbv_lernwelt.core.serializers import UserSerializer logger = structlog.get_logger(__name__) @@ -76,6 +77,14 @@ def vue_login(request): ) +@api_view(["GET"]) +def list_organisations(request): + if not request.user.is_authenticated: + return Response(status=403) + + return Response([{"id": _id, "name": name} for _id, name in ORGANISATIONS]) + + @api_view(["GET", "PUT"]) def me_user_view(request): if not request.user.is_authenticated: @@ -87,7 +96,7 @@ def me_user_view(request): if request.method == "PUT": serializer = UserSerializer( request.user, - data={"language": request.data.get("language", "de")}, + data=request.data, partial=True, ) if serializer.is_valid():