import { test } from 'node:test' import assert from 'node:assert/strict' import { canUseSession } from '../../lib/session-access' import { EMPTY_SITE_PAGES, isSafeMediaUrl, isAllowedEmbedUrl, validateSitePages } from '../../lib/site-pages' import { validateUserInput } from '../../lib/user-validation' test('sessions fail closed after account changes, deletion or suspension', () => { const user = { role: 'ADMIN', isActive: true, updatedAt: new Date(1000) } assert.equal(canUseSession(user, 1001), true) for (const candidate of [null, {...user,isActive:false}, {...user,role:'USER'}, {...user,updatedAt:new Date(2000)}]) assert.equal(canUseSession(candidate, 1001), false) assert.equal(canUseSession(user, undefined), false) }) test('media allowlist rejects normalized foreign origins and credentials', () => { for (const url of ['//evil.example/a', '/'+String.fromCharCode(92)+'evil.example/a','javascript:alert(1)','https://evil.example/a','https://signlanguage.alangu.de.evil.example/a','https://user:pass@signlanguage.alangu.de/player/']) assert.equal(isSafeMediaUrl(url), false, url) assert.equal(isSafeMediaUrl('/videos/dgs.mp4'), true) assert.equal(isAllowedEmbedUrl('https://signlanguage.alangu.de/player/?subtitle=true'), true) }) test('partial updates, placeholder publication and unpublishing are rejected', () => { const previous = {...EMPTY_SITE_PAGES, accessibility:'Veröffentlichte Erklärung'} assert.ok(validateSitePages({}, previous).length) assert.ok(validateSitePages({...EMPTY_SITE_PAGES}, previous).length) assert.ok(validateSitePages({...previous,accessibility:'{{STATUS}}'},previous).length) assert.deepEqual(validateSitePages({...previous,accessibility:'Neue Erklärung'},previous),[]) }) test('user input rejects unexpected roles, invalid types and bcrypt truncation', () => { const valid={email:'admin@example.org',role:'ADMIN',password:'A-safe-test-password'} assert.equal(validateUserInput(valid,true),null) for (const data of [{...valid,role:'ROOT'},{...valid,password:123},{...valid,password:'ü'.repeat(40)},{...valid,isActive:'false'}]) assert.ok(validateUserInput(data,true)) }) test('policy inputs reject objects and booleans in text fields without throwing', async () => { const {parsePolicyInput}=await import('../../lib/policy-input') for(const value of [null,[],{title:123},{recipients:{}},{isPublic:'false'},{legalBasis:['text']}]) assert.equal(parsePolicyInput(value),null) const data=parsePolicyInput({title:' Beispiel ',processingDescription:'Verarbeitung',recipients:'Amt',isPublic:false}) assert.equal(data?.title,'Beispiel') assert.equal(data?.isPublic,false) assert.equal(data?.responsible,null) })