diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index d86fafb4a..93663cf88 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -1,5 +1,4 @@ """User API Views""" -from authentik.core.api.groups import GroupSerializer from django.http.response import Http404 from django.urls import reverse_lazy from django.utils.http import urlencode @@ -14,6 +13,7 @@ from rest_framework.viewsets import ModelViewSet from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h from authentik.api.decorators import permission_required +from authentik.core.api.groups import GroupSerializer from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict from authentik.core.middleware import ( SESSION_IMPERSONATE_ORIGINAL_USER, diff --git a/authentik/providers/ldap/api.py b/authentik/providers/ldap/api.py index 30c15a878..d9900f3c5 100644 --- a/authentik/providers/ldap/api.py +++ b/authentik/providers/ldap/api.py @@ -15,6 +15,7 @@ class LDAPProviderSerializer(ProviderSerializer): model = LDAPProvider fields = ProviderSerializer.Meta.fields + [ "base_dn", + "search_group", ] @@ -35,7 +36,14 @@ class LDAPOutpostConfigSerializer(ModelSerializer): class Meta: model = LDAPProvider - fields = ["pk", "name", "base_dn", "bind_flow_slug", "application_slug"] + fields = [ + "pk", + "name", + "base_dn", + "bind_flow_slug", + "application_slug", + "search_group", + ] class LDAPOutpostConfigViewSet(ReadOnlyModelViewSet): diff --git a/authentik/providers/ldap/migrations/0002_ldapprovider_search_group.py b/authentik/providers/ldap/migrations/0002_ldapprovider_search_group.py new file mode 100644 index 000000000..afa4aa4a0 --- /dev/null +++ b/authentik/providers/ldap/migrations/0002_ldapprovider_search_group.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2 on 2021-04-26 19:57 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_core", "0019_source_managed"), + ("authentik_providers_ldap", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="ldapprovider", + name="search_group", + field=models.ForeignKey( + default=None, + help_text="Users in this group can do search queries. If not set, every user can execute search queries.", + null=True, + on_delete=django.db.models.deletion.SET_DEFAULT, + to="authentik_core.group", + ), + ), + ] diff --git a/authentik/providers/ldap/models.py b/authentik/providers/ldap/models.py index f85385734..fe970080b 100644 --- a/authentik/providers/ldap/models.py +++ b/authentik/providers/ldap/models.py @@ -1,11 +1,11 @@ """LDAP Provider""" -from typing import Iterable, Optional, Type +from typing import Iterable, Optional, Type, Union from django.db import models from django.utils.translation import gettext_lazy as _ from rest_framework.serializers import Serializer -from authentik.core.models import Provider +from authentik.core.models import Group, Provider from authentik.outposts.models import OutpostModel @@ -17,6 +17,17 @@ class LDAPProvider(OutpostModel, Provider): help_text=_("DN under which objects are accessible."), ) + search_group = models.ForeignKey( + Group, + null=True, + default=None, + on_delete=models.SET_DEFAULT, + help_text=_( + "Users in this group can do search queries. " + "If not set, every user can execute search queries." + ), + ) + @property def launch_url(self) -> Optional[str]: """LDAP never has a launch URL""" @@ -35,8 +46,8 @@ class LDAPProvider(OutpostModel, Provider): def __str__(self): return f"LDAP Provider {self.name}" - def get_required_objects(self) -> Iterable[models.Model]: - return [self] + def get_required_objects(self) -> Iterable[Union[models.Model, str]]: + return [self, "authentik_core.view_user", "authentik_core.view_group"] class Meta: diff --git a/swagger.yaml b/swagger.yaml index c17c6c229..ba3eaa966 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -16051,6 +16051,13 @@ definitions: title: Application slug type: string minLength: 1 + search_group: + title: Search group + description: Users in this group can do search queries. If not set, every + user can execute search queries. + type: string + format: uuid + x-nullable: true OpenIDConnectConfiguration: description: Embed OpenID Connect provider information required: @@ -17111,6 +17118,13 @@ definitions: description: DN under which objects are accessible. type: string minLength: 1 + search_group: + title: Search group + description: Users in this group can do search queries. If not set, every + user can execute search queries. + type: string + format: uuid + x-nullable: true OAuth2ProviderSetupURLs: type: object properties: diff --git a/web/src/pages/providers/ldap/LDAPProviderForm.ts b/web/src/pages/providers/ldap/LDAPProviderForm.ts index dc2d6a577..4a21f4766 100644 --- a/web/src/pages/providers/ldap/LDAPProviderForm.ts +++ b/web/src/pages/providers/ldap/LDAPProviderForm.ts @@ -1,4 +1,4 @@ -import { FlowDesignationEnum, FlowsApi, ProvidersApi, LDAPProvider } from "authentik-api"; +import { FlowDesignationEnum, FlowsApi, ProvidersApi, LDAPProvider, CoreApi } from "authentik-api"; import { t } from "@lingui/macro"; import { customElement, property } from "lit-element"; import { html, TemplateResult } from "lit-html"; @@ -69,6 +69,19 @@ export class LDAPProviderFormPage extends Form {

${t`Flow used for users to authenticate. Currently only identification and password stages are supported.`}

+ + +

${t`Users in the selected group can do search queries.`}

+