Skip to content

Commit

Permalink
settings: add LoginRequiredMiddleware
Browse files Browse the repository at this point in the history
  • Loading branch information
xavfernandez committed Dec 6, 2024
1 parent 5328db7 commit 9859c3b
Show file tree
Hide file tree
Showing 36 changed files with 145 additions and 39 deletions.
1 change: 1 addition & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.auth.middleware.LoginRequiredMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
# Third party
Expand Down
25 changes: 21 additions & 4 deletions config/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.decorators import login_not_required
from django.urls import include, path, re_path, register_converter
from django.views.generic import TemplateView

Expand Down Expand Up @@ -91,10 +92,26 @@
re_path(r"^webhooks/anymail/", include("anymail.urls")),
path("welcoming_tour/", include("itou.www.welcoming_tour.urls")),
# Static pages.
path("accessibility/", TemplateView.as_view(template_name="static/accessibility.html"), name="accessibility"),
path("legal/notice/", TemplateView.as_view(template_name="static/legal/notice.html"), name="legal-notice"),
path("legal/privacy/", TemplateView.as_view(template_name="static/legal/privacy.html"), name="legal-privacy"),
path("legal/terms/", TemplateView.as_view(template_name="static/legal/terms.html"), name="legal-terms"),
path(
"accessibility/",
login_not_required(TemplateView.as_view(template_name="static/accessibility.html")),
name="accessibility",
),
path(
"legal/notice/",
login_not_required(TemplateView.as_view(template_name="static/legal/notice.html")),
name="legal-notice",
),
path(
"legal/privacy/",
login_not_required(TemplateView.as_view(template_name="static/legal/privacy.html")),
name="legal-privacy",
),
path(
"legal/terms/",
login_not_required(TemplateView.as_view(template_name="static/legal/terms.html")),
name="legal-terms",
),
path("", include("itou.www.security.urls")),
path("gps/", include("itou.www.gps.urls")),
path("rdvi/", include("itou.www.rdv_insertion.urls")),
Expand Down
3 changes: 2 additions & 1 deletion itou/api/applicants_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
from itou.job_applications.models import JobApplication
from itou.users.enums import UserKind
from itou.users.models import User
from itou.utils.auth import LoginNotRequiredMixin

from .perms import ApplicantsAPIPermission
from .serializers import APIParametersSerializer, ApplicantSerializer


class ApplicantsView(generics.ListAPIView):
class ApplicantsView(LoginNotRequiredMixin, generics.ListAPIView):
authentication_classes = (
authentication.TokenAuthentication,
authentication.SessionAuthentication,
Expand Down
3 changes: 2 additions & 1 deletion itou/api/c4_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from itou.api.c4_api.serializers import C4CompanySerializer
from itou.companies.enums import COMPANY_KIND_RESERVED
from itou.companies.models import Company, CompanyMembership
from itou.utils.auth import LoginNotRequiredMixin


class C4APIUser(AnonymousUser):
Expand All @@ -27,7 +28,7 @@ def authenticate_credentials(self, key):
return C4APIUser(), None


class C4CompanyView(generics.ListAPIView):
class C4CompanyView(LoginNotRequiredMixin, generics.ListAPIView):
"""API pour le Marché de l'inclusion"""

authentication_classes = [C4Authentication]
Expand Down
3 changes: 2 additions & 1 deletion itou/api/data_inclusion_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from itou.api.data_inclusion_api import enums, serializers
from itou.companies.models import Company
from itou.prescribers.models import PrescriberOrganization
from itou.utils.auth import LoginNotRequiredMixin


@extend_schema(
Expand All @@ -18,7 +19,7 @@
many=True,
)
)
class DataInclusionStructureView(generics.ListAPIView):
class DataInclusionStructureView(LoginNotRequiredMixin, generics.ListAPIView):
"""
# API au format data.inclusion
Expand Down
3 changes: 2 additions & 1 deletion itou/api/employee_record_api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from itou.api import AUTH_TOKEN_EXPLANATION_TEXT
from itou.employee_record.models import EmployeeRecord, EmployeeRecordUpdateNotification, Status
from itou.utils.auth import LoginNotRequiredMixin

from .perms import EmployeeRecordAPIPermission
from .serializers import EmployeeRecordAPISerializer, EmployeeRecordUpdateNotificationAPISerializer
Expand All @@ -22,7 +23,7 @@ class EmployeeRecordRateThrottle(UserRateThrottle):
rate = "60/min"


class AbstractEmployeeRecordViewSet(viewsets.ReadOnlyModelViewSet):
class AbstractEmployeeRecordViewSet(LoginNotRequiredMixin, viewsets.ReadOnlyModelViewSet):
throttle_classes = [EmployeeRecordRateThrottle]

# Possible authentication frameworks:
Expand Down
3 changes: 2 additions & 1 deletion itou/api/geiq/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from itou.companies.models import Company
from itou.job_applications.enums import JobApplicationState, Prequalification, ProfessionalSituationExperience
from itou.job_applications.models import JobApplication, PriorAction
from itou.utils.auth import LoginNotRequiredMixin
from itou.utils.validators import validate_siren

from .serializers import GeiqJobApplicationSerializer
Expand Down Expand Up @@ -41,7 +42,7 @@ class InvalidSirenError(exceptions.APIException):
status_code = status.HTTP_400_BAD_REQUEST


class GeiqJobApplicationListView(generics.ListAPIView):
class GeiqJobApplicationListView(LoginNotRequiredMixin, generics.ListAPIView):
authentication_classes = (
GeiqApiAuthentication,
authentication.SessionAuthentication,
Expand Down
4 changes: 3 additions & 1 deletion itou/api/redoc_views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from django.templatetags.static import static
from drf_spectacular.views import SpectacularRedocView

from itou.utils.auth import LoginNotRequiredMixin

class ItouSpectacularRedocView(SpectacularRedocView):

class ItouSpectacularRedocView(LoginNotRequiredMixin, SpectacularRedocView):
@staticmethod
def _redoc_standalone():
return static("vendor/redoc/redoc.standalone.js")
3 changes: 2 additions & 1 deletion itou/api/siae_api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from itou.cities.models import City
from itou.common_apps.address.departments import DEPARTMENTS
from itou.companies.models import Company, JobDescription
from itou.utils.auth import LoginNotRequiredMixin

from .serializers import SiaeSerializer

Expand Down Expand Up @@ -119,7 +120,7 @@ class RestrictedUserRateThrottle(UserRateThrottle):
rate = "12/minute"


class SiaeViewSet(viewsets.ReadOnlyModelViewSet):
class SiaeViewSet(LoginNotRequiredMixin, viewsets.ReadOnlyModelViewSet):
"""
# Liste des SIAE
Expand Down
3 changes: 2 additions & 1 deletion itou/api/token_auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from rest_framework.response import Response

from itou.api import AUTH_TOKEN_EXPLANATION_TEXT
from itou.utils.auth import LoginNotRequiredMixin


logger = logging.getLogger(__name__)
Expand All @@ -14,7 +15,7 @@
TOKEN_ID_STR = "__token__"


class ObtainAuthToken(drf_authtoken_views.ObtainAuthToken):
class ObtainAuthToken(LoginNotRequiredMixin, drf_authtoken_views.ObtainAuthToken):
def post(self, request, *args, **kwargs):
if request.data.get("username") == TOKEN_ID_STR:
password = request.data.get("password")
Expand Down
3 changes: 2 additions & 1 deletion itou/api/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.contrib.auth.decorators import login_not_required
from django.urls import include, path
from drf_spectacular.views import SpectacularAPIView
from rest_framework import routers
Expand Down Expand Up @@ -41,7 +42,7 @@
# OAS 3 YAML schema (downloadable)
path(
"oas3/",
SpectacularAPIView.as_view(),
login_not_required(SpectacularAPIView.as_view()),
name="openapi_schema",
),
path(
Expand Down
4 changes: 4 additions & 0 deletions itou/openid_connect/france_connect/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_not_required
from django.http import HttpResponseRedirect, JsonResponse
from django.urls import reverse
from django.utils import crypto
Expand Down Expand Up @@ -34,6 +35,7 @@ def _redirect_to_job_seeker_login_on_error(error_msg, request=None, extra_tags="
return HttpResponseRedirect(reverse("login:job_seeker"))


@login_not_required
def france_connect_authorize(request):
# The redirect_uri should be defined in the FC settings to be allowed
# NB: the integration platform allows "http://127.0.0.1:8000/franceconnect/callback"
Expand All @@ -52,6 +54,7 @@ def france_connect_authorize(request):
return HttpResponseRedirect(f"{url}?{urlencode(data)}")


@login_not_required
def france_connect_callback(request):
code = request.GET.get("code")
if code is None:
Expand Down Expand Up @@ -160,6 +163,7 @@ def france_connect_callback(request):
return HttpResponseRedirect(next_url)


@login_not_required
def france_connect_logout(request):
# The user can be authentified on FC w/o a session on itou.
# https://partenaires.franceconnect.gouv.fr/fcp/fournisseur-service#sign_out
Expand Down
5 changes: 5 additions & 0 deletions itou/openid_connect/inclusion_connect/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_not_required
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils import crypto
Expand Down Expand Up @@ -120,6 +121,7 @@ def _add_user_kind_error_message(request, existing_user, new_user_kind):
)


@login_not_required
def inclusion_connect_authorize(request):
# Block access if ProConnect is enabled
if settings.PRO_CONNECT_BASE_URL:
Expand Down Expand Up @@ -166,6 +168,7 @@ def inclusion_connect_authorize(request):
return HttpResponseRedirect(f"{base_url}?{urlencode(data)}")


@login_not_required
def inclusion_connect_activate_account(request):
params = request.GET.copy()
email = params.get("user_email")
Expand Down Expand Up @@ -228,6 +231,7 @@ def _get_user_info(request, access_token):
return response.json(), None


@login_not_required
def inclusion_connect_callback(request):
# Block access if ProConnect is enabled
if settings.PRO_CONNECT_BASE_URL:
Expand Down Expand Up @@ -356,6 +360,7 @@ def inclusion_connect_callback(request):
return HttpResponseRedirect(next_url)


@login_not_required
def inclusion_connect_logout(request):
token = request.GET.get("token")
post_logout_redirect_url = request.GET.get("redirect_url", reverse("search:employers_home"))
Expand Down
5 changes: 5 additions & 0 deletions itou/openid_connect/pe_connect/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_not_required
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from django.urls import reverse
Expand Down Expand Up @@ -38,6 +39,7 @@ def _redirect_to_job_seeker_login_on_error(error_msg, request=None, extra_tags="
return HttpResponseRedirect(reverse("login:job_seeker"))


@login_not_required
def pe_connect_authorize(request):
# The redirect_uri should be defined in the PEAMU settings to be allowed
# NB: the integration platform allows "http://127.0.0.1:8000/pe_connect/callback"
Expand All @@ -56,6 +58,7 @@ def pe_connect_authorize(request):
return HttpResponseRedirect(f"{url}?{urlencode(data)}")


@login_not_required
def pe_connect_callback(request):
code = request.GET.get("code")
if code is None:
Expand Down Expand Up @@ -183,10 +186,12 @@ def pe_connect_callback(request):
return HttpResponseRedirect(next_url)


@login_not_required
def pe_connect_no_email(request, template_name="account/peamu_no_email.html"):
return render(request, template_name)


@login_not_required
def pe_connect_logout(request):
id_token = request.GET.get("id_token")

Expand Down
5 changes: 5 additions & 0 deletions itou/openid_connect/pro_connect/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_not_required
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils import crypto
Expand Down Expand Up @@ -109,6 +110,7 @@ def _add_user_kind_error_message(request, existing_user, new_user_kind):
)


@login_not_required
def pro_connect_authorize(request):
# Start a new session.
user_kind = request.GET.get("user_kind")
Expand Down Expand Up @@ -185,6 +187,7 @@ def _get_user_info(request, access_token):
return decoded_id_token, None


@login_not_required
def pro_connect_callback(request):
code = request.GET.get("code")
state = request.GET.get("state")
Expand Down Expand Up @@ -307,6 +310,7 @@ def pro_connect_callback(request):
return HttpResponseRedirect(next_url)


@login_not_required
def pro_connect_logout(request):
token = request.GET.get("token")
post_logout_redirect_url = reverse("pro_connect:logout_callback")
Expand All @@ -330,6 +334,7 @@ def pro_connect_logout(request):
return HttpResponseRedirect(complete_url)


@login_not_required
def pro_connect_logout_callback(request):
state = request.GET.get("state")
if state is None:
Expand Down
2 changes: 2 additions & 0 deletions itou/status/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from django.contrib.auth.decorators import login_not_required
from django.shortcuts import render

from . import models, probes


@login_not_required
def index(request):
probes_classes = sorted(probes.get_probes_classes(), key=lambda p: p.name)
probes_status_by_name = {ps.name: ps for ps in models.ProbeStatus.objects.all()}
Expand Down
8 changes: 8 additions & 0 deletions itou/utils/auth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from functools import wraps

from django.contrib.auth.decorators import login_not_required
from django.core.exceptions import PermissionDenied


Expand All @@ -15,3 +16,10 @@ def _check_user_view_wrapper(request, *args, **kwargs):
return wraps(view_func)(_check_user_view_wrapper)

return decorator


class LoginNotRequiredMixin:
@classmethod
def as_view(cls, *args, **kwargs):
view = super().as_view(*args, **kwargs)
return login_not_required(view)
2 changes: 2 additions & 0 deletions itou/utils/redirect_legacy_views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django.contrib.auth.decorators import login_not_required
from django.http import HttpResponsePermanentRedirect


@login_not_required
def redirect_siaes_views(request, *args, **kwargs):
return HttpResponsePermanentRedirect(request.get_full_path().replace("/siae", "/company", 1))
3 changes: 2 additions & 1 deletion itou/www/announcements/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

from itou.communications.models import AnnouncementCampaign, AnnouncementItem
from itou.users.enums import UserKind
from itou.utils.auth import LoginNotRequiredMixin
from itou.utils.pagination import pager
from itou.utils.urls import get_safe_url


class NewsView(TemplateView):
class NewsView(LoginNotRequiredMixin, TemplateView):
template_name = "announcements/news.html"

def get_context_data(self):
Expand Down
Loading

0 comments on commit 9859c3b

Please sign in to comment.