auth-yes/ui/components/admin/AdminUserDetailsScript.tsx
google-labs-jules[bot] 65f59521c0 feat(ui): decompose Admin UI with separate Drawers and Scripts
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>
2026-08-26 18:37:15 +00:00

179 lines
7.1 KiB
TypeScript

export const AdminUserDetailsScript = ({ allRoles }: { allRoles: any[] }) => {
return (
<script
dangerouslySetInnerHTML={{
__html: `
const ROLES_CATALOG = ${JSON.stringify(allRoles)};
function updateRoleOptions() {
const grantAppIdEl = document.getElementById('grantAppId');
if(!grantAppIdEl) return;
const appId = grantAppIdEl.value;
const roleSelect = document.getElementById('grantRole');
if(!roleSelect) return;
roleSelect.innerHTML = '';
const available = ROLES_CATALOG.filter(r => !r.app_id || r.app_id === appId);
if (available.length === 0) {
const opt = document.createElement('option');
opt.value = 'user';
opt.textContent = 'user';
roleSelect.appendChild(opt);
return;
}
available.forEach(r => {
const opt = document.createElement('option');
opt.value = r.name;
opt.textContent = r.name + (r.app_id ? ' (App Custom)' : ' (Global)');
roleSelect.appendChild(opt);
});
}
if (document.getElementById('grantAppId')) {
updateRoleOptions();
}
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);
}
}
async function handleUpdateProfile(e, userId) {
e.preventDefault();
const displayName = document.getElementById('displayNameInput').value.trim();
try {
const res = await fetch('/api/admin/users/' + userId + '/profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ displayName }),
});
const data = await res.json();
if (res.ok) {
showNotice('User display name saved successfully!', false);
setTimeout(() => window.location.reload(), 600);
} else {
showNotice(data.error || 'Failed to update display name', true);
}
} catch (err) {
showNotice('Network error updating display name', true);
}
}
async function handleGrantAccess(e, userId) {
e.preventDefault();
const appId = document.getElementById('grantAppId').value;
const role = document.getElementById('grantRole').value;
try {
const res = await fetch('/api/admin/users/' + userId + '/grants', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ appId, role }),
});
const data = await res.json();
if (res.ok) {
showNotice('Application access granted successfully!', false);
setTimeout(() => window.location.reload(), 600);
} else {
showNotice(data.error || 'Failed to update application grant', true);
}
} catch (err) {
showNotice('Network error updating grant', true);
}
}
async function revokeGrant(userId, appId, appName) {
if (!confirm('Revoke access to "' + appName + '" for this user?')) return;
try {
const res = await fetch('/api/admin/users/' + userId + '/grants/' + appId, {
method: 'DELETE',
});
if (res.ok) {
showNotice('Access revoked', false);
setTimeout(() => window.location.reload(), 600);
} else {
const data = await res.json();
showNotice(data.error || 'Failed to revoke grant', true);
}
} catch (err) {
showNotice('Network error revoking grant', true);
}
}
async function generateRecoveryLink(userId) {
try {
const res = await fetch('/api/admin/users/' + userId + '/recovery', { method: 'POST' });
const data = await res.json();
if (res.ok) {
const link = window.location.origin + '/recovery?code=' + data.recoveryCode;
document.getElementById('recovery-link-text').textContent = link;
document.getElementById('recovery-link-container').style.display = 'block';
showNotice('Recovery link generated!', false);
} else {
showNotice(data.error || 'Failed to generate link', true);
}
} catch (err) {
showNotice('Network error', true);
}
}
async function revokeSession(sessionId) {
if (!confirm('Revoke this session?')) return;
try {
const res = await fetch('/api/admin/sessions/' + sessionId, { method: 'DELETE' });
if (res.ok) {
showNotice('Session revoked', false);
setTimeout(() => window.location.reload(), 600);
} else {
showNotice('Failed to revoke session', true);
}
} catch (err) {
showNotice('Network error', true);
}
}
async function revokeAllSessions(userId) {
if (!confirm('Revoke ALL sessions for this user? They will be immediately logged out.')) return;
try {
const res = await fetch('/api/admin/users/' + userId + '/sessions', { method: 'DELETE' });
if (res.ok) {
showNotice('All sessions revoked', false);
setTimeout(() => window.location.reload(), 600);
} else {
showNotice('Failed to revoke all sessions', true);
}
} catch (err) {
showNotice('Network error', true);
}
}
async function deletePasskey(userId, passkeyId) {
if (!confirm('Permanently delete this device? The user will no longer be able to log in with it.')) return;
try {
const res = await fetch('/api/admin/users/' + userId + '/passkeys/' + passkeyId, { method: 'DELETE' });
const data = await res.json();
if (res.ok) {
showNotice('Passkey deleted', false);
setTimeout(() => window.location.reload(), 600);
} else {
showNotice(data.error || 'Failed to delete passkey', true);
}
} catch (err) {
showNotice('Network error', true);
}
}
`,
}}
/>
);
};