show device state in webui

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2024-01-03 13:19:36 +01:00
parent 90606fabf9
commit 7d9b66b6e6
No known key found for this signature in database
5 changed files with 116 additions and 3 deletions

View File

@ -5,7 +5,7 @@ from django_filters.rest_framework.backends import DjangoFilterBackend
from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer
from rest_framework import mixins from rest_framework import mixins
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import CharField, ChoiceField, JSONField, UUIDField from rest_framework.fields import CharField, ChoiceField, JSONField, UUIDField, DateTimeField
from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request from rest_framework.request import Request
@ -40,6 +40,7 @@ class MobileDeviceSerializer(DeviceSerializer):
"""Serializer for Mobile authenticator devices""" """Serializer for Mobile authenticator devices"""
state = MobileDeviceInfoSerializer(read_only=True) state = MobileDeviceInfoSerializer(read_only=True)
last_checkin = DateTimeField(read_only=True)
class Meta: class Meta:
model = MobileDevice model = MobileDevice

View File

@ -35322,8 +35322,13 @@ components:
allOf: allOf:
- $ref: '#/components/schemas/MobileDeviceInfo' - $ref: '#/components/schemas/MobileDeviceInfo'
readOnly: true readOnly: true
last_checkin:
type: string
format: date-time
readOnly: true
required: required:
- confirmed - confirmed
- last_checkin
- meta_model_name - meta_model_name
- name - name
- pk - pk

View File

@ -453,8 +453,13 @@ components:
allOf: allOf:
- $ref: '#/components/schemas/MobileDeviceInfo' - $ref: '#/components/schemas/MobileDeviceInfo'
readOnly: true readOnly: true
last_checkin:
type: string
format: date-time
readOnly: true
required: required:
- confirmed - confirmed
- last_checkin
- meta_model_name - meta_model_name
- name - name
- pk - pk

View File

@ -5,8 +5,11 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { until } from "lit/directives/until.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import { AuthenticatorsApi, Device } from "@goauthentik/api"; import { AuthenticatorsApi, Device } from "@goauthentik/api";
@ -16,6 +19,11 @@ export class UserDeviceTable extends Table<Device> {
userId?: number; userId?: number;
checkbox = true; checkbox = true;
expandable = true;
static get styles(): CSSResult[] {
return super.styles.concat(PFDescriptionList);
}
async apiEndpoint(): Promise<PaginatedResponse<Device>> { async apiEndpoint(): Promise<PaginatedResponse<Device>> {
return new AuthenticatorsApi(DEFAULT_CONFIG) return new AuthenticatorsApi(DEFAULT_CONFIG)
@ -95,6 +103,91 @@ export class UserDeviceTable extends Table<Device> {
>`; >`;
} }
renderExpanded(item: Device): TemplateResult {
return html`
<td role="cell" colspan="5">
<div class="pf-c-table__expandable-row-content">
<dl class="pf-c-description-list pf-m-horizontal">
${until(
new AuthenticatorsApi(DEFAULT_CONFIG)
.authenticatorsMobileRetrieve({
uuid: item.pk,
})
.then((device) => {
return html`
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("Last check-in")}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${device.lastCheckin.toLocaleString()}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("App version")}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${device.state.appVersion}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("Device model")}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${device.state.model}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("OS Version")}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${device.state.osVersion}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("Platform")}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${device.state.platform}
</div>
</dd>
</div>
`;
}),
)}
</dl>
</div>
</td>
`;
}
rowExpandable(item: Device): boolean {
return item.type.toLowerCase() === "authentik_stages_authenticator_mobile.mobiledevice";
}
row(item: Device): TemplateResult[] { row(item: Device): TemplateResult[] {
return [ return [
html`${item.name}`, html`${item.name}`,

View File

@ -149,6 +149,11 @@ export abstract class Table<T> extends AKElement implements TableLike {
@property({ type: Boolean }) @property({ type: Boolean })
expandable = false; expandable = false;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
rowExpandable(item: T): boolean {
return this.expandable;
}
@property({ attribute: false }) @property({ attribute: false })
expandedElements: T[] = []; expandedElements: T[] = [];
@ -375,7 +380,11 @@ export abstract class Table<T> extends AKElement implements TableLike {
: itemSelectHandler} : itemSelectHandler}
> >
${this.checkbox ? renderCheckbox() : html``} ${this.checkbox ? renderCheckbox() : html``}
${this.expandable ? renderExpansion() : html``} ${this.rowExpandable(item)
? renderExpansion()
: this.expandable
? html`<td></td>`
: html``}
${this.row(item).map((col) => { ${this.row(item).map((col) => {
return html`<td role="cell">${col}</td>`; return html`<td role="cell">${col}</td>`;
})} })}