b913a2bf90
Refs gitea:Adriano/AI-OS#310 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4.4 KiB
4.4 KiB
Task 5: API posts — ownership e assegnazione autore
Files:
- Modify:
src/pages/api/admin/posts/index.ts - Modify:
src/pages/api/admin/posts/[id].ts - Test:
tests/posts-ownership.test.ts(nuovo, a livello logico via funzione estratta)
Interfaces:
-
Consumes:
createPost,getPostById,updatePost,deletePost(Task 4),locals.userdal middleware. -
Produces: helper
canModifyPost(role: string, userId: number, post: { author_id: number | null }): booleaninsrc/lib/posts.ts. -
Step 1: Scrivi il test dell'ownership (livello logico)
Crea tests/posts-ownership.test.ts:
import { describe, it, expect } from 'vitest';
import { canModifyPost } from '../src/lib/posts';
describe('canModifyPost', () => {
const own = { author_id: 7 };
const other = { author_id: 8 };
const orphan = { author_id: null };
it('admin e superuser modificano qualsiasi post', () => {
for (const role of ['admin', 'superuser']) {
expect(canModifyPost(role, 7, other)).toBe(true);
expect(canModifyPost(role, 7, orphan)).toBe(true);
}
});
it('user modifica solo i propri', () => {
expect(canModifyPost('user', 7, own)).toBe(true);
expect(canModifyPost('user', 7, other)).toBe(false);
expect(canModifyPost('user', 7, orphan)).toBe(false);
});
});
- Step 2: Esegui e verifica il fallimento
Run: npm test -- tests/posts-ownership.test.ts
Expected: FAIL — canModifyPost non esiste.
- Step 3: Aggiungi
canModifyPostinposts.ts
export function canModifyPost(role: string, userId: number, post: { author_id: number | null }): boolean {
if (role === 'admin' || role === 'superuser') return true;
return post.author_id === userId;
}
- Step 4: Esegui e verifica il successo
Run: npm test -- tests/posts-ownership.test.ts
Expected: PASS.
- Step 5: Applica l'autore nel POST
In src/pages/api/admin/posts/index.ts, cambia la firma per leggere locals e passa author_id:
export const POST: APIRoute = async ({ request, locals }) => {
let data: Record<string, unknown>;
try { data = await request.json(); } catch { return json(400, { error: 'Dati non validi.' }); }
const parsed = parsePostBody(data);
if ('error' in parsed) return json(400, { error: parsed.error });
try {
const id = createPost(getDb(), { ...parsed.value, author_id: locals.user!.id });
return json(201, { id, slug: parsed.value.slug });
} catch (err: any) {
if (String(err?.message).includes('UNIQUE')) return json(400, { error: 'Slug già esistente.' });
throw err;
}
};
- Step 6: Applica l'ownership su PUT e DELETE
In src/pages/api/admin/posts/[id].ts, aggiorna gli import e i due handler:
import { getPostById, updatePost, deletePost, canModifyPost } from '../../../../lib/posts';
export const PUT: APIRoute = async ({ params, request, locals }) => {
const id = Number(params.id);
const existing = getPostById(getDb(), id);
if (!existing) return json(404, { error: 'Articolo non trovato.' });
if (!canModifyPost(locals.user!.role, locals.user!.id, existing)) return json(403, { error: 'Non puoi modificare questo articolo.' });
let data: Record<string, unknown>;
try { data = await request.json(); } catch { return json(400, { error: 'Dati non validi.' }); }
const parsed = parsePostBody(data);
if ('error' in parsed) return json(400, { error: parsed.error });
try {
updatePost(getDb(), id, parsed.value);
return json(200, { ok: true });
} catch (err: any) {
if (String(err?.message).includes('UNIQUE')) return json(400, { error: 'Slug già esistente.' });
throw err;
}
};
export const DELETE: APIRoute = ({ params, locals }) => {
const id = Number(params.id);
const existing = getPostById(getDb(), id);
if (!existing) return json(404, { error: 'Articolo non trovato.' });
if (!canModifyPost(locals.user!.role, locals.user!.id, existing)) return json(403, { error: 'Non puoi eliminare questo articolo.' });
deletePost(getDb(), id);
return json(200, { ok: true });
};
- Step 7: Verifica build + test
Run: npm run build && npm test
Expected: build OK, tutti i test verdi.
- Step 8: Commit
git add src/pages/api/admin/posts/index.ts src/pages/api/admin/posts/[id].ts src/lib/posts.ts tests/posts-ownership.test.ts
git commit -m "feat(posts-api): assegna autore in POST, ownership su PUT/DELETE"