Update views
This commit is contained in:
@ -0,0 +1,23 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{% block title %}Sshecret Admin{% endblock %}</title>
|
||||
|
||||
{% block head %}
|
||||
{% include 'base/partials/stylesheets.html.j2' %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body class="bg-gray-50 text-gray-900 min-h-screen flex flex-col">
|
||||
<main id="content" class="flex-1 overflow-y-auto" hx-target="this" hx-swap="innerHTML">
|
||||
<div class="" id="maincontent">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
{% block scripts %}
|
||||
{% include 'base/partials/scripts.html.j2' %}
|
||||
{% endblock %}
|
||||
{% block local_scripts %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@ -2,7 +2,9 @@
|
||||
{% block title %}Client {{ client.name }}{% endblock %}
|
||||
|
||||
{% block master %}
|
||||
{% include '/clients/partials/tree.html.j2' %}
|
||||
<div id="client-tree">
|
||||
{% include '/clients/partials/tree.html.j2' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
{% block title %}Clients{% endblock %}
|
||||
|
||||
{% block master %}
|
||||
{% include '/clients/partials/tree.html.j2' %}
|
||||
<div id="client-tree">
|
||||
{% include '/clients/partials/tree.html.j2' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@ -85,94 +85,9 @@
|
||||
</div>
|
||||
</sl-tab-panel>
|
||||
<sl-tab-panel name="events">
|
||||
|
||||
<table class="min-w-full lg:table-fixed divide-y divide-gray-200 dark:divide-gray-600" id="last-audit-events">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Timestamp</th>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Subsystem</th>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Message</th>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Origin</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white dark:bg-gray-800">
|
||||
{% for entry in events.results | list %}
|
||||
<tr class="{{ loop.cycle('', 'bg-gray-50 dark:bg-gray-700 ') }}hover:bg-gray-100 dark:hover:bg-gray-700" id="login-entry-{{ entry.id }}">
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
<p>{{ entry.timestamp }}<button data-popover-target="popover-audit-entry-{{ entry.id }}" data-popover-placement="bottom-end" type="button"><svg class="w-4 h-4 ms-2 text-gray-400 hover:text-gray-500" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"></path>
|
||||
</svg><span class="sr-only">Show information</span></button></p>
|
||||
|
||||
<div data-popover id="popover-audit-entry-{{entry.id}}" role="tooltip" class="absolute z-10 invisible inline-block text-sm text-gray-500 transition-opacity duration-300 bg-white border border-gray-200 rounded-lg shadow-xs opacity-0 w-80 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400">
|
||||
<dl class="max-w-md text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 px-2 py-2">
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">ID</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.id }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Subsystem</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.subsystem }}</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Timestamp</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.timestamp }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Operation</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.operation }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Client ID</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.client_id }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Client Name</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.client_name }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Secret ID</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.secret_id }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Secret Name</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.secret_name }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Message</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.message }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Origin</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.origin }}</dd>
|
||||
</div>
|
||||
{% if entry.data %}
|
||||
{% for key, value in entry.data.items() %}
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">{{ key | capitalize }}</dt>
|
||||
<dd class="text-xs font-semibold">{{ value }}</dd>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{{ entry.subsystem }}
|
||||
</td>
|
||||
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{{ entry.message }}
|
||||
</td>
|
||||
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{{ entry.origin }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="client-audit-events">
|
||||
{% include '/clients/partials/client_events.html.j2' %}
|
||||
</div>
|
||||
</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,157 @@
|
||||
<table class="min-w-full lg:table-fixed divide-y divide-gray-200 dark:divide-gray-600" id="last-audit-events">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Timestamp</th>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Subsystem</th>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Message</th>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Origin</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white dark:bg-gray-800" id="last-audit-events-body">
|
||||
|
||||
{% for entry in events.results | list %}
|
||||
<tr class="{{ loop.cycle('', 'bg-gray-50 dark:bg-gray-700 ') }}hover:bg-gray-100 dark:hover:bg-gray-700" id="login-entry-{{ entry.id }}">
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
<p>{{ entry.timestamp }}<button data-popover-target="popover-audit-entry-{{ entry.id }}" data-popover-placement="bottom-end" type="button"><svg class="w-4 h-4 ms-2 text-gray-400 hover:text-gray-500" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"></path>
|
||||
</svg><span class="sr-only">Show information</span></button></p>
|
||||
|
||||
<div data-popover id="popover-audit-entry-{{entry.id}}" role="tooltip" class="absolute z-10 invisible inline-block text-sm text-gray-500 transition-opacity duration-300 bg-white border border-gray-200 rounded-lg shadow-xs opacity-0 w-80 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400">
|
||||
<dl class="max-w-md text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 px-2 py-2">
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">ID</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.id }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Subsystem</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.subsystem }}</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Timestamp</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.timestamp }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Operation</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.operation }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Client ID</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.client_id }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Client Name</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.client_name }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Secret ID</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.secret_id }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Secret Name</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.secret_name }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Message</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.message }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">Origin</dt>
|
||||
<dd class="text-xs font-semibold">{{ entry.origin }}</dd>
|
||||
</div>
|
||||
{% if entry.data %}
|
||||
{% for key, value in entry.data.items() %}
|
||||
<div class="flex flex-col pb-3">
|
||||
<dt class="mb-1 text-gray-500 md:text-xs dark:text-gray-400">{{ key | capitalize }}</dt>
|
||||
<dd class="text-xs font-semibold">{{ value }}</dd>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{{ entry.subsystem }}
|
||||
</td>
|
||||
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{{ entry.message }}
|
||||
</td>
|
||||
|
||||
<td class="p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
{{ entry.origin }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<div
|
||||
class="sticky bottom-0 right-0 items-center w-full p-4 bg-white border-t border-gray-200 sm:flex sm:justify-between dark:bg-gray-800 dark:border-gray-700"
|
||||
>
|
||||
<div class="flex items-center mb-4 sm:mb-0">
|
||||
|
||||
<span class="text-sm font-normal text-gray-500 dark:text-gray-400"
|
||||
>Showing
|
||||
{% if events_paging.total < events_paging.last %}
|
||||
<span class="font-semibold text-gray-900 dark:text-white">{{events_paging.first }}-{{ events_paging.total}}</span> of
|
||||
{% else %}
|
||||
<span class="font-semibold text-gray-900 dark:text-white">{{events_paging.first }}-{{ events_paging.last}}</span> of
|
||||
{% endif %}
|
||||
<span class="font-semibold text-gray-900 dark:text-white"
|
||||
>{{ events_paging.total }}</span
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex space-x-1">
|
||||
|
||||
<button
|
||||
{% if events_paging.page == 1 %}
|
||||
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-gray-900 bg-white border border-gray-300 rounded hover:bg-gray-100 focus:ring-4 focus:ring-primary-300 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 transition duration-200 ease"
|
||||
disabled=""
|
||||
{% else %}
|
||||
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 transition duration-200 ease"
|
||||
hx-get="/clients/client/{{ client.id }}/events/{{ events_paging.page - 1 }}"
|
||||
hx-target="#client-audit-events"
|
||||
{% endif %}
|
||||
>
|
||||
Prev
|
||||
</button>
|
||||
{% for n in range(events_paging.total_pages) %}
|
||||
{% set p = n + 1 %}
|
||||
{% if p == events_paging.page %}
|
||||
<button
|
||||
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 transition duration-200 ease">
|
||||
|
||||
{{ p }}
|
||||
</button>
|
||||
{% else %}
|
||||
<button
|
||||
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-gray-900 bg-white border border-gray-300 rounded hover:bg-gray-100 focus:ring-4 focus:ring-primary-300 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 transition duration-200 ease"
|
||||
|
||||
hx-get="/clients/client/{{client.id}}/events/{{ p }}"
|
||||
hx-target="#client-audit-events"
|
||||
>
|
||||
{{ p }}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<button
|
||||
{% if events_paging.page < events_paging.total_pages %}
|
||||
|
||||
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 transition duration-200 ease"
|
||||
|
||||
hx-get="/clients/client/{{ client.id }}/events/{{ events_paging.page + 1 }}"
|
||||
hx-target="#client-audit-events"
|
||||
{% else %}
|
||||
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-gray-900 bg-white border border-gray-300 rounded hover:bg-gray-100 focus:ring-4 focus:ring-primary-300 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 transition duration-200 ease"
|
||||
disabled=""
|
||||
{% endif %}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -86,7 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</sl-details>
|
||||
{% if groups.groups %}
|
||||
{% if flat_groups.groups %}
|
||||
<sl-details summary="Group">
|
||||
<form
|
||||
hx-put="/secrets/set-group/{{ secret.name }}"
|
||||
@ -98,7 +98,7 @@
|
||||
<div class="relative w-full">
|
||||
<select id="group_name" name="group_name" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<option value="__ROOT">Ungrouped</option>
|
||||
{% for group in groups.groups %}
|
||||
{% for group in flat_groups.groups %}
|
||||
<option value="{{ group.group_name }}" {% if group.name == secret.group -%}selected{% endif %}>{{ group.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
@ -133,6 +133,10 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
token_data: dict[str, str] = {"sub": user.username}
|
||||
access_token = create_access_token(dependencies.settings, data=token_data)
|
||||
refresh_token = create_refresh_token(dependencies.settings, data=token_data)
|
||||
if next == "/refresh":
|
||||
# Don't redirect from login to refresh. Send to dashboard instead.
|
||||
next = "/"
|
||||
|
||||
response = RedirectResponse(url=next, status_code=status.HTTP_302_FOUND)
|
||||
response.set_cookie(
|
||||
"access_token",
|
||||
|
||||
@ -6,6 +6,7 @@ import logging
|
||||
import uuid
|
||||
from typing import Annotated
|
||||
from fastapi import APIRouter, Depends, Form, HTTPException, Query, Request, Response
|
||||
from fastapi.responses import RedirectResponse
|
||||
from pydantic import BaseModel, IPvAnyAddress, IPvAnyNetwork
|
||||
from sshecret_admin.frontend.views.common import PagingInfo
|
||||
|
||||
@ -20,6 +21,7 @@ from ..dependencies import FrontendDependencies
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
CLIENTS_PER_PAGE = 20
|
||||
EVENTS_PER_PAGE = 20
|
||||
|
||||
|
||||
class ClientUpdate(BaseModel):
|
||||
@ -165,7 +167,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
if not results:
|
||||
raise HTTPException(status_code=404, detail="Client not found.")
|
||||
events = await admin.get_audit_log_detailed(
|
||||
limit=10, client_name=results.client.name
|
||||
limit=EVENTS_PER_PAGE, client_name=results.client.name
|
||||
)
|
||||
template = "clients/client.html.j2"
|
||||
|
||||
@ -179,6 +181,9 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
headers["HX-Push-Url"] = request.url.path
|
||||
template = "clients/partials/client_details.html.j2"
|
||||
|
||||
events_paging = PagingInfo(
|
||||
page=1, limit=EVENTS_PER_PAGE, total=events.total, offset=0
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
template,
|
||||
@ -191,10 +196,45 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
"user": current_user,
|
||||
"results": results.results,
|
||||
"events": events,
|
||||
"events_paging": events_paging,
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
@app.get("/clients/client/{id}/events/{page}")
|
||||
async def get_client_events(
|
||||
request: Request,
|
||||
admin: Annotated[AdminBackend, Depends(dependencies.get_admin_backend)],
|
||||
id: str,
|
||||
page: int,
|
||||
) -> Response:
|
||||
"""Get more events for a client."""
|
||||
if not "HX-Request" in request.headers:
|
||||
return RedirectResponse(url=f"/clients/client/{id}")
|
||||
|
||||
client = await admin.get_client(("id", id))
|
||||
if not client:
|
||||
raise HTTPException(status_code=404, detail="Client not found.")
|
||||
offset = 0
|
||||
if page > 1:
|
||||
offset = (page - 1) * EVENTS_PER_PAGE
|
||||
events = await admin.get_audit_log_detailed(
|
||||
limit=EVENTS_PER_PAGE, client_name=client.name, offset=offset
|
||||
)
|
||||
|
||||
events_paging = PagingInfo(
|
||||
page=page, limit=EVENTS_PER_PAGE, total=events.total, offset=offset
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"clients/partials/client_events.html.j2",
|
||||
{
|
||||
"events": events,
|
||||
"client": client,
|
||||
"events_paging": events_paging,
|
||||
},
|
||||
)
|
||||
|
||||
@app.put("/clients/{id}")
|
||||
async def update_client(
|
||||
request: Request,
|
||||
@ -228,7 +268,13 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
|
||||
final_client = await admin.update_client(updated_client)
|
||||
|
||||
events = await admin.get_audit_log_detailed(limit=10, client_name=client.name)
|
||||
events = await admin.get_audit_log_detailed(
|
||||
limit=EVENTS_PER_PAGE, client_name=client.name
|
||||
)
|
||||
|
||||
events_paging = PagingInfo(
|
||||
page=1, limit=EVENTS_PER_PAGE, total=events.total, offset=0
|
||||
)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
@ -236,6 +282,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
{
|
||||
"client": final_client,
|
||||
"events": events,
|
||||
"events_paging": events_paging,
|
||||
},
|
||||
)
|
||||
|
||||
@ -249,6 +296,12 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
sources: list[str] | None = None
|
||||
if client.sources:
|
||||
sources = [source.strip() for source in client.sources.split(",")]
|
||||
await admin.create_client(
|
||||
name=client.name,
|
||||
public_key=client.public_key,
|
||||
description=client.description,
|
||||
sources=sources,
|
||||
)
|
||||
|
||||
headers = {"Hx-Refresh": "true"}
|
||||
return Response(
|
||||
|
||||
@ -173,6 +173,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
"""Get secret detail."""
|
||||
secret = await admin.get_secret(name)
|
||||
groups = await admin.get_secret_groups()
|
||||
flat_groups = await admin.get_secret_groups(flat=True)
|
||||
events = await admin.get_audit_log_detailed(limit=10, secret_name=name)
|
||||
|
||||
if not secret:
|
||||
@ -183,6 +184,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
context: dict[str, Any] = {
|
||||
"secret": secret,
|
||||
"groups": groups,
|
||||
"flat_groups": flat_groups,
|
||||
"events": events,
|
||||
"secret_page": True,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user