core: allow filtering users by the groups they are in

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-08-21 16:23:07 +02:00
parent ff24bc8cb8
commit 3e909ae6bb
6 changed files with 57 additions and 10 deletions

View File

@ -6,7 +6,7 @@ from django.db.models.query import QuerySet
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.http import urlencode from django.utils.http import urlencode
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django_filters.filters import BooleanFilter, CharFilter from django_filters.filters import BooleanFilter, CharFilter, ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet from django_filters.filterset import FilterSet
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_field from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_field
@ -149,6 +149,16 @@ class UsersFilter(FilterSet):
is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser") is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser")
groups_by_name = ModelMultipleChoiceFilter(
field_name="ak_groups__username",
to_field_name="username",
queryset=Group.objects.all(),
)
groups_by_pk = ModelMultipleChoiceFilter(
field_name="ak_groups",
queryset=Group.objects.all(),
)
# pylint: disable=unused-argument # pylint: disable=unused-argument
def filter_attributes(self, queryset, name, value): def filter_attributes(self, queryset, name, value):
"""Filter attributes by query args""" """Filter attributes by query args"""
@ -172,6 +182,8 @@ class UsersFilter(FilterSet):
"is_active", "is_active",
"is_superuser", "is_superuser",
"attributes", "attributes",
"groups_by_name",
"groups_by_pk",
] ]

View File

@ -37,7 +37,7 @@ class TestOAuthSource(TestCase):
data={ data={
"name": "foo", "name": "foo",
"slug": "bar", "slug": "bar",
"provider_type": "openid-connect", "provider_type": "openidconnect",
"consumer_key": "foo", "consumer_key": "foo",
"consumer_secret": "foo", "consumer_secret": "foo",
} }

View File

@ -42,6 +42,7 @@ func parseFilterForGroupSingle(req api.ApiCoreGroupsListRequest, f *ber.Packet)
case "cn": case "cn":
return req.Name(vv) return req.Name(vv)
case "member": case "member":
case "memberOf":
userDN, err := goldap.ParseDN(vv) userDN, err := goldap.ParseDN(vv)
if err != nil { if err != nil {
return req return req

View File

@ -1,6 +1,7 @@
package ldap package ldap
import ( import (
goldap "github.com/go-ldap/ldap/v3"
ber "github.com/nmcclain/asn1-ber" ber "github.com/nmcclain/asn1-ber"
"github.com/nmcclain/ldap" "github.com/nmcclain/ldap"
"goauthentik.io/api" "goauthentik.io/api"
@ -45,6 +46,14 @@ func parseFilterForUserSingle(req api.ApiCoreUsersListRequest, f *ber.Packet) ap
return req.Name(vv) return req.Name(vv)
case "mail": case "mail":
return req.Email(vv) return req.Email(vv)
case "member":
case "memberOf":
groupDN, err := goldap.ParseDN(vv)
if err != nil {
return req
}
name := groupDN.RDNs[0].Attributes[0].Value
return req.GroupsByName([]string{name})
} }
// TODO: Support int // TODO: Support int
default: default:

View File

@ -2914,6 +2914,23 @@ paths:
name: email name: email
schema: schema:
type: string type: string
- in: query
name: groups_by_name
schema:
type: array
items:
type: string
explode: true
style: form
- in: query
name: groups_by_pk
schema:
type: array
items:
type: string
format: uuid
explode: true
style: form
- in: query - in: query
name: is_active name: is_active
schema: schema:

View File

@ -36,13 +36,15 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
@property() @property()
set modelName(v: string | undefined) { set modelName(v: string | undefined) {
this._modelName = v; this._modelName = v;
new SourcesApi(DEFAULT_CONFIG).sourcesOauthSourceTypesList({ new SourcesApi(DEFAULT_CONFIG)
name: v?.replace("oauthsource", ""), .sourcesOauthSourceTypesList({
}).then((type) => { name: v?.replace("oauthsource", ""),
this.providerType = type[0]; })
}); .then((type) => {
this.providerType = type[0];
});
} }
get modelName(): string|undefined { get modelName(): string | undefined {
return this._modelName; return this._modelName;
} }
@ -85,7 +87,10 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
> >
<input <input
type="text" type="text"
value="${first(this.instance?.authorizationUrl, this.providerType.authorizationUrl)}" value="${first(
this.instance?.authorizationUrl,
this.providerType.authorizationUrl,
)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -100,7 +105,10 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
> >
<input <input
type="text" type="text"
value="${first(this.instance?.accessTokenUrl, this.providerType.accessTokenUrl)}" value="${first(
this.instance?.accessTokenUrl,
this.providerType.accessTokenUrl,
)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />