validate notification payload JSON

This commit is contained in:
2026-09-06 17:31:52 +03:00
parent 19b79c32a7
commit 89b9a85227
+13 -2
View File
@@ -28,6 +28,15 @@ function parseArrayJson(raw, label) {
throw new Error(`${label} verisi bozuk; bildirim işlemi durduruldu.`); throw new Error(`${label} verisi bozuk; bildirim işlemi durduruldu.`);
} }
} }
function parseObjectJson(raw, label) {
try {
const value = JSON.parse(raw || '{}');
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('nesne değil');
return value;
} catch {
throw new Error(`${label} verisi bozuk; bildirim işlemi durduruldu.`);
}
}
const SCHEMA = ` const SCHEMA = `
CREATE TABLE IF NOT EXISTS abonelikler ( CREATE TABLE IF NOT EXISTS abonelikler (
@@ -223,7 +232,9 @@ export function reserveDelivery(subscriptionId,payload,tenderIds,{clock=Date.now
if(row.state==='sending'&&row.lease_until>clock){db.exec('COMMIT');return null;} if(row.state==='sending'&&row.lease_until>clock){db.exec('COMMIT');return null;}
const lease=randomUUID(); const lease=randomUUID();
db.prepare("UPDATE notification_outbox SET state='sending',first_attempt=COALESCE(first_attempt,?),lease=?,lease_until=? WHERE id=?").run(clock,lease,clock+120000,row.id); db.prepare("UPDATE notification_outbox SET state='sending',first_attempt=COALESCE(first_attempt,?),lease=?,lease_until=? WHERE id=?").run(clock,lease,clock+120000,row.id);
db.exec('COMMIT');return {id:row.id,lease,payload:JSON.parse(row.payload),tenderIds:JSON.parse(row.tender_ids)}; const reservedPayload=parseObjectJson(row.payload, 'Bildirim');
const reservedTenderIds=parseArrayJson(row.tender_ids, 'İhale');
db.exec('COMMIT');return {id:row.id,lease,payload:reservedPayload,tenderIds:reservedTenderIds};
}catch(error){try{db.exec('ROLLBACK');}catch{}throw error;}finally{db.close();} }catch(error){try{db.exec('ROLLBACK');}catch{}throw error;}finally{db.close();}
} }
export function acceptDelivery(delivery,providerId) { export function acceptDelivery(delivery,providerId) {
@@ -258,7 +269,7 @@ export function holdDelivery(delivery,reason) {
export function deliveryQueue() { export function deliveryQueue() {
const db=open(); const db=open();
try{return db.prepare("SELECT o.*,r.actor,r.action,r.note,r.reviewed_at FROM notification_outbox o LEFT JOIN notification_outbox_reviews r ON r.id=o.id WHERE o.state IN ('pending','sending','uncertain','sent_manual','skipped') ORDER BY o.first_attempt DESC LIMIT 50").all().map(row=>{ try{return db.prepare("SELECT o.*,r.actor,r.action,r.note,r.reviewed_at FROM notification_outbox o LEFT JOIN notification_outbox_reviews r ON r.id=o.id WHERE o.state IN ('pending','sending','uncertain','sent_manual','skipped') ORDER BY o.first_attempt DESC LIMIT 50").all().map(row=>{
const payload=JSON.parse(row.payload); const payload=parseObjectJson(row.payload, 'Bildirim');
return {id:row.id,subscriptionId:row.subscription_id,to:payload.to,subject:payload.subject,state:row.state,error:row.error, return {id:row.id,subscriptionId:row.subscription_id,to:payload.to,subject:payload.subject,state:row.state,error:row.error,
firstAttempt:row.first_attempt,providerId:row.provider_id,review:row.action?{actor:row.actor,action:row.action,note:row.note,at:row.reviewed_at}:null}; firstAttempt:row.first_attempt,providerId:row.provider_id,review:row.action?{actor:row.actor,action:row.action,note:row.note,at:row.reviewed_at}:null};
});}finally{db.close();} });}finally{db.close();}