authentik.brands.utils

Brand utilities

 1"""Brand utilities"""
 2
 3from typing import Any
 4
 5from django.db.models import Case, F, IntegerField, Q, Value, When
 6from django.db.models.functions import Concat, Length
 7from django.http.request import HttpRequest
 8from django.utils.html import _json_script_escapes
 9from django.utils.safestring import mark_safe
10
11from authentik import authentik_full_version
12from authentik.brands.models import Brand
13from authentik.lib.sentry import get_http_meta
14from authentik.tenants.models import Tenant
15
16_q_default = Q(default=True)
17DEFAULT_BRAND = Brand(domain="fallback")
18
19
20def get_brand_for_request(request: HttpRequest) -> Brand:
21    """Get brand object for current request"""
22
23    brand = (
24        Brand.objects.annotate(
25            host_domain=Value(request.get_host()),
26            domain_length=Length("domain"),
27            match_priority=Case(
28                When(
29                    condition=Q(host_domain__iexact=F("domain"))
30                    | Q(host_domain__iendswith=Concat(Value("."), F("domain"))),
31                    then=F("domain_length"),
32                ),
33                default=Value(-1),
34                output_field=IntegerField(),
35            ),
36            is_default_fallback=Case(
37                When(
38                    condition=Q(default=True),
39                    then=Value(0),
40                ),
41                default=Value(-2),
42                output_field=IntegerField(),
43            ),
44        )
45        .filter(Q(match_priority__gt=-1) | Q(default=True))
46        .order_by("-match_priority", "-is_default_fallback")
47        .first()
48    )
49
50    if brand is None:
51        return DEFAULT_BRAND
52    return brand
53
54
55def context_processor(request: HttpRequest) -> dict[str, Any]:
56    """Context Processor that injects brand object into every template"""
57    brand = getattr(request, "brand", DEFAULT_BRAND)
58    tenant = getattr(request, "tenant", Tenant())
59    # similarly to `json_script` we escape everything HTML-related, however django
60    # only directly exposes this as a function that also wraps it in a <script> tag
61    # which we dont want for CSS
62    brand_css = mark_safe(str(brand.branding_custom_css).translate(_json_script_escapes))  # nosec
63    return {
64        "brand": brand,
65        "brand_css": brand_css,
66        "footer_links": tenant.footer_links,
67        "html_meta": {**get_http_meta()},
68        "version": authentik_full_version(),
69    }
DEFAULT_BRAND = <Brand: Brand fallback>
def get_brand_for_request( request: django.http.request.HttpRequest) -> authentik.brands.models.Brand:
21def get_brand_for_request(request: HttpRequest) -> Brand:
22    """Get brand object for current request"""
23
24    brand = (
25        Brand.objects.annotate(
26            host_domain=Value(request.get_host()),
27            domain_length=Length("domain"),
28            match_priority=Case(
29                When(
30                    condition=Q(host_domain__iexact=F("domain"))
31                    | Q(host_domain__iendswith=Concat(Value("."), F("domain"))),
32                    then=F("domain_length"),
33                ),
34                default=Value(-1),
35                output_field=IntegerField(),
36            ),
37            is_default_fallback=Case(
38                When(
39                    condition=Q(default=True),
40                    then=Value(0),
41                ),
42                default=Value(-2),
43                output_field=IntegerField(),
44            ),
45        )
46        .filter(Q(match_priority__gt=-1) | Q(default=True))
47        .order_by("-match_priority", "-is_default_fallback")
48        .first()
49    )
50
51    if brand is None:
52        return DEFAULT_BRAND
53    return brand

Get brand object for current request

def context_processor(request: django.http.request.HttpRequest) -> dict[str, typing.Any]:
56def context_processor(request: HttpRequest) -> dict[str, Any]:
57    """Context Processor that injects brand object into every template"""
58    brand = getattr(request, "brand", DEFAULT_BRAND)
59    tenant = getattr(request, "tenant", Tenant())
60    # similarly to `json_script` we escape everything HTML-related, however django
61    # only directly exposes this as a function that also wraps it in a <script> tag
62    # which we dont want for CSS
63    brand_css = mark_safe(str(brand.branding_custom_css).translate(_json_script_escapes))  # nosec
64    return {
65        "brand": brand,
66        "brand_css": brand_css,
67        "footer_links": tenant.footer_links,
68        "html_meta": {**get_http_meta()},
69        "version": authentik_full_version(),
70    }

Context Processor that injects brand object into every template