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