admin: migrate certificate-keypair list to web
This commit is contained in:
parent
60c244c31d
commit
4cfcc48b23
|
@ -1,122 +0,0 @@
|
|||
{% extends "administration/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load authentik_utils %}
|
||||
|
||||
{% block content %}
|
||||
<section class="pf-c-page__main-section pf-m-light">
|
||||
<div class="pf-c-content">
|
||||
<h1>
|
||||
<i class="pf-icon pf-icon-key"></i>
|
||||
{% trans 'Certificate-Key Pairs' %}
|
||||
</h1>
|
||||
<p>{% trans "Import certificates of external providers or create certificates to sign requests with." %}</p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||
<div class="pf-c-card">
|
||||
{% if object_list %}
|
||||
<div class="pf-c-toolbar">
|
||||
<div class="pf-c-toolbar__content">
|
||||
{% include 'partials/toolbar_search.html' %}
|
||||
<div class="pf-c-toolbar__bulk-select">
|
||||
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-create' %}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-primary">
|
||||
{% trans 'Create' %}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-generate' %}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-primary">
|
||||
{% trans 'Generate' %}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
<button role="ak-refresh" class="pf-c-button pf-m-primary">
|
||||
{% trans 'Refresh' %}
|
||||
</button>
|
||||
</div>
|
||||
{% include 'partials/pagination.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
|
||||
<thead>
|
||||
<tr role="row">
|
||||
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
|
||||
<th role="columnheader" scope="col">{% trans 'Private Key available' %}</th>
|
||||
<th role="columnheader" scope="col">{% trans 'Fingerprint' %}</th>
|
||||
<th role="cell"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody role="rowgroup">
|
||||
{% for kp in object_list %}
|
||||
<tr role="row">
|
||||
<th role="columnheader">
|
||||
<div>
|
||||
<div>{{ kp.name }}</div>
|
||||
</div>
|
||||
</th>
|
||||
<td role="cell">
|
||||
<span>
|
||||
{% if kp.key_data is not None %}
|
||||
{% trans 'Yes' %}
|
||||
{% else %}
|
||||
{% trans 'No' %}
|
||||
{% endif %}
|
||||
</span>
|
||||
</td>
|
||||
<td role="cell">
|
||||
<code>{{ kp.fingerprint }}</code>
|
||||
</td>
|
||||
<td>
|
||||
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-update' pk=kp.pk %}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
{% trans 'Edit' %}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-delete' pk=kp.pk %}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-danger">
|
||||
{% trans 'Delete' %}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pf-c-pagination pf-m-bottom">
|
||||
{% include 'partials/pagination.html' %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="pf-c-toolbar">
|
||||
<div class="pf-c-toolbar__content">
|
||||
{% include 'partials/toolbar_search.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-empty-state">
|
||||
<div class="pf-c-empty-state__content">
|
||||
<i class="pf-icon pf-icon-key pf-c-empty-state__icon" aria-hidden="true"></i>
|
||||
<h1 class="pf-c-title pf-m-lg">
|
||||
{% trans 'No Certificates.' %}
|
||||
</h1>
|
||||
<div class="pf-c-empty-state__body">
|
||||
{% if request.GET.search != "" %}
|
||||
{% trans "Your search query doesn't match any certificates." %}
|
||||
{% else %}
|
||||
{% trans 'Currently no certificates exist. Click the button below to create one.' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-create' %}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-primary">
|
||||
{% trans 'Create' %}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -1,28 +0,0 @@
|
|||
{% extends 'generic/form.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block above_form %}
|
||||
<h1>{% blocktrans with property_mapping=property_mapping %}Test {{ property_mapping }}{% endblocktrans %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block beneath_form %}
|
||||
{% if result %}
|
||||
<div class="pf-c-form__group ">
|
||||
<div class="pf-c-form__group-label">
|
||||
<label class="pf-c-form__label" for="context-1">
|
||||
<span class="pf-c-form__label-text">{% trans 'Result' %}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="pf-c-form__group-control">
|
||||
<div class="c-form__horizontal-group">
|
||||
<ak-codemirror mode="javascript"><textarea class="pf-c-form-control">{{ result }}</textarea></ak-codemirror>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block action %}
|
||||
{% trans 'Test' %}
|
||||
{% endblock %}
|
|
@ -1,148 +0,0 @@
|
|||
{% extends "administration/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load authentik_utils %}
|
||||
|
||||
{% block content %}
|
||||
<section class="pf-c-page__main-section pf-m-light">
|
||||
<div class="pf-c-content">
|
||||
<h1>
|
||||
<i class="pf-icon pf-icon-middleware"></i>
|
||||
{% trans 'Source' %}
|
||||
</h1>
|
||||
<p>{% trans "External Sources which can be used to get Identities into authentik, for example Social Providers like Twiter and GitHub or Enterprise Providers like ADFS and LDAP." %}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||
<div class="pf-c-card">
|
||||
{% if object_list %}
|
||||
<div class="pf-c-toolbar">
|
||||
<div class="pf-c-toolbar__content">
|
||||
{% include 'partials/toolbar_search.html' %}
|
||||
<div class="pf-c-toolbar__bulk-select">
|
||||
<ak-dropdown class="pf-c-dropdown">
|
||||
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
|
||||
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
|
||||
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
|
||||
</button>
|
||||
<ul class="pf-c-dropdown__menu" hidden>
|
||||
{% for type, name in types.items %}
|
||||
<li>
|
||||
<ak-modal-button href="{% url 'authentik_admin:source-create' %}?type={{ type }}">
|
||||
<button slot="trigger" class="pf-c-dropdown__menu-item">
|
||||
{{ name|verbose_name }}<br>
|
||||
<small>
|
||||
{{ name|doc }}
|
||||
</small>
|
||||
</button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</ak-dropdown>
|
||||
<button role="ak-refresh" class="pf-c-button pf-m-primary">
|
||||
{% trans 'Refresh' %}
|
||||
</button>
|
||||
</div>
|
||||
{% include 'partials/pagination.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
|
||||
<thead>
|
||||
<tr role="row">
|
||||
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
|
||||
<th role="columnheader" scope="col">{% trans 'Type' %}</th>
|
||||
<th role="columnheader" scope="col">{% trans 'Additional Info' %}</th>
|
||||
<th role="cell"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody role="rowgroup">
|
||||
{% for source in object_list %}
|
||||
<tr role="row">
|
||||
<th role="columnheader">
|
||||
<a href="/sources/{{ source.slug }}">
|
||||
<div>{{ source.name }}</div>
|
||||
{% if not source.enabled %}
|
||||
<small>{% trans 'Disabled' %}</small>
|
||||
{% endif %}
|
||||
</a>
|
||||
</th>
|
||||
<td role="cell">
|
||||
<span>
|
||||
{{ source|fieldtype }}
|
||||
</span>
|
||||
</td>
|
||||
<td role="cell">
|
||||
<span>
|
||||
{{ source.ui_additional_info|default:""|safe }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<ak-modal-button href="{% url 'authentik_admin:source-update' pk=source.pk %}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
{% trans 'Edit' %}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
<ak-modal-button href="{% url 'authentik_admin:source-delete' pk=source.pk %}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-danger">
|
||||
{% trans 'Delete' %}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pf-c-pagination pf-m-bottom">
|
||||
{% include 'partials/pagination.html' %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="pf-c-toolbar">
|
||||
<div class="pf-c-toolbar__content">
|
||||
{% include 'partials/toolbar_search.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-empty-state">
|
||||
<div class="pf-c-empty-state__content">
|
||||
<i class="pf-icon pf-icon-middleware pf-c-empty-state__icon" aria-hidden="true"></i>
|
||||
<h1 class="pf-c-title pf-m-lg">
|
||||
{% trans 'No Sources.' %}
|
||||
</h1>
|
||||
<div class="pf-c-empty-state__body">
|
||||
{% if request.GET.search != "" %}
|
||||
{% trans "Your search query doesn't match any sources." %}
|
||||
{% else %}
|
||||
{% trans 'Currently no sources exist. Click the button below to create one.' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<ak-dropdown class="pf-c-dropdown">
|
||||
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
|
||||
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
|
||||
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
|
||||
</button>
|
||||
<ul class="pf-c-dropdown__menu" hidden>
|
||||
{% for type, name in types.items %}
|
||||
<li>
|
||||
<ak-modal-button href="{% url 'authentik_admin:source-create' %}?type={{ type }}">
|
||||
<button slot="trigger" class="pf-c-dropdown__menu-item">
|
||||
{{ name|verbose_name }}<br>
|
||||
<small>
|
||||
{{ name|doc }}
|
||||
</small>
|
||||
</button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</ak-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -283,11 +283,6 @@ urlpatterns = [
|
|||
name="group-delete",
|
||||
),
|
||||
# Certificate-Key Pairs
|
||||
path(
|
||||
"crypto/certificates/",
|
||||
certificate_key_pair.CertificateKeyPairListView.as_view(),
|
||||
name="certificate_key_pair",
|
||||
),
|
||||
path(
|
||||
"crypto/certificates/create/",
|
||||
certificate_key_pair.CertificateKeyPairCreateView.as_view(),
|
||||
|
|
|
@ -5,18 +5,12 @@ from django.contrib.auth.mixins import (
|
|||
)
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.http.response import HttpResponse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import ListView, UpdateView
|
||||
from django.views.generic import UpdateView
|
||||
from django.views.generic.edit import FormView
|
||||
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
|
||||
from guardian.mixins import PermissionRequiredMixin
|
||||
|
||||
from authentik.admin.views.utils import (
|
||||
BackSuccessUrlMixin,
|
||||
DeleteMessageView,
|
||||
SearchListMixin,
|
||||
UserPaginateListMixin,
|
||||
)
|
||||
from authentik.admin.views.utils import BackSuccessUrlMixin, DeleteMessageView
|
||||
from authentik.crypto.builder import CertificateBuilder
|
||||
from authentik.crypto.forms import (
|
||||
CertificateKeyPairForm,
|
||||
|
@ -26,23 +20,6 @@ from authentik.crypto.models import CertificateKeyPair
|
|||
from authentik.lib.views import CreateAssignPermView
|
||||
|
||||
|
||||
class CertificateKeyPairListView(
|
||||
LoginRequiredMixin,
|
||||
PermissionListMixin,
|
||||
UserPaginateListMixin,
|
||||
SearchListMixin,
|
||||
ListView,
|
||||
):
|
||||
"""Show list of all keypairs"""
|
||||
|
||||
model = CertificateKeyPair
|
||||
permission_required = "authentik_crypto.view_certificatekeypair"
|
||||
ordering = "name"
|
||||
template_name = "administration/certificatekeypair/list.html"
|
||||
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
class CertificateKeyPairCreateView(
|
||||
SuccessMessageMixin,
|
||||
BackSuccessUrlMixin,
|
||||
|
@ -57,7 +34,7 @@ class CertificateKeyPairCreateView(
|
|||
permission_required = "authentik_crypto.add_certificatekeypair"
|
||||
|
||||
template_name = "generic/create.html"
|
||||
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
|
||||
success_url = "/"
|
||||
success_message = _("Successfully created Certificate-Key Pair")
|
||||
|
||||
|
||||
|
@ -75,7 +52,7 @@ class CertificateKeyPairGenerateView(
|
|||
permission_required = "authentik_crypto.add_certificatekeypair"
|
||||
|
||||
template_name = "administration/certificatekeypair/generate.html"
|
||||
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
|
||||
success_url = "/"
|
||||
success_message = _("Successfully generated Certificate-Key Pair")
|
||||
|
||||
def form_valid(self, form: CertificateKeyPairGenerateForm) -> HttpResponse:
|
||||
|
@ -103,7 +80,7 @@ class CertificateKeyPairUpdateView(
|
|||
permission_required = "authentik_crypto.change_certificatekeypair"
|
||||
|
||||
template_name = "generic/update.html"
|
||||
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
|
||||
success_url = "/"
|
||||
success_message = _("Successfully updated Certificate-Key Pair")
|
||||
|
||||
|
||||
|
@ -116,5 +93,5 @@ class CertificateKeyPairDeleteView(
|
|||
permission_required = "authentik_crypto.delete_certificatekeypair"
|
||||
|
||||
template_name = "generic/delete.html"
|
||||
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
|
||||
success_url = "/"
|
||||
success_message = _("Successfully deleted Certificate-Key Pair")
|
||||
|
|
|
@ -20,11 +20,16 @@ class CertificateKeyPairSerializer(ModelSerializer):
|
|||
|
||||
cert_expiry = DateTimeField(source="certificate.not_valid_after", read_only=True)
|
||||
cert_subject = SerializerMethodField()
|
||||
private_key_available = SerializerMethodField()
|
||||
|
||||
def get_cert_subject(self, instance: CertificateKeyPair) -> str:
|
||||
"""Get certificate subject as full rfc4514"""
|
||||
return instance.certificate.subject.rfc4514_string()
|
||||
|
||||
def get_private_key_available(self, instance: CertificateKeyPair) -> bool:
|
||||
"""Show if this keypair has a private key configured or not"""
|
||||
return instance.key_data != "" and instance.key_data is not None
|
||||
|
||||
def validate_certificate_data(self, value):
|
||||
"""Verify that input is a valid PEM x509 Certificate"""
|
||||
try:
|
||||
|
@ -58,6 +63,7 @@ class CertificateKeyPairSerializer(ModelSerializer):
|
|||
"key_data",
|
||||
"cert_expiry",
|
||||
"cert_subject",
|
||||
"private_key_available",
|
||||
]
|
||||
extra_kwargs = {
|
||||
"key_data": {"write_only": True},
|
||||
|
|
|
@ -7913,6 +7913,10 @@ definitions:
|
|||
title: Cert subject
|
||||
type: string
|
||||
readOnly: true
|
||||
private_key_available:
|
||||
title: Private key available
|
||||
type: boolean
|
||||
readOnly: true
|
||||
CertificateData:
|
||||
description: Get CertificateKeyPair's data
|
||||
type: object
|
||||
|
|
26
web/src/api/CertificateKeyPair.ts
Normal file
26
web/src/api/CertificateKeyPair.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
||||
|
||||
export class CertificateKeyPair {
|
||||
pk: string;
|
||||
name: string;
|
||||
fingerprint: string;
|
||||
cert_expiry: number;
|
||||
cert_subject: string;
|
||||
private_key_available: boolean;
|
||||
|
||||
constructor() {
|
||||
throw Error();
|
||||
}
|
||||
|
||||
static get(slug: string): Promise<CertificateKeyPair> {
|
||||
return DefaultClient.fetch<CertificateKeyPair>(["crypto", "certificatekeypairs", slug]);
|
||||
}
|
||||
|
||||
static list(filter?: QueryArguments): Promise<AKResponse<CertificateKeyPair>> {
|
||||
return DefaultClient.fetch<AKResponse<CertificateKeyPair>>(["crypto", "certificatekeypairs"], filter);
|
||||
}
|
||||
|
||||
static adminUrl(rest: string): string {
|
||||
return `/administration/crypto/certificates/${rest}`;
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
|
|||
new SidebarItem("Identity & Cryptography").children(
|
||||
new SidebarItem("User", "/administration/users/"),
|
||||
new SidebarItem("Groups", "/administration/groups/"),
|
||||
new SidebarItem("Certificates", "/administration/crypto/certificates"),
|
||||
new SidebarItem("Certificates", "/crypto/certificates"),
|
||||
new SidebarItem("Tokens", "/administration/tokens/"),
|
||||
).when((): Promise<boolean> => {
|
||||
return User.me().then(u => u.is_superuser);
|
||||
|
|
115
web/src/pages/crypto/CertificateKeyPairListPage.ts
Normal file
115
web/src/pages/crypto/CertificateKeyPairListPage.ts
Normal file
|
@ -0,0 +1,115 @@
|
|||
import { gettext } from "django";
|
||||
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 { TableColumn } from "../../elements/table/Table";
|
||||
import { CertificateKeyPair } from "../../api/CertificateKeyPair";
|
||||
|
||||
@customElement("ak-crypto-certificatekeypair-list")
|
||||
export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
|
||||
expandable = true;
|
||||
|
||||
searchEnabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
pageTitle(): string {
|
||||
return gettext("Certificate-Key Pairs");
|
||||
}
|
||||
pageDescription(): string {
|
||||
return gettext("Import certificates of external providers or create certificates to sign requests with.");
|
||||
}
|
||||
pageIcon(): string {
|
||||
return gettext("pf-icon pf-icon-key");
|
||||
}
|
||||
|
||||
@property()
|
||||
order = "name";
|
||||
|
||||
apiEndpoint(page: number): Promise<AKResponse<CertificateKeyPair>> {
|
||||
return CertificateKeyPair.list({
|
||||
ordering: this.order,
|
||||
page: page,
|
||||
search: this.search || "",
|
||||
});
|
||||
}
|
||||
|
||||
columns(): TableColumn[] {
|
||||
return [
|
||||
new TableColumn("Name", "name"),
|
||||
new TableColumn("Private key available?"),
|
||||
new TableColumn("Expiry date"),
|
||||
new TableColumn(""),
|
||||
];
|
||||
}
|
||||
|
||||
row(item: CertificateKeyPair): TemplateResult[] {
|
||||
return [
|
||||
html`${item.name}`,
|
||||
html`${gettext(item.private_key_available ? "Yes" : "No")}`,
|
||||
html`${new Date(item.cert_expiry * 1000).toLocaleString()}`,
|
||||
html`
|
||||
<ak-modal-button href="${CertificateKeyPair.adminUrl(`${item.pk}/update/`)}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
${gettext("Edit")}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
<ak-modal-button href="${CertificateKeyPair.adminUrl(`${item.pk}/delete/`)}">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-danger">
|
||||
${gettext("Delete")}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
renderExpanded(item: CertificateKeyPair): TemplateResult {
|
||||
return html`
|
||||
<td role="cell" colspan="3">
|
||||
<div class="pf-c-table__expandable-row-content">
|
||||
<dl class="pf-c-description-list pf-m-horizontal">
|
||||
<div class="pf-c-description-list__group">
|
||||
<dt class="pf-c-description-list__term">
|
||||
<span class="pf-c-description-list__text">${gettext("Certificate Fingerprint")}</span>
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">${item.fingerprint}</div>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="pf-c-description-list__group">
|
||||
<dt class="pf-c-description-list__term">
|
||||
<span class="pf-c-description-list__text">${gettext("Certificate Subjet")}</span>
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">${item.cert_subject}</div>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>`;
|
||||
}
|
||||
|
||||
renderToolbar(): TemplateResult {
|
||||
return html`
|
||||
<ak-modal-button href=${CertificateKeyPair.adminUrl("create/")}>
|
||||
<ak-spinner-button slot="trigger" class="pf-m-primary">
|
||||
${gettext("Create")}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
<ak-modal-button href=${CertificateKeyPair.adminUrl("generate/")}>
|
||||
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
${gettext("Generate")}
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</ak-modal-button>
|
||||
${super.renderToolbar()}
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ export class FlowDiagram extends LitElement {
|
|||
constructor() {
|
||||
super();
|
||||
this.addEventListener("ak-refresh", () => {
|
||||
if (!this._flowSlug) return
|
||||
if (!this._flowSlug) return;
|
||||
this.flowSlug = this._flowSlug;
|
||||
});
|
||||
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", (ev) => {
|
||||
|
|
|
@ -17,6 +17,7 @@ import "./pages/providers/ProviderListPage";
|
|||
import "./pages/providers/ProviderViewPage";
|
||||
import "./pages/property-mappings/PropertyMappingListPage";
|
||||
import "./pages/outposts/OutpostListPage";
|
||||
import "./pages/crypto/CertificateKeyPairListPage";
|
||||
|
||||
export const ROUTES: Route[] = [
|
||||
// Prevent infinite Shell loops
|
||||
|
@ -36,7 +37,7 @@ export const ROUTES: Route[] = [
|
|||
new Route(new RegExp(`^/sources/(?<slug>${SLUG_REGEX})$`)).then((args) => {
|
||||
return html`<ak-source-view .args=${args}></ak-source-view>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/flows$`), html`<ak-flow-list></ak-flow-list>`),
|
||||
new Route(new RegExp("^/flows$"), html`<ak-flow-list></ak-flow-list>`),
|
||||
new Route(new RegExp(`^/flows/(?<slug>${SLUG_REGEX})$`)).then((args) => {
|
||||
return html`<ak-flow-view .flowSlug=${args.slug}></ak-flow-view>`;
|
||||
}),
|
||||
|
@ -48,4 +49,5 @@ export const ROUTES: Route[] = [
|
|||
new Route(new RegExp("^/events/rules$"), html`<ak-event-rule-list></ak-event-rule-list>`),
|
||||
new Route(new RegExp("^/property-mappings$"), html`<ak-property-mapping-list></ak-property-mapping-list>`),
|
||||
new Route(new RegExp("^/outposts$"), html`<ak-outpost-list></ak-outpost-list>`),
|
||||
new Route(new RegExp("^/crypto/certificates$"), html`<ak-crypto-certificatekeypair-list></ak-crypto-certificatekeypair-list>`),
|
||||
];
|
||||
|
|
Reference in a new issue