move event_retention from brands to tenants
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
parent
4374bdedf6
commit
66ba607317
|
@ -54,7 +54,6 @@ class BrandSerializer(ModelSerializer):
|
|||
"flow_unenrollment",
|
||||
"flow_user_settings",
|
||||
"flow_device_code",
|
||||
"event_retention",
|
||||
"web_certificate",
|
||||
"attributes",
|
||||
]
|
||||
|
@ -125,7 +124,6 @@ class BrandViewSet(UsedByMixin, ModelViewSet):
|
|||
"flow_unenrollment",
|
||||
"flow_user_settings",
|
||||
"flow_device_code",
|
||||
"event_retention",
|
||||
"web_certificate",
|
||||
]
|
||||
ordering = ["domain"]
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# Generated by Django 4.2.7 on 2023-12-12 06:41
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("authentik_brands", "0004_tenant_flow_device_code"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="brand",
|
||||
name="event_retention",
|
||||
),
|
||||
]
|
|
@ -9,7 +9,6 @@ from structlog.stdlib import get_logger
|
|||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.lib.models import SerializerModel
|
||||
from authentik.lib.utils.time import timedelta_string_validator
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
@ -51,14 +50,6 @@ class Brand(SerializerModel):
|
|||
Flow, null=True, on_delete=models.SET_NULL, related_name="brand_device_code"
|
||||
)
|
||||
|
||||
event_retention = models.TextField(
|
||||
default="days=365",
|
||||
validators=[timedelta_string_validator],
|
||||
help_text=_(
|
||||
"Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2)."
|
||||
),
|
||||
)
|
||||
|
||||
web_certificate = models.ForeignKey(
|
||||
CertificateKeyPair,
|
||||
null=True,
|
||||
|
|
|
@ -64,27 +64,6 @@ class TestBrands(APITestCase):
|
|||
},
|
||||
)
|
||||
|
||||
def test_event_retention(self):
|
||||
"""Test brand's event retention"""
|
||||
brand = Brand.objects.create(
|
||||
domain="foo",
|
||||
default=True,
|
||||
branding_title="custom",
|
||||
event_retention="weeks=3",
|
||||
)
|
||||
factory = RequestFactory()
|
||||
request = factory.get("/")
|
||||
request.brand = brand
|
||||
event = Event.new(action=EventAction.SYSTEM_EXCEPTION, message="test").from_http(request)
|
||||
self.assertEqual(event.expires.day, (event.created + timedelta_from_string("weeks=3")).day)
|
||||
self.assertEqual(
|
||||
event.expires.month,
|
||||
(event.created + timedelta_from_string("weeks=3")).month,
|
||||
)
|
||||
self.assertEqual(
|
||||
event.expires.year, (event.created + timedelta_from_string("weeks=3")).year
|
||||
)
|
||||
|
||||
def test_create_default_multiple(self):
|
||||
"""Test attempted creation of multiple default brands"""
|
||||
Brand.objects.create(
|
||||
|
|
|
@ -42,6 +42,7 @@ from authentik.lib.utils.http import get_client_ip, get_http_session
|
|||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.policies.models import PolicyBindingModel
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
from authentik.tenants.models import Tenant
|
||||
|
||||
LOGGER = get_logger()
|
||||
if TYPE_CHECKING:
|
||||
|
@ -224,12 +225,14 @@ class Event(SerializerModel, ExpiringModel):
|
|||
if QS_QUERY in self.context["http_request"]["args"]:
|
||||
wrapped = self.context["http_request"]["args"][QS_QUERY]
|
||||
self.context["http_request"]["args"] = cleanse_dict(QueryDict(wrapped))
|
||||
if hasattr(request, "brand"):
|
||||
brand: Brand = request.brand
|
||||
if hasattr(request, "tenant"):
|
||||
tenant: Tenant = request.tenant
|
||||
# Because self.created only gets set on save, we can't use it's value here
|
||||
# hence we set self.created to now and then use it
|
||||
self.created = now()
|
||||
self.expires = self.created + timedelta_from_string(brand.event_retention)
|
||||
self.expires = self.created + timedelta_from_string(tenant.event_retention)
|
||||
if hasattr(request, "brand"):
|
||||
brand: Brand = request.brand
|
||||
self.brand = sanitize_dict(model_to_dict(brand))
|
||||
if hasattr(request, "user"):
|
||||
original_user = None
|
||||
|
|
|
@ -105,9 +105,10 @@ class SettingsSerializer(ModelSerializer):
|
|||
"default_user_change_name",
|
||||
"default_user_change_email",
|
||||
"default_user_change_username",
|
||||
"event_retention",
|
||||
"footer_links",
|
||||
"gdpr_compliance",
|
||||
"impersonation",
|
||||
"footer_links",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import django.db.models.deletion
|
|||
import django_tenants.postgresql_backend.base
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentik.lib.utils.time
|
||||
import authentik.tenants.models
|
||||
from authentik.lib.config import CONFIG
|
||||
|
||||
|
@ -22,9 +23,9 @@ def create_default_tenant(apps, schema_editor):
|
|||
default_user_change_name=CONFIG.get_bool("default_user_change_name", True),
|
||||
default_user_change_email=CONFIG.get_bool("default_user_change_email", False),
|
||||
default_user_change_username=CONFIG.get_bool("default_user_change_username", False),
|
||||
footer_links=CONFIG.get("footer_links", default=[]),
|
||||
gdpr_compliance=CONFIG.get_bool("gdpr_compliance", True),
|
||||
impersonation=CONFIG.get_bool("impersonation", True),
|
||||
footer_links=CONFIG.get("footer_links", default=[]),
|
||||
)
|
||||
|
||||
|
||||
|
@ -81,6 +82,22 @@ class Migration(migrations.Migration):
|
|||
help_text="Enable the ability for users to change their username.",
|
||||
),
|
||||
),
|
||||
(
|
||||
"event_retention",
|
||||
models.TextField(
|
||||
default="days=365",
|
||||
help_text="Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2).",
|
||||
validators=[authentik.lib.utils.time.timedelta_string_validator],
|
||||
),
|
||||
),
|
||||
(
|
||||
"footer_links",
|
||||
models.JSONField(
|
||||
blank=True,
|
||||
default=list,
|
||||
help_text="The option configures the footer links on the flow executor pages.",
|
||||
),
|
||||
),
|
||||
(
|
||||
"gdpr_compliance",
|
||||
models.BooleanField(
|
||||
|
@ -94,14 +111,6 @@ class Migration(migrations.Migration):
|
|||
default=True, help_text="Globally enable/disable impersonation."
|
||||
),
|
||||
),
|
||||
(
|
||||
"footer_links",
|
||||
models.JSONField(
|
||||
blank=True,
|
||||
default=list,
|
||||
help_text="The option configures the footer links on the flow executor pages.",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Tenant",
|
||||
|
|
|
@ -14,6 +14,7 @@ from structlog.stdlib import get_logger
|
|||
|
||||
from authentik.blueprints.apps import ManagedAppConfig
|
||||
from authentik.lib.models import SerializerModel
|
||||
from authentik.lib.utils.time import timedelta_string_validator
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
@ -57,6 +58,18 @@ class Tenant(TenantMixin, SerializerModel):
|
|||
default_user_change_username = models.BooleanField(
|
||||
help_text=_("Enable the ability for users to change their username."), default=False
|
||||
)
|
||||
event_retention = models.TextField(
|
||||
default="days=365",
|
||||
validators=[timedelta_string_validator],
|
||||
help_text=_(
|
||||
"Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2)."
|
||||
),
|
||||
)
|
||||
footer_links = models.JSONField(
|
||||
help_text=_("The option configures the footer links on the flow executor pages."),
|
||||
default=list,
|
||||
blank=True,
|
||||
)
|
||||
gdpr_compliance = models.BooleanField(
|
||||
help_text=_(
|
||||
"When enabled, all the events caused by a user "
|
||||
|
@ -67,11 +80,6 @@ class Tenant(TenantMixin, SerializerModel):
|
|||
impersonation = models.BooleanField(
|
||||
help_text=_("Globally enable/disable impersonation."), default=True
|
||||
)
|
||||
footer_links = models.JSONField(
|
||||
help_text=_("The option configures the footer links on the flow executor pages."),
|
||||
default=list,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.schema_name == "template":
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
"""Test event retention"""
|
||||
from django.test.client import RequestFactory
|
||||
from django_tenants.utils import get_public_schema_name
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.tenants.models import Tenant
|
||||
|
||||
|
||||
class TestEventRetention(APITestCase):
|
||||
"""Test event retention"""
|
||||
|
||||
def test_event_retention(self):
|
||||
"""Test brand's event retention"""
|
||||
default_tenant = Tenant.objects.get(schema_name=get_public_schema_name())
|
||||
default_tenant.event_retention = "weeks=3"
|
||||
default_tenant.save()
|
||||
factory = RequestFactory()
|
||||
request = factory.get("/")
|
||||
request.tenant = default_tenant
|
||||
event = Event.new(action=EventAction.SYSTEM_EXCEPTION, message="test").from_http(request)
|
||||
self.assertEqual(event.expires.day, (event.created + timedelta_from_string("weeks=3")).day)
|
||||
self.assertEqual(
|
||||
event.expires.month,
|
||||
(event.created + timedelta_from_string("weeks=3")).month,
|
||||
)
|
||||
self.assertEqual(
|
||||
event.expires.year, (event.created + timedelta_from_string("weeks=3")).year
|
||||
)
|
|
@ -8560,12 +8560,6 @@
|
|||
"type": "integer",
|
||||
"title": "Flow device code"
|
||||
},
|
||||
"event_retention": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"title": "Event retention",
|
||||
"description": "Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2)."
|
||||
},
|
||||
"web_certificate": {
|
||||
"type": "integer",
|
||||
"title": "Web certificate",
|
||||
|
|
56
schema.yml
56
schema.yml
|
@ -3373,10 +3373,6 @@ paths:
|
|||
name: domain
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: event_retention
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: flow_authentication
|
||||
schema:
|
||||
|
@ -29844,9 +29840,6 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
event_retention:
|
||||
type: string
|
||||
description: 'Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2).'
|
||||
web_certificate:
|
||||
type: string
|
||||
format: uuid
|
||||
|
@ -29902,10 +29895,6 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
event_retention:
|
||||
type: string
|
||||
minLength: 1
|
||||
description: 'Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2).'
|
||||
web_certificate:
|
||||
type: string
|
||||
format: uuid
|
||||
|
@ -36804,10 +36793,6 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
event_retention:
|
||||
type: string
|
||||
minLength: 1
|
||||
description: 'Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2).'
|
||||
web_certificate:
|
||||
type: string
|
||||
format: uuid
|
||||
|
@ -38740,6 +38725,15 @@ components:
|
|||
default_user_change_username:
|
||||
type: boolean
|
||||
description: Enable the ability for users to change their username.
|
||||
event_retention:
|
||||
type: string
|
||||
minLength: 1
|
||||
description: 'Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2).'
|
||||
footer_links:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
description: The option configures the footer links on the flow executor
|
||||
pages.
|
||||
gdpr_compliance:
|
||||
type: boolean
|
||||
description: When enabled, all the events caused by a user will be deleted
|
||||
|
@ -38747,11 +38741,6 @@ components:
|
|||
impersonation:
|
||||
type: boolean
|
||||
description: Globally enable/disable impersonation.
|
||||
footer_links:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
description: The option configures the footer links on the flow executor
|
||||
pages.
|
||||
PatchedStaticDeviceRequest:
|
||||
type: object
|
||||
description: Serializer for static authenticator devices
|
||||
|
@ -41638,6 +41627,14 @@ components:
|
|||
default_user_change_username:
|
||||
type: boolean
|
||||
description: Enable the ability for users to change their username.
|
||||
event_retention:
|
||||
type: string
|
||||
description: 'Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2).'
|
||||
footer_links:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
description: The option configures the footer links on the flow executor
|
||||
pages.
|
||||
gdpr_compliance:
|
||||
type: boolean
|
||||
description: When enabled, all the events caused by a user will be deleted
|
||||
|
@ -41645,11 +41642,6 @@ components:
|
|||
impersonation:
|
||||
type: boolean
|
||||
description: Globally enable/disable impersonation.
|
||||
footer_links:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
description: The option configures the footer links on the flow executor
|
||||
pages.
|
||||
SettingsRequest:
|
||||
type: object
|
||||
description: Settings Serializer
|
||||
|
@ -41667,6 +41659,15 @@ components:
|
|||
default_user_change_username:
|
||||
type: boolean
|
||||
description: Enable the ability for users to change their username.
|
||||
event_retention:
|
||||
type: string
|
||||
minLength: 1
|
||||
description: 'Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3,seconds=2).'
|
||||
footer_links:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
description: The option configures the footer links on the flow executor
|
||||
pages.
|
||||
gdpr_compliance:
|
||||
type: boolean
|
||||
description: When enabled, all the events caused by a user will be deleted
|
||||
|
@ -41674,11 +41675,6 @@ components:
|
|||
impersonation:
|
||||
type: boolean
|
||||
description: Globally enable/disable impersonation.
|
||||
footer_links:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
description: The option configures the footer links on the flow executor
|
||||
pages.
|
||||
SeverityEnum:
|
||||
enum:
|
||||
- notice
|
||||
|
|
|
@ -7,6 +7,7 @@ import "@goauthentik/elements/forms/FormGroup";
|
|||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/Radio";
|
||||
import "@goauthentik/elements/forms/SearchSelect";
|
||||
import "@goauthentik/elements/utils/TimeDeltaHelp";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
@ -120,6 +121,41 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
|
|||
help=${msg("Enable the ability for users to change their username.")}
|
||||
>
|
||||
</ak-switch-input>
|
||||
<ak-text-input
|
||||
name="eventRetention"
|
||||
label=${msg("Event retention")}
|
||||
required
|
||||
value="${this._settings?.eventRetention}"
|
||||
.bighelp=${html`<p class="pf-c-form__helper-text">
|
||||
${msg("Duration after which events will be deleted from the database.")}
|
||||
</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
'When using an external logging solution for archiving, this can be set to "minutes=5".',
|
||||
)}
|
||||
</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"This setting only affects new Events, as the expiration is saved per-event.",
|
||||
)}
|
||||
</p>
|
||||
<ak-utils-time-delta-help></ak-utils-time-delta-help>`}
|
||||
>
|
||||
</ak-text-input>
|
||||
<ak-textarea-input
|
||||
name="footerLinks"
|
||||
label=${msg("Footer links")}
|
||||
.value="${this._settings?.footerLinks}"
|
||||
.bighelp=${html`
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"This option configures the footer links on the flow executor pages. It must be a valid JSON list and can be used as follows:",
|
||||
)}
|
||||
<code>[{"name": "Link Name","href":"https://goauthentik.io"}]</code>
|
||||
</p>
|
||||
`}
|
||||
>
|
||||
</ak-textarea-input>
|
||||
<ak-switch-input
|
||||
name="gdprCompliance"
|
||||
label=${msg("GDPR compliance")}
|
||||
|
@ -136,20 +172,6 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
|
|||
help=${msg("Globally enable/disable impersonation.")}
|
||||
>
|
||||
</ak-switch-input>
|
||||
<ak-textarea-input
|
||||
name="footerLinks"
|
||||
label=${msg("Footer links")}
|
||||
.value="${this._settings?.footerLinks}"
|
||||
.bighelp=${html`
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"This option configures the footer links on the flow executor pages. It must be a valid JSON list and can be used as follows:",
|
||||
)}
|
||||
<code>[{"name": "Link Name","href":"https://goauthentik.io"}]</code>
|
||||
</p>
|
||||
`}
|
||||
>
|
||||
</ak-textarea-input>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -235,34 +235,6 @@ export class BrandForm extends ModelForm<Brand, string> {
|
|||
certificate=${this.instance?.webCertificate}
|
||||
></ak-crypto-certificate-search>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${msg("Event retention")}
|
||||
?required=${true}
|
||||
name="eventRetention"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
value="${first(this.instance?.eventRetention, "days=365")}"
|
||||
class="pf-c-form-control"
|
||||
required
|
||||
/>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg("Duration after which events will be deleted from the database.")}
|
||||
</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
'When using an external logging solution for archiving, this can be set to "minutes=5".',
|
||||
)}
|
||||
</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"This setting only affects new Events, as the expiration is saved per-event.",
|
||||
)}
|
||||
</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg('Format: "weeks=3;days=2;hours=3,seconds=2".')}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal label=${msg("Attributes")} name="attributes">
|
||||
<ak-codemirror
|
||||
mode=${CodeMirrorMode.YAML}
|
||||
|
|
|
@ -8,7 +8,7 @@ Certain information is stripped from events, to ensure no passwords or other cre
|
|||
|
||||
## Event retention
|
||||
|
||||
The event retention is configured on a per-brand level, with the default being set to 365 days. For events where a related brand cannot be found, the retention is also set to 365 days.
|
||||
The event retention is configured in the system settings interface, with the default being set to 365 days.
|
||||
|
||||
If you want to forward these events to another application, forward the log output of all authentik containers. Every event creation is logged with the log level "info". For this configuration, it is also recommended to set the internal retention pretty low (for example, `days=1`).
|
||||
|
||||
|
|
Reference in New Issue