import { test } from 'node:test' import assert from 'node:assert/strict' import http from 'node:http' import { mkdtemp, mkdir, writeFile, readFile, symlink, rm, stat, chmod } from 'node:fs/promises' import os from 'node:os' import path from 'node:path' import { createApp } from './app.mjs' const password='test-only-password-123456' async function fixture(t) { const dir=await mkdtemp(path.join(os.tmpdir(),'deskweb-test-')) await mkdir(path.join(dir,'dist'));await writeFile(path.join(dir,'dist/index.html'),'DeskWEB test') await mkdir(path.join(dir,'output')) const requests=[] const upstream=http.createServer(async(req,res)=>{ const chunks=[];for await(const chunk of req)chunks.push(chunk) requests.push({url:req.url,method:req.method,authorization:req.headers.authorization,body:Buffer.concat(chunks).toString()}) res.setHeader('Content-Type','application/json');res.setHeader('Set-Cookie','upstream-secret=hidden') if(req.url==='/api/fail'){res.writeHead(422);res.end('{"detail":"native validation"}');return} res.end('{"status":"ok"}') }) await new Promise(r=>upstream.listen(0,'127.0.0.1',r)) const app=await createApp({password,backendUrl:`http://127.0.0.1:${upstream.address().port}`,backendToken:'test-upstream-token',dist:path.join(dir,'dist'),roots:[{local:path.join(dir,'input'),backend:'/ltx/inputs',writable:true},{local:path.join(dir,'output'),backend:'/ltx/outputs'}],uploadLimit:1024}) await new Promise(r=>app.listen(0,'127.0.0.1',r)) t.after(async()=>{app.closeAllConnections();upstream.closeAllConnections();await Promise.all([new Promise(r=>app.close(r)),new Promise(r=>upstream.close(r))]);await rm(dir,{recursive:true,force:true})}) const base=`http://127.0.0.1:${app.address().port}` const login=await fetch(base+'/web/login',{method:'POST',headers:{'X-Deskweb-Request':'1'},body:JSON.stringify({password})}) assert.equal(login.status,200) const cookie=login.headers.get('set-cookie').split(';')[0] const call=(route,init={})=>fetch(base+route,{...init,headers:{Cookie:cookie,'X-Deskweb-Request':'1',...init.headers}}) return {dir,base,call,requests,cookie} } test('sign-in required; secret never returned; logout invalidates session',async t=>{ const {base,call}=await fixture(t) assert.equal((await fetch(base+'/web/session')).status,401) const session=await call('/web/session');assert.equal(session.status,200);assert.ok(!(await session.text()).includes('test-upstream-token')) assert.equal((await call('/web/logout',{method:'POST'})).status,200) assert.equal((await call('/web/session')).status,401) }) test('native API bytes, query, method and validation errors pass through; browser token replaced',async t=>{ const {call,requests}=await fixture(t) const body='{"prompt":"synthetic test","width":768,"custom_native_field":true}' const response=await call('/ltx/api/generate?native=1',{method:'POST',headers:{Authorization:'Bearer browser-value','Content-Type':'application/json'},body}) assert.equal(response.status,200);assert.equal(response.headers.get('set-cookie'),null) assert.deepEqual(requests[0],{url:'/api/generate?native=1',method:'POST',authorization:'Bearer test-upstream-token',body}) const invalid=await call('/ltx/api/fail');assert.equal(invalid.status,422);assert.equal(await invalid.text(),'{"detail":"native validation"}') }) test('reject cross-site and arbitrary upstream routes',async t=>{ const {call}=await fixture(t) assert.equal((await call('/ltx/api/generate',{method:'POST',headers:{Origin:'https://evil.example'}})).status,403) assert.equal((await call('/web/media?path=/ltx/outputs/a.mp4',{headers:{'Sec-Fetch-Site':'cross-site'}})).status,403) assert.equal((await call('/ltx//evil.example/api/generate')).status,404) }) test('upload, backend path, range playback and existence check',async t=>{ const {call,dir}=await fixture(t) const upload=await call('/web/upload?name=clip.mp4',{method:'POST',body:'0123456789'}) assert.equal(upload.status,201);const result=await upload.json();assert.ok(result.path.startsWith('/ltx/inputs/')) assert.equal((await stat(path.join(dir,'input',path.basename(result.path)))).mode & 0o777,0o640) assert.equal(await readFile(path.join(dir,'input',path.basename(result.path)),'utf8'),'0123456789') const media=await call('/web/media?path='+encodeURIComponent(result.path),{headers:{Range:'bytes=2-5'}}) assert.equal(media.status,206);assert.equal(media.headers.get('content-range'),'bytes 2-5/10');assert.equal(await media.text(),'2345') const exists=await call('/web/files',{method:'POST',body:JSON.stringify({action:'exists',paths:[result.path,'/etc/passwd']})}) assert.deepEqual(await exists.json(),{[result.path]:true,'/etc/passwd':false}) }) test('prevent file traversal, symlink escape, active file uploads, oversized uploads',async t=>{ const {call,dir}=await fixture(t) await writeFile(path.join(dir,'secret.mp4'),'hidden');await symlink(path.join(dir,'secret.mp4'),path.join(dir,'output','link.mp4')) for(const p of ['/etc/passwd','/ltx/outputs/../../secret.mp4','/ltx/outputs/link.mp4'])assert.equal((await call('/web/media?path='+encodeURIComponent(p))).status,403) assert.equal((await call('/web/upload?name=script.html',{method:'POST',body:'