44 lines
1.5 KiB
JavaScript
44 lines
1.5 KiB
JavaScript
export const SUBJECTS = {
|
|
STATEMENT_GET: 'verae.billing.statement.get',
|
|
BALANCE_ADJUST: 'verae.billing.balance.adjust',
|
|
AUTHZ_CHECK: 'verae.access.authz.check',
|
|
};
|
|
const PLANE = 'staff';
|
|
|
|
async function authz(subject, payload) {
|
|
const http = process.env.AUTHZ_URL;
|
|
if (!http && !process.env.NATS_URL) return { allow: true, subject };
|
|
if (http) {
|
|
const r = await fetch(`${http.replace(/\/$/, '')}/check`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json' },
|
|
body: JSON.stringify({ plane: PLANE, subject, kind: payload?.kind, payload, principal: payload?.agent }),
|
|
});
|
|
return r.json();
|
|
}
|
|
return { allow: true, subject };
|
|
}
|
|
|
|
export async function billingRequest(subject, payload) {
|
|
const decision = await authz(subject, payload);
|
|
if (decision && decision.allow === false) {
|
|
const err = new Error(decision.reason || 'denied');
|
|
err.status = 403;
|
|
err.decision = decision;
|
|
throw err;
|
|
}
|
|
const url = process.env.NATS_URL;
|
|
if (!url) return null;
|
|
try {
|
|
const { connect, StringCodec } = await import('nats');
|
|
const nc = await connect({ servers: url.split(','), name: 'zappier-customer-service' });
|
|
const sc = StringCodec();
|
|
const m = await nc.request(subject, sc.encode(JSON.stringify({ ...payload, plane: PLANE })), { timeout: 2000 });
|
|
const out = JSON.parse(sc.decode(m.data) || '{}');
|
|
await nc.close();
|
|
return out;
|
|
} catch (err) {
|
|
if (err.status === 403) throw err;
|
|
return null;
|
|
}
|
|
}
|