0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-06 22:40:26 -05:00
verdaccio/packages/plugins/htpasswd/tests/htpasswd.test.ts
Juan Picado 124e5f2de7
chore: migrate htpasswd package vitest (#4889)
* migrate htpasswd package

* update versions

* Update htpasswd.passwords.test.ts
2024-10-07 08:28:30 +02:00

123 lines
4.1 KiB
TypeScript

import bcrypt from 'bcryptjs';
import crypto from 'crypto';
import path from 'path';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Config, parseConfigFile } from '@verdaccio/config';
import { pluginUtils } from '@verdaccio/core';
import HTPasswd, { DEFAULT_SLOW_VERIFY_MS, HTPasswdConfig } from '../src/htpasswd';
const options = {
logger: { warn: vi.fn(), info: vi.fn() },
config: new Config(parseConfigFile(path.join(__dirname, './__fixtures__/config.yaml'))),
} as any as pluginUtils.PluginOptions;
const config = {
file: './htpasswd',
max_users: 1000,
} as HTPasswdConfig;
describe('HTPasswd', () => {
let wrapper;
beforeEach(() => {
wrapper = new HTPasswd(config, options);
vi.resetModules();
vi.clearAllMocks();
// @ts-ignore
crypto.randomBytes = vi.fn(() => {
return {
toString: (): string => '$6',
};
});
});
describe('constructor()', () => {
const error = vi.fn();
const warn = vi.fn();
const info = vi.fn();
const emptyPluginOptions = {
config: {
configPath: '',
},
logger: { warn, info, error },
} as any as pluginUtils.PluginOptions;
test('should ensure file path configuration exists', () => {
expect(function () {
new HTPasswd({} as HTPasswdConfig, emptyPluginOptions);
}).toThrow(/should specify "file" in config/);
});
test('should switch to bcrypt if incorrect algorithm is set', () => {
let invalidConfig = { algorithm: 'invalid', ...config } as HTPasswdConfig;
new HTPasswd(invalidConfig, emptyPluginOptions);
expect(warn).toHaveBeenCalledWith(
'The algorithm selected %s is invalid, switching to to default one "bcrypt", password validation can be affected',
'invalid'
);
expect(info).toHaveBeenCalled();
});
});
describe('authenticate()', () => {
test.each([
{ username: 'test1111', password: 'test1111' },
{ username: 'username', password: 'password' },
{ username: 'bcrypt', password: 'password' },
])('it should authenticate user $username with given credentials', ({ username, password }) => {
return new Promise((done) => {
const generateCallback = (username) => (error, userGroups) => {
expect(error).toBeNull();
expect(userGroups).toContain(username);
done();
};
wrapper.adduser(username, password, () => {
wrapper.authenticate(username, password, generateCallback(username));
});
});
});
test.each([
{ username: 'test1111', password: 'test1111' },
{ username: 'username', password: 'password' },
{ username: 'bcrypt', password: 'password' },
])('it should not authenticate use $username with given credentials', ({ username }) => {
return new Promise((done) => {
const generateCallback = () => (error) => {
expect(error).toBeNull();
// expect(userGroups).toBeFalsy();
done();
};
wrapper.authenticate(username, 'somerandompassword', generateCallback());
});
});
// TODO: flakes on CI
test.skip('it should warn on slow password verification', () => {
return new Promise((done) => {
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
bcrypt.compare = vi.fn((_passwd, _hash) => {
return new Promise((resolve) => setTimeout(resolve, DEFAULT_SLOW_VERIFY_MS + 1)).then(
() => true
);
});
const callback = (a, b): void => {
expect(a).toBeNull();
expect(b).toContain('bcrypt');
const mockWarn = options.logger.warn as any;
expect(mockWarn.mock.calls.length).toBe(1);
const [{ user, durationMs }, message] = mockWarn.mock.calls[0];
expect(user).toEqual('bcrypt');
expect(durationMs).toBeGreaterThan(DEFAULT_SLOW_VERIFY_MS);
expect(message).toEqual('Password for user "@{user}" took @{durationMs}ms to verify');
done(true);
};
wrapper.authenticate('bcrypt', 'password', callback);
});
});
});
});