This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import {test} from 'node:test';
|
||||
import {iframeCode,viewerURL,mountShare} from './share.js';
|
||||
const base='https://render.sadentel.net';
|
||||
for(const path of ['/view/','/compare/','/view/pcb/','/compare/pcb/']){
|
||||
test(`share ${path} preserves the private capability`,()=>{
|
||||
const url=viewerURL(path+'a'.repeat(48),'read-token',base);
|
||||
const code=iframeCode(url,base);
|
||||
assert.ok(code.includes(`src="${base}${path}${'a'.repeat(48)}#token=read-token"`));
|
||||
assert.ok(code.includes('width="100%"')&&code.includes('height="800"'));
|
||||
assert.equal(new URL(url).search,'');
|
||||
assert.ok(!code.includes('X-API-Key'));
|
||||
});
|
||||
}
|
||||
test('unlisted iframe does not gain a token',()=>{
|
||||
assert.ok(!iframeCode('/view/'+'a'.repeat(48),base).includes('#token='));
|
||||
});
|
||||
test('iframe escapes attributes and rejects executable URL schemes',()=>{
|
||||
const code=iframeCode(base+'/view/test?x=1&y=2#token=" onload="bad',base);
|
||||
assert.ok(!code.includes(' onload="bad'));
|
||||
assert.ok(code.includes('%22') && code.includes('&'));
|
||||
for(const url of ['javascript:alert(1)','data:text/html,hello','https://user:secret@example.test/view/id'])assert.throws(()=>iframeCode(url,base));
|
||||
});
|
||||
|
||||
test('Share reveals the iframe and copies its read token without sending a request',async t=>{
|
||||
class Element {
|
||||
constructor(){this.children=[];this.events={};this.attributes={};}
|
||||
append(...items){this.children.push(...items);}
|
||||
setAttribute(key,value){this.attributes[key]=value;}
|
||||
addEventListener(name,callback){this.events[name]=callback;}
|
||||
focus(){} select(){}
|
||||
}
|
||||
const saved=new Map(['document','location','navigator'].map(key=>[key,Object.getOwnPropertyDescriptor(globalThis,key)]));
|
||||
let copied='';
|
||||
Object.defineProperty(globalThis,'document',{configurable:true,value:{createElement:()=>new Element()}});
|
||||
Object.defineProperty(globalThis,'location',{configurable:true,value:{origin:base}});
|
||||
Object.defineProperty(globalThis,'navigator',{configurable:true,value:{clipboard:{writeText:async code=>{copied=code;}}}});
|
||||
t.after(()=>{for(const [key,descriptor]of saved)if(descriptor)Object.defineProperty(globalThis,key,descriptor);else delete globalThis[key];});
|
||||
const host=new Element();mountShare(host,base+'/view/'+'a'.repeat(48)+'#token=private-read');
|
||||
const [toggle,panel]=host.children[0].children;
|
||||
assert.equal(panel.hidden,true);toggle.events.click();assert.equal(panel.hidden,false);
|
||||
const textarea=panel.children[1],copy=panel.children[3];
|
||||
assert.ok(textarea.value.includes('#token=private-read'));assert.equal(textarea.readOnly,true);
|
||||
await copy.events.click();assert.equal(copied,textarea.value);
|
||||
toggle.events.click();assert.equal(panel.hidden,true);
|
||||
});
|
||||
مرجع در شماره جدید
مسدود کردن کاربر