Add moderation permissions and durable player records
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import Database from 'better-sqlite3';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import {
|
||||
migrateModeratorRole,
|
||||
migrateRememberedSessions,
|
||||
migrateSuperViewerRole
|
||||
} from '../../src/lib/server/auth/schema.js';
|
||||
@@ -153,3 +154,84 @@ describe('remembered session migration', () => {
|
||||
expect(handle.pragma('foreign_key_check')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('moderator role migration', () => {
|
||||
it('preserves all account roles and remembered sessions while extending the role constraint', () => {
|
||||
const upgrade = migrations.find((entry) => entry.name === 'moderator authentication role')!;
|
||||
runMigrations(handle, migrations.slice(0, upgrade.version - 1));
|
||||
handle.exec(`
|
||||
UPDATE auth_sessions SET remembered=1 WHERE user_id='admin';
|
||||
INSERT INTO auth_users VALUES
|
||||
('super','Super','Super','super-password-hash','super_viewer',0,0,10,20,NULL);
|
||||
INSERT INTO auth_sessions VALUES ('super-token-hash','super',10,1000,100,1);
|
||||
`);
|
||||
const tables = ['auth_users', 'auth_audit', 'auth_rate_limits', 'servers'];
|
||||
const original = tables.map(rows);
|
||||
const sessions = handle.prepare('SELECT * FROM auth_sessions ORDER BY rowid').all();
|
||||
expect(() =>
|
||||
handle.exec("UPDATE auth_users SET role='moderator' WHERE id='viewer'")
|
||||
).toThrow('CHECK constraint failed');
|
||||
|
||||
runMigrations(handle, migrations);
|
||||
|
||||
expect(tables.map(rows)).toEqual(original);
|
||||
expect(handle.prepare('SELECT * FROM auth_sessions ORDER BY rowid').all()).toEqual(
|
||||
sessions
|
||||
);
|
||||
expect(handle.pragma('foreign_keys', { simple: true })).toBe(1);
|
||||
expect(handle.pragma('foreign_key_check')).toEqual([]);
|
||||
expect(handle.pragma('foreign_key_list(auth_sessions)')).toEqual([
|
||||
expect.objectContaining({ table: 'auth_users', from: 'user_id', on_delete: 'CASCADE' })
|
||||
]);
|
||||
handle.exec("UPDATE auth_users SET role='moderator' WHERE id='viewer'");
|
||||
const users = rows('auth_users');
|
||||
const schemaVersion = handle.pragma('schema_version', { simple: true });
|
||||
migrateModeratorRole(handle);
|
||||
expect(rows('auth_users')).toEqual(users);
|
||||
expect(handle.prepare('SELECT * FROM auth_sessions ORDER BY rowid').all()).toEqual(
|
||||
sessions
|
||||
);
|
||||
expect(handle.pragma('schema_version', { simple: true })).toBe(schemaVersion);
|
||||
expect(() => handle.exec("UPDATE auth_users SET role='unknown' WHERE id='viewer'")).toThrow(
|
||||
'CHECK constraint failed'
|
||||
);
|
||||
expect(() =>
|
||||
handle.exec("UPDATE auth_users SET username='ADMINISTRATOR' WHERE id='viewer'")
|
||||
).toThrow('UNIQUE constraint failed');
|
||||
handle.exec("DELETE FROM auth_users WHERE id='super'");
|
||||
expect(handle.prepare("SELECT * FROM auth_sessions WHERE user_id='super'").all()).toEqual(
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects an unsafe rebuild and rolls back the upgrade if existing references are broken', () => {
|
||||
const upgrade = migrations.find((entry) => entry.name === 'moderator authentication role')!;
|
||||
runMigrations(handle, migrations.slice(0, upgrade.version - 1));
|
||||
const users = rows('auth_users');
|
||||
const sessions = handle.prepare('SELECT * FROM auth_sessions ORDER BY rowid').all();
|
||||
expect(() => migrateModeratorRole(handle)).toThrow('foreign keys to be disabled');
|
||||
expect(rows('auth_users')).toEqual(users);
|
||||
expect(handle.prepare('SELECT * FROM auth_sessions ORDER BY rowid').all()).toEqual(
|
||||
sessions
|
||||
);
|
||||
handle.pragma('foreign_keys = OFF');
|
||||
handle.exec("INSERT INTO auth_sessions VALUES ('orphan','missing',10,1000,100,1)");
|
||||
handle.pragma('foreign_keys = ON');
|
||||
|
||||
expect(() => runMigrations(handle, migrations)).toThrow('left broken references');
|
||||
|
||||
expect(handle.pragma('user_version', { simple: true })).toBe(upgrade.version - 1);
|
||||
expect(handle.pragma('foreign_keys', { simple: true })).toBe(1);
|
||||
expect(rows('auth_users')).toEqual(users);
|
||||
expect(
|
||||
handle.prepare("SELECT name FROM sqlite_master WHERE name='auth_users_moderator'").get()
|
||||
).toBeUndefined();
|
||||
handle.exec("DELETE FROM auth_sessions WHERE token_hash='orphan'");
|
||||
runMigrations(handle, migrations);
|
||||
expect(rows('auth_users')).toEqual(users);
|
||||
expect(handle.prepare('SELECT * FROM auth_sessions ORDER BY rowid').all()).toEqual(
|
||||
sessions
|
||||
);
|
||||
expect(handle.pragma('foreign_key_check')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user