141 lines
7.1 KiB
Plaintext
141 lines
7.1 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Admin - Client Management</title>
|
|
<link rel="stylesheet" href="/css/admin_styles.css">
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>Client Application Management</h1>
|
|
<div class="nav-links">
|
|
<a href="/admin">Manage Secrets</a>
|
|
<a href="/admin/clients">Manage Clients</a>
|
|
<a href="/admin/logout" class="logout-link">Logout</a>
|
|
</div>
|
|
|
|
<% if (message && message.text) { %>
|
|
<div class="alert <%= message.type === 'success' ? 'alert-success' : 'alert-error' %>">
|
|
<%= message.text %>
|
|
</div>
|
|
<% } %>
|
|
|
|
<% if (!managingClientGroups) { %>
|
|
<div class="settings-section">
|
|
<h3>WebSocket Settings (Debug)</h3>
|
|
<form action="/admin/settings/toggle-auto-approve-ws" method="POST">
|
|
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
|
<label for="autoApproveWsToggle" class="form-group">
|
|
<input type="checkbox" id="autoApproveWsToggle" name="autoApproveWs" <%= autoApproveWsEnabled ? 'checked' : '' %>>
|
|
Automatically Approve New WebSocket Registrations
|
|
</label>
|
|
<button type="submit" class="btn ml-2">Update Setting</button>
|
|
</form>
|
|
</div>
|
|
<% } %>
|
|
|
|
<% if (managingClientGroups) { %>
|
|
<h2>Manage Associated Groups for Client: <span class="mono"><%= managingClientGroups.client.name %> (<%= managingClientGroups.client.id %>)</span></h2>
|
|
<form action="/admin/clients/<%= managingClientGroups.client.id %>/groups/update" method="POST">
|
|
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
|
<div class="form-group checkbox-list">
|
|
<label>Available Groups (select to associate):</label>
|
|
<% if (managingClientGroups.allGroups && managingClientGroups.allGroups.length > 0) { %>
|
|
<% managingClientGroups.allGroups.forEach(group => { %>
|
|
<div>
|
|
<input type="checkbox"
|
|
id="group_<%= group.id %>"
|
|
name="associatedGroupIds"
|
|
value="<%= group.id %>"
|
|
<%= managingClientGroups.client.associatedGroupIds.includes(group.id) ? 'checked' : '' %>>
|
|
<label for="group_<%= group.id %>"><%= group.name %> (ID: <%= group.id %>)</label>
|
|
</div>
|
|
<% }); %>
|
|
<% } else { %>
|
|
<p>No groups available to associate. Create groups in the main admin panel first.</p>
|
|
<% } %>
|
|
</div>
|
|
<button type="submit" class="btn">Update Associated Groups</button>
|
|
<a href="/admin/clients" class="btn btn-secondary">Back to Client List</a>
|
|
</form>
|
|
<% } else { %>
|
|
<h2>Pending Client Registrations</h2>
|
|
<% if (pendingClients && pendingClients.length > 0) { %>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Client ID / Temp ID</th>
|
|
<th>Requested Secrets (Legacy)</th>
|
|
<th>Date Registered</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% pendingClients.forEach(client => { %>
|
|
<tr>
|
|
<td><%= client.name %></td>
|
|
<td class="mono"><%= client.id %></td>
|
|
<td><%= client.requestedSecretKeys && client.requestedSecretKeys.length > 0 ? client.requestedSecretKeys.join(', ') : 'None' %></td>
|
|
<td><%= new Date(client.dateCreated).toLocaleString() %></td>
|
|
<td class="actions">
|
|
<form action="/admin/clients/approve/<%= client.id %>" method="POST" class="form-inline">
|
|
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
|
<button type="submit" class="approve">Approve</button>
|
|
</form>
|
|
<form action="/admin/clients/reject/<%= client.id %>" method="POST" class="form-inline">
|
|
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
|
<button type="submit" class="reject">Reject</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<% }); %>
|
|
</tbody>
|
|
</table>
|
|
<% } else { %>
|
|
<p>No pending client registrations.</p>
|
|
<% } %>
|
|
|
|
<h2>Approved Clients</h2>
|
|
<% if (approvedClients && approvedClients.length > 0) { %>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Client ID</th>
|
|
<th>Associated Groups</th>
|
|
<th>Date Approved/Updated</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% approvedClients.forEach(client => { %>
|
|
<tr>
|
|
<td><%= client.name %></td>
|
|
<td class="mono"><%= client.id %></td>
|
|
<td><%= client.associatedGroupNames %></td> <%# Now using associatedGroupNames from server %>
|
|
<td><%= new Date(client.dateUpdated).toLocaleString() %></td>
|
|
<td class="actions">
|
|
<a href="/admin/clients/<%= client.id %>/groups">Manage Groups</a>
|
|
<form action="/admin/clients/revoke/<%= client.id %>" method="POST" class="form-inline">
|
|
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
|
<button type="submit" class="delete">Revoke</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<% }); %>
|
|
</tbody>
|
|
</table>
|
|
<% } else { %>
|
|
<p>No approved clients.</p>
|
|
<% } %>
|
|
<% } %>
|
|
</div>
|
|
|
|
<%# The script for auto-approve toggle has been removed as it's now a form submission %>
|
|
<%# The csrfToken is still available globally in the template if other scripts need it, %>
|
|
<%# passed directly from the route handler. %>
|
|
|
|
</body>
|
|
</html>
|