17 lines
1.8 KiB
JavaScript
17 lines
1.8 KiB
JavaScript
/** Authenticated read with the existing context guard; no token in URL/history. */
|
|
async function verifiedCsvDownload({id,token,sha256,isCurrent,pathForId,fetcher=fetch}){
|
|
if(!Number.isSafeInteger(Number(id))||Number(id)<1||!token||!/^[a-f0-9]{64}$/.test(sha256))throw Error('Resultado ou SHA indisponível. Consulte novamente.');
|
|
const check=()=>{if(!isCurrent())throw Error('O contexto mudou. A descarga anterior foi ignorada.');};check();
|
|
const response=await fetcher(pathForId(Number(id)),{credentials:'same-origin',headers:{Accept:'text/csv','X-SGF-Context':token}});check();
|
|
if(!response.ok){const problem=await response.json().catch(()=>({}));const error=Error(problem.message||'Não foi possível descarregar este resultado revisto.');error.status=response.status;throw error;}
|
|
if(!/^text\/csv(?:;|$)/i.test(response.headers.get('content-type')??'')||response.headers.get('x-content-sha256')!==sha256)throw Error('A resposta não corresponde à exportação congelada.');
|
|
const bytes=await response.arrayBuffer();check();const digest=await crypto.subtle.digest('SHA-256',bytes);check();const actual=[...new Uint8Array(digest)].map(n=>n.toString(16).padStart(2,'0')).join('');if(actual!==sha256)throw Error('O ficheiro não confere com o SHA conservado.');return{bytes,sha256:actual};
|
|
}
|
|
|
|
export const statementDownload=args=>verifiedCsvDownload({...args,pathForId:id=>'/api/general-ledger/statements/exports/'+id});
|
|
export const fiscalMapDownload=args=>verifiedCsvDownload({...args,pathForId:id=>'/api/fiscal-assessments/forms/'+id+'/export'});
|
|
|
|
export const remunerationDownload=args=>verifiedCsvDownload({...args,pathForId:id=>'/api/remunerations/exports/'+id});
|
|
|
|
export const personnelDownload=args=>verifiedCsvDownload({...args,pathForId:id=>'/api/hr-personnel/exports/'+id});
|