From 3eeda7ac084dbfb7db6a0bb68b91c205b1b5b344 Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Tue, 17 Dec 2024 10:22:25 +0100 Subject: [PATCH] [#486] Update TokenAuthConfigurationStep --- docker/setup_configuration/data.yaml | 8 +- .../setup_configuration/models/token_auth.py | 18 ++++- .../setup_configuration/steps/token_auth.py | 79 +++++++++++++------ 3 files changed, 81 insertions(+), 24 deletions(-) diff --git a/docker/setup_configuration/data.yaml b/docker/setup_configuration/data.yaml index d294cc49..50e5fab9 100644 --- a/docker/setup_configuration/data.yaml +++ b/docker/setup_configuration/data.yaml @@ -46,7 +46,13 @@ tokenauth: organization: Organization 1 application: Application 1 administration: Administration 1 - is_superuser: true + permissions: + - object_type: 3a82fb7f-fc9b-4104-9804-993f639d6d0d + mode: read_only + - object_type: ca754b52-3f37-4c49-837c-130e8149e337 + mode: read_only + - object_type: feeaa795-d212-4fa2-bb38-2c34996e5702 + mode: read_and_write oidc_db_config_enable: true diff --git a/src/objects/setup_configuration/models/token_auth.py b/src/objects/setup_configuration/models/token_auth.py index 5adf5746..aa7d1752 100644 --- a/src/objects/setup_configuration/models/token_auth.py +++ b/src/objects/setup_configuration/models/token_auth.py @@ -1,9 +1,25 @@ from django_setup_configuration.models import ConfigurationModel +from pydantic import UUID4, Field -from objects.token.models import TokenAuth +from objects.token.models import Permission, TokenAuth + + +class TokenAuthPermissionConfigurationModel(ConfigurationModel): + object_type: UUID4 + fields: dict | None = Field(default=None) + + class Meta: + django_model_refs = { + Permission: ( + "mode", + "use_fields", + ), + } class TokenAuthConfigurationModel(ConfigurationModel): + permissions: list[TokenAuthPermissionConfigurationModel] + class Meta: django_model_refs = { TokenAuth: ( diff --git a/src/objects/setup_configuration/steps/token_auth.py b/src/objects/setup_configuration/steps/token_auth.py index 09577370..a8e6b8a7 100644 --- a/src/objects/setup_configuration/steps/token_auth.py +++ b/src/objects/setup_configuration/steps/token_auth.py @@ -1,4 +1,5 @@ import logging +from typing import Any from django.core.exceptions import ValidationError from django.db import IntegrityError @@ -6,10 +7,11 @@ from django_setup_configuration.configuration import BaseConfigurationStep from django_setup_configuration.exceptions import ConfigurationRunFailed +from objects.core.models import ObjectType from objects.setup_configuration.models.token_auth import ( TokenAuthGroupConfigurationModel, ) -from objects.token.models import TokenAuth +from objects.token.models import Permission, TokenAuth logger = logging.getLogger(__name__) @@ -18,7 +20,7 @@ class TokenAuthConfigurationStep( BaseConfigurationStep[TokenAuthGroupConfigurationModel] ): """ - Configure tokens for other applications to access Objects API + Configure tokens with permissions for other applications to access Objects API """ namespace = "tokenauth" @@ -27,14 +29,53 @@ class TokenAuthConfigurationStep( verbose_name = "Configuration to set up authentication tokens for objects" config_model = TokenAuthGroupConfigurationModel + def _full_clean(self, instance: Any) -> None: + try: + instance.full_clean(exclude=("id",), validate_unique=False) + except ValidationError as exception: + raise ConfigurationRunFailed( + ("Validation error(s) during instance cleaning: %s" % type(instance)) + ) from exception + + def _configure_permissions(self, token: TokenAuth, permissions: list) -> None: + if len(permissions) == 0: + logger.warning("No permissions provided for %s", token.identifier) + + for permission in permissions: + permission_kwargs = { + "token_auth": token, + "object_type": ObjectType.objects.get(uuid=permission.object_type), + "mode": permission.mode, + "use_fields": permission.use_fields, + "fields": permission.fields, + } + + permission_instance = Permission(**permission_kwargs) + self._full_clean(permission_instance) + + try: + Permission.objects.update_or_create( + token_auth=permission_kwargs["token_auth"], + object_type=permission_kwargs["object_type"], + defaults={ + "mode": permission_kwargs["mode"], + "use_fields": permission_kwargs["use_fields"], + "fields": permission_kwargs["fields"], + }, + ) + except IntegrityError as exception: + raise ConfigurationRunFailed( + ("Failed configuring permission for token %s" % token.identifier) + ) from exception + def execute(self, model: TokenAuthGroupConfigurationModel) -> None: if len(model.items) == 0: logger.warning("No tokens provided for configuration") for item in model.items: - logger.info(f"Configuring {item.identifier}") + logger.info("Configuring %s", item.identifier) - model_kwargs = { + token_kwargs = { "identifier": item.identifier, "token": item.token, "contact_person": item.contact_person, @@ -45,31 +86,25 @@ def execute(self, model: TokenAuthGroupConfigurationModel) -> None: "is_superuser": item.is_superuser, } - token_instance = TokenAuth(**model_kwargs) - - try: - token_instance.full_clean(exclude=("id",), validate_unique=False) - except ValidationError as exception: - exception_message = ( - f"Validation error(s) occured for {item.identifier}." - ) - raise ConfigurationRunFailed(exception_message) from exception - - logger.debug(f"No validation errors found for {item.identifier}") + token_instance = TokenAuth(**token_kwargs) + self._full_clean(token_instance) try: - logger.debug(f"Saving {item.identifier}") - - TokenAuth.objects.update_or_create( + logger.debug("Saving %s", item.identifier) + token, _ = TokenAuth.objects.update_or_create( identifier=item.identifier, defaults={ key: value - for key, value in model_kwargs.items() + for key, value in token_kwargs.items() if key != "identifier" }, ) + self._configure_permissions(token, item.permissions) + except IntegrityError as exception: - exception_message = f"Failed configuring token {item.identifier}." - raise ConfigurationRunFailed(exception_message) from exception - logger.info(f"Configured {item.identifier}") + raise ConfigurationRunFailed( + "Failed configuring token %s" % token.identifier + ) from exception + + logger.info("Configured %s", item.identifier)