All checks were successful
Container-Image bauen und veröffentlichen / build-and-push (push) Successful in 5m15s
43 lines
2.6 KiB
TypeScript
43 lines
2.6 KiB
TypeScript
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)
|
|
})
|