diff --git a/authentik/tenants/management/commands/__init__.py b/authentik/admin/management/__init__.py similarity index 100% rename from authentik/tenants/management/commands/__init__.py rename to authentik/admin/management/__init__.py diff --git a/authentik/admin/management/commands/__init__.py b/authentik/admin/management/commands/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/tenants/management/commands/createsuperuser.py b/authentik/admin/management/commands/createsuperuser.py similarity index 100% rename from authentik/tenants/management/commands/createsuperuser.py rename to authentik/admin/management/commands/createsuperuser.py diff --git a/authentik/tenants/management/commands/set_flag.py b/authentik/admin/management/commands/set_flag.py similarity index 62% rename from authentik/tenants/management/commands/set_flag.py rename to authentik/admin/management/commands/set_flag.py index 8a45796361..d1e8371942 100644 --- a/authentik/tenants/management/commands/set_flag.py +++ b/authentik/admin/management/commands/set_flag.py @@ -1,19 +1,19 @@ from argparse import ArgumentParser from typing import Any -from authentik.tenants.management import TenantCommand -from authentik.tenants.utils import get_current_tenant +from django.core.management import BaseCommand + +from authentik.admin.utils import get_system_settings -class Command(TenantCommand): - +class Command(BaseCommand): def add_arguments(self, parser: ArgumentParser): parser.add_argument("flag_key", type=str) parser.add_argument("flag_value", type=str) def handle(self, *, flag_key: str, flag_value: Any, **options): - tenant = get_current_tenant() + settings = get_system_settings() val = flag_value.lower() == "true" - tenant.flags[flag_key] = val - tenant.save() + settings.flags[flag_key] = val + settings.save() self.stdout.write(f"Set flag '{flag_key}' to {val}.") diff --git a/authentik/blueprints/management/commands/export_blueprint.py b/authentik/blueprints/management/commands/export_blueprint.py index c8371595e2..db747bc5c7 100644 --- a/authentik/blueprints/management/commands/export_blueprint.py +++ b/authentik/blueprints/management/commands/export_blueprint.py @@ -1,19 +1,18 @@ """Export blueprint of current authentik install""" -from django.core.management.base import no_translations +from django.core.management.base import BaseCommand, no_translations from structlog.stdlib import get_logger from authentik.blueprints.v1.exporter import Exporter -from authentik.tenants.management import TenantCommand LOGGER = get_logger() -class Command(TenantCommand): +class Command(BaseCommand): """Export blueprint of current authentik install""" @no_translations - def handle_per_tenant(self, *args, **options): + def handle(self, *args, **options): """Export blueprint of current authentik install""" exporter = Exporter() self.stdout.write(exporter.export_to_string()) diff --git a/authentik/core/management/commands/change_user_type.py b/authentik/core/management/commands/change_user_type.py index 2fbfff4c52..db85b62c8a 100644 --- a/authentik/core/management/commands/change_user_type.py +++ b/authentik/core/management/commands/change_user_type.py @@ -1,10 +1,11 @@ """Change user type""" +from django.core.management.base import BaseCommand + from authentik.core.models import User, UserTypes -from authentik.tenants.management import TenantCommand -class Command(TenantCommand): +class Command(BaseCommand): """Change user type""" def add_arguments(self, parser): @@ -12,7 +13,7 @@ class Command(TenantCommand): parser.add_argument("--all", action="store_true", default=False) parser.add_argument("usernames", nargs="*", type=str) - def handle_per_tenant(self, **options): + def handle(self, **options): new_type = UserTypes(options["type"]) qs = ( User.objects.exclude_anonymous() diff --git a/authentik/core/management/commands/clearsessions.py b/authentik/core/management/commands/clearsessions.py index b06fdcbfaa..6418212769 100644 --- a/authentik/core/management/commands/clearsessions.py +++ b/authentik/core/management/commands/clearsessions.py @@ -3,13 +3,12 @@ from importlib import import_module from django.conf import settings - -from authentik.tenants.management import TenantCommand +from django.core.management.base import BaseCommand -class Command(TenantCommand): +class Command(BaseCommand): """Delete all sessions""" - def handle_per_tenant(self, **options): + def handle(self, **options): engine = import_module(settings.SESSION_ENGINE) engine.SessionStore.clear_expired() diff --git a/authentik/crypto/management/commands/import_certificate.py b/authentik/crypto/management/commands/import_certificate.py index 708e908207..beb7328ae9 100644 --- a/authentik/crypto/management/commands/import_certificate.py +++ b/authentik/crypto/management/commands/import_certificate.py @@ -2,22 +2,21 @@ from sys import exit as sys_exit -from django.core.management.base import no_translations +from django.core.management.base import BaseCommand, no_translations from rest_framework.exceptions import ValidationError from structlog.stdlib import get_logger from authentik.crypto.api import CertificateKeyPairSerializer from authentik.crypto.models import CertificateKeyPair -from authentik.tenants.management import TenantCommand LOGGER = get_logger() -class Command(TenantCommand): +class Command(BaseCommand): """Import certificate""" @no_translations - def handle_per_tenant(self, *args, **options): + def handle(self, *args, **options): """Import certificate""" keypair = CertificateKeyPair.objects.filter(name=options["name"]).first() dirty = False diff --git a/authentik/providers/scim/management/commands/scim_sync.py b/authentik/providers/scim/management/commands/scim_sync.py index 7eca362755..5da8883d41 100644 --- a/authentik/providers/scim/management/commands/scim_sync.py +++ b/authentik/providers/scim/management/commands/scim_sync.py @@ -1,20 +1,20 @@ """SCIM Sync""" +from django.core.management.base import BaseCommand from structlog.stdlib import get_logger from authentik.providers.scim.models import SCIMProvider -from authentik.tenants.management import TenantCommand LOGGER = get_logger() -class Command(TenantCommand): +class Command(BaseCommand): """Run sync for an SCIM Provider""" def add_arguments(self, parser): parser.add_argument("providers", nargs="+", type=str) - def handle_per_tenant(self, **options): + def handle(self, **options): for provider_name in options["providers"]: provider = SCIMProvider.objects.filter(name=provider_name).first() if not provider: diff --git a/authentik/recovery/management/commands/create_admin_group.py b/authentik/recovery/management/commands/create_admin_group.py index e5720e7a55..9fcc45975b 100644 --- a/authentik/recovery/management/commands/create_admin_group.py +++ b/authentik/recovery/management/commands/create_admin_group.py @@ -2,14 +2,14 @@ from argparse import ArgumentParser +from django.core.management.base import BaseCommand from django.utils.translation import gettext as _ from authentik.core.models import User from authentik.recovery.lib import create_admin_group -from authentik.tenants.management import TenantCommand -class Command(TenantCommand): +class Command(BaseCommand): """Create admin group if the default group gets deleted""" help = _("Create admin group if the default group gets deleted.") @@ -17,7 +17,7 @@ class Command(TenantCommand): def add_arguments(self, parser: ArgumentParser): parser.add_argument("user", action="store", help="User to add to the admin group.") - def handle_per_tenant(self, *args, **options): + def handle(self, *args, **options): """Create admin group if the default group gets deleted""" username = options.get("user") user = User.objects.filter(username=username).first() diff --git a/authentik/recovery/management/commands/create_recovery_key.py b/authentik/recovery/management/commands/create_recovery_key.py index 7c602ed314..2f83e668e1 100644 --- a/authentik/recovery/management/commands/create_recovery_key.py +++ b/authentik/recovery/management/commands/create_recovery_key.py @@ -3,16 +3,16 @@ from datetime import timedelta from getpass import getuser +from django.core.management.base import BaseCommand from django.utils.timesince import timesince from django.utils.timezone import now from django.utils.translation import gettext as _ from authentik.core.models import User from authentik.recovery.lib import create_recovery_token -from authentik.tenants.management import TenantCommand -class Command(TenantCommand): +class Command(BaseCommand): """Create Token used to recover access""" help = _("Create a Key which can be used to restore access to authentik.") @@ -35,7 +35,7 @@ class Command(TenantCommand): ) parser.add_argument("user", action="store", help="Which user the Token gives access to.") - def handle_per_tenant(self, *args, **options): + def handle(self, *args, **options): """Create Token used to recover access""" duration = int(options.get("duration", 60)) expiry = now() + timedelta(minutes=duration) diff --git a/authentik/sources/kerberos/management/commands/kerberos_check_connection.py b/authentik/sources/kerberos/management/commands/kerberos_check_connection.py index 33d75e57c3..dd3f1d7b13 100644 --- a/authentik/sources/kerberos/management/commands/kerberos_check_connection.py +++ b/authentik/sources/kerberos/management/commands/kerberos_check_connection.py @@ -2,21 +2,21 @@ from json import dumps +from django.core.management.base import BaseCommand from structlog.stdlib import get_logger from authentik.sources.kerberos.models import KerberosSource -from authentik.tenants.management import TenantCommand LOGGER = get_logger() -class Command(TenantCommand): +class Command(BaseCommand): """Check connectivity to Kerberos servers for a source""" def add_arguments(self, parser): parser.add_argument("source_slugs", nargs="?", type=str) - def handle_per_tenant(self, **options): + def handle(self, **options): sources = KerberosSource.objects.filter(enabled=True) if options["source_slugs"]: sources = KerberosSource.objects.filter(slug__in=options["source_slugs"]) diff --git a/authentik/sources/kerberos/management/commands/kerberos_sync.py b/authentik/sources/kerberos/management/commands/kerberos_sync.py index ff49dde4d1..39b30cb83a 100644 --- a/authentik/sources/kerberos/management/commands/kerberos_sync.py +++ b/authentik/sources/kerberos/management/commands/kerberos_sync.py @@ -1,21 +1,21 @@ """Kerberos Sync""" +from django.core.management.base import BaseCommand from structlog.stdlib import get_logger from authentik.sources.kerberos.models import KerberosSource from authentik.sources.kerberos.sync import KerberosSync -from authentik.tenants.management import TenantCommand LOGGER = get_logger() -class Command(TenantCommand): +class Command(BaseCommand): """Run sync for an Kerberos Source""" def add_arguments(self, parser): parser.add_argument("source_slugs", nargs="+", type=str) - def handle_per_tenant(self, **options): + def handle(self, **options): for source_slug in options["source_slugs"]: source = KerberosSource.objects.filter(slug=source_slug).first() if not source: diff --git a/authentik/sources/ldap/management/commands/ldap_check_connection.py b/authentik/sources/ldap/management/commands/ldap_check_connection.py index 0bde7bfec5..cb19908e02 100644 --- a/authentik/sources/ldap/management/commands/ldap_check_connection.py +++ b/authentik/sources/ldap/management/commands/ldap_check_connection.py @@ -2,21 +2,21 @@ from json import dumps +from django.core.management.base import BaseCommand from structlog.stdlib import get_logger from authentik.sources.ldap.models import LDAPSource -from authentik.tenants.management import TenantCommand LOGGER = get_logger() -class Command(TenantCommand): +class Command(BaseCommand): """Check connectivity to LDAP servers for a source""" def add_arguments(self, parser): parser.add_argument("source_slugs", nargs="?", type=str) - def handle_per_tenant(self, **options): + def handle(self, **options): sources = LDAPSource.objects.filter(enabled=True) if options["source_slugs"]: sources = LDAPSource.objects.filter(slug__in=options["source_slugs"]) diff --git a/authentik/sources/ldap/management/commands/ldap_sync.py b/authentik/sources/ldap/management/commands/ldap_sync.py index ed3952818a..b98f7f9b90 100644 --- a/authentik/sources/ldap/management/commands/ldap_sync.py +++ b/authentik/sources/ldap/management/commands/ldap_sync.py @@ -1,20 +1,20 @@ """LDAP Sync""" +from django.core.management.base import BaseCommand from structlog.stdlib import get_logger from authentik.sources.ldap.models import LDAPSource -from authentik.tenants.management import TenantCommand LOGGER = get_logger() -class Command(TenantCommand): +class Command(BaseCommand): """Run sync for an LDAP Source""" def add_arguments(self, parser): parser.add_argument("source_slugs", nargs="+", type=str) - def handle_per_tenant(self, **options): + def handle(self, **options): for source_slug in options["source_slugs"]: source = LDAPSource.objects.filter(slug=source_slug).first() if not source: diff --git a/authentik/stages/email/management/commands/test_email.py b/authentik/stages/email/management/commands/test_email.py index 9595b72ff7..5f3635ba4f 100644 --- a/authentik/stages/email/management/commands/test_email.py +++ b/authentik/stages/email/management/commands/test_email.py @@ -2,19 +2,18 @@ from uuid import uuid4 -from django.core.management.base import no_translations +from django.core.management.base import BaseCommand, no_translations from authentik.stages.email.models import EmailStage from authentik.stages.email.tasks import send_mail from authentik.stages.email.utils import TemplateEmailMessage -from authentik.tenants.management import TenantCommand -class Command(TenantCommand): +class Command(BaseCommand): """Send a test-email with global settings""" @no_translations - def handle_per_tenant(self, *args, **options): + def handle(self, *args, **options): """Send a test-email with global settings""" delete_stage = False if options["stage"]: diff --git a/authentik/tenants/management/__init__.py b/authentik/tenants/management/__init__.py deleted file mode 100644 index 2f59bac740..0000000000 --- a/authentik/tenants/management/__init__.py +++ /dev/null @@ -1,44 +0,0 @@ -"""authentik tenants management command utils""" - -from django.core.management.base import BaseCommand -from django.db import connection -from django_tenants.utils import get_public_schema_name - -from authentik.tenants.models import Tenant - - -class TenantCommand(BaseCommand): - """Generic command class useful for running any existing command - on a particular tenant.""" - - def create_parser(self, prog_name, subcommand, **kwargs): - parser = super().create_parser(prog_name, subcommand, **kwargs) - self.add_base_argument( - parser, - "-s", - "--schema", - default=get_public_schema_name(), - help="Tenant schema name.", - dest="schema_name", - ) - return parser - - def handle(self, *args, **options): - verbosity = int(options.get("verbosity")) - - schema_name = options["schema_name"] or self.schema_name - connection.set_schema_to_public() - if verbosity >= 1: - self.stderr.write( - self.style.NOTICE("Switching to schema '") - + self.style.SQL_TABLE(schema_name) - + self.style.NOTICE("'") - ) - connection.set_tenant(Tenant.objects.get(schema_name=schema_name)) - self.handle_per_tenant(*args, **options) - - def handle_per_tenant(self, *args, **options): - """The actual logic of the command.""" - raise NotImplementedError( - "subclasses of TenantCommand must provide a handle_per_tenant() method" - )