mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
96 lines
3.0 KiB
JavaScript
96 lines
3.0 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const { test } = require('node:test');
|
|
const {
|
|
createLocalOwnerCredentialRecoveryService,
|
|
} = require('../dist/credential-recovery');
|
|
|
|
test('issues a distinct credential and replays acknowledged completion', async () => {
|
|
const previous = {
|
|
credentialId: `own_${'a'.repeat(22)}`,
|
|
version: 1,
|
|
pepperKeyId: 'owner-key-1',
|
|
state: 'active',
|
|
subject: { type: 'user', id: `usr_${'b'.repeat(22)}` },
|
|
subjectStatus: 'active',
|
|
secretDigest: '1'.repeat(64),
|
|
createdAtMs: 100,
|
|
notBeforeAtMs: 100,
|
|
expiresAtMs: 100000000,
|
|
};
|
|
let recovery = null;
|
|
const credentials = {
|
|
async resolve(credentialId) {
|
|
return credentialId === previous.credentialId ? previous : null;
|
|
},
|
|
};
|
|
const repository = {
|
|
async resolve() {
|
|
return recovery;
|
|
},
|
|
async issue(command) {
|
|
recovery = {
|
|
issueMutationId: command.mutationId,
|
|
issueRequestId: command.requestId,
|
|
subjectId: command.replacementCredential.subject.id,
|
|
previousCredentialId: command.previousCredentialId,
|
|
previousCredentialVersion: command.expectedPreviousVersion,
|
|
replacementCredential: command.replacementCredential,
|
|
state: 'issued',
|
|
issuedAtMs: command.replacementCredential.createdAtMs,
|
|
};
|
|
return { status: 'inserted', recovery };
|
|
},
|
|
async acknowledge() {
|
|
throw new Error('not used');
|
|
},
|
|
async complete(command) {
|
|
assert.equal(recovery.state, 'acknowledged');
|
|
recovery = {
|
|
...recovery,
|
|
state: 'completed',
|
|
completeMutationId: command.mutationId,
|
|
completeRequestId: command.requestId,
|
|
revokedCredentialVersion: command.revokedCredential.version,
|
|
completedAtMs: command.revokedCredential.createdAtMs,
|
|
};
|
|
return { status: 'inserted', recovery };
|
|
},
|
|
};
|
|
let nowMs = 1000;
|
|
const service = createLocalOwnerCredentialRecoveryService(
|
|
repository,
|
|
credentials,
|
|
Buffer.alloc(32, 7).toString('base64url'),
|
|
{
|
|
pepperKeyId: 'owner-key-1',
|
|
now: () => nowMs,
|
|
randomBytes: (size) => Buffer.alloc(size, size),
|
|
},
|
|
);
|
|
const issueMutationId = '00000000-0000-4000-8000-000000000801';
|
|
const issued = await service.issue({
|
|
mutationId: issueMutationId,
|
|
requestId: 'recover-issue-801',
|
|
previousCredentialId: previous.credentialId,
|
|
expectedPreviousVersion: 1,
|
|
});
|
|
assert.equal(issued.status, 'inserted');
|
|
assert.notEqual(issued.replacementCredentialId, previous.credentialId);
|
|
assert.match(issued.replacementCredentialToken, /^ql3c_/);
|
|
|
|
recovery = {
|
|
...recovery,
|
|
state: 'acknowledged',
|
|
deliveryDigest: '2'.repeat(64),
|
|
acknowledgedAtMs: 1100,
|
|
};
|
|
nowMs = 1200;
|
|
const completion = {
|
|
issueMutationId,
|
|
mutationId: '00000000-0000-4000-8000-000000000802',
|
|
requestId: 'recover-complete-802',
|
|
};
|
|
assert.equal((await service.complete(completion)).status, 'inserted');
|
|
assert.equal((await service.complete(completion)).status, 'existing');
|
|
});
|