60 lines
4.3 KiB
JavaScript
60 lines
4.3 KiB
JavaScript
import fs from 'node:fs/promises';
|
|
import assert from 'node:assert/strict';
|
|
|
|
const base = 'http://127.0.0.1:8001';
|
|
const fixture = JSON.parse(await fs.readFile('C:/laragon/data/sgf-tempo/secrets/browser-fixture.json', 'utf8'));
|
|
const results = [];
|
|
function client() {
|
|
const cookies = new Map();
|
|
let csrf = ''; let context = '';
|
|
return {
|
|
cookies,
|
|
async request(path, method = 'GET', body, {token = context, csrfHeader = true} = {}) {
|
|
const headers = {Accept:'application/json', 'Content-Type':'application/json', Cookie:[...cookies].map(([k,v]) => `${k}=${v}`).join('; '), 'X-SGF-Context':token};
|
|
if (csrfHeader) headers['X-CSRF-TOKEN'] = csrf;
|
|
const response = await fetch(base+path, {method, headers, ...(body === undefined ? {} : {body:JSON.stringify(body)})});
|
|
for (const cookie of response.headers.getSetCookie()) { const pair=cookie.split(';',1)[0]; const split=pair.indexOf('='); cookies.set(pair.slice(0,split),pair.slice(split+1)); }
|
|
const data = await response.json().catch(() => ({}));
|
|
if (data.csrf) csrf=data.csrf;
|
|
if (data.context?.token) context=data.context.token;
|
|
return {status:response.status,data};
|
|
},
|
|
async login(email) {
|
|
assert.equal((await this.request('/api/session')).status,200);
|
|
assert.equal((await this.request('/api/login','POST',{email,password:fixture.password})).status,200);
|
|
},
|
|
async select(company=fixture.company,unit=fixture.unit) {
|
|
const result=await this.request('/api/context','POST',{tenant_id:fixture.tenant,company_id:company,unit_id:unit});
|
|
assert.equal(result.status,200); return result.data.context.token;
|
|
}
|
|
};
|
|
}
|
|
const manager=client(); await manager.login('gestor@example.test'); const token=await manager.select();
|
|
assert.equal((await manager.request(`/api/companies/${fixture.company}`,'PATCH',{name:'CSRF must refuse'},{csrfHeader:false})).status,419);
|
|
results.push('CSRF: pedido de alteração sem token/origem válida recusado (419).');
|
|
const reader=client(); await reader.login('consulta@example.test'); const readerToken=await reader.select();
|
|
assert.equal((await reader.request(`/api/companies/${fixture.sibling}`)).status,403);
|
|
assert.equal((await reader.request(`/api/units/${fixture.hidden}`)).status,403);
|
|
assert.equal((await reader.request(`/api/companies/${fixture.company}`,'PATCH',{name:'Not allowed'})).status,403);
|
|
results.push('URLs/API: empresa do mesmo tenant e unidade sem acesso recusadas; consulta não permite edição (403).');
|
|
const grant={email:'consulta@example.test',permission:'company.edit',reason:'Prova HTTP sintética'};
|
|
assert.equal((await manager.request('/api/accesses','POST',grant)).status,200);
|
|
assert.equal((await reader.request(`/api/companies/${fixture.company}`,'PATCH',{name:'Empresa Horizonte — Prova HTTP'})).status,200);
|
|
assert.equal((await manager.request('/api/accesses/revoke','POST',grant)).status,200);
|
|
assert.equal((await reader.request(`/api/companies/${fixture.company}`,'PATCH',{name:'Revoked'})).status,403);
|
|
results.push('Concessão e revogação: efeito no pedido seguinte em sessão independente (200 → 403).');
|
|
await manager.select(fixture.sibling,null);
|
|
assert.equal((await manager.request(`/api/companies/${fixture.company}`,'PATCH',{name:'Stale'},{token})).status,409);
|
|
results.push('Formulário anterior à mudança de contexto recusado (409).');
|
|
const limited=client(); await limited.login('limitado@example.test'); await limited.select();
|
|
assert.equal((await limited.request('/api/accesses','POST',grant)).status,403);
|
|
results.push('Gestor limitado não consegue conceder edição que não possui (403).');
|
|
const oldCookies=new Map(reader.cookies);
|
|
assert.equal((await reader.request('/api/logout','POST')).status,200);
|
|
reader.cookies.clear(); for(const [key,value] of oldCookies) reader.cookies.set(key,value);
|
|
assert.equal((await reader.request('/api/context')).status,401);
|
|
results.push('Replay do cookie da sessão terminada recusado (401).');
|
|
await manager.request('/api/logout','POST'); await limited.request('/api/logout','POST');
|
|
await fs.writeFile(new URL('../docs/proofs/http-results.json',import.meta.url),JSON.stringify({environment:'sgf_tempo_test, browser-testing, localhost:8001',results},null,2));
|
|
console.log(results.join('\n'));
|