diff --git a/Pipfile.lock b/Pipfile.lock index ccb1fd41c..179b121c6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1423,11 +1423,11 @@ }, "astroid": { "hashes": [ - "sha256:4db03ab5fc3340cf619dbc25e42c2cc3755154ce6009469766d7143d1fc2ee4e", - "sha256:8a398dfce302c13f14bab13e2b14fe385d32b73f4e4853b9bdfb64598baa1975" + "sha256:19fd2d2e12bc3cae95687e8264b6593fe07339181a273eeb095da0e70faf4399", + "sha256:54810a3639365ae98b1f03897e73918111acb3a494065b9970a822e940764fa4" ], "markers": "python_version ~= '3.6'", - "version": "==2.5.6" + "version": "==2.6.1" }, "attrs": { "hashes": [ @@ -1585,7 +1585,7 @@ "sha256:83510593e07e433b77bd5bff0f6f607dbafa06d1a89022616f02d8b699cfcd56", "sha256:8e2c107091cfec7286bc0f68a547d0ba4c094d460b732075b6fba674f1035c0c" ], - "markers": "python_version < '4' and python_full_version >= '3.6.1'", + "markers": "python_version < '4.0' and python_full_version >= '3.6.1'", "version": "==5.9.1" }, "lazy-object-proxy": { @@ -1671,11 +1671,11 @@ }, "pylint": { "hashes": [ - "sha256:0a049c5d47b629d9070c3932d13bff482b12119b6a241a93bc460b0be16953c8", - "sha256:792b38ff30903884e4a9eab814ee3523731abd3c463f3ba48d7b627e87013484" + "sha256:45b68315081027f1f8cbd20f870d23152ff94090487f022e7c32694a70954d65", + "sha256:697f69ec93ad6ec9cf0eecff54ac7e1fb836e1330807a2d077173de42b54cf14" ], "index": "pypi", - "version": "==2.8.3" + "version": "==2.9.0" }, "pylint-django": { "hashes": [ diff --git a/authentik/core/models.py b/authentik/core/models.py index b144d4761..df003cc54 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -5,14 +5,13 @@ from typing import Any, Optional, Type from urllib.parse import urlencode from uuid import uuid4 -import django.db.models.options as options from deepmerge import always_merger from django.conf import settings from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import UserManager as DjangoUserManager from django.core import validators from django.db import models -from django.db.models import Q, QuerySet +from django.db.models import Q, QuerySet, options from django.http import HttpRequest from django.templatetags.static import static from django.utils.functional import cached_property diff --git a/authentik/crypto/builder.py b/authentik/crypto/builder.py index 51ad4defb..9b6848981 100644 --- a/authentik/crypto/builder.py +++ b/authentik/crypto/builder.py @@ -16,11 +16,6 @@ from authentik.crypto.models import CertificateKeyPair class CertificateBuilder: """Build self-signed certificates""" - __public_key = None - __private_key = None - __builder = None - __certificate = None - common_name: str def __init__(self): diff --git a/authentik/events/api/notification_transport.py b/authentik/events/api/notification_transport.py index 3b34e8287..ad4d9f187 100644 --- a/authentik/events/api/notification_transport.py +++ b/authentik/events/api/notification_transport.py @@ -46,7 +46,7 @@ class NotificationTransportTestSerializer(Serializer): messages = ListField(child=CharField()) - def create(self, request: Request) -> Response: + def create(self, validated_data: Request) -> Response: raise NotImplementedError def update(self, request: Request) -> Response: diff --git a/authentik/events/geo.py b/authentik/events/geo.py index dccd22351..57e1cd4ed 100644 --- a/authentik/events/geo.py +++ b/authentik/events/geo.py @@ -27,10 +27,9 @@ class GeoIPDict(TypedDict): class GeoIPReader: """Slim wrapper around GeoIP API""" - __reader: Optional[Reader] = None - __last_mtime: float = 0.0 - def __init__(self): + self.__reader: Optional[Reader] = None + self.__last_mtime: float = 0.0 self.__open() def __open(self): diff --git a/authentik/flows/transfer/importer.py b/authentik/flows/transfer/importer.py index c9405cada..c0e942a68 100644 --- a/authentik/flows/transfer/importer.py +++ b/authentik/flows/transfer/importer.py @@ -40,15 +40,11 @@ def transaction_rollback(): class FlowImporter: """Import Flow from json""" - __import: FlowBundle - - __pk_map: dict[Any, Model] - logger: BoundLogger def __init__(self, json_input: str): + self.__pk_map: dict[Any, Model] = {} self.logger = get_logger() - self.__pk_map = {} import_dict = loads(json_input) try: self.__import = from_dict(FlowBundle, import_dict) diff --git a/authentik/lib/config.py b/authentik/lib/config.py index 8656756f3..3673b1d8a 100644 --- a/authentik/lib/config.py +++ b/authentik/lib/config.py @@ -26,10 +26,9 @@ class ConfigLoader: loaded_file = [] - __config = {} - def __init__(self): super().__init__() + self.__config = {} base_dir = os.path.realpath(os.path.join(os.path.dirname(__file__), "../..")) for path in SEARCH_PATHS: # Check if path is relative, and if so join with base_dir diff --git a/authentik/outposts/channels.py b/authentik/outposts/channels.py index a9aed6200..29ab35ab7 100644 --- a/authentik/outposts/channels.py +++ b/authentik/outposts/channels.py @@ -69,7 +69,7 @@ class OutpostConsumer(AuthJsonConsumer): self.last_uid = self.channel_name # pylint: disable=unused-argument - def disconnect(self, close_code): + def disconnect(self, code): if self.outpost and self.last_uid: state = OutpostState.for_instance_uid(self.outpost, self.last_uid) if self.channel_name in state.channel_ids: diff --git a/authentik/policies/api/bindings.py b/authentik/policies/api/bindings.py index 62603834e..a9d03fe61 100644 --- a/authentik/policies/api/bindings.py +++ b/authentik/policies/api/bindings.py @@ -82,13 +82,13 @@ class PolicyBindingSerializer(ModelSerializer): "timeout", ] - def validate(self, data: OrderedDict) -> OrderedDict: + def validate(self, attrs: OrderedDict) -> OrderedDict: """Check that either policy, group or user is set.""" count = sum( [ - bool(data.get("policy", None)), - bool(data.get("group", None)), - bool(data.get("user", None)), + bool(attrs.get("policy", None)), + bool(attrs.get("group", None)), + bool(attrs.get("user", None)), ] ) invalid = count > 1 @@ -97,7 +97,7 @@ class PolicyBindingSerializer(ModelSerializer): raise ValidationError("Only one of 'policy', 'group' or 'user' can be set.") if empty: raise ValidationError("One of 'policy', 'group' or 'user' must be set.") - return data + return attrs class PolicyBindingViewSet(UsedByMixin, ModelViewSet): diff --git a/authentik/policies/engine.py b/authentik/policies/engine.py index 1377d8228..9f69b514b 100644 --- a/authentik/policies/engine.py +++ b/authentik/policies/engine.py @@ -62,12 +62,6 @@ class PolicyEngine: # Allow objects with no policies attached to pass empty_result: bool - __pbm: PolicyBindingModel - __cached_policies: list[PolicyResult] - __processes: list[PolicyProcessInfo] - - __expected_result_count: int - def __init__( self, pbm: PolicyBindingModel, user: User, request: HttpRequest = None ): @@ -83,8 +77,8 @@ class PolicyEngine: self.request.obj = pbm if request: self.request.set_http_request(request) - self.__cached_policies = [] - self.__processes = [] + self.__cached_policies: list[PolicyResult] = [] + self.__processes: list[PolicyProcessInfo] = [] self.use_cache = True self.__expected_result_count = 0 diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py index 5ee94bfe2..8ada987b9 100644 --- a/authentik/providers/oauth2/models.py +++ b/authentik/providers/oauth2/models.py @@ -278,7 +278,7 @@ class OAuth2Provider(Provider): """Guess launch_url based on first redirect_uri""" if self.redirect_uris == "": return None - main_url = self.redirect_uris.split("\n")[0] + main_url = self.redirect_uris.split("\n", maxsplit=1)[0] launch_url = urlparse(main_url) return main_url.replace(launch_url.path, "") diff --git a/authentik/root/messages/consumer.py b/authentik/root/messages/consumer.py index f71073d1c..dcc3b5a0f 100644 --- a/authentik/root/messages/consumer.py +++ b/authentik/root/messages/consumer.py @@ -15,7 +15,7 @@ class MessageConsumer(JsonWebsocketConsumer): cache.set(f"user_{self.session_key}_messages_{self.channel_name}", True, None) # pylint: disable=unused-argument - def disconnect(self, close_code): + def disconnect(self, code): cache.delete(f"user_{self.session_key}_messages_{self.channel_name}") def event_update(self, event: dict): diff --git a/authentik/sources/oauth/types/manager.py b/authentik/sources/oauth/types/manager.py index 8d27a1d27..268b42b81 100644 --- a/authentik/sources/oauth/types/manager.py +++ b/authentik/sources/oauth/types/manager.py @@ -36,7 +36,8 @@ class SourceType: class SourceTypeManager: """Manager to hold all Source types.""" - __sources: list[SourceType] = [] + def __init__(self) -> None: + self.__sources: list[SourceType] = [] def type(self): """Class decorator to register classes inline.""" diff --git a/authentik/stages/authenticator_validate/stage.py b/authentik/stages/authenticator_validate/stage.py index 719115512..d8491522b 100644 --- a/authentik/stages/authenticator_validate/stage.py +++ b/authentik/stages/authenticator_validate/stage.py @@ -74,12 +74,12 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse): duo, self.stage.request, self.stage.get_pending_user() ) - def validate(self, data: dict): + def validate(self, attrs: dict): # Checking if the given data is from a valid device class is done above # Here we only check if the any data was sent at all - if "code" not in data and "webauthn" not in data and "duo" not in data: + if "code" not in attrs and "webauthn" not in attrs and "duo" not in attrs: raise ValidationError("Empty response") - return data + return attrs class AuthenticatorValidateStageView(ChallengeStageView): @@ -163,7 +163,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): # pylint: disable=unused-argument def challenge_valid( - self, challenge: AuthenticatorValidationChallengeResponse + self, response: AuthenticatorValidationChallengeResponse ) -> HttpResponse: # All validation is done by the serializer return self.executor.stage_ok() diff --git a/authentik/stages/email/stage.py b/authentik/stages/email/stage.py index 3cc0c710d..f706502ad 100644 --- a/authentik/stages/email/stage.py +++ b/authentik/stages/email/stage.py @@ -38,7 +38,7 @@ class EmailChallengeResponse(ChallengeResponse): component = CharField(default="ak-stage-email") - def validate(self, data): + def validate(self, attrs): raise ValidationError("") diff --git a/authentik/stages/identification/stage.py b/authentik/stages/identification/stage.py index 88248e76c..dad27f923 100644 --- a/authentik/stages/identification/stage.py +++ b/authentik/stages/identification/stage.py @@ -73,9 +73,9 @@ class IdentificationChallengeResponse(ChallengeResponse): pre_user: Optional[User] = None - def validate(self, data: dict[str, Any]) -> dict[str, Any]: + def validate(self, attrs: dict[str, Any]) -> dict[str, Any]: """Validate that user exists, and optionally their password""" - uid_field = data["uid_field"] + uid_field = attrs["uid_field"] current_stage: IdentificationStage = self.stage.executor.current_stage pre_user = self.stage.get_user(uid_field) @@ -101,9 +101,9 @@ class IdentificationChallengeResponse(ChallengeResponse): self.pre_user = pre_user if not current_stage.password_stage: # No password stage select, don't validate the password - return data + return attrs - password = data["password"] + password = attrs["password"] try: user = authenticate( self.stage.request, @@ -116,7 +116,7 @@ class IdentificationChallengeResponse(ChallengeResponse): self.pre_user = user except PermissionDenied as exc: raise ValidationError(str(exc)) from exc - return data + return attrs class IdentificationStageView(ChallengeStageView): diff --git a/authentik/stages/prompt/stage.py b/authentik/stages/prompt/stage.py index 7479ca4a2..b9ab2d578 100644 --- a/authentik/stages/prompt/stage.py +++ b/authentik/stages/prompt/stage.py @@ -146,8 +146,6 @@ def password_single_validator_factory() -> Callable[[PromptChallenge, str], Any] class ListPolicyEngine(PolicyEngine): """Slightly modified policy engine, which uses a list instead of a PolicyBindingModel""" - __list: list[Policy] - def __init__( self, policies: list[Policy], user: User, request: HttpRequest = None ) -> None: diff --git a/tests/integration/test_outpost_docker.py b/tests/integration/test_outpost_docker.py index 10d4b9876..491172291 100644 --- a/tests/integration/test_outpost_docker.py +++ b/tests/integration/test_outpost_docker.py @@ -62,11 +62,14 @@ class OutpostDockerTests(TestCase): ) authentication_kp = CertificateKeyPair.objects.create( name="docker-authentication", + # pylint: disable=consider-using-with certificate_data=open(f"{self.ssl_folder}/client/cert.pem").read(), + # pylint: disable=consider-using-with key_data=open(f"{self.ssl_folder}/client/key.pem").read(), ) verification_kp = CertificateKeyPair.objects.create( name="docker-verification", + # pylint: disable=consider-using-with certificate_data=open(f"{self.ssl_folder}/client/ca.pem").read(), ) self.service_connection = DockerServiceConnection.objects.create( diff --git a/tests/integration/test_proxy_docker.py b/tests/integration/test_proxy_docker.py index 2b499e626..bb30e7a3a 100644 --- a/tests/integration/test_proxy_docker.py +++ b/tests/integration/test_proxy_docker.py @@ -62,11 +62,14 @@ class TestProxyDocker(TestCase): ) authentication_kp = CertificateKeyPair.objects.create( name="docker-authentication", + # pylint: disable=consider-using-with certificate_data=open(f"{self.ssl_folder}/client/cert.pem").read(), + # pylint: disable=consider-using-with key_data=open(f"{self.ssl_folder}/client/key.pem").read(), ) verification_kp = CertificateKeyPair.objects.create( name="docker-verification", + # pylint: disable=consider-using-with certificate_data=open(f"{self.ssl_folder}/client/ca.pem").read(), ) self.service_connection = DockerServiceConnection.objects.create(