@ -1,12 +1,13 @@
 | 
			
		||||
"""authentik API AppConfig"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikAPIConfig(AppConfig):
 | 
			
		||||
class AuthentikAPIConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik API Config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.api"
 | 
			
		||||
    label = "authentik_api"
 | 
			
		||||
    mountpoint = "api/"
 | 
			
		||||
    verbose_name = "authentik API"
 | 
			
		||||
    default = True
 | 
			
		||||
    mountpoint = "api/"
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,7 @@ from inspect import ismethod
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from django.db import DatabaseError, InternalError, ProgrammingError
 | 
			
		||||
from dramatiq.broker import get_broker
 | 
			
		||||
from structlog.stdlib import BoundLogger, get_logger
 | 
			
		||||
 | 
			
		||||
from authentik.lib.utils.time import fqdn_rand
 | 
			
		||||
@ -92,10 +93,6 @@ class ManagedAppConfig(AppConfig):
 | 
			
		||||
        """Get a list of schedule specs that must exist in the default tenant"""
 | 
			
		||||
        return []
 | 
			
		||||
 | 
			
		||||
    def _reconcile_schedules(self, schedules: list[ScheduleSpec]):
 | 
			
		||||
        for schedule in schedules:
 | 
			
		||||
            schedule.update_or_create()
 | 
			
		||||
 | 
			
		||||
    def _reconcile_tenant(self) -> None:
 | 
			
		||||
        """reconcile ourselves for tenanted methods"""
 | 
			
		||||
        from authentik.tenants.models import Tenant
 | 
			
		||||
@ -108,7 +105,6 @@ class ManagedAppConfig(AppConfig):
 | 
			
		||||
        for tenant in tenants:
 | 
			
		||||
            with tenant:
 | 
			
		||||
                self._reconcile(self.RECONCILE_TENANT_CATEGORY)
 | 
			
		||||
                self._reconcile_schedules(self.tenant_schedule_specs)
 | 
			
		||||
 | 
			
		||||
    def _reconcile_global(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
@ -119,7 +115,6 @@ class ManagedAppConfig(AppConfig):
 | 
			
		||||
 | 
			
		||||
        with schema_context(get_public_schema_name()):
 | 
			
		||||
            self._reconcile(self.RECONCILE_GLOBAL_CATEGORY)
 | 
			
		||||
            self._reconcile_schedules(self.global_schedule_specs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikBlueprintsConfig(ManagedAppConfig):
 | 
			
		||||
@ -131,9 +126,15 @@ class AuthentikBlueprintsConfig(ManagedAppConfig):
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
    @ManagedAppConfig.reconcile_global
 | 
			
		||||
    def load_blueprints_v1_tasks(self):
 | 
			
		||||
        """Load v1 tasks"""
 | 
			
		||||
        self.import_module("authentik.blueprints.v1.tasks")
 | 
			
		||||
    def tasks_middlewares(self):
 | 
			
		||||
        from authentik.blueprints.v1.tasks import BlueprintWatcherMiddleware
 | 
			
		||||
 | 
			
		||||
        get_broker().add_middleware(BlueprintWatcherMiddleware())
 | 
			
		||||
 | 
			
		||||
    # @ManagedAppConfig.reconcile_global
 | 
			
		||||
    # def load_blueprints_v1_tasks(self):
 | 
			
		||||
    #     """Load v1 tasks"""
 | 
			
		||||
    #     self.import_module("authentik.blueprints.v1.tasks")
 | 
			
		||||
 | 
			
		||||
    @ManagedAppConfig.reconcile_tenant
 | 
			
		||||
    def blueprints_discovery(self):
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								authentik/blueprints/tasks.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								authentik/blueprints/tasks.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
# Import all v1 tasks for auto task discovery
 | 
			
		||||
from authentik.blueprints.v1.tasks import *  # noqa: F403
 | 
			
		||||
@ -65,7 +65,7 @@ class BlueprintWatcherMiddleware(Middleware):
 | 
			
		||||
        )
 | 
			
		||||
        observer.start()
 | 
			
		||||
 | 
			
		||||
    def before_worker_boot(self, broker, worker):
 | 
			
		||||
    def after_worker_boot(self, broker, worker):
 | 
			
		||||
        self.start_blueprint_watcher()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,15 @@
 | 
			
		||||
"""authentik brands app"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikBrandsConfig(AppConfig):
 | 
			
		||||
class AuthentikBrandsConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik Brand app"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.brands"
 | 
			
		||||
    label = "authentik_brands"
 | 
			
		||||
    verbose_name = "authentik Brands"
 | 
			
		||||
    default = True
 | 
			
		||||
    mountpoints = {
 | 
			
		||||
        "authentik.brands.urls_root": "",
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -317,7 +317,7 @@ class Outpost(ScheduledModel, SerializerModel, ManagedModel):
 | 
			
		||||
            ScheduleSpec(
 | 
			
		||||
                actor_name="authentik.outposts.tasks.outpost_controller",
 | 
			
		||||
                uid=self.pk,
 | 
			
		||||
                args=(self.pk, "up"),
 | 
			
		||||
                args=(self.pk,),
 | 
			
		||||
                kwargs={"action": "up", "from_cache": False},
 | 
			
		||||
                crontab=f"{fqdn_rand('outpost_controller')} */4 * * *",
 | 
			
		||||
                description=_(
 | 
			
		||||
 | 
			
		||||
@ -134,8 +134,9 @@ def outpost_controller(outpost_pk: str, action: str = "up", from_cache: bool = F
 | 
			
		||||
 | 
			
		||||
@actor
 | 
			
		||||
def outpost_token_ensurer():
 | 
			
		||||
    """Periodically ensure that all Outposts have valid Service Accounts
 | 
			
		||||
    and Tokens"""
 | 
			
		||||
    """
 | 
			
		||||
    Periodically ensure that all Outposts have valid Service Accounts and Tokens
 | 
			
		||||
    """
 | 
			
		||||
    self: Task = CurrentTask.get_task()
 | 
			
		||||
    all_outposts = Outpost.objects.all()
 | 
			
		||||
    for outpost in all_outposts:
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""Authentik policy dummy app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikPolicyDummyConfig(AppConfig):
 | 
			
		||||
class AuthentikPolicyDummyConfig(ManagedAppConfig):
 | 
			
		||||
    """Authentik policy_dummy app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.policies.dummy"
 | 
			
		||||
    label = "authentik_policies_dummy"
 | 
			
		||||
    verbose_name = "authentik Policies.Dummy"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik Event Matcher policy app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikPoliciesEventMatcherConfig(AppConfig):
 | 
			
		||||
class AuthentikPoliciesEventMatcherConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik Event Matcher policy app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.policies.event_matcher"
 | 
			
		||||
    label = "authentik_policies_event_matcher"
 | 
			
		||||
    verbose_name = "authentik Policies.Event Matcher"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""Authentik policy_expiry app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikPolicyExpiryConfig(AppConfig):
 | 
			
		||||
class AuthentikPolicyExpiryConfig(ManagedAppConfig):
 | 
			
		||||
    """Authentik policy_expiry app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.policies.expiry"
 | 
			
		||||
    label = "authentik_policies_expiry"
 | 
			
		||||
    verbose_name = "authentik Policies.Expiry"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""Authentik policy_expression app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikPolicyExpressionConfig(AppConfig):
 | 
			
		||||
class AuthentikPolicyExpressionConfig(ManagedAppConfig):
 | 
			
		||||
    """Authentik policy_expression app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.policies.expression"
 | 
			
		||||
    label = "authentik_policies_expression"
 | 
			
		||||
    verbose_name = "authentik Policies.Expression"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""Authentik policy geoip app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikPolicyGeoIPConfig(AppConfig):
 | 
			
		||||
class AuthentikPolicyGeoIPConfig(ManagedAppConfig):
 | 
			
		||||
    """Authentik policy_geoip app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.policies.geoip"
 | 
			
		||||
    label = "authentik_policies_geoip"
 | 
			
		||||
    verbose_name = "authentik Policies.GeoIP"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik Password policy app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikPoliciesPasswordConfig(AppConfig):
 | 
			
		||||
class AuthentikPoliciesPasswordConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik Password policy app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.policies.password"
 | 
			
		||||
    label = "authentik_policies_password"
 | 
			
		||||
    verbose_name = "authentik Policies.Password"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik ldap provider app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikProviderLDAPConfig(AppConfig):
 | 
			
		||||
class AuthentikProviderLDAPConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik ldap provider app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.providers.ldap"
 | 
			
		||||
    label = "authentik_providers_ldap"
 | 
			
		||||
    verbose_name = "authentik Providers.LDAP"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik radius provider app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikProviderRadiusConfig(AppConfig):
 | 
			
		||||
class AuthentikProviderRadiusConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik radius provider app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.providers.radius"
 | 
			
		||||
    label = "authentik_providers_radius"
 | 
			
		||||
    verbose_name = "authentik Providers.Radius"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,13 @@
 | 
			
		||||
"""authentik SAML IdP app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikProviderSAMLConfig(AppConfig):
 | 
			
		||||
class AuthentikProviderSAMLConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik SAML IdP app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.providers.saml"
 | 
			
		||||
    label = "authentik_providers_saml"
 | 
			
		||||
    verbose_name = "authentik Providers.SAML"
 | 
			
		||||
    mountpoint = "application/saml/"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,13 @@
 | 
			
		||||
"""authentik Recovery app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikRecoveryConfig(AppConfig):
 | 
			
		||||
class AuthentikRecoveryConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik Recovery app config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.recovery"
 | 
			
		||||
    label = "authentik_recovery"
 | 
			
		||||
    verbose_name = "authentik Recovery"
 | 
			
		||||
    mountpoint = "recovery/"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik plex config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikSourcePlexConfig(AppConfig):
 | 
			
		||||
class AuthentikSourcePlexConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik source plex config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.sources.plex"
 | 
			
		||||
    label = "authentik_sources_plex"
 | 
			
		||||
    verbose_name = "authentik Sources.Plex"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""Authenticator"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageAuthenticatorConfig(AppConfig):
 | 
			
		||||
class AuthentikStageAuthenticatorConfig(ManagedAppConfig):
 | 
			
		||||
    """Authenticator App config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.authenticator"
 | 
			
		||||
    label = "authentik_stages_authenticator"
 | 
			
		||||
    verbose_name = "authentik Stages.Authenticator"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""SMS"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageAuthenticatorSMSConfig(AppConfig):
 | 
			
		||||
class AuthentikStageAuthenticatorSMSConfig(ManagedAppConfig):
 | 
			
		||||
    """SMS App config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.authenticator_sms"
 | 
			
		||||
    label = "authentik_stages_authenticator_sms"
 | 
			
		||||
    verbose_name = "authentik Stages.Authenticator.SMS"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""TOTP"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageAuthenticatorTOTPConfig(AppConfig):
 | 
			
		||||
class AuthentikStageAuthenticatorTOTPConfig(ManagedAppConfig):
 | 
			
		||||
    """TOTP App config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.authenticator_totp"
 | 
			
		||||
    label = "authentik_stages_authenticator_totp"
 | 
			
		||||
    verbose_name = "authentik Stages.Authenticator.TOTP"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""Authenticator Validation Stage"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageAuthenticatorValidateConfig(AppConfig):
 | 
			
		||||
class AuthentikStageAuthenticatorValidateConfig(ManagedAppConfig):
 | 
			
		||||
    """Authenticator Validation Stage"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.authenticator_validate"
 | 
			
		||||
    label = "authentik_stages_authenticator_validate"
 | 
			
		||||
    verbose_name = "authentik Stages.Authenticator.Validate"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik captcha app"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageCaptchaConfig(AppConfig):
 | 
			
		||||
class AuthentikStageCaptchaConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik captcha app"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.captcha"
 | 
			
		||||
    label = "authentik_stages_captcha"
 | 
			
		||||
    verbose_name = "authentik Stages.Captcha"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik consent app"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageConsentConfig(AppConfig):
 | 
			
		||||
class AuthentikStageConsentConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik consent app"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.consent"
 | 
			
		||||
    label = "authentik_stages_consent"
 | 
			
		||||
    verbose_name = "authentik Stages.Consent"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik deny stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageDenyConfig(AppConfig):
 | 
			
		||||
class AuthentikStageDenyConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik deny stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.deny"
 | 
			
		||||
    label = "authentik_stages_deny"
 | 
			
		||||
    verbose_name = "authentik Stages.Deny"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik dummy stage config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageDummyConfig(AppConfig):
 | 
			
		||||
class AuthentikStageDummyConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik dummy stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.dummy"
 | 
			
		||||
    label = "authentik_stages_dummy"
 | 
			
		||||
    verbose_name = "authentik Stages.Dummy"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik identification stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageIdentificationConfig(AppConfig):
 | 
			
		||||
class AuthentikStageIdentificationConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik identification stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.identification"
 | 
			
		||||
    label = "authentik_stages_identification"
 | 
			
		||||
    verbose_name = "authentik Stages.Identification"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik invitation stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageInvitationConfig(AppConfig):
 | 
			
		||||
class AuthentikStageInvitationConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik invitation stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.invitation"
 | 
			
		||||
    label = "authentik_stages_invitation"
 | 
			
		||||
    verbose_name = "authentik Stages.Invitation"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik core app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStagePasswordConfig(AppConfig):
 | 
			
		||||
class AuthentikStagePasswordConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik password stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.password"
 | 
			
		||||
    label = "authentik_stages_password"
 | 
			
		||||
    verbose_name = "authentik Stages.Password"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik prompt stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStagePromptConfig(AppConfig):
 | 
			
		||||
class AuthentikStagePromptConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik prompt stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.prompt"
 | 
			
		||||
    label = "authentik_stages_prompt"
 | 
			
		||||
    verbose_name = "authentik Stages.Prompt"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik redirect app"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageRedirectConfig(AppConfig):
 | 
			
		||||
class AuthentikStageRedirectConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik redirect app"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.redirect"
 | 
			
		||||
    label = "authentik_stages_redirect"
 | 
			
		||||
    verbose_name = "authentik Stages.Redirect"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik delete stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageUserDeleteConfig(AppConfig):
 | 
			
		||||
class AuthentikStageUserDeleteConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik delete stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.user_delete"
 | 
			
		||||
    label = "authentik_stages_user_delete"
 | 
			
		||||
    verbose_name = "authentik Stages.User Delete"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik login stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageUserLoginConfig(AppConfig):
 | 
			
		||||
class AuthentikStageUserLoginConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik login stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.user_login"
 | 
			
		||||
    label = "authentik_stages_user_login"
 | 
			
		||||
    verbose_name = "authentik Stages.User Login"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik logout stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageUserLogoutConfig(AppConfig):
 | 
			
		||||
class AuthentikStageUserLogoutConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik logout stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.user_logout"
 | 
			
		||||
    label = "authentik_stages_user_logout"
 | 
			
		||||
    verbose_name = "authentik Stages.User Logout"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
"""authentik write stage app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthentikStageUserWriteConfig(AppConfig):
 | 
			
		||||
class AuthentikStageUserWriteConfig(ManagedAppConfig):
 | 
			
		||||
    """authentik write stage config"""
 | 
			
		||||
 | 
			
		||||
    name = "authentik.stages.user_write"
 | 
			
		||||
    label = "authentik_stages_user_write"
 | 
			
		||||
    verbose_name = "authentik Stages.User Write"
 | 
			
		||||
    default = True
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ class AuthentikTasksConfig(ManagedAppConfig):
 | 
			
		||||
        broker.add_middleware(Pipelines())
 | 
			
		||||
        broker.add_middleware(Retries(max_retries=max_retries))
 | 
			
		||||
        broker.add_middleware(Results(backend=PostgresBackend(), store_results=True))
 | 
			
		||||
 | 
			
		||||
        broker.add_middleware(FullyQualifiedActorName())
 | 
			
		||||
        broker.add_middleware(CurrentTask())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -319,20 +319,29 @@ class _PostgresConsumer(Consumer):
 | 
			
		||||
 | 
			
		||||
    @raise_connection_error
 | 
			
		||||
    def requeue(self, messages: Iterable[Message]):
 | 
			
		||||
        for message in messages:
 | 
			
		||||
            self.unlock_queue.put_nowait(message)
 | 
			
		||||
        self.query_set.filter(
 | 
			
		||||
            message_id__in=[message.message_id for message in messages],
 | 
			
		||||
        ).update(
 | 
			
		||||
            state=TaskState.QUEUED,
 | 
			
		||||
        )
 | 
			
		||||
        # We don't care about locks, requeue occurs on worker stop
 | 
			
		||||
        # TODO: this is not true, we need to handle them
 | 
			
		||||
        for message in messages:
 | 
			
		||||
            self.in_processing.remove(message.message_id)
 | 
			
		||||
        self._purge_locks()
 | 
			
		||||
 | 
			
		||||
    def _fetch_pending_notifies(self) -> list[Notify]:
 | 
			
		||||
        self.logger.debug(f"Polling for lost messages in {self.queue_name}")
 | 
			
		||||
        notifies = self.query_set.filter(
 | 
			
		||||
            state__in=(TaskState.QUEUED, TaskState.CONSUMED),
 | 
			
		||||
            queue_name=self.queue_name,
 | 
			
		||||
        ).values_list("message_id", flat=True)
 | 
			
		||||
        notifies = (
 | 
			
		||||
            self.query_set.filter(
 | 
			
		||||
                state__in=(TaskState.QUEUED, TaskState.CONSUMED),
 | 
			
		||||
                queue_name=self.queue_name,
 | 
			
		||||
            )
 | 
			
		||||
            .exclude(
 | 
			
		||||
                message_id__in=self.in_processing,
 | 
			
		||||
            )
 | 
			
		||||
            .values_list("message_id", flat=True)
 | 
			
		||||
        )
 | 
			
		||||
        channel = channel_name(self.queue_name, ChannelIdentifier.ENQUEUE)
 | 
			
		||||
        return [Notify(pid=0, channel=channel, payload=item) for item in notifies]
 | 
			
		||||
 | 
			
		||||
@ -383,7 +392,7 @@ class _PostgresConsumer(Consumer):
 | 
			
		||||
 | 
			
		||||
        processing = len(self.in_processing)
 | 
			
		||||
        if processing >= self.prefetch:
 | 
			
		||||
            # Wait and don't consume the message, other worker will be fast
 | 
			
		||||
            # Wait and don't consume the message, other worker will be faster
 | 
			
		||||
            self.misses, backoff_ms = compute_backoff(self.misses, max_backoff=1000)
 | 
			
		||||
            self.logger.debug(
 | 
			
		||||
                f"Too many messages in processing: {processing}. Sleeping {backoff_ms} ms"
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.core.management.base import BaseCommand
 | 
			
		||||
from django.utils.module_loading import module_has_submodule
 | 
			
		||||
 | 
			
		||||
@ -48,7 +49,7 @@ class Command(BaseCommand):
 | 
			
		||||
    ):
 | 
			
		||||
        executable_name = "dramatiq-gevent" if use_gevent else "dramatiq"
 | 
			
		||||
        executable_path = self._resolve_executable(executable_name)
 | 
			
		||||
        watch_args = ["--watch", "."] if use_watcher else []
 | 
			
		||||
        watch_args = ["--watch", "."] if use_watcher or settings.DEBUG else []
 | 
			
		||||
        if watch_args and use_polling_watcher:
 | 
			
		||||
            watch_args.append("--watch-use-polling")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -35,8 +35,8 @@ class ScheduleSerializer(ModelSerializer):
 | 
			
		||||
        try:
 | 
			
		||||
            actor: Actor = get_broker().get_actor(instance.actor_name)
 | 
			
		||||
        except ActorNotFound:
 | 
			
		||||
            return None
 | 
			
		||||
        return actor.fn.__doc__
 | 
			
		||||
            return "FIXME this shouldn't happen"
 | 
			
		||||
        return actor.fn.__doc__.strip()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ScheduleViewSet(
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
from authentik.blueprints.apps import ManagedAppConfig
 | 
			
		||||
from authentik.lib.utils.reflection import get_apps
 | 
			
		||||
from authentik.tasks.schedules.lib import ScheduleSpec
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -21,3 +22,26 @@ class AuthentikTasksSchedulesConfig(ManagedAppConfig):
 | 
			
		||||
                    spec.rel_obj = obj
 | 
			
		||||
                    schedules.append(spec)
 | 
			
		||||
        return schedules
 | 
			
		||||
 | 
			
		||||
    def _reconcile_schedules(self, specs: list[ScheduleSpec]):
 | 
			
		||||
        from django.db import transaction
 | 
			
		||||
 | 
			
		||||
        from authentik.tasks.schedules.models import Schedule
 | 
			
		||||
 | 
			
		||||
        with transaction.atomic():
 | 
			
		||||
            pks_to_keep = []
 | 
			
		||||
            for spec in specs:
 | 
			
		||||
                schedule = spec.update_or_create()
 | 
			
		||||
                pks_to_keep.append(schedule.pk)
 | 
			
		||||
            Schedule.objects.exclude(pk__in=pks_to_keep).delete()
 | 
			
		||||
 | 
			
		||||
    @ManagedAppConfig.reconcile_tenant
 | 
			
		||||
    def reconcile_tenant_schedules(self):
 | 
			
		||||
        from authentik.tenants.utils import get_current_tenant, get_public_schema_name
 | 
			
		||||
 | 
			
		||||
        schedule_specs = []
 | 
			
		||||
        for app in get_apps():
 | 
			
		||||
            schedule_specs.extend(app.tenant_schedule_specs)
 | 
			
		||||
            if get_current_tenant().schema_name == get_public_schema_name():
 | 
			
		||||
                schedule_specs.extend(app.global_schedule_specs)
 | 
			
		||||
        self._reconcile_schedules(schedule_specs)
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,10 @@
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import warnings
 | 
			
		||||
 | 
			
		||||
from cryptography.hazmat.backends.openssl.backend import backend
 | 
			
		||||
from defusedxml import defuse_stdlib
 | 
			
		||||
from django.utils.autoreload import DJANGO_AUTORELOAD_ENV
 | 
			
		||||
 | 
			
		||||
from authentik.lib.config import CONFIG
 | 
			
		||||
from lifecycle.migrate import run_migrations
 | 
			
		||||
from lifecycle.wait_for_db import wait_for_db
 | 
			
		||||
 | 
			
		||||
warnings.filterwarnings("ignore", "SelectableGroups dict interface")
 | 
			
		||||
warnings.filterwarnings(
 | 
			
		||||
@ -25,21 +21,15 @@ defuse_stdlib()
 | 
			
		||||
if CONFIG.get_bool("compliance.fips.enabled", False):
 | 
			
		||||
    backend._enable_fips()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
 | 
			
		||||
wait_for_db()
 | 
			
		||||
print(sys.argv)
 | 
			
		||||
if (
 | 
			
		||||
    len(sys.argv) > 1
 | 
			
		||||
    # Explicitly only run migrate for server and worker
 | 
			
		||||
    # `bootstrap_tasks` is a special case as that command might be triggered by the `ak`
 | 
			
		||||
    # script to pre-run certain tasks for an automated install
 | 
			
		||||
    and sys.argv[1] in ["dev_server", "worker", "bootstrap_tasks"]
 | 
			
		||||
    # and don't run if this is the child process of a dev_server
 | 
			
		||||
    and os.environ.get(DJANGO_AUTORELOAD_ENV, None) is None
 | 
			
		||||
):
 | 
			
		||||
    run_migrations()
 | 
			
		||||
 | 
			
		||||
import django  # noqa: E402
 | 
			
		||||
 | 
			
		||||
django.setup()
 | 
			
		||||
 | 
			
		||||
from authentik.root.signals import post_startup, pre_startup, startup  # noqa: E402
 | 
			
		||||
 | 
			
		||||
_startup_sender = type("WorkerStartup", (object,), {})
 | 
			
		||||
pre_startup.send(sender=_startup_sender)
 | 
			
		||||
startup.send(sender=_startup_sender)
 | 
			
		||||
post_startup.send(sender=_startup_sender)
 | 
			
		||||
 | 
			
		||||
@ -108,6 +108,7 @@ func NewWebServer() *WebServer {
 | 
			
		||||
func (ws *WebServer) Start() {
 | 
			
		||||
	go ws.runMetricsServer()
 | 
			
		||||
	go ws.attemptStartBackend()
 | 
			
		||||
	go ws.attemptStartWorker()
 | 
			
		||||
	go ws.listenPlain()
 | 
			
		||||
	go ws.listenTLS()
 | 
			
		||||
}
 | 
			
		||||
@ -137,6 +138,12 @@ func (ws *WebServer) attemptStartBackend() {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ws *WebServer) attemptStartWorker() {
 | 
			
		||||
	if ws.worker == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ws *WebServer) Core() *gounicorn.GoUnicorn {
 | 
			
		||||
	return ws.g
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ type Worker struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func New(healthcheck func() bool) *Worker {
 | 
			
		||||
	logger := log.WithField("logger", "authentik.router.unicorn")
 | 
			
		||||
	logger := log.WithField("logger", "authentik.router.worker")
 | 
			
		||||
	w := &Worker{
 | 
			
		||||
		Healthcheck:     healthcheck,
 | 
			
		||||
		log:             logger,
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user