diff --git a/.env.template b/.env.template index 22dfb7b..adf57e1 100644 --- a/.env.template +++ b/.env.template @@ -22,4 +22,5 @@ ALLOWED_HOSTS= CSRF_TRUSTED_ORIGINS= OIDC_RP_CLIENT_ID= -OIDC_WELLKNOWN= \ No newline at end of file +OIDC_WELLKNOWN= +OIDC_CACHE_USERINFO= \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9d2aae6..7e7e742 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ COPY --chown=appuser:appuser marbas /app/marbas COPY --chown=appuser:appuser sde /app/sde COPY --chown=appuser:appuser api /app/api COPY --chown=appuser:appuser authentication /app/authentication +COPY --chown=appuser:appuser static /app/static USER appuser CMD ["uvicorn", "marbas.asgi:application", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/api/serializers.py b/api/serializers.py index 0f8a838..8276732 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -23,7 +23,6 @@ class AcquisitionSerializer(serializers.ModelSerializer): class TypeTrackingSerializer(serializers.ModelSerializer): - type = sde_serializers.SDETypeSerializer() class Meta: model = models.TypeTracking fields = '__all__' diff --git a/api/views.py b/api/views.py index cafc350..7431826 100644 --- a/api/views.py +++ b/api/views.py @@ -4,14 +4,23 @@ from django.db.models import Q from django.contrib.auth import models as auth_models from django.core.cache import cache from rest_framework import viewsets, permissions, settings -from rest_framework.decorators import api_view +from rest_framework.decorators import api_view, action from rest_framework.response import Response from api import serializers, models from sde import serializers as sde_serializers, models as sde_models -class UserViewSet(viewsets.ModelViewSet): +class LoggedUserOnly: + permission_classes = [permissions.IsAuthenticated] + def get_queryset(self): + return self.queryset.filter(user=self.request.user) + + def perform_create(self, serializer): + serializer.save(user=self.request.user) + + +class UserViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint that allows users to be viewed or edited. """ @@ -20,7 +29,8 @@ class UserViewSet(viewsets.ModelViewSet): permission_classes = [permissions.IsAuthenticated] -class GroupViewSet(viewsets.ModelViewSet): + +class GroupViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint that allows groups to be viewed or edited. """ @@ -29,22 +39,20 @@ class GroupViewSet(viewsets.ModelViewSet): permission_classes = [permissions.IsAuthenticated] -class AcquisitionViewSet(viewsets.ModelViewSet): +class AcquisitionViewSet(LoggedUserOnly, viewsets.ModelViewSet): """ API endpoint that allows acquisitions to be viewed or edited. """ queryset = models.Acquisition.objects.all().order_by('-date') serializer_class = serializers.AcquisitionSerializer - permission_classes = [permissions.IsAuthenticated] -class TypeTrackingViewSet(viewsets.ModelViewSet): +class TypeTrackingViewSet(LoggedUserOnly, viewsets.ModelViewSet): """ API endpoint that allows types tracking to be viewed or edited. """ queryset = models.TypeTracking.objects.all() serializer_class = serializers.TypeTrackingSerializer - permission_classes = [permissions.IsAuthenticated] @api_view(['POST']) diff --git a/authentication/backends.py b/authentication/backends.py index 6f9ca33..38f08d6 100644 --- a/authentication/backends.py +++ b/authentication/backends.py @@ -5,6 +5,7 @@ from django.http import JsonResponse from django.contrib.auth import authenticate from django.contrib.auth.models import User from django.contrib.auth.backends import ModelBackend +from django.conf import settings from rest_framework.exceptions import AuthenticationFailed @@ -23,7 +24,7 @@ class CustomOIDCBackend(OIDCAuthenticationBackend): """Hack to use the same auth as DRF""" back = OIDCAuthentication() try: - u, tok = back.authenticate(request) + u, tok = back.authenticate(request) or (None, None) except AuthenticationFailed: u = None return u @@ -34,7 +35,7 @@ class CustomOIDCBackend(OIDCAuthenticationBackend): print("no cache found for userinfo-{access_token} yet.") userinfo = super().get_userinfo(access_token, id_token, payload) if userinfo: - cache.set(f'userinfo-{access_token}', userinfo, timeout=60*60*24) + cache.set(f'userinfo-{access_token}', userinfo, timeout=settings.OIDC_CACHE_USERINFO) return userinfo def update_user(self, user, claims): # TODO: update groups? diff --git a/authentication/migrations/__init__.py b/authentication/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 5849a62..994804c 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -13,6 +13,7 @@ services: - ./sde:/app/sde - ./authentication:/app/authentication - ./manage.py:/app/manage.py + - ./static:/app/static command: sh -c "python manage.py makemigrations && python manage.py migrate" depends_on: db: @@ -32,6 +33,7 @@ services: - ./authentication:/app/authentication - ./manage.py:/app/manage.py - ./static_eve:/app/static_eve + - ./static:/app/static command: ["uvicorn", "marbas.asgi:application", "--host", "0.0.0.0", "--port", "8000", "--reload"] healthcheck: test: python manage.py health_check diff --git a/marbas/settings.py b/marbas/settings.py index f4a6aba..9650cbf 100644 --- a/marbas/settings.py +++ b/marbas/settings.py @@ -45,7 +45,7 @@ REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'mozilla_django_oidc.contrib.drf.OIDCAuthentication', - # 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.SessionAuthentication', ], } @@ -162,6 +162,7 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.2/howto/static-files/ +STATIC_ROOT = 'static/' STATIC_URL = 'static/' # Default primary key field type @@ -184,3 +185,4 @@ if WN := os.getenv("OIDC_WELLKNOWN"): OIDC_OP_AUTHORIZATION_ENDPOINT = oauth_conf["authorization_endpoint"] OIDC_OP_TOKEN_ENDPOINT = oauth_conf["token_endpoint"] OIDC_OP_USER_ENDPOINT = oauth_conf["userinfo_endpoint"] +OIDC_CACHE_USERINFO = os.getenv("OIDC_CACHE_USERINFO") diff --git a/marbas/urls.py b/marbas/urls.py index 5214780..ea4876b 100644 --- a/marbas/urls.py +++ b/marbas/urls.py @@ -15,6 +15,9 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.urls import include, path +from django.conf import settings +from django.conf.urls.static import static +from django.contrib import admin from rest_framework.schemas import get_schema_view from django.views.generic import TemplateView @@ -23,6 +26,7 @@ urlpatterns = [ path('api/', include("api.urls")), path('sde/', include("sde.urls")), path('auth/', include("authentication.urls")), + path('admin/', admin.site.urls), path('sso/', include('esi.urls', namespace='esi')), path('openapi/', get_schema_view( title="marbas", @@ -38,4 +42,4 @@ urlpatterns = [ extra_context={'schema_url': 'openapi-schema'} ), name='redoc'), path('ht/', include('health_check.urls')), -] +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)