Phase 2 Admin Drawers & Scripts execution: - Extract `AppDrawer`, `InviteDrawer`, `RoleEditorDrawer`, and `GrantDrawer`. - Extract `AdminAppsScript`, `AdminInvitesScript`, `AdminRolesScript`, and `AdminUserDetailsScript`. - Hook extracted components into their respective pages. - Format `AdminRolesPage.tsx` and all modified files using `deno fmt`. Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
124 lines
6.0 KiB
TypeScript
124 lines
6.0 KiB
TypeScript
export const AdminAppsScript = () => {
|
|
return (
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `
|
|
function showNotice(msg, isError) {
|
|
const banner = document.getElementById('status-banner');
|
|
if (banner) {
|
|
banner.textContent = msg;
|
|
banner.style.display = 'block';
|
|
banner.style.background = isError ? 'var(--danger-bg)' : 'var(--success-bg)';
|
|
banner.style.color = isError ? 'var(--danger-text)' : 'var(--success-text)';
|
|
banner.style.border = isError ? '1px solid var(--danger-border)' : '1px solid var(--success-border)';
|
|
setTimeout(() => { banner.style.display = 'none'; }, 5000);
|
|
}
|
|
}
|
|
|
|
function filterAppsList() {
|
|
const query = document.getElementById('appSearchInput').value.toLowerCase().trim();
|
|
document.querySelectorAll('.app-row').forEach(r => {
|
|
const text = r.getAttribute('data-search') || '';
|
|
r.style.display = text.includes(query) ? '' : 'none';
|
|
});
|
|
document.querySelectorAll('.app-card').forEach(c => {
|
|
const text = c.getAttribute('data-search') || '';
|
|
c.style.display = text.includes(query) ? '' : 'none';
|
|
});
|
|
}
|
|
|
|
function openCreateAppDrawer() {
|
|
document.getElementById('editAppId').value = '';
|
|
document.querySelector('#appFormModal h3').textContent = 'Register New Subsidiary Application';
|
|
document.getElementById('appName').value = '';
|
|
document.getElementById('appSpiffeId').value = '';
|
|
document.getElementById('appSpiffeId').readOnly = false;
|
|
document.getElementById('spiffeIdContainer').style.display = 'block';
|
|
document.getElementById('appDescription').value = '';
|
|
document.getElementById('appDomain').value = '';
|
|
document.getElementById('appIsPublic').checked = false;
|
|
document.getElementById('appBypassPaths').value = '';
|
|
document.getElementById('appAllowedCidrs').value = '';
|
|
document.getElementById('appFormModal').style.display = 'flex';
|
|
}
|
|
|
|
function openEditAppDrawer(appJson) {
|
|
const app = JSON.parse(appJson);
|
|
document.getElementById('editAppId').value = app.id;
|
|
document.querySelector('#appFormModal h3').textContent = 'Edit Application: ' + app.name;
|
|
document.getElementById('appName').value = app.name || '';
|
|
document.getElementById('appSpiffeId').value = app.spiffe_id || '';
|
|
document.getElementById('appSpiffeId').readOnly = true;
|
|
document.getElementById('appDescription').value = app.description || '';
|
|
document.getElementById('appDomain').value = app.domain || '';
|
|
document.getElementById('appIsPublic').checked = !!app.is_public;
|
|
document.getElementById('appBypassPaths').value = Array.isArray(app.bypass_paths) ? app.bypass_paths.join(', ') : (app.bypass_paths || '');
|
|
document.getElementById('appAllowedCidrs').value = Array.isArray(app.allowed_cidrs) ? app.allowed_cidrs.join(', ') : (app.allowed_cidrs || '');
|
|
document.getElementById('appFormModal').style.display = 'flex';
|
|
}
|
|
|
|
function closeAppDrawer() {
|
|
document.getElementById('appFormModal').style.display = 'none';
|
|
}
|
|
|
|
async function handleSaveApp(e) {
|
|
e.preventDefault();
|
|
const editId = document.getElementById('editAppId').value;
|
|
const name = document.getElementById('appName').value.trim();
|
|
const spiffeId = document.getElementById('appSpiffeId').value.trim();
|
|
const description = document.getElementById('appDescription').value.trim();
|
|
const domain = document.getElementById('appDomain').value.trim();
|
|
const is_public = document.getElementById('appIsPublic').checked;
|
|
const bypass_paths = document.getElementById('appBypassPaths').value.split(',').map(s => s.trim()).filter(Boolean);
|
|
const allowed_cidrs = document.getElementById('appAllowedCidrs').value.split(',').map(s => s.trim()).filter(Boolean);
|
|
|
|
if (!name || (!editId && !spiffeId)) {
|
|
showNotice('Application name and SPIFFE ID are required', true);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const url = editId ? ('/api/admin/apps/' + editId) : '/api/admin/apps';
|
|
const method = editId ? 'PUT' : 'POST';
|
|
const res = await fetch(url, {
|
|
method,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ name, spiffeId, description, domain, is_public, bypass_paths, allowed_cidrs }),
|
|
});
|
|
const data = await res.json();
|
|
if (res.ok) {
|
|
showNotice(editId ? 'Application updated successfully!' : 'Application registered successfully!', false);
|
|
setTimeout(() => window.location.reload(), 600);
|
|
} else {
|
|
showNotice(data.error || 'Failed to save application', true);
|
|
}
|
|
} catch (err) {
|
|
showNotice('Network error saving application', true);
|
|
}
|
|
}
|
|
|
|
async function deleteApp(appId, appName) {
|
|
if (!confirm('Are you sure you want to delete "' + appName + '"? All active user permissions for this app will be revoked.')) {
|
|
return;
|
|
}
|
|
try {
|
|
const res = await fetch('/api/admin/apps/' + appId, {
|
|
method: 'DELETE',
|
|
});
|
|
if (res.ok) {
|
|
showNotice('Application deleted', false);
|
|
setTimeout(() => window.location.reload(), 600);
|
|
} else {
|
|
const data = await res.json();
|
|
showNotice(data.error || 'Failed to delete application', true);
|
|
}
|
|
} catch (err) {
|
|
showNotice('Network error', true);
|
|
}
|
|
}
|
|
`,
|
|
}}
|
|
/>
|
|
);
|
|
};
|