feat(isac): add avatar oversight queue
This commit is contained in:
@@ -8,6 +8,7 @@ import { AVATAR_PRESETS, AvatarValidationError, processAvatarUpload, saveUploade
|
||||
import { createMagicLinkToken } from '$lib/server/auth/magic-link';
|
||||
import { emailDeliveryConfigured, sendAuthenticationLink } from '$lib/server/auth/mail';
|
||||
import { canRemoveAuthenticationMethod, getAuthenticationMethods } from '$lib/server/auth/methods';
|
||||
import { recordIsacAudit } from '$lib/server/audit';
|
||||
|
||||
export const load: PageServerLoad = async ({ cookies, url }) => {
|
||||
const user = await getSessionUser(cookies);
|
||||
@@ -145,8 +146,10 @@ export const actions: Actions = {
|
||||
if (!(file instanceof File)) return fail(400, { avatarError: 'Choose an image to upload.' });
|
||||
try {
|
||||
const output = await processAvatarUpload(file);
|
||||
await saveUploadedAvatar(await getDatabase(), user.id, output);
|
||||
return { avatarChanged: true };
|
||||
const database = await getDatabase();
|
||||
const uploadedAt = await saveUploadedAvatar(database, user.id, output);
|
||||
await recordIsacAudit({ actorId: user.id, category: 'user_moderation', action: 'avatar.submitted', entityId: user.id, after: { status: 'pending', uploadedAt, byteSize: output.length } });
|
||||
return { avatarChanged: true, avatarReviewQueued: true };
|
||||
} catch (error) {
|
||||
if (error instanceof AvatarValidationError) return fail(400, { avatarError: error.message });
|
||||
throw error;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
return 'passkeys';
|
||||
}
|
||||
function initialAvatarPanel(): AvatarPanel {
|
||||
return form?.avatarError ? 'upload' : 'presets';
|
||||
return form?.avatarError || form?.avatarReviewQueued ? 'upload' : 'presets';
|
||||
}
|
||||
let accountPanel = $state<AccountPanel>(initialAccountPanel());
|
||||
let accessPanel = $state<AccessPanel>(initialAccessPanel());
|
||||
@@ -111,7 +111,7 @@
|
||||
<ImageUploadInput name="avatar" accept="image/jpeg,image/png,image/webp,image/avif" required emptyLabel="NO AVATAR SELECTED" browseLabel="CHOOSE AVATAR"/>
|
||||
<small class="identity-note">JPEG, PNG, WebP, or AVIF · 5 MiB maximum · cropped to a 256 px square.</small>
|
||||
{#if form?.avatarError}<p class="error">{form.avatarError}</p>{/if}
|
||||
{#if form?.avatarChanged}<p class="success">Avatar updated.</p>{/if}
|
||||
{#if form?.avatarChanged}<p class="success">{form?.avatarReviewQueued ? 'Avatar active now · queued for Oversight review.' : 'Avatar updated.'}</p>{/if}
|
||||
<button class="secondary console-action">UPLOAD CUSTOM AVATAR →</button>
|
||||
</PendingForm>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user