Files
dsh-web/scripts/test-orphan-live.mjs

24 lines
2.5 KiB
JavaScript

import assert from 'node:assert/strict';
import {readFileSync,mkdirSync,existsSync} from 'node:fs';
import {execFileSync} from 'node:child_process';
import {randomBytes} from 'node:crypto';
const base=process.env.TEST_PANEL_URL, root=process.env.TEST_DATA_ROOT;
assert.ok(base&&root&&process.env.TEST_PASSWORD_FILE);
let cookie='',csrf='';
async function req(path,method='GET',body){const r=await fetch(base+path,{method,headers:{Cookie:cookie,Origin:base,'X-CSRF-Token':csrf,...(body instanceof FormData?{}:{'Content-Type':'application/json'})},body:body===undefined?undefined:body instanceof FormData?body:JSON.stringify(body)});if(path==='/api/login')cookie=r.headers.getSetCookie().map(x=>x.split(';')[0]).join('; ');return {status:r.status,data:await r.json()};}
const login=await req('/api/login','POST',{username:'admin',password:readFileSync(process.env.TEST_PASSWORD_FILE,'utf8').trim()});assert.equal(login.status,200);csrf=login.data.csrf_token;
const uid=login.data.user.id, inst=randomBytes(16).toString('hex'), home=root+'/workspaces/'+uid+'/instances/'+inst+'/home', workspace=root+'/workspaces/'+uid+'/files';
mkdirSync(home,{recursive:true});
const id=execFileSync('docker',['create','--name','dsh-inst-'+inst,'--label','dsh-mgr.role=dsh','--label','dsh-mgr.instance='+inst,'--label','dsh-mgr.owner='+uid,'--mount','type=bind,source='+home+',target=/data/dsh-home','--mount','type=bind,source='+workspace+',target=/workspace','--entrypoint','/bin/true','dsh-web:0.2.0-rc.2-2'],{encoding:'utf8'}).trim();
assert.ok((await req('/api/orphans')).data.includes(id));
assert.equal((await req('/api/orphans?id='+id+'&confirm=wrong','DELETE')).status,400);
assert.equal((await req('/api/orphans?id='+id+'&confirm='+id,'DELETE')).status,200);
assert.ok(existsSync(home));assert.ok(existsSync(workspace));
assert.ok(!(await req('/api/orphans')).data.includes(id));
console.log('PASS real stopped orphan reclaimed, confirmation enforced, bind directories retained');
const denied=new FormData();denied.set('path','.');denied.set('file',new Blob(['harmless fixture']),'design-denied.exe');
assert.equal((await req('/api/ws/upload','POST',denied)).status,415);
const name='design-allowed-'+inst+'.txt', allowed=new FormData();allowed.set('path','.');allowed.set('file',new Blob(['harmless fixture']),name);
assert.equal((await req('/api/ws/upload','POST',allowed)).status,200);assert.equal((await req('/api/ws/delete?path='+name,'DELETE')).status,200);
console.log('PASS configured upload whitelist accepts .txt and rejects .exe');