API: add endpoint to show by what objects an object is used (#995)

* core: add used_by API to show what objects are affected before deletion

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* web/elements: add support for used_by API

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* core: add authentik_used_by_shadows to shadow other models

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* web: implement used_by API

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* *: fix duplicate imports

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* core: add action field to used_by api

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* web: add UI for used_by action

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* web: add notice to tenant form

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* core: fix naming in used_by

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* web: check length for used_by

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* core: fix used_by for non-pk models

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* *: improve __str__ on models

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* core: add support for many to many in used_by

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens L
2021-06-10 11:58:12 +02:00
committed by GitHub
parent bf683514ee
commit 34ae9e6dab
98 changed files with 2713 additions and 130 deletions

View File

@ -1,20 +1,30 @@
import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { EVENT_REFRESH } from "../../constants";
import { ModalButton } from "../buttons/ModalButton";
import { MessageLevel } from "../messages/Message";
import { showMessage } from "../messages/MessageContainer";
import "../buttons/SpinnerButton";
import { UsedBy, UsedByActionEnum } from "authentik-api";
import PFList from "@patternfly/patternfly/components/List/list.css";
import { until } from "lit-html/directives/until";
@customElement("ak-forms-delete")
export class DeleteForm extends ModalButton {
static get styles(): CSSResult[] {
return super.styles.concat(PFList);
}
@property({attribute: false})
obj?: Record<string, unknown>;
@property()
objectLabel?: string;
@property({attribute: false})
usedBy?: () => Promise<UsedBy[]>;
@property({attribute: false})
delete!: () => Promise<unknown>;
@ -69,6 +79,40 @@ export class DeleteForm extends ModalButton {
</p>
</form>
</section>
${this.usedBy ? until(this.usedBy().then(usedBy => {
if (usedBy.length < 1) {
return html``;
}
return html`
<section class="pf-c-page__main-section">
<form class="pf-c-form pf-m-horizontal">
<p>
${t`The following objects use ${objName} `}
</p>
<ul class="pf-c-list">
${usedBy.map(ub => {
let consequence = "";
switch (ub.action) {
case UsedByActionEnum.Cascade:
consequence = t`object will be DELETED`;
break;
case UsedByActionEnum.CascadeMany:
consequence = t`connecting object will be deleted`;
break;
case UsedByActionEnum.SetDefault:
consequence = t`reference will be reset to default value`;
break;
case UsedByActionEnum.SetNull:
consequence = t`reference will be set to an empty value`;
break;
}
return html`<li>${t`${ub.name} (${consequence})`}</li>`;
})}
</ul>
</form>
</section>
`;
})) : html``}
<footer class="pf-c-modal-box__footer">
<ak-spinner-button
.callAction=${() => {

View File

@ -44,9 +44,14 @@ export class UserOAuthCodeList extends Table<ExpiringBaseGrantModel> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Authorization Code`}
.usedBy=${() => {
return new Oauth2Api(DEFAULT_CONFIG).oauth2AuthorizationCodesUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new Oauth2Api(DEFAULT_CONFIG).oauth2AuthorizationCodesDestroy({
id: item.pk || 0,
id: item.pk,
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -68,9 +68,14 @@ export class UserOAuthRefreshList extends Table<RefreshTokenModel> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Refresh Code`}
.usedBy=${() => {
return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensDestroy({
id: item.pk || 0,
id: item.pk,
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -45,6 +45,11 @@ export class AuthenticatedSessionList extends Table<AuthenticatedSession> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Session`}
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreAuthenticatedSessionsUsedByList({
uuid: item.uuid || "",
});
}}
.delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreAuthenticatedSessionsDestroy({
uuid: item.uuid || "",

View File

@ -40,9 +40,14 @@ export class UserConsentList extends Table<UserConsent> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Consent`}
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUserConsentUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUserConsentDestroy({
id: item.pk || 0,
id: item.pk,
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -1144,6 +1144,9 @@ msgid "Disable"
msgstr "Disable"
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
msgid "Disable Duo authenticator"
msgstr "Disable Duo authenticator"
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
msgid "Disable Static Tokens"
msgstr "Disable Static Tokens"
@ -1293,11 +1296,14 @@ msgstr "Email: Text field with Email type."
msgid "Enable"
msgstr "Enable"
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
msgid "Enable Duo authenticator"
msgstr "Enable Duo authenticator"
#: src/pages/sources/ldap/LDAPSourceForm.ts
msgid "Enable StartTLS"
msgstr "Enable StartTLS"
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
msgid "Enable Static Tokens"
msgstr "Enable Static Tokens"
@ -2148,6 +2154,10 @@ msgstr "Matches Event's Client IP (strict matching, for network matching use an
msgid "Matches an event against a set of criteria. If any of the configured values match, the policy passes."
msgstr "Matches an event against a set of criteria. If any of the configured values match, the policy passes."
#: src/pages/tenants/TenantForm.ts
msgid "Matching is done based on domain suffix, so if you enter domain.tld, foo.domain.tld will still match."
msgstr "Matching is done based on domain suffix, so if you enter domain.tld, foo.domain.tld will still match."
#: src/pages/policies/expiry/ExpiryPolicyForm.ts
msgid "Maximum age (in days)"
msgstr "Maximum age (in days)"
@ -3805,6 +3815,10 @@ msgstr "The external URL you'll access the application at. Include any non-stand
msgid "The external URL you'll authenticate at. Can be the same domain as authentik."
msgstr "The external URL you'll authenticate at. Can be the same domain as authentik."
#: src/elements/forms/DeleteForm.ts
msgid "The following objects use {objName}"
msgstr "The following objects use {objName}"
#: src/pages/policies/dummy/DummyPolicyForm.ts
msgid "The policy takes a random time to execute. This controls the minimum time it will take."
msgstr "The policy takes a random time to execute. This controls the minimum time it will take."
@ -4519,6 +4533,18 @@ msgstr "authentik LDAP Backend"
msgid "no tabs defined"
msgstr "no tabs defined"
#: src/elements/forms/DeleteForm.ts
msgid "object will be DELETED"
msgstr "object will be DELETED"
#: src/elements/forms/DeleteForm.ts
msgid "reference will be reset to default value"
msgstr "reference will be reset to default value"
#: src/elements/forms/DeleteForm.ts
msgid "reference will be set to an empty value"
msgstr "reference will be set to an empty value"
#: src/elements/Expand.ts
#: src/elements/Expand.ts
msgid "{0}"
@ -4532,6 +4558,10 @@ msgstr "{0} (\"{1}\", of type {2})"
msgid "{0} ({1})"
msgstr "{0} ({1})"
#: src/elements/forms/DeleteForm.ts
msgid "{0} ({consequence})"
msgstr "{0} ({consequence})"
#: src/elements/table/TablePagination.ts
msgid "{0} - {1} of {2}"
msgstr "{0} - {1} of {2}"

View File

@ -1136,6 +1136,9 @@ msgid "Disable"
msgstr ""
#:
msgid "Disable Duo authenticator"
msgstr ""
#:
msgid "Disable Static Tokens"
msgstr ""
@ -1286,10 +1289,13 @@ msgid "Enable"
msgstr ""
#:
msgid "Enable StartTLS"
msgid "Enable Duo authenticator"
msgstr ""
#:
msgid "Enable StartTLS"
msgstr ""
#:
msgid "Enable Static Tokens"
msgstr ""
@ -2140,6 +2146,10 @@ msgstr ""
msgid "Matches an event against a set of criteria. If any of the configured values match, the policy passes."
msgstr ""
#:
msgid "Matching is done based on domain suffix, so if you enter domain.tld, foo.domain.tld will still match."
msgstr ""
#:
msgid "Maximum age (in days)"
msgstr ""
@ -3797,6 +3807,10 @@ msgstr ""
msgid "The external URL you'll authenticate at. Can be the same domain as authentik."
msgstr ""
#:
msgid "The following objects use {objName}"
msgstr ""
#:
msgid "The policy takes a random time to execute. This controls the minimum time it will take."
msgstr ""
@ -4505,6 +4519,18 @@ msgstr ""
msgid "no tabs defined"
msgstr ""
#:
msgid "object will be DELETED"
msgstr ""
#:
msgid "reference will be reset to default value"
msgstr ""
#:
msgid "reference will be set to an empty value"
msgstr ""
#:
#:
msgid "{0}"
@ -4518,6 +4544,10 @@ msgstr ""
msgid "{0} ({1})"
msgstr ""
#:
msgid "{0} ({consequence})"
msgstr ""
#:
msgid "{0} - {1} of {2}"
msgstr ""

View File

@ -103,9 +103,14 @@ export class ApplicationListPage extends TablePage<Application> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Application`}
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreApplicationsUsedByList({
slug: item.slug
});
}}
.delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreApplicationsDestroy({
slug: item.slug || ""
slug: item.slug
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -79,9 +79,14 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Certificate-Key Pair`}
.usedBy=${() => {
return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsUsedByList({
kpUuid: item.pk
});
}}
.delete=${() => {
return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsDestroy({
kpUuid: item.pk || ""
kpUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -1,7 +1,7 @@
import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { until } from "lit-html/directives/until";
import { ActionEnum, FlowsApi } from "authentik-api";
import { EventMatcherPolicyActionEnum, FlowsApi } from "authentik-api";
import "../../elements/Spinner";
import "../../elements/Expand";
import { PFSize } from "../../elements/Spinner";
@ -142,14 +142,14 @@ export class EventInfo extends LitElement {
return html`<ak-spinner size=${PFSize.Medium}></ak-spinner>`;
}
switch (this.event?.action) {
case ActionEnum.ModelCreated:
case ActionEnum.ModelUpdated:
case ActionEnum.ModelDeleted:
case EventMatcherPolicyActionEnum.ModelCreated:
case EventMatcherPolicyActionEnum.ModelUpdated:
case EventMatcherPolicyActionEnum.ModelDeleted:
return html`
<h3>${t`Affected model:`}</h3>
${this.getModelInfo(this.event.context?.model as EventContext)}
`;
case ActionEnum.AuthorizeApplication:
case EventMatcherPolicyActionEnum.AuthorizeApplication:
return html`<div class="pf-l-flex">
<div class="pf-l-flex__item">
<h3>${t`Authorized application:`}</h3>
@ -166,17 +166,17 @@ export class EventInfo extends LitElement {
</div>
</div>
<ak-expand>${this.defaultResponse()}</ak-expand>`;
case ActionEnum.EmailSent:
case EventMatcherPolicyActionEnum.EmailSent:
return html`<h3>${t`Email info:`}</h3>
${this.getEmailInfo(this.event.context)}
<ak-expand>
<iframe srcdoc=${this.event.context.body}></iframe>
</ak-expand>`;
case ActionEnum.SecretView:
case EventMatcherPolicyActionEnum.SecretView:
return html`
<h3>${t`Secret:`}</h3>
${this.getModelInfo(this.event.context.secret as EventContext)}`;
case ActionEnum.PropertyMappingException:
case EventMatcherPolicyActionEnum.PropertyMappingException:
return html`<div class="pf-l-flex">
<div class="pf-l-flex__item">
<h3>${t`Exception`}</h3>
@ -188,7 +188,7 @@ export class EventInfo extends LitElement {
</div>
</div>
<ak-expand>${this.defaultResponse()}</ak-expand>`;
case ActionEnum.PolicyException:
case EventMatcherPolicyActionEnum.PolicyException:
return html`<div class="pf-l-flex">
<div class="pf-l-flex__item">
<h3>${t`Binding`}</h3>
@ -207,7 +207,7 @@ export class EventInfo extends LitElement {
</div>
</div>
<ak-expand>${this.defaultResponse()}</ak-expand>`;
case ActionEnum.PolicyExecution:
case EventMatcherPolicyActionEnum.PolicyExecution:
return html`<div class="pf-l-flex">
<div class="pf-l-flex__item">
<h3>${t`Binding`}</h3>
@ -235,10 +235,10 @@ export class EventInfo extends LitElement {
</div>
</div>
<ak-expand>${this.defaultResponse()}</ak-expand>`;
case ActionEnum.ConfigurationError:
case EventMatcherPolicyActionEnum.ConfigurationError:
return html`<h3>${this.event.context.message}</h3>
<ak-expand>${this.defaultResponse()}</ak-expand>`;
case ActionEnum.UpdateAvailable:
case EventMatcherPolicyActionEnum.UpdateAvailable:
return html`<h3>${t`New version available!`}</h3>
<a
target="_blank"
@ -247,7 +247,7 @@ export class EventInfo extends LitElement {
</a>`;
// Action types which typically don't record any extra context.
// If context is not empty, we fall to the default response.
case ActionEnum.Login:
case EventMatcherPolicyActionEnum.Login:
if ("using_source" in this.event.context) {
return html`<div class="pf-l-flex">
<div class="pf-l-flex__item">
@ -257,11 +257,11 @@ export class EventInfo extends LitElement {
</div>`;
}
return this.defaultResponse();
case ActionEnum.LoginFailed:
case EventMatcherPolicyActionEnum.LoginFailed:
return html`
<h3>${t`Attempted to log in as ${this.event.context.username}`}</h3>
<ak-expand>${this.defaultResponse()}</ak-expand>`;
case ActionEnum.Logout:
case EventMatcherPolicyActionEnum.Logout:
if (this.event.context === {}) {
return html`<span>${t`No additional data available.`}</span>`;
}

View File

@ -73,9 +73,14 @@ export class RuleListPage extends TablePage<NotificationRule> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Notification rule`}
.usedBy=${() => {
return new EventsApi(DEFAULT_CONFIG).eventsRulesUsedByList({
pbmUuid: item.pk
});
}}
.delete=${() => {
return new EventsApi(DEFAULT_CONFIG).eventsRulesDestroy({
pbmUuid: item.pk || ""
pbmUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -77,9 +77,14 @@ export class TransportListPage extends TablePage<NotificationTransport> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Notifications Transport`}
.usedBy=${() => {
return new EventsApi(DEFAULT_CONFIG).eventsTransportsUsedByList({
uuid: item.pk
});
}}
.delete=${() => {
return new EventsApi(DEFAULT_CONFIG).eventsTransportsDestroy({
uuid: item.pk || ""
uuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -82,9 +82,14 @@ export class BoundStagesList extends Table<FlowStageBinding> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Stage binding`}
.usedBy=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsBindingsUsedByList({
fsbUuid: item.pk
});
}}
.delete=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsBindingsDestroy({
fsbUuid: item.pk || "",
fsbUuid: item.pk,
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -78,6 +78,11 @@ export class FlowListPage extends TablePage<Flow> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Flow`}
.usedBy=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesUsedByList({
slug: item.slug
});
}}
.delete=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesDestroy({
slug: item.slug

View File

@ -72,9 +72,14 @@ export class GroupListPage extends TablePage<Group> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Group`}
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreGroupsUsedByList({
groupUuid: item.pk
});
}}
.delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreGroupsDestroy({
groupUuid: item.pk || ""
groupUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -77,9 +77,14 @@ export class OutpostListPage extends TablePage<Outpost> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Outpost`}
.usedBy=${() => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesUsedByList({
uuid: item.pk
});
}}
.delete=${() => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesDestroy({
uuid: item.pk || ""
uuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -93,9 +93,14 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
<ak-forms-delete
.obj=${item}
objectLabel=${t`Outpost Service-connection`}
.usedBy=${() => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllUsedByList({
uuid: item.pk
});
}}
.delete=${() => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllDestroy({
uuid: item.pk || ""
uuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -137,9 +137,14 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Policy binding`}
.usedBy=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsUsedByList({
policyBindingUuid: item.pk
});
}}
.delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsDestroy({
policyBindingUuid: item.pk || "",
policyBindingUuid: item.pk,
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -107,9 +107,14 @@ export class PolicyListPage extends TablePage<Policy> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Policy`}
.usedBy=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllUsedByList({
policyUuid: item.pk
});
}}
.delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllDestroy({
policyUuid: item.pk || ""
policyUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -55,6 +55,11 @@ export class IPReputationListPage extends TablePage<IPReputation> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`IP Reputation`}
.usedBy=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationIpsUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationIpsDestroy({
id: item.pk,

View File

@ -55,6 +55,11 @@ export class UserReputationListPage extends TablePage<UserReputation> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`User Reputation`}
.usedBy=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersDestroy({
id: item.pk,

View File

@ -97,9 +97,14 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Property Mapping`}
.usedBy=${() => {
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllUsedByList({
pmUuid: item.pk
});
}}
.delete=${() => {
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllDestroy({
pmUuid: item.pk || ""
pmUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -90,9 +90,14 @@ export class ProviderListPage extends TablePage<Provider> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Provider`}
.usedBy=${() => {
return new ProvidersApi(DEFAULT_CONFIG).providersAllUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new ProvidersApi(DEFAULT_CONFIG).providersAllDestroy({
id: item.pk || 0
id: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -86,9 +86,14 @@ export class SourceListPage extends TablePage<Source> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Source`}
.usedBy=${() => {
return new SourcesApi(DEFAULT_CONFIG).sourcesAllUsedByList({
slug: item.slug
});
}}
.delete=${() => {
return new SourcesApi(DEFAULT_CONFIG).sourcesAllDestroy({
slug: item.slug || ""
slug: item.slug
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -102,9 +102,14 @@ export class StageListPage extends TablePage<Stage> {
<ak-forms-delete
.obj=${item}
objectLabel=${item.verboseName || ""}
.usedBy=${() => {
return new StagesApi(DEFAULT_CONFIG).stagesAllUsedByList({
stageUuid: item.pk
});
}}
.delete=${() => {
return new StagesApi(DEFAULT_CONFIG).stagesAllDestroy({
stageUuid: item.pk || ""
stageUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -58,9 +58,14 @@ export class InvitationListPage extends TablePage<Invitation> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Invitation`}
.usedBy=${() => {
return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsUsedByList({
inviteUuid: item.pk
});
}}
.delete=${() => {
return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsDestroy({
inviteUuid: item.pk || ""
inviteUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -77,9 +77,14 @@ export class PromptListPage extends TablePage<Prompt> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Prompt`}
.usedBy=${() => {
return new StagesApi(DEFAULT_CONFIG).stagesPromptPromptsUsedByList({
promptUuid: item.pk
});
}}
.delete=${() => {
return new StagesApi(DEFAULT_CONFIG).stagesPromptPromptsDestroy({
promptUuid: item.pk || ""
promptUuid: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">

View File

@ -47,6 +47,7 @@ export class TenantForm extends ModelForm<Tenant, string> {
?required=${true}
name="domain">
<input type="text" value="${first(this.instance?.domain, window.location.host)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Matching is done based on domain suffix, so if you enter domain.tld, foo.domain.tld will still match.`}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="default">
<div class="pf-c-check">

View File

@ -68,6 +68,11 @@ export class TenantListPage extends TablePage<Tenant> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Tenant`}
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreTenantsUsedByList({
tenantUuid: item.tenantUuid
});
}}
.delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreTenantsDestroy({
tenantUuid: item.tenantUuid

View File

@ -58,6 +58,11 @@ export class TokenListPage extends TablePage<Token> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`Token`}
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreTokensUsedByList({
identifier: item.identifier
});
}}
.delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreTokensDestroy({
identifier: item.identifier

View File

@ -31,7 +31,7 @@ export class UserSettingsAuthenticatorDuo extends BaseUserSettings {
});
});
}}>
${t`Disable Static Tokens`}
${t`Disable Duo authenticator`}
</button>
</div>`;
}
@ -47,7 +47,7 @@ export class UserSettingsAuthenticatorDuo extends BaseUserSettings {
<div class="pf-c-card__footer">
${this.configureUrl ?
html`<a href="${this.configureUrl}?next=/%23%2Fuser"
class="pf-c-button pf-m-primary">${t`Enable Static Tokens`}
class="pf-c-button pf-m-primary">${t`Enable Duo authenticator`}
</a>`: html``}
</div>`;
}

View File

@ -111,9 +111,14 @@ export class UserListPage extends TablePage<User> {
<ak-forms-delete
.obj=${item}
objectLabel=${t`User`}
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUsersUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUsersDestroy({
id: item.pk || 0
id: item.pk
});
}}>
<button slot="trigger" class="pf-c-dropdown__menu-item">