Add public agent profiles and community moderation

This commit is contained in:
JB
2026-07-27 15:38:27 -04:00
parent efb0ccdc7e
commit 6b76110b76
28 changed files with 2101 additions and 64 deletions
+9 -3
View File
@@ -26,9 +26,15 @@ export async function softDeleteAccount(
`UPDATE users SET username=?,login_username=NULL,password_hash=NULL,discord_id=NULL,role='user' WHERE id=?`
)).run(deletedUsername, userId);
await (await database.prepare(
`INSERT INTO user_profiles(user_id,display_name,updated_at) VALUES(?,?,?)
ON CONFLICT(user_id) DO UPDATE SET display_name=excluded.display_name,updated_at=excluded.updated_at`
)).run(userId, 'Deleted Agent', now);
`INSERT INTO user_profiles(user_id,display_name,bio_markdown,is_public,bio_updated_at,updated_at)
VALUES(?,?,?,0,?,?)
ON CONFLICT(user_id) DO UPDATE SET
display_name=excluded.display_name,
bio_markdown='',
is_public=0,
bio_updated_at=excluded.bio_updated_at,
updated_at=excluded.updated_at`
)).run(userId, 'Deleted Agent', '', now, now);
await (await database.prepare('DELETE FROM sessions WHERE user_id=?')).run(userId);
await (await database.prepare('DELETE FROM magic_link_tokens WHERE user_id=?')).run(userId);
await (await database.prepare('DELETE FROM webauthn_challenges WHERE user_id=?')).run(userId);
+26
View File
@@ -0,0 +1,26 @@
import { describe, expect, it } from 'vitest';
import { normalizeUserMarkdown, renderUserMarkdown } from '../markdown';
describe('user Markdown', () => {
it('escapes raw HTML and blocks executable links', () => {
const rendered = renderUserMarkdown(
'<script>alert(1)</script> [unsafe](javascript:alert(1)) [safe](https://shd.build)'
);
expect(rendered).toContain('&lt;script&gt;');
expect(rendered).not.toContain('<script>');
expect(rendered).not.toContain('javascript:');
expect(rendered).toContain('href="https://shd.build/"');
});
it('renders the supported biography formatting subset', () => {
expect(renderUserMarkdown('## Agent\n\n- **Medic**\n- _Support_')).toBe(
'<h4>Agent</h4><ul><li><strong>Medic</strong></li><li><em>Support</em></li></ul>'
);
});
it('bounds Unicode characters and rejects control characters', () => {
expect(normalizeUserMarkdown('漢字', 2)).toBe('漢字');
expect(normalizeUserMarkdown('漢字A', 2)).toBeNull();
expect(normalizeUserMarkdown('hello\u0000world', 20)).toBeNull();
});
});