Bound account requests and reject stale or malformed private responses
This commit is contained in:
+8
-24
@@ -6,34 +6,17 @@ import { sessionGuard } from './sessionGuard.js';
|
||||
*/
|
||||
import { getToken } from './auth.js';
|
||||
|
||||
const auth = () => ({ Authorization: `Bearer ${getToken()}`, 'Content-Type': 'application/json' });
|
||||
|
||||
async function iste(url, opts = {}) {
|
||||
const res = await fetch(url, { ...opts, headers: { ...auth(), ...(opts.headers || {}) } });
|
||||
const d = await res.json().catch(() => ({}));
|
||||
if (!d.success) {
|
||||
// nginx/proxy hataları JSON değil HTML döner; kullanıcıya anlamlı mesaj ver.
|
||||
const proxyMesaj = {
|
||||
413: 'Dosya sunucunun kabul ettiği boyutu aşıyor (en fazla 10 MB).',
|
||||
502: 'Sunucuya ulaşılamadı, biraz sonra tekrar deneyin.',
|
||||
504: 'Sunucu zamanında yanıt vermedi; büyük dosyada tekrar deneyin.',
|
||||
}[res.status];
|
||||
const e = new Error(d.error || proxyMesaj || `İstek başarısız (HTTP ${res.status})`);
|
||||
e.kod = d.kod;
|
||||
throw e;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
import { accountRequest as iste, requireArray, requireObject } from './accountRequest.js';
|
||||
|
||||
// --- Plan & kota ---
|
||||
export const getPlan = () => iste('/api/me/plan');
|
||||
|
||||
/** Belirli bir ihaleye yüklenmiş belgeler */
|
||||
export const listTenderDocuments = (ikn) =>
|
||||
iste(`/api/me/documents?ikn=${encodeURIComponent(ikn)}`).then((d) => d.belgeler || []);
|
||||
iste(`/api/me/documents?ikn=${encodeURIComponent(ikn)}`).then((d) => requireArray(d,'belgeler'));
|
||||
|
||||
// --- Kullanıcı verisi ---
|
||||
export const getAllUserData = () => iste('/api/me/data').then((d) => d.veri || {});
|
||||
export const getAllUserData = () => iste('/api/me/data').then((d) => requireObject(d,'veri'));
|
||||
export const setUserData = (anahtar, deger) =>
|
||||
iste('/api/me/data', { method: 'PUT', body: JSON.stringify({ anahtar, deger }) });
|
||||
|
||||
@@ -43,7 +26,7 @@ export const createApiKey = (ad) => apiKeyRequest('POST', { ad });
|
||||
export const revokeApiKey = (id) => apiKeyRequest('DELETE', { id });
|
||||
|
||||
// --- Belgeler ---
|
||||
export const listDocuments = () => iste('/api/me/documents');
|
||||
export const listDocuments = () => iste('/api/me/documents').then(d=>{requireArray(d,'belgeler');return d;});
|
||||
export const deleteDocument = (id) => iste(`/api/me/documents?id=${encodeURIComponent(id)}`, { method: 'DELETE' });
|
||||
|
||||
export async function uploadDocument(file, kategori, ikn, ek = {}) {
|
||||
@@ -56,6 +39,7 @@ export async function uploadDocument(file, kategori, ikn, ek = {}) {
|
||||
});
|
||||
if (!current()) throw new Error('Oturum değişti; dosyayı yeniden seçin.');
|
||||
return iste('/api/me/documents', {
|
||||
timeoutMs:120000,
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ ad: file.name, mime: file.type, kategori, ikn, icerikBase64, ...ek }),
|
||||
});
|
||||
@@ -106,12 +90,12 @@ export const telegramTest = () => iste('/api/me/telegram', { method: 'POST', bod
|
||||
export const telegramSil = () => iste('/api/me/telegram', { method: 'DELETE' });
|
||||
|
||||
// --- Takip bildirimleri (zeyilname / sonuç) ---
|
||||
export const bildirimleriGetir = () => iste('/api/me/bildirimler').then((d) => d.bildirimler || []);
|
||||
export const bildirimleriGetir = () => iste('/api/me/bildirimler').then((d) => requireArray(d,'bildirimler'));
|
||||
export const bildirimOkundu = (idler) => iste('/api/me/bildirimler', { method: 'POST', body: JSON.stringify({ idler }) });
|
||||
|
||||
export const getTenderStates = () => iste('/api/me/tender-state').then(d => d.records || {});
|
||||
export const getTenderStates = () => iste('/api/me/tender-state').then(d => requireObject(d,'records'));
|
||||
export const saveTenderState = (key, patch, snapshot, version) =>
|
||||
iste('/api/me/tender-state', {method:'PUT',body:JSON.stringify({key,patch,snapshot,version})}).then(d => d.record);
|
||||
iste('/api/me/tender-state', {method:'PUT',body:JSON.stringify({key,patch,snapshot,version})}).then(d => requireObject(d,'record'));
|
||||
|
||||
export const reportDocumentReadError = (id, expectedProcessing) =>
|
||||
iste('/api/me/documents/read-error', { method:'POST', body:JSON.stringify({id,expectedProcessing:expectedProcessing ?? null}) });
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import {getToken} from './auth.js';
|
||||
import {awaitWithAbort} from './abortable.js';
|
||||
|
||||
export async function accountRequest(url, {signal,timeoutMs=30000,...options}={}) {
|
||||
const token=getToken(), controller=new AbortController();
|
||||
const cancel=()=>controller.abort(signal.reason);
|
||||
if(signal?.aborted)cancel();else signal?.addEventListener('abort',cancel,{once:true});
|
||||
let timedOut=false;
|
||||
const timer=setTimeout(()=>{timedOut=true;controller.abort();},timeoutMs);
|
||||
const assertSession=()=>{if(getToken()!==token)throw new Error('Oturum değişti; güncel hesapla yeniden deneyin.');};
|
||||
try {
|
||||
controller.signal.throwIfAborted();
|
||||
const res=await awaitWithAbort(fetch(url,{...options,signal:controller.signal,headers:{'Content-Type':'application/json',...options.headers,Authorization:`Bearer ${token}`}}),controller.signal);
|
||||
assertSession();
|
||||
let data;
|
||||
try {data=await awaitWithAbort(res.json(),controller.signal);}
|
||||
catch(error) {controller.signal.throwIfAborted();if(!(error instanceof SyntaxError))throw error;}
|
||||
assertSession();
|
||||
if(!res.ok || data?.success!==true) {
|
||||
const proxy={413:'Dosya sunucunun kabul ettiği boyutu aşıyor (en fazla 10 MB).',502:'Sunucuya ulaşılamadı, biraz sonra tekrar deneyin.',504:'Sunucu zamanında yanıt vermedi.'};
|
||||
const error=new Error(data?.error || proxy[res.status] || `İstek başarısız (HTTP ${res.status}).`);
|
||||
error.kod=data?.kod;throw error;
|
||||
}
|
||||
return data;
|
||||
} catch(error) {
|
||||
assertSession();
|
||||
if(timedOut)throw new Error(!options.method || options.method==='GET'
|
||||
? 'Bilgiler zamanında alınamadı. Yeniden deneyin.'
|
||||
: 'İşlem sonucu zamanında alınamadı. Tekrar işlem yapmadan önce kaydı yenileyin; işlem sunucuda gerçekleşmiş olabilir.');
|
||||
throw error;
|
||||
} finally {clearTimeout(timer);signal?.removeEventListener('abort',cancel);}
|
||||
}
|
||||
export function requireArray(data,field) {
|
||||
if(!Array.isArray(data[field]))throw new Error('Sunucu listeyi eksik veya geçersiz döndürdü. Yeniden deneyin.');
|
||||
return data[field];
|
||||
}
|
||||
export function requireObject(data,field) {
|
||||
const value=data[field];
|
||||
if(!value || typeof value!=='object' || Array.isArray(value))throw new Error('Sunucu kayıtları eksik veya geçersiz döndürdü. Yeniden deneyin.');
|
||||
return value;
|
||||
}
|
||||
Reference in New Issue
Block a user