chore: CRM-NEW baseline
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const { signHS256, verifyHS256 } = require('../src/jwt');
|
||||
const { createIdentity } = require('../src/identity');
|
||||
|
||||
const SECRET = 'test-inbox-secret';
|
||||
|
||||
function decode(jwt) {
|
||||
return JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString('utf8'));
|
||||
}
|
||||
|
||||
test('jwt: sign/verify roundtrip + tamper detection', () => {
|
||||
const token = signHS256({ external_user_id: 'cust-1', email: 'a@b.c' }, SECRET, 60);
|
||||
const payload = verifyHS256(token, SECRET);
|
||||
assert.equal(payload.external_user_id, 'cust-1');
|
||||
assert.equal(payload.email, 'a@b.c');
|
||||
|
||||
const [h, c, s] = token.split('.');
|
||||
const tampered = `${h}.${c}.${s.slice(0, -1)}x`;
|
||||
assert.equal(verifyHS256(tampered, SECRET), null);
|
||||
assert.equal(verifyHS256(token, 'wrong-secret'), null);
|
||||
});
|
||||
|
||||
test('identity: dev mode issues LibreDesk widget JWT', async () => {
|
||||
const identity = createIdentity({
|
||||
libredeskInboxSecret: SECRET,
|
||||
identityDevMode: true,
|
||||
identityTtlSec: 120,
|
||||
siteJwtSecret: '',
|
||||
memberRpcUrl: '',
|
||||
rpcTimeoutMs: 1000,
|
||||
});
|
||||
const out = await identity.issue({ email: 'Customer@Example.com', externalUserId: 'cust-9', firstName: 'Jan' });
|
||||
const claims = decode(out.userJWT);
|
||||
assert.equal(claims.external_user_id, 'cust-9');
|
||||
assert.equal(claims.email, 'customer@example.com');
|
||||
assert.equal(claims.first_name, 'Jan');
|
||||
assert.ok(claims.exp > Math.floor(Date.now() / 1000));
|
||||
});
|
||||
|
||||
test('identity: site token mode verifies HS256 and resolves email via RPC', async () => {
|
||||
const siteToken = signHS256({ userId: 12345, type: 2, tenantId: 't1' }, 'site-secret', 60);
|
||||
const rpc = {
|
||||
calls: [],
|
||||
async call(addr, method, params) {
|
||||
this.calls.push({ addr, method, params });
|
||||
return { result: { email: 'buyer@example.nl' } };
|
||||
},
|
||||
};
|
||||
const identity = createIdentity(
|
||||
{
|
||||
libredeskInboxSecret: SECRET,
|
||||
identityDevMode: false,
|
||||
identityTtlSec: 60,
|
||||
siteJwtSecret: 'site-secret',
|
||||
memberRpcUrl: 'jsonrpc://member:1',
|
||||
rpcTimeoutMs: 1000,
|
||||
},
|
||||
{ rpc }
|
||||
);
|
||||
const out = await identity.issue({ token: siteToken });
|
||||
const claims = decode(out.userJWT);
|
||||
assert.equal(claims.external_user_id, '12345');
|
||||
assert.equal(claims.email, 'buyer@example.nl');
|
||||
assert.equal(rpc.calls[0].method, '/customer/getBasicByCustomerId');
|
||||
assert.equal(rpc.calls[0].params[0].customerId, '12345');
|
||||
});
|
||||
|
||||
test('identity: rejects bad site token and unknown origin mode', async () => {
|
||||
const identity = createIdentity(
|
||||
{ libredeskInboxSecret: SECRET, identityDevMode: false, identityTtlSec: 60, siteJwtSecret: 'site-secret', memberRpcUrl: '', rpcTimeoutMs: 1000 },
|
||||
{ rpc: { call: async () => ({}) } }
|
||||
);
|
||||
await assert.rejects(() => identity.issue({ token: 'not-a-jwt' }), /invalid or expired/);
|
||||
await assert.rejects(() => identity.issue({ email: 'x@y.z' }), /token is required/);
|
||||
});
|
||||
Reference in New Issue
Block a user