mirror of
https://github.com/goauthentik/authentik.git
synced 2026-06-17 19:09:11 +03:00
enterprise/search: move QL to open source] (#21484)
* enterprise/search move to /search * use make gen for schema updates * update docs * re-org Signed-off-by: Jens Langhammer <jens@goauthentik.io> * cleanup more Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix web Signed-off-by: Jens Langhammer <jens@goauthentik.io> * oops Signed-off-by: Jens Langhammer <jens@goauthentik.io> * huh Signed-off-by: Jens Langhammer <jens@goauthentik.io> * typing Signed-off-by: Jens Langhammer <jens@goauthentik.io> * gen Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
"""Pagination which includes total pages and current page"""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from drf_spectacular.plumbing import build_object_type
|
||||
from rest_framework import pagination
|
||||
from rest_framework.response import Response
|
||||
|
||||
from authentik.api.search.ql import QLSearch
|
||||
from authentik.api.v3.schema.pagination import PAGINATION
|
||||
from authentik.api.v3.schema.search import AUTOCOMPLETE_SCHEMA
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django.db.models import QuerySet
|
||||
from rest_framework.request import Request
|
||||
|
||||
|
||||
class Pagination(pagination.PageNumberPagination):
|
||||
@@ -13,14 +21,14 @@ class Pagination(pagination.PageNumberPagination):
|
||||
page_query_param = "page"
|
||||
page_size_query_param = "page_size"
|
||||
|
||||
def get_page_size(self, request):
|
||||
def get_page_size(self, request: Request) -> int:
|
||||
if self.page_size_query_param in request.query_params:
|
||||
page_size = super().get_page_size(request)
|
||||
if page_size is not None:
|
||||
return min(super().get_page_size(request), request.tenant.pagination_max_page_size)
|
||||
return request.tenant.pagination_default_page_size
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
def get_paginated_response(self, data) -> Response:
|
||||
previous_page_number = 0
|
||||
if self.page.has_previous():
|
||||
previous_page_number = self.page.previous_page_number()
|
||||
@@ -39,16 +47,33 @@ class Pagination(pagination.PageNumberPagination):
|
||||
"end_index": self.page.end_index(),
|
||||
},
|
||||
"results": data,
|
||||
"autocomplete": self.get_autocomplete(),
|
||||
}
|
||||
)
|
||||
|
||||
def paginate_queryset(self, queryset: QuerySet, request: Request, view=None):
|
||||
self.view = view
|
||||
return super().paginate_queryset(queryset, request, view)
|
||||
|
||||
def get_autocomplete(self):
|
||||
schema = QLSearch().get_schema(self.request, self.view)
|
||||
introspections = {}
|
||||
if hasattr(self.view, "get_ql_fields"):
|
||||
from authentik.api.search.schema import AKQLSchemaSerializer
|
||||
|
||||
introspections = AKQLSchemaSerializer().serialize(
|
||||
schema(self.page.paginator.object_list.model)
|
||||
)
|
||||
return introspections
|
||||
|
||||
def get_paginated_response_schema(self, schema):
|
||||
return build_object_type(
|
||||
properties={
|
||||
"pagination": PAGINATION.ref,
|
||||
"results": schema,
|
||||
"autocomplete": AUTOCOMPLETE_SCHEMA.ref,
|
||||
},
|
||||
required=["pagination", "results"],
|
||||
required=["pagination", "results", "autocomplete"],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
"""DjangoQL search"""
|
||||
|
||||
from django.apps import apps
|
||||
from django.db.models import QuerySet
|
||||
from djangoql.ast import Name
|
||||
from djangoql.exceptions import DjangoQLError
|
||||
from djangoql.queryset import apply_search
|
||||
from djangoql.schema import DjangoQLSchema
|
||||
from drf_spectacular.plumbing import ResolvedComponent, build_object_type
|
||||
from rest_framework.filters import SearchFilter
|
||||
from rest_framework.request import Request
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.enterprise.search.fields import JSONSearchField
|
||||
from authentik.api.search.fields import JSONSearchField
|
||||
|
||||
LOGGER = get_logger()
|
||||
AUTOCOMPLETE_SCHEMA = ResolvedComponent(
|
||||
name="Autocomplete",
|
||||
object="Autocomplete",
|
||||
type=ResolvedComponent.SCHEMA,
|
||||
schema=build_object_type(additionalProperties={}),
|
||||
)
|
||||
|
||||
|
||||
class BaseSchema(DjangoQLSchema):
|
||||
@@ -48,10 +40,6 @@ class QLSearch(SearchFilter):
|
||||
super().__init__()
|
||||
self._fallback = SearchFilter()
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
return apps.get_app_config("authentik_enterprise").enabled()
|
||||
|
||||
def get_search_terms(self, request: Request) -> str:
|
||||
"""Search terms are set by a ?search=... query parameter,
|
||||
and may be comma and/or whitespace delimited."""
|
||||
@@ -73,7 +61,7 @@ class QLSearch(SearchFilter):
|
||||
def filter_queryset(self, request: Request, queryset: QuerySet, view) -> QuerySet:
|
||||
search_query = self.get_search_terms(request)
|
||||
schema = self.get_schema(request, view)
|
||||
if len(search_query) == 0 or not self.enabled:
|
||||
if len(search_query) == 0:
|
||||
return self._fallback.filter_queryset(request, queryset, view)
|
||||
try:
|
||||
return apply_search(queryset, search_query, schema=schema)
|
||||
@@ -1,8 +1,6 @@
|
||||
from djangoql.serializers import DjangoQLSchemaSerializer
|
||||
from drf_spectacular.generators import SchemaGenerator
|
||||
|
||||
from authentik.enterprise.search.fields import JSONSearchField
|
||||
from authentik.enterprise.search.ql import AUTOCOMPLETE_SCHEMA
|
||||
from authentik.api.search.fields import JSONSearchField
|
||||
|
||||
|
||||
class AKQLSchemaSerializer(DjangoQLSchemaSerializer):
|
||||
@@ -20,9 +18,3 @@ class AKQLSchemaSerializer(DjangoQLSchemaSerializer):
|
||||
if isinstance(field, JSONSearchField):
|
||||
result["relation"] = field.relation()
|
||||
return result
|
||||
|
||||
|
||||
def postprocess_schema_search_autocomplete(result, generator: SchemaGenerator, **kwargs):
|
||||
generator.registry.register_on_missing(AUTOCOMPLETE_SCHEMA)
|
||||
|
||||
return result
|
||||
@@ -1,5 +1,4 @@
|
||||
from json import loads
|
||||
from unittest.mock import PropertyMock, patch
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.urls import reverse
|
||||
@@ -8,10 +7,6 @@ from rest_framework.test import APITestCase
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
|
||||
|
||||
@patch(
|
||||
"authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
|
||||
PropertyMock(return_value=True),
|
||||
)
|
||||
class QLTest(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
@@ -0,0 +1,20 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from drf_spectacular.plumbing import ResolvedComponent, build_object_type
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from drf_spectacular.generators import SchemaGenerator
|
||||
|
||||
|
||||
AUTOCOMPLETE_SCHEMA = ResolvedComponent(
|
||||
name="Autocomplete",
|
||||
object="Autocomplete",
|
||||
type=ResolvedComponent.SCHEMA,
|
||||
schema=build_object_type(additionalProperties={}),
|
||||
)
|
||||
|
||||
|
||||
def postprocess_schema_search_autocomplete(result, generator: SchemaGenerator, **kwargs):
|
||||
generator.registry.register_on_missing(AUTOCOMPLETE_SCHEMA)
|
||||
|
||||
return result
|
||||
@@ -7,6 +7,7 @@ from django.http import Http404
|
||||
from django.utils.translation import gettext as _
|
||||
from django_filters.filters import CharFilter, ModelMultipleChoiceFilter
|
||||
from django_filters.filterset import FilterSet
|
||||
from djangoql.schema import BoolField, StrField
|
||||
from drf_spectacular.utils import (
|
||||
OpenApiParameter,
|
||||
OpenApiResponse,
|
||||
@@ -25,6 +26,9 @@ from rest_framework.serializers import ListSerializer, ValidationError
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.api.authentication import TokenAuthentication
|
||||
from authentik.api.search.fields import (
|
||||
JSONSearchField,
|
||||
)
|
||||
from authentik.api.validation import validate
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.utils import JSONDictField, ModelSerializer, PassiveSerializer
|
||||
@@ -265,12 +269,6 @@ class GroupViewSet(UsedByMixin, ModelViewSet):
|
||||
]
|
||||
|
||||
def get_ql_fields(self):
|
||||
from djangoql.schema import BoolField, StrField
|
||||
|
||||
from authentik.enterprise.search.fields import (
|
||||
JSONSearchField,
|
||||
)
|
||||
|
||||
return [
|
||||
StrField(Group, "name"),
|
||||
BoolField(Group, "is_superuser", nullable=True),
|
||||
|
||||
@@ -22,6 +22,7 @@ from django_filters.filters import (
|
||||
UUIDFilter,
|
||||
)
|
||||
from django_filters.filterset import FilterSet
|
||||
from djangoql.schema import BoolField, StrField
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import (
|
||||
OpenApiParameter,
|
||||
@@ -55,6 +56,10 @@ from rest_framework.viewsets import ModelViewSet
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.api.authentication import TokenAuthentication
|
||||
from authentik.api.search.fields import (
|
||||
ChoiceSearchField,
|
||||
JSONSearchField,
|
||||
)
|
||||
from authentik.api.validation import validate
|
||||
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
|
||||
from authentik.brands.models import Brand
|
||||
@@ -524,13 +529,6 @@ class UserViewSet(
|
||||
]
|
||||
|
||||
def get_ql_fields(self):
|
||||
from djangoql.schema import BoolField, StrField
|
||||
|
||||
from authentik.enterprise.search.fields import (
|
||||
ChoiceSearchField,
|
||||
JSONSearchField,
|
||||
)
|
||||
|
||||
return [
|
||||
StrField(User, "username"),
|
||||
StrField(User, "name"),
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
"""Enterprise app config"""
|
||||
|
||||
from authentik.enterprise.apps import EnterpriseConfig
|
||||
|
||||
|
||||
class AuthentikEnterpriseSearchConfig(EnterpriseConfig):
|
||||
"""Enterprise app config"""
|
||||
|
||||
name = "authentik.enterprise.search"
|
||||
label = "authentik_search"
|
||||
verbose_name = "authentik Enterprise.Search"
|
||||
default = True
|
||||
@@ -1,51 +0,0 @@
|
||||
from rest_framework.response import Response
|
||||
|
||||
from authentik.api.pagination import Pagination
|
||||
from authentik.enterprise.search.ql import AUTOCOMPLETE_SCHEMA, QLSearch
|
||||
|
||||
|
||||
class AutocompletePagination(Pagination):
|
||||
|
||||
def paginate_queryset(self, queryset, request, view=None):
|
||||
self.view = view
|
||||
return super().paginate_queryset(queryset, request, view)
|
||||
|
||||
def get_autocomplete(self):
|
||||
schema = QLSearch().get_schema(self.request, self.view)
|
||||
introspections = {}
|
||||
if hasattr(self.view, "get_ql_fields"):
|
||||
from authentik.enterprise.search.schema import AKQLSchemaSerializer
|
||||
|
||||
introspections = AKQLSchemaSerializer().serialize(
|
||||
schema(self.page.paginator.object_list.model)
|
||||
)
|
||||
return introspections
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
previous_page_number = 0
|
||||
if self.page.has_previous():
|
||||
previous_page_number = self.page.previous_page_number()
|
||||
next_page_number = 0
|
||||
if self.page.has_next():
|
||||
next_page_number = self.page.next_page_number()
|
||||
return Response(
|
||||
{
|
||||
"pagination": {
|
||||
"next": next_page_number,
|
||||
"previous": previous_page_number,
|
||||
"count": self.page.paginator.count,
|
||||
"current": self.page.number,
|
||||
"total_pages": self.page.paginator.num_pages,
|
||||
"start_index": self.page.start_index(),
|
||||
"end_index": self.page.end_index(),
|
||||
},
|
||||
"results": data,
|
||||
"autocomplete": self.get_autocomplete(),
|
||||
}
|
||||
)
|
||||
|
||||
def get_paginated_response_schema(self, schema):
|
||||
final_schema = super().get_paginated_response_schema(schema)
|
||||
final_schema["properties"]["autocomplete"] = AUTOCOMPLETE_SCHEMA.ref
|
||||
final_schema["required"].append("autocomplete")
|
||||
return final_schema
|
||||
@@ -1,20 +0,0 @@
|
||||
SPECTACULAR_SETTINGS = {
|
||||
"POSTPROCESSING_HOOKS": [
|
||||
"authentik.api.v3.schema.response.postprocess_schema_register",
|
||||
"authentik.api.v3.schema.response.postprocess_schema_responses",
|
||||
"authentik.api.v3.schema.query.postprocess_schema_query_params",
|
||||
"authentik.api.v3.schema.cleanup.postprocess_schema_remove_unused",
|
||||
"authentik.enterprise.search.schema.postprocess_schema_search_autocomplete",
|
||||
"authentik.api.v3.schema.enum.postprocess_schema_enums",
|
||||
],
|
||||
}
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
"DEFAULT_PAGINATION_CLASS": "authentik.enterprise.search.pagination.AutocompletePagination",
|
||||
"DEFAULT_FILTER_BACKENDS": [
|
||||
"authentik.enterprise.search.ql.QLSearch",
|
||||
"authentik.rbac.filters.ObjectFilter",
|
||||
"django_filters.rest_framework.DjangoFilterBackend",
|
||||
"rest_framework.filters.OrderingFilter",
|
||||
],
|
||||
}
|
||||
@@ -14,7 +14,6 @@ TENANT_APPS = [
|
||||
"authentik.enterprise.providers.ssf",
|
||||
"authentik.enterprise.providers.ws_federation",
|
||||
"authentik.enterprise.reports",
|
||||
"authentik.enterprise.search",
|
||||
"authentik.enterprise.stages.authenticator_endpoint_gdtc",
|
||||
"authentik.enterprise.stages.mtls",
|
||||
"authentik.enterprise.stages.source",
|
||||
|
||||
@@ -11,6 +11,8 @@ from django.db.models.functions import TruncHour
|
||||
from django.db.models.query_utils import Q
|
||||
from django.utils.text import slugify
|
||||
from django.utils.timezone import now
|
||||
from djangoql.schema import DateTimeField as QLDateTimeFIeld
|
||||
from djangoql.schema import IntField, StrField
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import OpenApiParameter, extend_schema
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
@@ -27,6 +29,7 @@ from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.api.search.fields import ChoiceSearchField, JSONSearchField
|
||||
from authentik.api.validation import validate
|
||||
from authentik.core.api.object_types import TypeCreateSerializer
|
||||
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
|
||||
@@ -171,10 +174,6 @@ class EventViewSet(
|
||||
filterset_class = EventsFilter
|
||||
|
||||
def get_ql_fields(self):
|
||||
from djangoql.schema import DateTimeField, IntField, StrField
|
||||
|
||||
from authentik.enterprise.search.fields import ChoiceSearchField, JSONSearchField
|
||||
|
||||
return [
|
||||
ChoiceSearchField(Event, "action"),
|
||||
StrField(Event, "event_uuid"),
|
||||
@@ -216,7 +215,7 @@ class EventViewSet(
|
||||
),
|
||||
),
|
||||
),
|
||||
DateTimeField(Event, "created", suggest_options=True),
|
||||
QLDateTimeFIeld(Event, "created", suggest_options=True),
|
||||
]
|
||||
|
||||
@extend_schema(
|
||||
|
||||
@@ -49,6 +49,7 @@ class TestRBACPermissionRoles(APITestCase):
|
||||
self.assertJSONEqual(
|
||||
res.content,
|
||||
{
|
||||
"autocomplete": {},
|
||||
"pagination": {
|
||||
"next": 0,
|
||||
"previous": 0,
|
||||
|
||||
@@ -208,6 +208,7 @@ SPECTACULAR_SETTINGS = {
|
||||
"authentik.api.v3.schema.response.postprocess_schema_responses",
|
||||
"authentik.api.v3.schema.query.postprocess_schema_query_params",
|
||||
"authentik.api.v3.schema.cleanup.postprocess_schema_remove_unused",
|
||||
"authentik.api.v3.schema.search.postprocess_schema_search_autocomplete",
|
||||
"authentik.api.v3.schema.enum.postprocess_schema_enums",
|
||||
],
|
||||
}
|
||||
@@ -215,10 +216,10 @@ SPECTACULAR_SETTINGS = {
|
||||
REST_FRAMEWORK = {
|
||||
"DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination",
|
||||
"DEFAULT_FILTER_BACKENDS": [
|
||||
"authentik.api.search.ql.QLSearch",
|
||||
"authentik.rbac.filters.ObjectFilter",
|
||||
"django_filters.rest_framework.DjangoFilterBackend",
|
||||
"rest_framework.filters.OrderingFilter",
|
||||
"rest_framework.filters.SearchFilter",
|
||||
],
|
||||
"DEFAULT_PERMISSION_CLASSES": ("authentik.rbac.permissions.ObjectPermissions",),
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||
|
||||
@@ -8934,7 +8934,6 @@
|
||||
"authentik.enterprise.providers.ssf",
|
||||
"authentik.enterprise.providers.ws_federation",
|
||||
"authentik.enterprise.reports",
|
||||
"authentik.enterprise.search",
|
||||
"authentik.enterprise.stages.authenticator_endpoint_gdtc",
|
||||
"authentik.enterprise.stages.mtls",
|
||||
"authentik.enterprise.stages.source"
|
||||
|
||||
Generated
-2
@@ -97,7 +97,6 @@ const (
|
||||
APPENUM_AUTHENTIK_ENTERPRISE_PROVIDERS_SSF AppEnum = "authentik.enterprise.providers.ssf"
|
||||
APPENUM_AUTHENTIK_ENTERPRISE_PROVIDERS_WS_FEDERATION AppEnum = "authentik.enterprise.providers.ws_federation"
|
||||
APPENUM_AUTHENTIK_ENTERPRISE_REPORTS AppEnum = "authentik.enterprise.reports"
|
||||
APPENUM_AUTHENTIK_ENTERPRISE_SEARCH AppEnum = "authentik.enterprise.search"
|
||||
APPENUM_AUTHENTIK_ENTERPRISE_STAGES_AUTHENTICATOR_ENDPOINT_GDTC AppEnum = "authentik.enterprise.stages.authenticator_endpoint_gdtc"
|
||||
APPENUM_AUTHENTIK_ENTERPRISE_STAGES_MTLS AppEnum = "authentik.enterprise.stages.mtls"
|
||||
APPENUM_AUTHENTIK_ENTERPRISE_STAGES_SOURCE AppEnum = "authentik.enterprise.stages.source"
|
||||
@@ -181,7 +180,6 @@ var AllowedAppEnumEnumValues = []AppEnum{
|
||||
"authentik.enterprise.providers.ssf",
|
||||
"authentik.enterprise.providers.ws_federation",
|
||||
"authentik.enterprise.reports",
|
||||
"authentik.enterprise.search",
|
||||
"authentik.enterprise.stages.authenticator_endpoint_gdtc",
|
||||
"authentik.enterprise.stages.mtls",
|
||||
"authentik.enterprise.stages.source",
|
||||
|
||||
@@ -23,6 +23,7 @@ var _ MappedNullable = &PaginatedExtraRoleObjectPermissionList{}
|
||||
type PaginatedExtraRoleObjectPermissionList struct {
|
||||
Pagination Pagination `json:"pagination"`
|
||||
Results []ExtraRoleObjectPermission `json:"results"`
|
||||
Autocomplete map[string]interface{} `json:"autocomplete"`
|
||||
AdditionalProperties map[string]interface{}
|
||||
}
|
||||
|
||||
@@ -32,10 +33,11 @@ type _PaginatedExtraRoleObjectPermissionList PaginatedExtraRoleObjectPermissionL
|
||||
// This constructor will assign default values to properties that have it defined,
|
||||
// and makes sure properties required by API are set, but the set of arguments
|
||||
// will change when the set of required properties is changed
|
||||
func NewPaginatedExtraRoleObjectPermissionList(pagination Pagination, results []ExtraRoleObjectPermission) *PaginatedExtraRoleObjectPermissionList {
|
||||
func NewPaginatedExtraRoleObjectPermissionList(pagination Pagination, results []ExtraRoleObjectPermission, autocomplete map[string]interface{}) *PaginatedExtraRoleObjectPermissionList {
|
||||
this := PaginatedExtraRoleObjectPermissionList{}
|
||||
this.Pagination = pagination
|
||||
this.Results = results
|
||||
this.Autocomplete = autocomplete
|
||||
return &this
|
||||
}
|
||||
|
||||
@@ -95,6 +97,30 @@ func (o *PaginatedExtraRoleObjectPermissionList) SetResults(v []ExtraRoleObjectP
|
||||
o.Results = v
|
||||
}
|
||||
|
||||
// GetAutocomplete returns the Autocomplete field value
|
||||
func (o *PaginatedExtraRoleObjectPermissionList) GetAutocomplete() map[string]interface{} {
|
||||
if o == nil {
|
||||
var ret map[string]interface{}
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.Autocomplete
|
||||
}
|
||||
|
||||
// GetAutocompleteOk returns a tuple with the Autocomplete field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *PaginatedExtraRoleObjectPermissionList) GetAutocompleteOk() (map[string]interface{}, bool) {
|
||||
if o == nil {
|
||||
return map[string]interface{}{}, false
|
||||
}
|
||||
return o.Autocomplete, true
|
||||
}
|
||||
|
||||
// SetAutocomplete sets field value
|
||||
func (o *PaginatedExtraRoleObjectPermissionList) SetAutocomplete(v map[string]interface{}) {
|
||||
o.Autocomplete = v
|
||||
}
|
||||
|
||||
func (o PaginatedExtraRoleObjectPermissionList) MarshalJSON() ([]byte, error) {
|
||||
toSerialize, err := o.ToMap()
|
||||
if err != nil {
|
||||
@@ -107,6 +133,7 @@ func (o PaginatedExtraRoleObjectPermissionList) ToMap() (map[string]interface{},
|
||||
toSerialize := map[string]interface{}{}
|
||||
toSerialize["pagination"] = o.Pagination
|
||||
toSerialize["results"] = o.Results
|
||||
toSerialize["autocomplete"] = o.Autocomplete
|
||||
|
||||
for key, value := range o.AdditionalProperties {
|
||||
toSerialize[key] = value
|
||||
@@ -122,6 +149,7 @@ func (o *PaginatedExtraRoleObjectPermissionList) UnmarshalJSON(data []byte) (err
|
||||
requiredProperties := []string{
|
||||
"pagination",
|
||||
"results",
|
||||
"autocomplete",
|
||||
}
|
||||
|
||||
allProperties := make(map[string]interface{})
|
||||
@@ -153,6 +181,7 @@ func (o *PaginatedExtraRoleObjectPermissionList) UnmarshalJSON(data []byte) (err
|
||||
if err = json.Unmarshal(data, &additionalProperties); err == nil {
|
||||
delete(additionalProperties, "pagination")
|
||||
delete(additionalProperties, "results")
|
||||
delete(additionalProperties, "autocomplete")
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
|
||||
-3
@@ -165,8 +165,6 @@ pub enum AppEnum {
|
||||
AuthentikEnterpriseProvidersWsFederation,
|
||||
#[serde(rename = "authentik.enterprise.reports")]
|
||||
AuthentikEnterpriseReports,
|
||||
#[serde(rename = "authentik.enterprise.search")]
|
||||
AuthentikEnterpriseSearch,
|
||||
#[serde(rename = "authentik.enterprise.stages.authenticator_endpoint_gdtc")]
|
||||
AuthentikEnterpriseStagesAuthenticatorEndpointGdtc,
|
||||
#[serde(rename = "authentik.enterprise.stages.mtls")]
|
||||
@@ -290,7 +288,6 @@ impl std::fmt::Display for AppEnum {
|
||||
write!(f, "authentik.enterprise.providers.ws_federation")
|
||||
}
|
||||
Self::AuthentikEnterpriseReports => write!(f, "authentik.enterprise.reports"),
|
||||
Self::AuthentikEnterpriseSearch => write!(f, "authentik.enterprise.search"),
|
||||
Self::AuthentikEnterpriseStagesAuthenticatorEndpointGdtc => {
|
||||
write!(f, "authentik.enterprise.stages.authenticator_endpoint_gdtc")
|
||||
}
|
||||
|
||||
+4
@@ -16,16 +16,20 @@ pub struct PaginatedExtraRoleObjectPermissionList {
|
||||
pub pagination: models::Pagination,
|
||||
#[serde(rename = "results")]
|
||||
pub results: Vec<models::ExtraRoleObjectPermission>,
|
||||
#[serde(rename = "autocomplete")]
|
||||
pub autocomplete: std::collections::HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
impl PaginatedExtraRoleObjectPermissionList {
|
||||
pub fn new(
|
||||
pagination: models::Pagination,
|
||||
results: Vec<models::ExtraRoleObjectPermission>,
|
||||
autocomplete: std::collections::HashMap<String, serde_json::Value>,
|
||||
) -> PaginatedExtraRoleObjectPermissionList {
|
||||
PaginatedExtraRoleObjectPermissionList {
|
||||
pagination,
|
||||
results,
|
||||
autocomplete,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
-1
@@ -94,7 +94,6 @@ export const AppEnum = {
|
||||
AuthentikEnterpriseProvidersSsf: "authentik.enterprise.providers.ssf",
|
||||
AuthentikEnterpriseProvidersWsFederation: "authentik.enterprise.providers.ws_federation",
|
||||
AuthentikEnterpriseReports: "authentik.enterprise.reports",
|
||||
AuthentikEnterpriseSearch: "authentik.enterprise.search",
|
||||
AuthentikEnterpriseStagesAuthenticatorEndpointGdtc:
|
||||
"authentik.enterprise.stages.authenticator_endpoint_gdtc",
|
||||
AuthentikEnterpriseStagesMtls: "authentik.enterprise.stages.mtls",
|
||||
|
||||
@@ -38,6 +38,12 @@ export interface PaginatedExtraRoleObjectPermissionList {
|
||||
* @memberof PaginatedExtraRoleObjectPermissionList
|
||||
*/
|
||||
results: Array<ExtraRoleObjectPermission>;
|
||||
/**
|
||||
*
|
||||
* @type {{ [key: string]: any; }}
|
||||
* @memberof PaginatedExtraRoleObjectPermissionList
|
||||
*/
|
||||
autocomplete: { [key: string]: any };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +54,7 @@ export function instanceOfPaginatedExtraRoleObjectPermissionList(
|
||||
): value is PaginatedExtraRoleObjectPermissionList {
|
||||
if (!("pagination" in value) || value["pagination"] === undefined) return false;
|
||||
if (!("results" in value) || value["results"] === undefined) return false;
|
||||
if (!("autocomplete" in value) || value["autocomplete"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,6 +74,7 @@ export function PaginatedExtraRoleObjectPermissionListFromJSONTyped(
|
||||
return {
|
||||
pagination: PaginationFromJSON(json["pagination"]),
|
||||
results: (json["results"] as Array<any>).map(ExtraRoleObjectPermissionFromJSON),
|
||||
autocomplete: json["autocomplete"],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,5 +95,6 @@ export function PaginatedExtraRoleObjectPermissionListToJSONTyped(
|
||||
return {
|
||||
pagination: PaginationToJSON(value["pagination"]),
|
||||
results: (value["results"] as Array<any>).map(ExtraRoleObjectPermissionToJSON),
|
||||
autocomplete: value["autocomplete"],
|
||||
};
|
||||
}
|
||||
|
||||
+156
-154
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,7 @@ export class GroupMemberSelectTable extends Table<User> {
|
||||
public override searchPlaceholder = msg("Search for users by username or display name...");
|
||||
public override searchLabel = msg("Search Users");
|
||||
public override label = msg("Select Users");
|
||||
public overridesupportsQL = true;
|
||||
public override supportsQL = true;
|
||||
|
||||
public override checkbox = true;
|
||||
public override checkboxChip = true;
|
||||
|
||||
@@ -17,7 +17,6 @@ import { GroupResult } from "#common/utils";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { intersectionObserver } from "#elements/decorators/intersection-observer";
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import { WithSession } from "#elements/mixins/session";
|
||||
import { type TransclusionElement } from "#elements/modals/shared";
|
||||
import { getURLParam, updateURLParams } from "#elements/router/RouteMatch";
|
||||
@@ -81,7 +80,7 @@ export interface ColumnOptions {
|
||||
* @template D An optional `toJSON()` result type.
|
||||
*/
|
||||
export abstract class Table<T extends object, D = T>
|
||||
extends WithLicenseSummary(WithSession(AKElement))
|
||||
extends WithSession(AKElement)
|
||||
implements TableLike, TransclusionElement
|
||||
{
|
||||
static styles: CSSResult[] = [
|
||||
@@ -871,10 +870,8 @@ export abstract class Table<T extends object, D = T>
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const isQL = this.supportsQL && this.hasEnterpriseLicense;
|
||||
|
||||
return html`<ak-table-search
|
||||
class="pf-c-toolbar__item pf-m-search-filter ${isQL ? "ql" : ""}"
|
||||
class="pf-c-toolbar__item pf-m-search-filter ${this.supportsQL ? "ql" : ""}"
|
||||
part="toolbar-search"
|
||||
.defaultValue=${this.search}
|
||||
label=${ifDefined(this.searchLabel)}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import "#components/ak-search-ql/index";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import { PaginatedResponse } from "#elements/table/Table";
|
||||
import { ifPresent } from "#elements/utils/attributes";
|
||||
|
||||
@@ -16,7 +15,7 @@ import PFInputGroup from "@patternfly/patternfly/components/InputGroup/input-gro
|
||||
import PFToolbar from "@patternfly/patternfly/components/Toolbar/toolbar.css";
|
||||
|
||||
@customElement("ak-table-search")
|
||||
export class TableSearchForm extends WithLicenseSummary(AKElement) {
|
||||
export class TableSearchForm extends AKElement {
|
||||
@property({ type: String, reflect: false })
|
||||
public defaultValue?: string;
|
||||
|
||||
@@ -111,7 +110,7 @@ export class TableSearchForm extends WithLicenseSummary(AKElement) {
|
||||
};
|
||||
|
||||
protected renderInput(): TemplateResult {
|
||||
if (this.supportsQL && this.hasEnterpriseLicense) {
|
||||
if (this.supportsQL) {
|
||||
return html`<ak-search-ql
|
||||
label=${ifPresent(this.label)}
|
||||
role="presentation"
|
||||
|
||||
@@ -31,10 +31,6 @@ View recent events on both a world map view with pinpoints indicating where each
|
||||
|
||||
You can export authentik event logs to a CSV file.
|
||||
|
||||
#### [Advanced queries](../sys-mgmt/events/logging-events.mdx#advanced-queries)
|
||||
|
||||
Allows you to construct advanced queries to find specific event logs using syntax similar to DjangoQL.
|
||||
|
||||
### [Google Workspace integration](../add-secure-apps/providers/gws/index.md)
|
||||
|
||||
The Google Workspace provider syncs users and groups from authentik to Google Workspace, making authentik the source of truth. It supports direct syncs for real-time changes and automatically linking existing entities.
|
||||
|
||||
@@ -47,7 +47,7 @@ You can export your authentik instance's events to a CSV file. To generate a dat
|
||||
|
||||
To review, download, or delete past data exports, navigate to **Events** > **Data Exports** in the Admin interface.
|
||||
|
||||
## Advanced queries for event logs :ak-enterprise {#advanced-queries}
|
||||
## Advanced queries for event logs {#advanced-queries}
|
||||
|
||||
You can construct advanced queries to find specific event logs. In the Admin interface, navigate to **Events** > **Logs**, and then use the auto-complete in the **Search** field or enter your own queries to return results with greater specificity.
|
||||
|
||||
@@ -84,7 +84,7 @@ brand.name = "my brand"
|
||||
```
|
||||
|
||||
```sh Search event by user
|
||||
user.username in ["ana", "akadmin"]
|
||||
user.username in ("ana", "akadmin")
|
||||
```
|
||||
|
||||
For more examples, refer to the list of [Event actions](./event-actions.md) and the related examples for each type of event.
|
||||
|
||||
@@ -33,7 +33,7 @@ You should see a confirmation pop-up on the top-right of the screen that the use
|
||||
To create a super-user, you need to add the user to a group that has super-user permissions. For more information, refer to [Create a Group](../groups/manage_groups.mdx#create-a-group).
|
||||
:::
|
||||
|
||||
## Advanced queries for users:ak-enterprise {#advanced-queries}
|
||||
## Advanced queries for users {#advanced-queries}
|
||||
|
||||
You can create advanced queries to locate specific users within the list shown under **Directory** > **Users** in the Admin interface. Use the auto-complete in the **Search** field or enter your own queries to return results with greater specificity.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user