Turn lab IAM on, move portal to access-web, harden sessions and receipts.
Some checks are pending
offline / test (push) Waiting to run
Some checks are pending
offline / test (push) Waiting to run
Fleet and department doors now check STAFF_IAM_URL. Walkthrough: cs can credit (agent is the IAM user) and cannot export; operator can fleet POST; admin /me is owner. Portal is the public web door at :3021/portal/. IAM sessions persist; login is rate-limited per user; receipt PDF is branded. lan-134 stays disabled.
This commit is contained in:
parent
d299d245e8
commit
c32b65038a
20 changed files with 277 additions and 73 deletions
|
|
@ -23,7 +23,7 @@ export async function iamCheck(req, permission) {
|
|||
|
||||
export async function denyOrRedirect(req, res, json, { permission, html }) {
|
||||
const out = await iamCheck(req, permission);
|
||||
if (out.ok) return true;
|
||||
if (out.ok) return out;
|
||||
const login = iamBase() || (process.env.STAFF_SESSION_URL || 'http://127.0.0.1:3028').replace(/\/$/, '');
|
||||
if (html) {
|
||||
res.writeHead(302, { location: `${login}/login?next=${encodeURIComponent('http://' + (req.headers.host || '127.0.0.1') + '/')}` });
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ const server = http.createServer(async (req, res) => {
|
|||
return json(200, { ok: true, role: 'zappier-customer-service', nats: Boolean(process.env.NATS_URL) });
|
||||
}
|
||||
if (req.method === 'GET' && url.pathname === '/customers') {
|
||||
if (!(await denyOrRedirect(req, res, json, { permission: 'cs.review' }))) return;
|
||||
return json(200, { customers: await listCustomers(EDGE, KEY) });
|
||||
}
|
||||
const review = url.pathname.match(/^\/review\/([^/]+)$/);
|
||||
|
|
@ -64,11 +65,13 @@ const server = http.createServer(async (req, res) => {
|
|||
return json(out.status, out.body);
|
||||
}
|
||||
if (req.method === 'POST' && url.pathname === '/credits') {
|
||||
if (!(await denyOrRedirect(req, res, json, { permission: 'cs.credit' }))) return;
|
||||
const who = await denyOrRedirect(req, res, json, { permission: 'cs.credit' });
|
||||
if (!who) return;
|
||||
const chunks = [];
|
||||
for await (const c of req) chunks.push(c);
|
||||
const payload = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}');
|
||||
const nats = await billingRequest(SUBJECTS.BALANCE_ADJUST, { ...payload, kind: 'credit' });
|
||||
if (who.user?.username) payload.agent = who.user.username;
|
||||
const nats = await billingRequest(SUBJECTS.BALANCE_ADJUST, { ...payload, kind: 'credit', principal: payload.agent });
|
||||
if (nats) return json(200, { ...nats, source: 'nats' });
|
||||
const r = await fetch(`${BOOKS}/adjust`, {
|
||||
method: 'POST',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue