move to another tab, update status card

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Marc 'risson' Schmitt
2026-06-16 18:32:26 +02:00
parent da2621b0c7
commit 28a3a288c8
7 changed files with 119 additions and 69 deletions
-1
View File
@@ -85,7 +85,6 @@ def excluded_models() -> list[type[Model]]:
# Classes that have other dependencies
Session,
AuthenticatedSession,
LDAPSourceSync,
)
+8 -1
View File
@@ -27,6 +27,7 @@ class LDAPSourceSerializer(SourceSerializer):
"""LDAP Source Serializer"""
connectivity = SerializerMethodField()
last_sync = SerializerMethodField()
client_certificate = PrimaryKeyRelatedField(
allow_null=True,
help_text="Client certificate to authenticate against the LDAP Server's Certificate.",
@@ -40,6 +41,11 @@ class LDAPSourceSerializer(SourceSerializer):
"""Get cached source connectivity"""
return cache.get(CACHE_KEY_STATUS + source.slug, None)
def get_last_sync(self, source: LDAPSource) -> LDAPSourceSyncSerializer | None:
if last_sync := source.ldapsourcesync_set.order_by("-started_at").first():
return LDAPSourceSyncSerializer(last_sync).data
return None
def validate_sync_users_password(self, sync_users_password: bool) -> bool:
"""Check that only a single source has password_sync on"""
if sync_users_password:
@@ -99,6 +105,7 @@ class LDAPSourceSerializer(SourceSerializer):
"lookup_groups_from_user",
"delete_not_found_objects",
"sync_outgoing_trigger_mode",
"last_sync",
]
extra_kwargs = {"bind_password": {"write_only": True}}
@@ -119,7 +126,7 @@ class LDAPSourceSyncSerializer(SyncSerializer):
class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
"""LDAP Source Viewset"""
queryset = LDAPSource.objects.all()
queryset = LDAPSource.objects.prefetch_related("ldapsourcesync_set").all()
serializer_class = LDAPSourceSerializer
lookup_field = "slug"
filterset_fields = [
+9
View File
@@ -288,6 +288,12 @@ export interface LDAPSource {
* @memberof LDAPSource
*/
syncOutgoingTriggerMode?: SyncOutgoingTriggerModeEnum;
/**
*
* @type {string}
* @memberof LDAPSource
*/
readonly lastSync: string;
}
/**
@@ -307,6 +313,7 @@ export function instanceOfLDAPSource(value: object): value is LDAPSource {
if (!("serverUri" in value) || value["serverUri"] === undefined) return false;
if (!("baseDn" in value) || value["baseDn"] === undefined) return false;
if (!("connectivity" in value) || value["connectivity"] === undefined) return false;
if (!("lastSync" in value) || value["lastSync"] === undefined) return false;
return true;
}
@@ -391,6 +398,7 @@ export function LDAPSourceFromJSONTyped(json: any, ignoreDiscriminator: boolean)
json["sync_outgoing_trigger_mode"] == null
? undefined
: SyncOutgoingTriggerModeEnumFromJSON(json["sync_outgoing_trigger_mode"]),
lastSync: json["last_sync"],
};
}
@@ -410,6 +418,7 @@ export function LDAPSourceToJSONTyped(
| "icon_url"
| "icon_themed_urls"
| "connectivity"
| "last_sync"
> | null,
ignoreDiscriminator: boolean = false,
): any {
+4
View File
@@ -42334,12 +42334,16 @@ components:
allOf:
- $ref: '#/components/schemas/SyncOutgoingTriggerModeEnum'
description: When to trigger sync for outgoing providers
last_sync:
type: string
readOnly: true
required:
- base_dn
- component
- connectivity
- icon_themed_urls
- icon_url
- last_sync
- managed
- meta_model_name
- name
@@ -1,55 +0,0 @@
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import { AKElement } from "#elements/Base";
import { SlottedTemplateResult } from "#elements/types";
import { msg } from "@lit/localize";
import { CSSResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFList from "@patternfly/patternfly/components/List/list.css";
@customElement("ak-source-ldap-connectivity")
export class LDAPSourceConnectivity extends AKElement {
@property()
connectivity: {
[key: string]: {
[key: string]: string;
};
} | null = null;
static styles: CSSResult[] = [PFList];
render(): SlottedTemplateResult {
if (!this.connectivity) {
return html`${msg("No connectivity status available.")}`;
}
return html`<ul class="pf-c-list">
${Object.keys(this.connectivity).map((serverKey) => {
let serverLabel = html`${serverKey}`;
if (serverKey === "__all__") {
serverLabel = html`<b>${msg("Global status")}</b>`;
}
const server = this.connectivity![serverKey];
const content = html`${serverLabel}: ${server.status}`;
let tooltip = html`${content}`;
if (server.status === "ok") {
tooltip = html`<pf-tooltip position="top">
<ul slot="content" class="pf-c-list">
<li>${msg("Vendor")}: ${server.vendor}</li>
<li>${msg("Version")}: ${server.version}</li>
</ul>
${content}
</pf-tooltip>`;
}
return html`<li>${tooltip}</li>`;
})}
</ul>`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-source-ldap-connectivity": LDAPSourceConnectivity;
}
}
@@ -0,0 +1,81 @@
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import "#elements/tasks/TaskStatus";
import { AKElement } from "#elements/Base";
import { SlottedTemplateResult } from "#elements/types";
import renderDescriptionList from "#components/DescriptionList";
import { LDAPSourceSync } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import PFList from "@patternfly/patternfly/components/List/list.css";
@customElement("ak-source-ldap-status")
export class LDAPSourceStatus extends AKElement {
@property()
connectivity: {
[key: string]: {
[key: string]: string;
};
} | null = null;
@property()
lastSync?: LDAPSourceSync;
static styles: CSSResult[] = [PFDescriptionList, PFList];
render(): SlottedTemplateResult {
return html`
${renderDescriptionList([
[
msg("Connection"),
this.connectivity
? html`
<ul class="pf-c-list">
${Object.keys(this.connectivity).map((serverKey) => {
let serverLabel = html`${serverKey}`;
if (serverKey === "__all__") {
serverLabel = html`<b>${msg("Global status")}</b>`;
}
const server = this.connectivity![serverKey];
const content = html`${serverLabel}: ${server.status}`;
let tooltip = html`${content}`;
if (server.status === "ok") {
tooltip = html`<pf-tooltip position="top">
<ul slot="content" class="pf-c-list">
<li>${msg("Vendor")}: ${server.vendor}</li>
<li>${msg("Version")}: ${server.version}</li>
</ul>
${content}
</pf-tooltip>`;
}
return html`<li>${tooltip}</li>`;
})}
</ul>
`
: html`${msg("No connectivity status available.")}`,
],
[
msg("Last synchronisation"),
this.lastSync !== undefined
? html`
<ak-task-status .status=${this.lastSync.status}></ak-task-status>
${this.lastSync.finishedAt}
`
: html`${msg("Synchronisation never ran.")}`,
],
])}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-source-ldap-status": LDAPSourceStatus;
}
}
@@ -1,5 +1,5 @@
import "#admin/rbac/ak-rbac-object-permission-page";
import "#admin/sources/ldap/LDAPSourceConnectivity";
import "#admin/sources/ldap/LDAPSourceStatus";
import "#admin/sources/ldap/LDAPSourceUserList";
import "#admin/sources/ldap/LDAPSourceSyncList";
import "#admin/sources/ldap/LDAPSourceGroupList";
@@ -124,12 +124,13 @@ export class LDAPSourceViewPage extends AKElement {
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl"
>
<div class="pf-c-card__title">
<p>${msg("Connectivity")}</p>
<p>${msg("Status")}</p>
</div>
<div class="pf-c-card__body">
<ak-source-ldap-connectivity
<ak-source-ldap-status
.connectivity=${this.source?.connectivity}
></ak-source-ldap-connectivity>
.lastSync=${this.source?.lastSync}
></ak-source-ldap-status>
</div>
</div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
@@ -142,16 +143,20 @@ export class LDAPSourceViewPage extends AKElement {
.relObjId="${this.source?.pk}"
></ak-schedule-list>
</div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__title">
<p>${msg("Previous synchronisations")}</p>
</div>
<ak-source-ldap-sync-list
.source=${this.source}
></ak-source-ldap-sync-list>
</div>
</div>
</div>
<section
role="tabpanel"
tabindex="0"
slot="page-syncs"
id="page-syncs"
aria-label="${msg("Previous synchronisations")}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-l-grid pf-m-gutter">
<ak-source-ldap-sync-list .source=${this.source}></ak-source-ldap-sync-list>
</div>
</section>
<section
role="tabpanel"
tabindex="0"