manicanldes-backend/test/password.spec.ts

51 lines
1.8 KiB
TypeScript

import { PasswordService } from '../src/identity/password.service';
import { issueToken, hashToken } from '../src/identity/tokens';
import { createUserSchema, roleSchema } from '../src/identity/identity.schemas';
describe('passwords and token primitives', () => {
const passwords = new PasswordService();
it('salts equal passwords independently and verifies them', async () => {
const first = await passwords.hash('a secure long passphrase');
const second = await passwords.hash('a secure long passphrase');
expect(first).not.toBe(second);
expect(await passwords.verify('a secure long passphrase', first)).toBe(
true,
);
expect(await passwords.verify('wrong', first)).toBe(false);
await passwords.dummyVerify('anything');
});
it.each([
'',
'bcrypt$bad',
'scrypt-v1$x$x',
'scrypt-v1$' + 'a'.repeat(32) + '$' + 'a'.repeat(128) + '$extra',
])('fails closed for malformed stored hash %s', async (value) => {
expect(await passwords.verify('password', value)).toBe(false);
});
it('issues random URL-safe tokens and one-way digests', () => {
const first = issueToken();
expect(first.token).toMatch(/^[A-Za-z0-9_-]{43}$/);
expect(first.tokenHash).toMatch(/^[a-f0-9]{64}$/);
expect(hashToken(first.token)).toBe(first.tokenHash);
expect(issueToken().token).not.toBe(first.token);
});
it('validates long passphrases, known permissions and duplicate permissions', () => {
expect(
createUserSchema.safeParse({
email: 'a@example.com',
name: 'A',
password: 'short',
}).success,
).toBe(false);
expect(
roleSchema.safeParse({ name: 'Role', permissions: ['anything'] }).success,
).toBe(false);
expect(
roleSchema.safeParse({
name: 'Role',
permissions: ['users.read', 'users.read'],
}).success,
).toBe(false);
});
});