Coverage for app/venv/lib/python3.14/site-packages/weblate/legal/middleware.py: 0%
27 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
1# Copyright © Michal Čihař <michal@weblate.org>
2#
3# SPDX-License-Identifier: GPL-3.0-or-later
5from __future__ import annotations
7import re
8from typing import TYPE_CHECKING
10from django.shortcuts import redirect
11from django.urls import reverse
12from django.utils.http import urlencode
13from django.utils.translation import gettext
15from weblate.legal.models import Agreement
16from weblate.utils import messages
18if TYPE_CHECKING:
19 from weblate.auth.models import AuthenticatedHttpRequest
22class RequireTOSMiddleware:
23 """Middleware to enforce TOS confirmation on certain requests."""
25 def __init__(self, get_response=None) -> None:
26 self.get_response = get_response
27 # Ignored paths regexp, mostly covers API and legal pages
28 self.matcher = re.compile(
29 r"^/(legal|about|contact|api|static|widget|data|hooks|avatar|healthz|js|css)/"
30 )
32 def process_view(
33 self, request: AuthenticatedHttpRequest, view_func, view_args, view_kwargs
34 ):
35 """Check request whether user has agreed to TOS."""
36 # We intercept only GET requests for authenticated users
37 if request.method != "GET" or not request.user.is_authenticated:
38 return None
40 # Some paths are ignored
41 if self.matcher.match(request.path):
42 return None
44 # Check TOS agreement
45 agreement = Agreement.objects.get_or_create(user=request.user)[0]
46 if not agreement.is_current():
47 messages.info(
48 request,
49 gettext(
50 "We have an updated version of the General Terms and Conditions document, "
51 "please read it and confirm that you agree with it."
52 ),
53 )
54 return redirect(
55 "{}?{}".format(
56 reverse("legal:confirm"),
57 urlencode({"next": request.get_full_path()}),
58 )
59 )
61 # Explicitly return None for all non-matching requests
62 return None
64 def __call__(self, request: AuthenticatedHttpRequest):
65 return self.get_response(request)