fix: enforce private feedback access across list and detail
Deploy EG-BIM QA Gateway / deploy (push) Successful in 50s

This commit is contained in:
root committed 2026-11-13 10:28:00 +09:00
1 parent e2e70c13ac
commit a5a5f24f92
10 files changed
+379 -24

No files matched your search

+40
View File
@@ -209,4 +209,44 @@ try {
await context.close();
}
for (const scenario of ['private-upstream-leak', 'private-upstream-denied']) {
const context = await browser.newContext();
const page = await context.newPage();
const commentRequests = [];
const secret = {id:id(1),requester_id:OWNER,is_secret:true,title:'PRIVATE_TITLE',contents:'PRIVATE_BODY',attachments:[{url:'/fixture/PRIVATE_FILE'}]};
await context.addInitScript(({secret}) => {
localStorage.setItem('baron.qa.posts.egbim',JSON.stringify([{...secret,secret:true,content:'PRIVATE_CACHED_BODY'}]));
localStorage.setItem('baron.qa.comments.egbim',JSON.stringify({[secret.id]:[{content:'PRIVATE_CACHED_COMMENT'}]}));
},{secret});
await page.route('**/*',async route => {
const url = new URL(route.request().url());
if(url.origin!=='https://qa.example.test') return route.abort();
const send = (body,status=200) => route.fulfill({status,contentType:'application/json',body:JSON.stringify(body)});
if(url.pathname==='/auth/session') return send({authenticated:true,user:{requesterId:'another-user',name:'동명이인'}});
if(url.pathname==='/api/feedbacks') return send({items:[secret],meta:{total:1}});
if(url.pathname.endsWith('/comments')) {commentRequests.push(url.pathname);return send({comments:[{content:'PRIVATE_COMMENT'}]});}
if(url.pathname==='/api/feedbacks/'+id(1)) return scenario==='private-upstream-denied' ? send({error:'private_feedback_forbidden'},403) : send({feedback:secret});
try {
const path=url.pathname.endsWith('/')?url.pathname+'index.html':url.pathname;
const contentType=path.endsWith('.css')?'text/css':path.endsWith('.js')?'application/javascript':path.endsWith('.html')?'text/html':'application/octet-stream';
return route.fulfill({contentType,body:await readFile(root+path)});
} catch {return route.abort();}
});
await page.goto('https://qa.example.test/egbim/');
await page.waitForFunction(()=>document.querySelector('#qaRows').textContent.includes('비밀글입니다.'));
assert.doesNotMatch(await page.locator('#qaRows').textContent(),/PRIVATE_/);
assert.equal(await page.locator('#qaRows tr a').count(),0);
await page.locator('#qaRows tr').click();
assert.equal(await page.locator('#detailModal').isVisible(),false);
await page.goto('https://qa.example.test/egbim/?view=detail&id='+id(1));
await page.waitForFunction(()=>document.querySelector('[data-detail-title]')?.textContent==='비밀글입니다.');
assert.doesNotMatch(await page.locator('#detailModal').textContent(),/PRIVATE_/);
assert.equal(await page.locator('#commentForm').isVisible(),false);
assert.equal(await page.locator('#editButton').isVisible(),false);
assert.equal(await page.locator('#deleteButton').isVisible(),false);
assert.equal(await page.locator('[data-detail-attachments] a').count(),0);
assert.deepEqual(commentRequests,[]);
console.log(JSON.stringify({scenario,result:'PASS'}));
await context.close();
}
}finally{await browser.close();}