security: harden data auth and deployment

This commit is contained in:
2026-09-17 18:31:35 +12:00
parent a6d1c73837
commit 5639dbcb83
32 changed files with 1401 additions and 378 deletions
+18 -4
View File
@@ -36,6 +36,7 @@ type Profile = {
type Invite = {
id: number
code: string
code_available?: boolean
label?: string | null
description?: string | null
profile_id?: number | null
@@ -501,17 +502,30 @@ export default function AdminInviteManagementPage() {
}
const copyInviteLink = async (invite: Invite) => {
const url = `${signupBaseUrl}?code=${encodeURIComponent(invite.code)}`
try {
let usableInvite = invite
if (!invite.code_available) {
const response = await authFetch(`${getApiBase()}/admin/invites/${invite.id}/rotate`, {
method: 'POST',
})
if (!response.ok) {
if (handleAuthResponse(response)) return
throw new Error((await response.text()) || 'Could not generate a replacement link.')
}
const data = await response.json()
usableInvite = data.invite as Invite
setInvites((current) => current.map((item) => item.id === invite.id ? usableInvite : item))
}
const url = `${signupBaseUrl}?code=${encodeURIComponent(usableInvite.code)}`
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(url)
setStatus(`Copied invite link for ${invite.code}.`)
setStatus(`Copied the invite link. Keep it safe; Magent will not display it again after this page reloads.`)
} else {
window.prompt('Copy invite link', url)
}
} catch (err) {
console.error(err)
window.prompt('Copy invite link', url)
setError(err instanceof Error ? err.message : 'Could not generate or copy the invite link.')
}
}
@@ -1666,7 +1680,7 @@ export default function AdminInviteManagementPage() {
</div>
<div className="admin-inline-actions">
<button type="button" className="ghost-button" onClick={() => copyInviteLink(invite)}>
Copy link
{invite.code_available ? 'Copy link' : 'Generate replacement link'}
</button>
<button
type="button"