Piattaforme riservate: ruolo dedicato e port della dashboard Stress Index
Il ruolo `campus` diventa `piattaforme` e non apre più solo la sezione Biohacking: copre tutte le aree riservate, con migrazione guardata sugli utenti esistenti. Nell'header la vecchia voce Biohacking lascia il posto a un menu Piattaforme con i due link, visibile solo a chi ha il ruolo, e /piattaforme diventa la pagina di atterraggio. Stress Index è portata dentro il sito: le nove viste dell'area professionisti diventano pagine Astro sotto /piattaforme/stress-index, con lo stile del sito al posto del design system del prototipo. React resta solo dove serve davvero — grafici recharts e scheda cliente — il resto è Astro con un filo di JS. I dati sono ancora quelli dimostrativi, raccolti in lib/stress-index/data.ts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,50 +0,0 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import type Database from 'better-sqlite3';
|
||||
import { createDb } from '../src/lib/db';
|
||||
import { createUser, login, getSessionUser, canAccessAdminPath, landingFor, isRole } from '../src/lib/auth';
|
||||
|
||||
let db: Database.Database;
|
||||
beforeEach(() => { db = createDb(':memory:'); });
|
||||
|
||||
describe('ruolo campus', () => {
|
||||
it('createUser accetta campus e getSessionUser lo ritorna', () => {
|
||||
createUser(db, 'c', 'segreta123', 'campus');
|
||||
expect(getSessionUser(db, login(db, 'c', 'segreta123')!)).toMatchObject({ role: 'campus' });
|
||||
});
|
||||
|
||||
it('isRole valida campus', () => {
|
||||
expect(isRole('campus')).toBe(true);
|
||||
});
|
||||
|
||||
it('landingFor porta campus alla sezione campus', () => {
|
||||
expect(landingFor('campus')).toBe('/campus');
|
||||
});
|
||||
});
|
||||
|
||||
describe('canAccessAdminPath con campus', () => {
|
||||
it('campus: sezione campus e logout sì, resto del pannello no', () => {
|
||||
expect(canAccessAdminPath('campus', '/campus')).toBe(true);
|
||||
expect(canAccessAdminPath('campus', '/campus/')).toBe(true);
|
||||
expect(canAccessAdminPath('campus', '/campus/corso-base/lezione-01')).toBe(true);
|
||||
expect(canAccessAdminPath('campus', '/campus/assets/slide/x.png')).toBe(true);
|
||||
expect(canAccessAdminPath('campus', '/admin/logout')).toBe(true);
|
||||
expect(canAccessAdminPath('campus', '/admin')).toBe(false);
|
||||
expect(canAccessAdminPath('campus', '/admin/new')).toBe(false);
|
||||
expect(canAccessAdminPath('campus', '/admin/content')).toBe(false);
|
||||
expect(canAccessAdminPath('campus', '/admin/users')).toBe(false);
|
||||
expect(canAccessAdminPath('campus', '/api/admin/posts')).toBe(false);
|
||||
expect(canAccessAdminPath('campus', '/api/admin/upload')).toBe(false);
|
||||
});
|
||||
|
||||
it('admin accede alla sezione campus', () => {
|
||||
expect(canAccessAdminPath('admin', '/campus')).toBe(true);
|
||||
expect(canAccessAdminPath('admin', '/campus/corso-base')).toBe(true);
|
||||
});
|
||||
|
||||
it('superuser e user non accedono alla sezione campus', () => {
|
||||
expect(canAccessAdminPath('superuser', '/campus')).toBe(false);
|
||||
expect(canAccessAdminPath('superuser', '/campus/corso-base')).toBe(false);
|
||||
expect(canAccessAdminPath('user', '/campus')).toBe(false);
|
||||
expect(canAccessAdminPath('user', '/campus/assets/slide/x.png')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import type Database from 'better-sqlite3';
|
||||
import { mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { createDb } from '../src/lib/db';
|
||||
import { createUser, login, getSessionUser, canAccessAdminPath, landingFor, isRole } from '../src/lib/auth';
|
||||
|
||||
let db: Database.Database;
|
||||
beforeEach(() => { db = createDb(':memory:'); });
|
||||
|
||||
describe('ruolo piattaforme', () => {
|
||||
it('createUser accetta piattaforme e getSessionUser lo ritorna', () => {
|
||||
createUser(db, 'c', 'segreta123', 'piattaforme');
|
||||
expect(getSessionUser(db, login(db, 'c', 'segreta123')!)).toMatchObject({ role: 'piattaforme' });
|
||||
});
|
||||
|
||||
it('isRole valida piattaforme e non più il vecchio campus', () => {
|
||||
expect(isRole('piattaforme')).toBe(true);
|
||||
expect(isRole('campus')).toBe(false);
|
||||
});
|
||||
|
||||
it("landingFor porta piattaforme all'indice delle piattaforme", () => {
|
||||
expect(landingFor('piattaforme')).toBe('/piattaforme');
|
||||
});
|
||||
});
|
||||
|
||||
describe('canAccessAdminPath con piattaforme', () => {
|
||||
it('piattaforme: sezioni riservate e logout sì, resto del pannello no', () => {
|
||||
expect(canAccessAdminPath('piattaforme', '/campus')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/campus/')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/campus/corso-base/lezione-01')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/campus/assets/slide/x.png')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/piattaforme')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/piattaforme/stress-index')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/piattaforme/stress-index/clienti')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/admin/logout')).toBe(true);
|
||||
expect(canAccessAdminPath('piattaforme', '/admin')).toBe(false);
|
||||
expect(canAccessAdminPath('piattaforme', '/admin/new')).toBe(false);
|
||||
expect(canAccessAdminPath('piattaforme', '/admin/content')).toBe(false);
|
||||
expect(canAccessAdminPath('piattaforme', '/admin/users')).toBe(false);
|
||||
expect(canAccessAdminPath('piattaforme', '/api/admin/posts')).toBe(false);
|
||||
expect(canAccessAdminPath('piattaforme', '/api/admin/upload')).toBe(false);
|
||||
});
|
||||
|
||||
it('admin accede a tutte le piattaforme', () => {
|
||||
expect(canAccessAdminPath('admin', '/campus')).toBe(true);
|
||||
expect(canAccessAdminPath('admin', '/campus/corso-base')).toBe(true);
|
||||
expect(canAccessAdminPath('admin', '/piattaforme')).toBe(true);
|
||||
expect(canAccessAdminPath('admin', '/piattaforme/stress-index')).toBe(true);
|
||||
});
|
||||
|
||||
it('superuser e user non accedono alle piattaforme', () => {
|
||||
expect(canAccessAdminPath('superuser', '/campus')).toBe(false);
|
||||
expect(canAccessAdminPath('superuser', '/campus/corso-base')).toBe(false);
|
||||
expect(canAccessAdminPath('superuser', '/piattaforme')).toBe(false);
|
||||
expect(canAccessAdminPath('superuser', '/piattaforme/stress-index')).toBe(false);
|
||||
expect(canAccessAdminPath('user', '/campus')).toBe(false);
|
||||
expect(canAccessAdminPath('user', '/campus/assets/slide/x.png')).toBe(false);
|
||||
expect(canAccessAdminPath('user', '/piattaforme')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// La rinomina del ruolo va verificata su un DB su file: le migrazioni girano all'apertura,
|
||||
// quindi serve chiudere e riaprire lo stesso database con dentro una riga al vecchio valore.
|
||||
describe('migrazione del ruolo campus → piattaforme', () => {
|
||||
let dir: string;
|
||||
beforeEach(() => { dir = mkdtempSync(join(tmpdir(), 'ilab-db-')); });
|
||||
afterEach(() => { rmSync(dir, { recursive: true, force: true }); });
|
||||
|
||||
it('rinomina gli utenti rimasti al vecchio ruolo, lasciando stare gli altri', () => {
|
||||
const file = join(dir, 'test.db');
|
||||
const first = createDb(file);
|
||||
createUser(first, 'vecchio', 'segreta123', 'campus' as never);
|
||||
createUser(first, 'redattore', 'segreta123', 'superuser');
|
||||
first.close();
|
||||
|
||||
const second = createDb(file);
|
||||
const roles = second.prepare('SELECT username, role FROM users ORDER BY username').all() as
|
||||
{ username: string; role: string }[];
|
||||
second.close();
|
||||
|
||||
expect(roles).toEqual([
|
||||
{ username: 'redattore', role: 'superuser' },
|
||||
{ username: 'vecchio', role: 'piattaforme' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user