From 85f15848449ae7619f86f6937cb9fcc922ccd7c3 Mon Sep 17 00:00:00 2001 From: Jens L Date: Sun, 14 Jan 2024 21:21:06 +0100 Subject: [PATCH] providers/rac: fix property mapping without enterprise (#8144) * make rac blueprint only run when enterprise is active Signed-off-by: Jens Langhammer * make rac api same as other mappings Signed-off-by: Jens Langhammer * automatically scale size sent by device pixel ratio Signed-off-by: Jens Langhammer * actually always allow creation of rac mappings Signed-off-by: Jens Langhammer * fix missing application in flow context Signed-off-by: Jens Langhammer * fix wizard showing enterprise warning when license is installed Signed-off-by: Jens Langhammer * cleanup Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer --- authentik/blueprints/v1/importer.py | 8 ++++++-- .../providers/rac/api/property_mappings.py | 19 ++++++++++++++++--- authentik/enterprise/providers/rac/views.py | 9 +++++++-- schema.yml | 6 +++++- .../PropertyMappingWizard.ts | 4 +++- web/src/enterprise/rac/index.ts | 8 ++++++-- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/authentik/blueprints/v1/importer.py b/authentik/blueprints/v1/importer.py index eb4942958..13ee74063 100644 --- a/authentik/blueprints/v1/importer.py +++ b/authentik/blueprints/v1/importer.py @@ -35,7 +35,7 @@ from authentik.core.models import ( Source, UserSourceConnection, ) -from authentik.enterprise.models import LicenseUsage +from authentik.enterprise.models import LicenseKey, LicenseUsage from authentik.events.utils import cleanse_dict from authentik.flows.models import FlowToken, Stage from authentik.lib.models import SerializerModel @@ -108,12 +108,16 @@ class Importer: self.__pk_map: dict[Any, Model] = {} self._import = blueprint self.logger = get_logger() - ctx = {} + ctx = self.default_context() always_merger.merge(ctx, self._import.context) if context: always_merger.merge(ctx, context) self._import.context = ctx + def default_context(self): + """Default context""" + return {"goauthentik.io/enterprise/licensed": LicenseKey.get_total().is_valid()} + @staticmethod def from_string(yaml_input: str, context: dict | None = None) -> "Importer": """Parse YAML string and create blueprint importer from it""" diff --git a/authentik/enterprise/providers/rac/api/property_mappings.py b/authentik/enterprise/providers/rac/api/property_mappings.py index 4afef68bb..360ad978a 100644 --- a/authentik/enterprise/providers/rac/api/property_mappings.py +++ b/authentik/enterprise/providers/rac/api/property_mappings.py @@ -1,15 +1,18 @@ """RAC Provider API Views""" +from django_filters.filters import AllValuesMultipleFilter +from django_filters.filterset import FilterSet +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import extend_schema_field from rest_framework.fields import CharField from rest_framework.viewsets import ModelViewSet from authentik.core.api.propertymappings import PropertyMappingSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import JSONDictField -from authentik.enterprise.api import EnterpriseRequiredMixin from authentik.enterprise.providers.rac.models import RACPropertyMapping -class RACPropertyMappingSerializer(EnterpriseRequiredMixin, PropertyMappingSerializer): +class RACPropertyMappingSerializer(PropertyMappingSerializer): """RACPropertyMapping Serializer""" static_settings = JSONDictField() @@ -26,6 +29,16 @@ class RACPropertyMappingSerializer(EnterpriseRequiredMixin, PropertyMappingSeria fields = PropertyMappingSerializer.Meta.fields + ["static_settings"] +class RACPropertyMappingFilter(FilterSet): + """Filter for RACPropertyMapping""" + + managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed")) + + class Meta: + model = RACPropertyMapping + fields = ["name", "managed"] + + class RACPropertyMappingViewSet(UsedByMixin, ModelViewSet): """RACPropertyMapping Viewset""" @@ -33,4 +46,4 @@ class RACPropertyMappingViewSet(UsedByMixin, ModelViewSet): serializer_class = RACPropertyMappingSerializer search_fields = ["name"] ordering = ["name"] - filterset_fields = ["name", "managed"] + filterset_class = RACPropertyMappingFilter diff --git a/authentik/enterprise/providers/rac/views.py b/authentik/enterprise/providers/rac/views.py index 4b93aee76..c1dc2c667 100644 --- a/authentik/enterprise/providers/rac/views.py +++ b/authentik/enterprise/providers/rac/views.py @@ -15,7 +15,7 @@ from authentik.events.models import Event, EventAction from authentik.flows.challenge import RedirectChallenge from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.models import in_memory_stage -from authentik.flows.planner import FlowPlanner +from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner from authentik.flows.stage import RedirectStage from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.lib.utils.time import timedelta_from_string @@ -39,7 +39,12 @@ class RACStartView(EnterprisePolicyAccessView): planner = FlowPlanner(self.provider.authorization_flow) planner.allow_empty_flows = True try: - plan = planner.plan(self.request) + plan = planner.plan( + self.request, + { + PLAN_CONTEXT_APPLICATION: self.application, + }, + ) except FlowNonApplicableException: raise Http404 plan.insert_stage( diff --git a/schema.yml b/schema.yml index 85dd0e5f5..a838ce9a8 100644 --- a/schema.yml +++ b/schema.yml @@ -13961,7 +13961,11 @@ paths: - in: query name: managed schema: - type: string + type: array + items: + type: string + explode: true + style: form - in: query name: name schema: diff --git a/web/src/admin/property-mappings/PropertyMappingWizard.ts b/web/src/admin/property-mappings/PropertyMappingWizard.ts index 4f0ab6122..59b62c39c 100644 --- a/web/src/admin/property-mappings/PropertyMappingWizard.ts +++ b/web/src/admin/property-mappings/PropertyMappingWizard.ts @@ -5,6 +5,7 @@ import "@goauthentik/admin/property-mappings/PropertyMappingSAMLForm"; import "@goauthentik/admin/property-mappings/PropertyMappingScopeForm"; import "@goauthentik/admin/property-mappings/PropertyMappingTestForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import "@goauthentik/elements/Alert"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/wizard/FormWizardPage"; @@ -63,7 +64,7 @@ export class InitialPropertyMappingWizardPage extends WizardPage { ]; this.host.isValid = true; }} - ?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false} + ?disabled=${type.requiresEnterprise ? this.enterprise?.hasLicense : false} /> ${this.mappingTypes.map((type) => { diff --git a/web/src/enterprise/rac/index.ts b/web/src/enterprise/rac/index.ts index e5a9e04e7..bf09917d4 100644 --- a/web/src/enterprise/rac/index.ts +++ b/web/src/enterprise/rac/index.ts @@ -83,8 +83,12 @@ export class RacInterface extends Interface { // Keep track of current connection attempt connectionAttempt = 0; - static domSize(): DOMRect { - return document.body.getBoundingClientRect(); + static domSize(): { width: number; height: number } { + const size = document.body.getBoundingClientRect(); + return { + width: size.width * window.devicePixelRatio, + height: size.height * window.devicePixelRatio, + }; } constructor() {