web: misc fixes for admin and flow inspector (#12461)
* fix flow inspector not closable on error Signed-off-by: Jens Langhammer <jens@goauthentik.io> # Conflicts: # authentik/enterprise/providers/ssf/views/configuration.py * unrelated: fix flow inspector for in memory stages Signed-off-by: Jens Langhammer <jens@goauthentik.io> * only open inspector when there's size Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix relative links Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -1,5 +1,7 @@
|
|||||||
"""Flow Stage API Views"""
|
"""Flow Stage API Views"""
|
||||||
|
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
from django.urls.base import reverse
|
from django.urls.base import reverse
|
||||||
from drf_spectacular.utils import extend_schema
|
from drf_spectacular.utils import extend_schema
|
||||||
from rest_framework import mixins
|
from rest_framework import mixins
|
||||||
@ -27,6 +29,11 @@ class StageSerializer(ModelSerializer, MetaNameSerializer):
|
|||||||
component = SerializerMethodField()
|
component = SerializerMethodField()
|
||||||
flow_set = FlowSetSerializer(many=True, required=False)
|
flow_set = FlowSetSerializer(many=True, required=False)
|
||||||
|
|
||||||
|
def to_representation(self, instance: Stage):
|
||||||
|
if isinstance(instance, Stage) and instance.is_in_memory:
|
||||||
|
instance.stage_uuid = uuid4()
|
||||||
|
return super().to_representation(instance)
|
||||||
|
|
||||||
def get_component(self, obj: Stage) -> str:
|
def get_component(self, obj: Stage) -> str:
|
||||||
"""Get object type so that we know how to edit the object"""
|
"""Get object type so that we know how to edit the object"""
|
||||||
if obj.__class__ == Stage:
|
if obj.__class__ == Stage:
|
||||||
|
@ -102,8 +102,12 @@ class Stage(SerializerModel):
|
|||||||
user settings are available, or a challenge."""
|
user settings are available, or a challenge."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_in_memory(self):
|
||||||
|
return hasattr(self, "__in_memory_type")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if hasattr(self, "__in_memory_type"):
|
if self.is_in_memory:
|
||||||
return f"In-memory Stage {getattr(self, '__in_memory_type')}"
|
return f"In-memory Stage {getattr(self, '__in_memory_type')}"
|
||||||
return f"Stage {self.name}"
|
return f"Stage {self.name}"
|
||||||
|
|
||||||
|
@ -142,7 +142,11 @@ export class NavigationButtons extends AKElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`<div class="pf-c-page__header-tools-item">
|
return html`<div class="pf-c-page__header-tools-item">
|
||||||
<a class="pf-c-button pf-m-plain" type="button" href="#/settings">
|
<a
|
||||||
|
class="pf-c-button pf-m-plain"
|
||||||
|
type="button"
|
||||||
|
href="${globalAK().api.base}if/user/#/settings"
|
||||||
|
>
|
||||||
<pf-tooltip position="top" content=${msg("Settings")}>
|
<pf-tooltip position="top" content=${msg("Settings")}>
|
||||||
<i class="fas fa-cog" aria-hidden="true"></i>
|
<i class="fas fa-cog" aria-hidden="true"></i>
|
||||||
</pf-tooltip>
|
</pf-tooltip>
|
||||||
|
@ -96,7 +96,7 @@ export class UserOAuthAccessTokenList extends Table<TokenModel> {
|
|||||||
<small>${item.expires.toLocaleString()}</small>`
|
<small>${item.expires.toLocaleString()}</small>`
|
||||||
: msg("-")}`,
|
: msg("-")}`,
|
||||||
html`<ak-chip-group>
|
html`<ak-chip-group>
|
||||||
${item.scope.map((scope) => {
|
${item.scope.sort().map((scope) => {
|
||||||
return html`<ak-chip .removable=${false}>${scope}</ak-chip>`;
|
return html`<ak-chip .removable=${false}>${scope}</ak-chip>`;
|
||||||
})}
|
})}
|
||||||
</ak-chip-group>`,
|
</ak-chip-group>`,
|
||||||
|
@ -97,7 +97,7 @@ export class UserOAuthRefreshTokenList extends Table<TokenModel> {
|
|||||||
<small>${item.expires.toLocaleString()}</small>`
|
<small>${item.expires.toLocaleString()}</small>`
|
||||||
: msg("-")}`,
|
: msg("-")}`,
|
||||||
html`<ak-chip-group>
|
html`<ak-chip-group>
|
||||||
${item.scope.map((scope) => {
|
${item.scope.sort().map((scope) => {
|
||||||
return html`<ak-chip .removable=${false}>${scope}</ak-chip>`;
|
return html`<ak-chip .removable=${false}>${scope}</ak-chip>`;
|
||||||
})}
|
})}
|
||||||
</ak-chip-group>`,
|
</ak-chip-group>`,
|
||||||
|
@ -231,7 +231,11 @@ export class FlowExecutor extends Interface implements StageHost {
|
|||||||
|
|
||||||
async firstUpdated(): Promise<void> {
|
async firstUpdated(): Promise<void> {
|
||||||
configureSentry();
|
configureSentry();
|
||||||
if (this.config?.capabilities.includes(CapabilitiesEnum.CanDebug)) {
|
if (
|
||||||
|
this.config?.capabilities.includes(CapabilitiesEnum.CanDebug) &&
|
||||||
|
// Only open inspector automatically in debug when we have enough space for it
|
||||||
|
window.innerWidth >= 768
|
||||||
|
) {
|
||||||
this.inspectorOpen = true;
|
this.inspectorOpen = true;
|
||||||
}
|
}
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
@ -87,16 +87,37 @@ export class FlowInspector extends AKElement {
|
|||||||
return stage;
|
return stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderHeader() {
|
||||||
|
return html` <div class="pf-c-notification-drawer__header">
|
||||||
|
<div class="text">
|
||||||
|
<h1 class="pf-c-notification-drawer__header-title">${msg("Flow inspector")}</h1>
|
||||||
|
</div>
|
||||||
|
<div class="pf-c-notification-drawer__header-action">
|
||||||
|
<div class="pf-c-notification-drawer__header-action-close">
|
||||||
|
<button
|
||||||
|
@click=${() => {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent(EVENT_FLOW_INSPECTOR_TOGGLE, {
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
class="pf-c-button pf-m-plain"
|
||||||
|
type="button"
|
||||||
|
aria-label=${msg("Close")}
|
||||||
|
>
|
||||||
|
<i class="fas fa-times" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
renderAccessDenied(): TemplateResult {
|
renderAccessDenied(): TemplateResult {
|
||||||
return html`<div class="pf-c-drawer__body pf-m-no-padding">
|
return html`<div class="pf-c-drawer__body pf-m-no-padding">
|
||||||
<div class="pf-c-notification-drawer">
|
<div class="pf-c-notification-drawer">
|
||||||
<div class="pf-c-notification-drawer__header">
|
${this.renderHeader()}
|
||||||
<div class="text">
|
|
||||||
<h1 class="pf-c-notification-drawer__header-title">
|
|
||||||
${msg("Flow inspector")}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="pf-c-notification-drawer__body">
|
<div class="pf-c-notification-drawer__body">
|
||||||
<div class="pf-l-stack pf-m-gutter">
|
<div class="pf-l-stack pf-m-gutter">
|
||||||
<div class="pf-l-stack__item">
|
<div class="pf-l-stack__item">
|
||||||
@ -116,36 +137,17 @@ export class FlowInspector extends AKElement {
|
|||||||
}
|
}
|
||||||
if (!this.state) {
|
if (!this.state) {
|
||||||
this.advanceHandler();
|
this.advanceHandler();
|
||||||
return html`<ak-empty-state loading> </ak-empty-state>`;
|
return html`<div class="pf-c-drawer__body pf-m-no-padding">
|
||||||
|
<div class="pf-c-notification-drawer">
|
||||||
|
${this.renderHeader()}
|
||||||
|
<div class="pf-c-notification-drawer__body"></div>
|
||||||
|
<ak-empty-state loading> </ak-empty-state>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
}
|
}
|
||||||
return html`<div class="pf-c-drawer__body pf-m-no-padding">
|
return html`<div class="pf-c-drawer__body pf-m-no-padding">
|
||||||
<div class="pf-c-notification-drawer">
|
<div class="pf-c-notification-drawer">
|
||||||
<div class="pf-c-notification-drawer__header">
|
${this.renderHeader()}
|
||||||
<div class="text">
|
|
||||||
<h1 class="pf-c-notification-drawer__header-title">
|
|
||||||
${msg("Flow inspector")}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div class="pf-c-notification-drawer__header-action">
|
|
||||||
<div class="pf-c-notification-drawer__header-action-close">
|
|
||||||
<button
|
|
||||||
@click=${() => {
|
|
||||||
this.dispatchEvent(
|
|
||||||
new CustomEvent(EVENT_FLOW_INSPECTOR_TOGGLE, {
|
|
||||||
bubbles: true,
|
|
||||||
composed: true,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
class="pf-c-button pf-m-plain"
|
|
||||||
type="button"
|
|
||||||
aria-label=${msg("Close")}
|
|
||||||
>
|
|
||||||
<i class="fas fa-times" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="pf-c-notification-drawer__body">
|
<div class="pf-c-notification-drawer__body">
|
||||||
<div class="pf-l-stack pf-m-gutter">
|
<div class="pf-l-stack pf-m-gutter">
|
||||||
<div class="pf-l-stack__item">
|
<div class="pf-l-stack__item">
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
EVENT_NOTIFICATION_DRAWER_TOGGLE,
|
EVENT_NOTIFICATION_DRAWER_TOGGLE,
|
||||||
EVENT_WS_MESSAGE,
|
EVENT_WS_MESSAGE,
|
||||||
} from "@goauthentik/common/constants";
|
} from "@goauthentik/common/constants";
|
||||||
|
import { globalAK } from "@goauthentik/common/global";
|
||||||
import { configureSentry } from "@goauthentik/common/sentry";
|
import { configureSentry } from "@goauthentik/common/sentry";
|
||||||
import { UIConfig } from "@goauthentik/common/ui/config";
|
import { UIConfig } from "@goauthentik/common/ui/config";
|
||||||
import { me } from "@goauthentik/common/users";
|
import { me } from "@goauthentik/common/users";
|
||||||
@ -165,7 +166,7 @@ class UserInterfacePresentation extends AKElement {
|
|||||||
|
|
||||||
return html`<a
|
return html`<a
|
||||||
class="pf-c-button pf-m-secondary pf-m-small pf-u-display-none pf-u-display-block-on-md"
|
class="pf-c-button pf-m-secondary pf-m-small pf-u-display-none pf-u-display-block-on-md"
|
||||||
href="/if/admin/"
|
href="${globalAK().api.base}if/admin/"
|
||||||
slot="extra"
|
slot="extra"
|
||||||
>
|
>
|
||||||
${msg("Admin interface")}
|
${msg("Admin interface")}
|
||||||
|
Reference in New Issue
Block a user