Skip to content

Commit 27856ec

Browse files
authored
brands: add option to set global default flow background (#13079)
* brands: add option to set global default flow background Signed-off-by: Jens Langhammer <[email protected]> * test Signed-off-by: Jens Langhammer <[email protected]> --------- Signed-off-by: Jens Langhammer <[email protected]>
1 parent e4a8c05 commit 27856ec

File tree

12 files changed

+99
-10
lines changed

12 files changed

+99
-10
lines changed

authentik/brands/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Meta:
5050
"branding_logo",
5151
"branding_favicon",
5252
"branding_custom_css",
53+
"branding_default_flow_background",
5354
"flow_authentication",
5455
"flow_invalidation",
5556
"flow_recovery",
@@ -127,6 +128,7 @@ class BrandViewSet(UsedByMixin, ModelViewSet):
127128
"branding_title",
128129
"branding_logo",
129130
"branding_favicon",
131+
"branding_default_flow_background",
130132
"flow_authentication",
131133
"flow_invalidation",
132134
"flow_recovery",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.0.13 on 2025-03-19 22:54
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("authentik_brands", "0008_brand_branding_custom_css"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="brand",
15+
name="branding_default_flow_background",
16+
field=models.TextField(default="/static/dist/assets/images/flow_background.jpg"),
17+
),
18+
]

authentik/brands/models.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class Brand(SerializerModel):
3434
branding_logo = models.TextField(default="/static/dist/assets/icons/icon_left_brand.svg")
3535
branding_favicon = models.TextField(default="/static/dist/assets/icons/icon.png")
3636
branding_custom_css = models.TextField(default="", blank=True)
37+
branding_default_flow_background = models.TextField(
38+
default="/static/dist/assets/images/flow_background.jpg"
39+
)
3740

3841
flow_authentication = models.ForeignKey(
3942
Flow, null=True, on_delete=models.SET_NULL, related_name="brand_authentication"
@@ -85,6 +88,12 @@ def branding_favicon_url(self) -> str:
8588
return CONFIG.get("web.path", "/")[:-1] + self.branding_favicon
8689
return self.branding_favicon
8790

91+
def branding_default_flow_background_url(self) -> str:
92+
"""Get branding_default_flow_background with the correct prefix"""
93+
if self.branding_default_flow_background.startswith("/static"):
94+
return CONFIG.get("web.path", "/")[:-1] + self.branding_default_flow_background
95+
return self.branding_default_flow_background
96+
8897
@property
8998
def serializer(self) -> Serializer:
9099
from authentik.brands.api import BrandSerializer

authentik/brands/tests.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,27 @@ def test_webfinger_oidc(self):
124124
"subject": None,
125125
},
126126
)
127+
128+
def test_branding_url(self):
129+
"""Test branding attributes return correct values"""
130+
brand = create_test_brand()
131+
brand.branding_default_flow_background = "https://goauthentik.io/img/icon.png"
132+
brand.branding_favicon = "https://goauthentik.io/img/icon.png"
133+
brand.branding_logo = "https://goauthentik.io/img/icon.png"
134+
brand.save()
135+
self.assertEqual(
136+
brand.branding_default_flow_background_url(), "https://goauthentik.io/img/icon.png"
137+
)
138+
self.assertJSONEqual(
139+
self.client.get(reverse("authentik_api:brand-current")).content.decode(),
140+
{
141+
"branding_logo": "https://goauthentik.io/img/icon.png",
142+
"branding_favicon": "https://goauthentik.io/img/icon.png",
143+
"branding_title": "authentik",
144+
"branding_custom_css": "",
145+
"matched_domain": brand.domain,
146+
"ui_footer_links": [],
147+
"ui_theme": Themes.AUTOMATIC,
148+
"default_locale": "",
149+
},
150+
)

authentik/core/templates/login/base_full.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{% load i18n %}
55

66
{% block head_before %}
7-
<link rel="prefetch" href="{% static 'dist/assets/images/flow_background.jpg' %}" />
7+
<link rel="prefetch" href="{{ request.brand.branding_default_flow_background_url }}" />
88
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}">
99
<link rel="stylesheet" type="text/css" href="{% static 'dist/theme-dark.css' %}" media="(prefers-color-scheme: dark)">
1010
{% include "base/header_js.html" %}
@@ -13,7 +13,7 @@
1313
{% block head %}
1414
<style>
1515
:root {
16-
--ak-flow-background: url("{% static 'dist/assets/images/flow_background.jpg' %}");
16+
--ak-flow-background: url("{{ request.brand.branding_default_flow_background_url }}");
1717
--pf-c-background-image--BackgroundImage: var(--ak-flow-background);
1818
--pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background);
1919
--pf-c-background-image--BackgroundImage--sm: var(--ak-flow-background);

authentik/flows/models.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from uuid import uuid4
77

88
from django.db import models
9+
from django.http import HttpRequest
910
from django.utils.translation import gettext_lazy as _
1011
from model_utils.managers import InheritanceManager
1112
from rest_framework.serializers import BaseSerializer
@@ -178,14 +179,11 @@ class Flow(SerializerModel, PolicyBindingModel):
178179
help_text=_("Required level of authentication and authorization to access a flow."),
179180
)
180181

181-
@property
182-
def background_url(self) -> str:
182+
def background_url(self, request: HttpRequest) -> str:
183183
"""Get the URL to the background image. If the name is /static or starts with http
184184
it is returned as-is"""
185185
if not self.background:
186-
return (
187-
CONFIG.get("web.path", "/")[:-1] + "/static/dist/assets/images/flow_background.jpg"
188-
)
186+
return request.brand.branding_default_flow_background_url()
189187
if self.background.name.startswith("http"):
190188
return self.background.name
191189
if self.background.name.startswith("/static"):

authentik/flows/stage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ def _get_challenge(self, *args, **kwargs) -> Challenge:
184184
flow_info = ContextualFlowInfo(
185185
data={
186186
"title": self.format_title(),
187-
"background": self.executor.flow.background_url,
187+
"background": self.executor.flow.background_url(self.request),
188188
"cancel_url": reverse("authentik_flows:cancel"),
189189
"layout": self.executor.flow.layout,
190190
}

authentik/flows/tests/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ def assertStageResponse(
2727
self.assertIsNotNone(raw_response["component"])
2828
if flow:
2929
self.assertIn("flow_info", raw_response)
30-
self.assertEqual(raw_response["flow_info"]["background"], flow.background_url)
3130
self.assertEqual(
3231
raw_response["flow_info"]["cancel_url"], reverse("authentik_flows:cancel")
3332
)

authentik/flows/tests/test_inspector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test(self):
4949
"captcha_stage": None,
5050
"component": "ak-stage-identification",
5151
"flow_info": {
52-
"background": flow.background_url,
52+
"background": "/static/dist/assets/images/flow_background.jpg",
5353
"cancel_url": reverse("authentik_flows:cancel"),
5454
"title": flow.title,
5555
"layout": "stacked",

blueprints/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13020,6 +13020,11 @@
1302013020
"type": "string",
1302113021
"title": "Branding custom css"
1302213022
},
13023+
"branding_default_flow_background": {
13024+
"type": "string",
13025+
"minLength": 1,
13026+
"title": "Branding default flow background"
13027+
},
1302313028
"flow_authentication": {
1302413029
"type": "string",
1302513030
"format": "uuid",

0 commit comments

Comments
 (0)