diff --git a/authentik/policies/reputation/api.py b/authentik/policies/reputation/api.py index 45644350f4..b0af68b60e 100644 --- a/authentik/policies/reputation/api.py +++ b/authentik/policies/reputation/api.py @@ -1,6 +1,8 @@ """Reputation policy API Views""" from django.utils.translation import gettext_lazy as _ +from django_filters.filters import BaseInFilter, CharFilter +from django_filters.filterset import FilterSet from rest_framework import mixins from rest_framework.exceptions import ValidationError from rest_framework.viewsets import GenericViewSet, ModelViewSet @@ -11,6 +13,10 @@ from authentik.policies.api.policies import PolicySerializer from authentik.policies.reputation.models import Reputation, ReputationPolicy +class CharInFilter(BaseInFilter, CharFilter): + pass + + class ReputationPolicySerializer(PolicySerializer): """Reputation Policy Serializer""" @@ -38,6 +44,16 @@ class ReputationPolicyViewSet(UsedByMixin, ModelViewSet): ordering = ["name"] +class ReputationFilter(FilterSet): + """Filter for reputation""" + + identifier_in = CharInFilter(field_name="identifier", lookup_expr="in") + + class Meta: + model = Reputation + fields = ["identifier", "ip", "score"] + + class ReputationSerializer(ModelSerializer): """Reputation Serializer""" @@ -66,5 +82,5 @@ class ReputationViewSet( queryset = Reputation.objects.all() serializer_class = ReputationSerializer search_fields = ["identifier", "ip", "score"] - filterset_fields = ["identifier", "ip", "score"] + filterset_class = ReputationFilter ordering = ["ip"] diff --git a/schema.yml b/schema.yml index e0cfad4389..31b0d9c515 100644 --- a/schema.yml +++ b/schema.yml @@ -13080,6 +13080,15 @@ paths: name: identifier schema: type: string + - in: query + name: identifier_in + schema: + type: array + items: + type: string + description: Multiple values may be separated by commas. + explode: false + style: form - in: query name: ip schema: diff --git a/web/src/admin/users/UserViewPage.ts b/web/src/admin/users/UserViewPage.ts index f5188d12be..db5f9001fe 100644 --- a/web/src/admin/users/UserViewPage.ts +++ b/web/src/admin/users/UserViewPage.ts @@ -36,11 +36,13 @@ import "@goauthentik/elements/oauth/UserRefreshTokenList"; import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import "@goauthentik/elements/user/SessionList"; import "@goauthentik/elements/user/UserConsentList"; +import "@goauthentik/elements/user/UserReputationList"; import "@goauthentik/elements/user/sources/SourceSettings"; import { msg, str } from "@lit/localize"; import { TemplateResult, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; @@ -274,6 +276,21 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) { +
+
+
+ + +
+
+
{ + @property() + targetUsername!: string; + + @property() + targetEmail!: string | undefined; + + async apiEndpoint(page: number): Promise> { + const identifiers = [this.targetUsername]; + if (this.targetEmail !== undefined) { + identifiers.push(this.targetEmail); + } + return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresList({ + identifierIn: identifiers, + ordering: this.order, + page: page, + pageSize: (await uiConfig()).pagination.perPage, + }); + } + + checkbox = true; + clearOnRefresh = true; + order = "identifier"; + + columns(): TableColumn[] { + return [ + new TableColumn(msg("Identifier"), "identifier"), + new TableColumn(msg("IP"), "ip"), + new TableColumn(msg("Score"), "score"), + new TableColumn(msg("Updated"), "updated"), + ]; + } + + renderToolbarSelected(): TemplateResult { + const disabled = this.selectedElements.length < 1; + return html` { + return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresUsedByList({ + reputationUuid: item.pk || "", + }); + }} + .delete=${(item: Reputation) => { + return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresDestroy({ + reputationUuid: item.pk || "", + }); + }} + > + + `; + } + + row(item: Reputation): TemplateResult[] { + return [ + html`${item.identifier}`, + html`${item.ipGeoData?.country + ? html` ${getUnicodeFlagIcon(item.ipGeoData.country)} ` + : html``} + ${item.ip}`, + html`${item.score}`, + html`
${getRelativeTime(item.updated)}
+ ${item.updated.toLocaleString()}`, + ]; + } +}