Skip to content

Commit e46c370

Browse files
committed
New Admin UI
1 parent 430af4b commit e46c370

27 files changed

+4584
-2052
lines changed

webroot/adm/client-key.html

Lines changed: 356 additions & 229 deletions
Large diffs are not rendered by default.
Lines changed: 205 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,226 @@
11
<html>
22
<head>
3-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
4-
<script src="/js/main.js"></script>
3+
<meta charset="UTF-8">
4+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
5+
<script src="/js/main.js"></script>
6+
<script type="module" src="/js/dangerModal.js"></script>
7+
<script type="module" src="/js/operations.js"></script>
8+
<script type="module" src="/js/output.js"></script>
9+
<script type="module" src="/js/roleBadge.js"></script>
10+
<link rel="stylesheet" href="/css/style.css">
511
</head>
612
<body>
713
<h1>UID2 Env - Client Side Keypair Management</h1>
814

915
<a href="/">Back</a>
1016

11-
<br>
12-
<br>
13-
14-
<h3>Inputs</h3>
15-
16-
<label for="subscriptionId">Subscription id:</label>
17-
<input type="text" id="subscriptionId" name="subscriptionId">
18-
<label for="siteId">Site id:</label>
19-
<input type="text" id="siteId" name="siteId">
20-
<label for="name">Keypair Name:</label>
21-
<input type="text" id="name" name="name">
22-
<label for="disable">Disable Keypair:</label>
23-
<input type="checkbox" id="disable" name="disable" value="true">
24-
25-
<br>
26-
<br>
27-
28-
<h3>Operations</h3>
29-
30-
<ul>
31-
<li class="ro-sem" style="display: none"><a href="#" id="doList">List Keypairs</a></li>
32-
<li class="ro-sem" style="display: none"><a href="#" id="doListSite">List Keypairs By Site Id</a></li>
33-
<li class="ro-sem" style="display: none"><a href="#" id="doListSubscription">Reveal Keypair By Subscription Id</a></li>
34-
<li class="ro-sem" style="display: none"><a href="#" id="doCreate">Create Keypair</a></li>
35-
<li class="ro-sem" style="display: none"><a href="#" id="doUpdate">Update Keypair</a></li>
36-
<li class="ro-sem" style="display: none"><a href="#" id="doDelete">Delete Keypair</a></li>
37-
</ul>
38-
39-
<br>
40-
41-
<h3>Output</h3>
42-
43-
<div id="output">
44-
<pre id="errorOutput"></pre>
45-
<pre id="standardOutput"></pre>
17+
<div class="main-content">
18+
<div class="operations-container"></div>
19+
<div class="output-container"></div>
4620
</div>
4721

48-
<script language="JavaScript">
49-
$(document).ready(function () {
50-
$('#doList').on('click', function () {
51-
doApiCall('GET', '/api/client_side_keypairs/list', '#standardOutput', '#errorOutput');
52-
});
53-
54-
$('#doListSite').on('click', function () {
55-
const siteId = parseInt($('#siteId').val())
56-
if(!siteId) {
57-
$('#errorOutput').text("required parameters: site_id")
58-
return
22+
<script type="module">
23+
import { initializeOperations } from '/js/operations.js';
24+
import { initializeOutput } from '/js/output.js';
25+
26+
document.addEventListener('DOMContentLoaded', function () {
27+
const operationConfig = [
28+
{
29+
type: 'read-only',
30+
title: 'Read Only Operations',
31+
operations: [
32+
{
33+
id: 'doList',
34+
title: 'List Keypairs',
35+
role: 'maintainer',
36+
inputs: [],
37+
apiCall: {
38+
method: 'GET',
39+
url: '/api/client_side_keypairs/list'
40+
}
41+
},
42+
{
43+
id: 'doListSite',
44+
title: 'List Keypairs By Site ID',
45+
role: 'maintainer',
46+
inputs: [
47+
{
48+
id: 'siteId-listSite',
49+
name: 'siteId',
50+
label: 'Site ID',
51+
required: true,
52+
size: 1,
53+
type: 'number'
5954
}
60-
doApiCallWithCallback('GET', '/api/client_side_keypairs/list', function (text) {
61-
let resp = JSON.parse(text)
62-
resp = resp.filter(obj => obj.site_id === siteId)
63-
$('#standardOutput').text(JSON.stringify(resp, null, 2));
64-
}, errorCallback);
65-
});
66-
67-
$('#doListSubscription').on('click', function () {
68-
const subscriptionId = $('#subscriptionId').val()
69-
if(!subscriptionId) {
70-
$('#errorOutput').text("required parameters: subscription_id")
71-
return
55+
],
56+
apiCall: {
57+
method: 'GET',
58+
url: '/api/client_side_keypairs/list'
59+
},
60+
postProcess: (response, inputs) => {
61+
const siteId = parseInt(inputs.siteId);
62+
return response.filter(keypair => keypair.site_id === siteId);
63+
}
64+
},
65+
{
66+
id: 'doListSubscription',
67+
title: 'Get Keypair By Subscription ID',
68+
role: 'maintainer',
69+
inputs: [
70+
{
71+
id: 'subscriptionId-get',
72+
name: 'subscriptionId',
73+
label: 'Subscription ID',
74+
required: true,
75+
size: 2
7276
}
73-
const url = '/api/client_side_keypairs/' + encodeURIComponent(subscriptionId);
74-
75-
doApiCall('GET', url, '#standardOutput', '#errorOutput');
76-
});
77-
78-
$('#doCreate').on('click', function () {
79-
const siteId = $('#siteId').val();
80-
const name = $('#name').val();
81-
const disabled = ($('#disable').is(':checked'));
82-
if (!siteId) {
83-
$('#errorOutput').text("required parameters: site_id")
84-
return
77+
],
78+
apiCall: {
79+
method: 'GET',
80+
getUrl: (inputs) => `/api/client_side_keypairs/${encodeURIComponent(inputs.subscriptionId)}`
81+
}
82+
}
83+
]
84+
},
85+
{
86+
type: 'write',
87+
title: 'Write Operations',
88+
operations: [
89+
{
90+
id: 'doCreate',
91+
title: 'Add Keypair',
92+
role: 'maintainer',
93+
inputs: [
94+
{
95+
id: 'siteId-create',
96+
name: 'siteId',
97+
label: 'Site ID',
98+
required: true,
99+
size: 1,
100+
type: 'number'
101+
},
102+
{
103+
id: 'name-create',
104+
name: 'name',
105+
label: 'Keypair Name',
106+
required: false,
107+
size: 2
108+
},
109+
{
110+
id: 'disable-create',
111+
name: 'disable',
112+
label: 'Disable Keypair',
113+
type: 'checkbox',
114+
size: 1
85115
}
86-
87-
const payload = {"site_id": parseInt(siteId), "name": name, "disabled": disabled}
88-
89-
doApiCall('POST', '/api/client_side_keypairs/add', '#standardOutput', '#errorOutput', JSON.stringify(payload));
90-
});
91-
92-
$('#doUpdate').on('click', function () {
93-
const subscriptionId = $('#subscriptionId').val()
94-
const name = $('#name').val();
95-
const disabled = ($('#disable').is(':checked'));
96-
97-
if (!subscriptionId) {
98-
$('#errorOutput').text("required parameters: subscription_id")
99-
return
116+
],
117+
apiCall: {
118+
method: 'POST',
119+
url: '/api/client_side_keypairs/add',
120+
getPayload: (inputs) => ({
121+
site_id: parseInt(inputs.siteId),
122+
name: inputs.name || '',
123+
disabled: inputs.disable || false
124+
})
125+
}
126+
},
127+
{
128+
id: 'doUpdate',
129+
title: 'Update Keypair',
130+
role: 'maintainer',
131+
inputs: [
132+
{
133+
id: 'subscriptionId-update',
134+
name: 'subscriptionId',
135+
label: 'Subscription ID',
136+
required: true,
137+
size: 2
138+
},
139+
{
140+
id: 'name-update',
141+
name: 'name',
142+
label: 'Keypair Name',
143+
required: false,
144+
size: 2
145+
},
146+
{
147+
id: 'disable-update',
148+
name: 'disable',
149+
label: 'Disable Keypair',
150+
type: 'checkbox',
151+
size: 1
100152
}
101-
102-
const confirmationMessage = getUpdateKeypairConfirmationMessage(disabled, subscriptionId);
103-
if (!confirm(confirmationMessage)) return;
104-
105-
const payload = {"subscription_id": subscriptionId, "disabled" : disabled}
106-
if (name) {
107-
payload["name"] = name
153+
],
154+
preProcess: (inputs) => {
155+
// Show confirmation dialog with appropriate message
156+
const disabled = inputs.disable;
157+
const action = disabled ? 'disable' : 'enable';
158+
const baseMessage = `You may ignore this warning if you are not changing the disabled status of this keypair.\n\nAre you sure you want to ${action} ${inputs.subscriptionId}?`;
159+
160+
let confirmationMessage;
161+
if (disabled) {
162+
confirmationMessage = `Disabling this client-side keypair will prevent it from using CSTG.\nBefore proceeding, ensure there is no valid traffic, and confirm that the participant has provided consent.\n\n${baseMessage}`;
163+
} else {
164+
confirmationMessage = `Enabling this client-side keypair will allow it to use CSTG.\n\n${baseMessage}`;
108165
}
109-
110-
doApiCall('POST', '/api/client_side_keypairs/update', '#standardOutput', '#errorOutput', JSON.stringify(payload));
111-
});
112-
113-
$('#doDelete').on('click', function () {
114-
const subscriptionId = $('#subscriptionId').val();
115-
if (!subscriptionId) {
116-
$('#errorOutput').text("required parameters: subscription_id");
117-
return;
166+
167+
return confirm(confirmationMessage) ? inputs : null;
168+
},
169+
apiCall: {
170+
method: 'POST',
171+
url: '/api/client_side_keypairs/update',
172+
getPayload: (inputs) => {
173+
const payload = {
174+
subscription_id: inputs.subscriptionId,
175+
disabled: inputs.disable || false
176+
};
177+
if (inputs.name) {
178+
payload.name = inputs.name;
179+
}
180+
return payload;
118181
}
119-
120-
if (!confirm(`Are you sure you want to delete ${subscriptionId}?`)) return;
121-
122-
const payload = {"subscription_id": subscriptionId};
123-
124-
doApiCall('POST', '/api/client_side_keypairs/delete', '#standardOutput', '#errorOutput', JSON.stringify(payload));
125-
});
126-
127-
});
128-
129-
function getUpdateKeypairConfirmationMessage(disabled, subscriptionId) {
130-
let action = disabled ? 'disable' : 'enable';
131-
let confirmationMessage = `You may ignore this warning if you are not changing the disabled status of this keypair.\n\nAre you sure you want to ${action} ${subscriptionId}?`;
132-
133-
if (disabled) {
134-
confirmationMessage = `Disabling this client-side keypair will prevent it from using CSTG.\nBefore proceeding, ensure there is no valid traffic, and confirm that the participant has provided consent.\n\n${confirmationMessage}`;
135-
} else {
136-
confirmationMessage = `Enabling this client-side keypair will allow it to use CSTG.\n\n${confirmationMessage}`;
182+
}
137183
}
138-
return confirmationMessage;
184+
]
185+
},
186+
{
187+
type: 'danger-zone',
188+
title: '☠️ Danger Zone ☠️',
189+
operations: [
190+
{
191+
id: 'doDelete',
192+
title: 'Delete Keypair',
193+
role: 'elevated',
194+
inputs: [
195+
{
196+
id: 'subscriptionId-delete',
197+
name: 'subscriptionId',
198+
label: 'Subscription ID',
199+
required: true,
200+
size: 2
201+
}
202+
],
203+
description: 'This will permanently delete the client-side keypair. This action cannot be undone.',
204+
preProcess: (inputs) => {
205+
const message = `Are you sure you want to delete ${inputs.subscriptionId}?`;
206+
return confirm(message) ? inputs : null;
207+
},
208+
apiCall: {
209+
method: 'POST',
210+
url: '/api/client_side_keypairs/delete',
211+
getPayload: (inputs) => ({
212+
subscription_id: inputs.subscriptionId
213+
})
214+
}
215+
}
216+
]
139217
}
218+
];
219+
220+
initializeOperations(operationConfig);
221+
initializeOutput();
222+
});
140223
</script>
141224

142225
</body>
143-
</html>
226+
</html>

0 commit comments

Comments
 (0)