web/admin: add UI for reputations

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-05-29 23:01:45 +02:00
parent 31ad09c391
commit c89b8a5f7c
9 changed files with 237 additions and 3 deletions

View file

@ -73,6 +73,12 @@ export class AdminInterface extends Interface {
<ak-sidebar-item path="/policy/policies"> <ak-sidebar-item path="/policy/policies">
<span slot="label">${t`Policies`}</span> <span slot="label">${t`Policies`}</span>
</ak-sidebar-item> </ak-sidebar-item>
<ak-sidebar-item path="/policy/reputation/ip">
<span slot="label">${t`Reputation policy - IPs`}</span>
</ak-sidebar-item>
<ak-sidebar-item path="/policy/reputation/user">
<span slot="label">${t`Reputation policy - Users`}</span>
</ak-sidebar-item>
<ak-sidebar-item path="/core/property-mappings"> <ak-sidebar-item path="/core/property-mappings">
<span slot="label">${t`Property Mappings`}</span> <span slot="label">${t`Property Mappings`}</span>
</ak-sidebar-item> </ak-sidebar-item>

View file

@ -985,6 +985,8 @@ msgstr "Define how notifications are sent to users, like Email or Webhook."
#: src/pages/outposts/OutpostListPage.ts #: src/pages/outposts/OutpostListPage.ts
#: src/pages/outposts/ServiceConnectionListPage.ts #: src/pages/outposts/ServiceConnectionListPage.ts
#: src/pages/policies/PolicyListPage.ts #: src/pages/policies/PolicyListPage.ts
#: src/pages/policies/reputation/IPReputationListPage.ts
#: src/pages/policies/reputation/UserReputationListPage.ts
#: src/pages/property-mappings/PropertyMappingListPage.ts #: src/pages/property-mappings/PropertyMappingListPage.ts
#: src/pages/providers/ProviderListPage.ts #: src/pages/providers/ProviderListPage.ts
#: src/pages/sources/SourcesListPage.ts #: src/pages/sources/SourcesListPage.ts
@ -1698,6 +1700,15 @@ msgstr "How many attempts a user has before the flow is canceled. To lock the us
msgid "ID" msgid "ID"
msgstr "ID" msgstr "ID"
#: src/pages/policies/reputation/IPReputationListPage.ts
msgid "IP"
msgstr "IP"
#: src/pages/policies/reputation/IPReputationListPage.ts
#: src/pages/policies/reputation/IPReputationListPage.ts
msgid "IP Reputation"
msgstr "IP Reputation"
#: src/pages/applications/ApplicationForm.ts #: src/pages/applications/ApplicationForm.ts
msgid "Icon" msgid "Icon"
msgstr "Icon" msgstr "Icon"
@ -1796,6 +1807,10 @@ msgstr "Invalidation"
msgid "Invalidation flow" msgid "Invalidation flow"
msgstr "Invalidation flow" msgstr "Invalidation flow"
#: src/pages/stages/invitation/InvitationListPage.ts
msgid "Invitation"
msgstr "Invitation"
#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts
#: src/pages/stages/invitation/InvitationListPage.ts #: src/pages/stages/invitation/InvitationListPage.ts
msgid "Invitations" msgid "Invitations"
@ -2619,7 +2634,6 @@ msgstr "Private key, acquired from https://www.google.com/recaptcha/intro/v3.htm
msgid "Profile URL" msgid "Profile URL"
msgstr "Profile URL" msgstr "Profile URL"
#: src/pages/stages/invitation/InvitationListPage.ts
#: src/pages/stages/prompt/PromptListPage.ts #: src/pages/stages/prompt/PromptListPage.ts
msgid "Prompt" msgid "Prompt"
msgstr "Prompt" msgstr "Prompt"
@ -2815,6 +2829,22 @@ msgstr "Reload"
msgid "Remove the user from the current session." msgid "Remove the user from the current session."
msgstr "Remove the user from the current session." msgstr "Remove the user from the current session."
#: src/pages/policies/reputation/IPReputationListPage.ts
msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
msgstr "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
#: src/pages/policies/reputation/UserReputationListPage.ts
msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
msgstr "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
#: src/interfaces/AdminInterface.ts
msgid "Reputation policy - IPs"
msgstr "Reputation policy - IPs"
#: src/interfaces/AdminInterface.ts
msgid "Reputation policy - Users"
msgstr "Reputation policy - Users"
#: src/pages/events/EventInfo.ts #: src/pages/events/EventInfo.ts
#: src/pages/events/EventInfo.ts #: src/pages/events/EventInfo.ts
msgid "Request" msgid "Request"
@ -2942,6 +2972,11 @@ msgstr "Scope which the client can specify to access these properties."
msgid "Scopes" msgid "Scopes"
msgstr "Scopes" msgstr "Scopes"
#: src/pages/policies/reputation/IPReputationListPage.ts
#: src/pages/policies/reputation/UserReputationListPage.ts
msgid "Score"
msgstr "Score"
#: src/elements/table/TableSearch.ts #: src/elements/table/TableSearch.ts
msgid "Search..." msgid "Search..."
msgstr "Search..." msgstr "Search..."
@ -4075,6 +4110,11 @@ msgstr "User Info"
msgid "User Property Mappings" msgid "User Property Mappings"
msgstr "User Property Mappings" msgstr "User Property Mappings"
#: src/pages/policies/reputation/UserReputationListPage.ts
#: src/pages/policies/reputation/UserReputationListPage.ts
msgid "User Reputation"
msgstr "User Reputation"
#: src/pages/user-settings/UserSettingsPage.ts #: src/pages/user-settings/UserSettingsPage.ts
msgid "User Settings" msgid "User Settings"
msgstr "User Settings" msgstr "User Settings"
@ -4131,6 +4171,7 @@ msgid "Userinfo URL"
msgstr "Userinfo URL" msgstr "Userinfo URL"
#: src/flows/stages/identification/IdentificationStage.ts #: src/flows/stages/identification/IdentificationStage.ts
#: src/pages/policies/reputation/UserReputationListPage.ts
#: src/pages/stages/identification/IdentificationStageForm.ts #: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/user-settings/UserDetailsPage.ts #: src/pages/user-settings/UserDetailsPage.ts
#: src/pages/users/UserForm.ts #: src/pages/users/UserForm.ts

View file

@ -990,6 +990,8 @@ msgstr ""
#: #:
#: #:
#: #:
#:
#:
msgid "Delete" msgid "Delete"
msgstr "" msgstr ""
@ -1690,6 +1692,15 @@ msgstr ""
msgid "ID" msgid "ID"
msgstr "" msgstr ""
#:
msgid "IP"
msgstr ""
#:
#:
msgid "IP Reputation"
msgstr ""
#: #:
msgid "Icon" msgid "Icon"
msgstr "" msgstr ""
@ -1788,6 +1799,10 @@ msgstr ""
msgid "Invalidation flow" msgid "Invalidation flow"
msgstr "" msgstr ""
#:
msgid "Invitation"
msgstr ""
#: #:
#: #:
msgid "Invitations" msgid "Invitations"
@ -2611,7 +2626,6 @@ msgstr ""
msgid "Profile URL" msgid "Profile URL"
msgstr "" msgstr ""
#:
#: #:
msgid "Prompt" msgid "Prompt"
msgstr "" msgstr ""
@ -2807,6 +2821,22 @@ msgstr ""
msgid "Remove the user from the current session." msgid "Remove the user from the current session."
msgstr "" msgstr ""
#:
msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
msgstr ""
#:
msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
msgstr ""
#:
msgid "Reputation policy - IPs"
msgstr ""
#:
msgid "Reputation policy - Users"
msgstr ""
#: #:
#: #:
msgid "Request" msgid "Request"
@ -2934,6 +2964,11 @@ msgstr ""
msgid "Scopes" msgid "Scopes"
msgstr "" msgstr ""
#:
#:
msgid "Score"
msgstr ""
#: #:
msgid "Search..." msgid "Search..."
msgstr "" msgstr ""
@ -4063,6 +4098,11 @@ msgstr ""
msgid "User Property Mappings" msgid "User Property Mappings"
msgstr "" msgstr ""
#:
#:
msgid "User Reputation"
msgstr ""
#: #:
msgid "User Settings" msgid "User Settings"
msgstr "" msgstr ""
@ -4123,6 +4163,7 @@ msgstr ""
#: #:
#: #:
#: #:
#:
msgid "Username" msgid "Username"
msgstr "" msgstr ""

View file

@ -0,0 +1,70 @@
import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../../api/Client";
import { TablePage } from "../../../elements/table/TablePage";
import "../../../elements/buttons/ModalButton";
import "../../../elements/buttons/SpinnerButton";
import "../../../elements/forms/DeleteForm";
import "../../../elements/forms/ModalForm";
import { TableColumn } from "../../../elements/table/Table";
import { PAGE_SIZE } from "../../../constants";
import { IPReputation, PoliciesApi } from "authentik-api";
import { DEFAULT_CONFIG } from "../../../api/Config";
@customElement("ak-policy-reputation-ip-list")
export class IPReputationListPage extends TablePage<IPReputation> {
searchEnabled(): boolean {
return true;
}
pageTitle(): string {
return t`IP Reputation`;
}
pageDescription(): string {
return t`Reputation for IPs. Scores are decreased for each failed login and increased for each successful login.`;
}
pageIcon(): string {
return "fa fa-ban";
}
@property()
order = "ip";
apiEndpoint(page: number): Promise<AKResponse<IPReputation>> {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationIpsList({
ordering: this.order,
page: page,
pageSize: PAGE_SIZE,
search: this.search || "",
});
}
columns(): TableColumn[] {
return [
new TableColumn(t`IP`, "ip"),
new TableColumn(t`Score`, "score"),
new TableColumn(""),
];
}
row(item: IPReputation): TemplateResult[] {
return [
html`${item.ip}`,
html`${item.score}`,
html`
<ak-forms-delete
.obj=${item}
objectLabel=${t`IP Reputation`}
.delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationIpsDestroy({
id: item.pk,
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`}
</button>
</ak-forms-delete>`,
];
}
}

View file

@ -0,0 +1,70 @@
import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../../api/Client";
import { TablePage } from "../../../elements/table/TablePage";
import "../../../elements/buttons/ModalButton";
import "../../../elements/buttons/SpinnerButton";
import "../../../elements/forms/DeleteForm";
import "../../../elements/forms/ModalForm";
import { TableColumn } from "../../../elements/table/Table";
import { PAGE_SIZE } from "../../../constants";
import { UserReputation, PoliciesApi } from "authentik-api";
import { DEFAULT_CONFIG } from "../../../api/Config";
@customElement("ak-policy-reputation-user-list")
export class UserReputationListPage extends TablePage<UserReputation> {
searchEnabled(): boolean {
return true;
}
pageTitle(): string {
return t`User Reputation`;
}
pageDescription(): string {
return t`Reputation for usernames. Scores are decreased for each failed login and increased for each successful login.`;
}
pageIcon(): string {
return "fa fa-ban";
}
@property()
order = "username";
apiEndpoint(page: number): Promise<AKResponse<UserReputation>> {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersList({
ordering: this.order,
page: page,
pageSize: PAGE_SIZE,
search: this.search || "",
});
}
columns(): TableColumn[] {
return [
new TableColumn(t`Username`, "username"),
new TableColumn(t`Score`, "score"),
new TableColumn(""),
];
}
row(item: UserReputation): TemplateResult[] {
return [
html`${item.username}`,
html`${item.score}`,
html`
<ak-forms-delete
.obj=${item}
objectLabel=${t`User Reputation`}
.delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersDestroy({
id: item.pk,
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`}
</button>
</ak-forms-delete>`,
];
}
}

View file

@ -57,7 +57,7 @@ export class InvitationListPage extends TablePage<Invitation> {
html` html`
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${t`Prompt`} objectLabel=${t`Invitation`}
.delete=${() => { .delete=${() => {
return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsDestroy({ return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsDestroy({
inviteUuid: item.pk || "" inviteUuid: item.pk || ""

View file

@ -4,6 +4,7 @@ import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/forms/FormGroup";
import { first } from "../../utils"; import { first } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm"; import { ModelForm } from "../../elements/forms/ModelForm";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";

View file

@ -16,6 +16,8 @@ import "./pages/LibraryPage";
import "./pages/outposts/OutpostListPage"; import "./pages/outposts/OutpostListPage";
import "./pages/outposts/ServiceConnectionListPage"; import "./pages/outposts/ServiceConnectionListPage";
import "./pages/policies/PolicyListPage"; import "./pages/policies/PolicyListPage";
import "./pages/policies/reputation/IPReputationListPage";
import "./pages/policies/reputation/UserReputationListPage";
import "./pages/property-mappings/PropertyMappingListPage"; import "./pages/property-mappings/PropertyMappingListPage";
import "./pages/providers/ProviderListPage"; import "./pages/providers/ProviderListPage";
import "./pages/providers/ProviderViewPage"; import "./pages/providers/ProviderViewPage";
@ -54,6 +56,8 @@ export const ROUTES: Route[] = [
new Route(new RegExp("^/core/tokens$"), html`<ak-token-list></ak-token-list>`), new Route(new RegExp("^/core/tokens$"), html`<ak-token-list></ak-token-list>`),
new Route(new RegExp("^/core/tenants$"), html`<ak-tenant-list></ak-tenant-list>`), new Route(new RegExp("^/core/tenants$"), html`<ak-tenant-list></ak-tenant-list>`),
new Route(new RegExp("^/policy/policies$"), html`<ak-policy-list></ak-policy-list>`), new Route(new RegExp("^/policy/policies$"), html`<ak-policy-list></ak-policy-list>`),
new Route(new RegExp("^/policy/reputation/ip$"), html`<ak-policy-reputation-ip-list></ak-policy-reputation-ip-list>`),
new Route(new RegExp("^/policy/reputation/user$"), html`<ak-policy-reputation-user-list></ak-policy-reputation-user-list>`),
new Route(new RegExp("^/identity/groups$"), html`<ak-group-list></ak-group-list>`), new Route(new RegExp("^/identity/groups$"), html`<ak-group-list></ak-group-list>`),
new Route(new RegExp("^/identity/users$"), html`<ak-user-list></ak-user-list>`), new Route(new RegExp("^/identity/users$"), html`<ak-user-list></ak-user-list>`),
new Route(new RegExp(`^/identity/users/(?<id>${ID_REGEX})$`)).then((args) => { new Route(new RegExp(`^/identity/users/(?<id>${ID_REGEX})$`)).then((args) => {

View file

@ -25,6 +25,7 @@ title: Next
## Minor changes ## Minor changes
- You can now specify which sources should be shown on an Identification stage. - You can now specify which sources should be shown on an Identification stage.
- Add UI for the reputation of IPs and usernames for reputation policies.
## Upgrading ## Upgrading