mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-23 22:27:34 -05:00
b56d5cec39
* chore: relocated mock package * refactor: relocate local-storage htpasswd to plugins because they are * chore: format
308 lines
9.2 KiB
TypeScript
308 lines
9.2 KiB
TypeScript
/* eslint-disable jest/no-mocks-import */
|
|
import crypto from 'crypto';
|
|
// @ts-ignore
|
|
import fs from 'fs';
|
|
|
|
import MockDate from 'mockdate';
|
|
|
|
import HTPasswd, { VerdaccioConfigApp } from '../src/htpasswd';
|
|
import { HtpasswdHashAlgorithm } from '../src/utils';
|
|
|
|
// FIXME: remove this mocks imports
|
|
import Logger from './__mocks__/Logger';
|
|
import Config from './__mocks__/Config';
|
|
|
|
const stuff = {
|
|
logger: new Logger(),
|
|
config: new Config(),
|
|
};
|
|
|
|
const config = {
|
|
file: './htpasswd',
|
|
max_users: 1000,
|
|
};
|
|
|
|
const getDefaultConfig = (): VerdaccioConfigApp => ({
|
|
file: './htpasswd',
|
|
max_users: 1000,
|
|
});
|
|
|
|
describe('HTPasswd', () => {
|
|
let wrapper;
|
|
|
|
beforeEach(() => {
|
|
wrapper = new HTPasswd(getDefaultConfig(), stuff as unknown as VerdaccioConfigApp);
|
|
jest.resetModules();
|
|
|
|
crypto.randomBytes = jest.fn(() => {
|
|
return {
|
|
toString: (): string => '$6',
|
|
};
|
|
});
|
|
});
|
|
|
|
describe('constructor()', () => {
|
|
const emptyPluginOptions = { config: {} } as VerdaccioConfigApp;
|
|
|
|
test('should files whether file path does not exist', () => {
|
|
expect(function () {
|
|
new HTPasswd({}, emptyPluginOptions);
|
|
}).toThrow(/should specify "file" in config/);
|
|
});
|
|
|
|
test('should throw error about incorrect algorithm', () => {
|
|
expect(function () {
|
|
let config = getDefaultConfig();
|
|
config.algorithm = 'invalid' as any;
|
|
new HTPasswd(config, emptyPluginOptions);
|
|
}).toThrow(/Invalid algorithm "invalid"/);
|
|
});
|
|
});
|
|
|
|
describe('authenticate()', () => {
|
|
test('it should authenticate user with given credentials', (done) => {
|
|
const callbackTest = (a, b): void => {
|
|
expect(a).toBeNull();
|
|
expect(b).toContain('test');
|
|
done();
|
|
};
|
|
const callbackUsername = (a, b): void => {
|
|
expect(a).toBeNull();
|
|
expect(b).toContain('username');
|
|
done();
|
|
};
|
|
wrapper.authenticate('test', 'test', callbackTest);
|
|
wrapper.authenticate('username', 'password', callbackUsername);
|
|
});
|
|
|
|
test('it should not authenticate user with given credentials', (done) => {
|
|
const callback = (a, b): void => {
|
|
expect(a).toBeNull();
|
|
expect(b).toBeFalsy();
|
|
done();
|
|
};
|
|
wrapper.authenticate('test', 'somerandompassword', callback);
|
|
});
|
|
});
|
|
|
|
describe('addUser()', () => {
|
|
test('it should not pass sanity check', (done) => {
|
|
const callback = (a): void => {
|
|
expect(a.message).toEqual('unauthorized access');
|
|
done();
|
|
};
|
|
wrapper.adduser('test', 'somerandompassword', callback);
|
|
});
|
|
|
|
test('it should add the user', (done) => {
|
|
let dataToWrite;
|
|
// @ts-ignore
|
|
fs.writeFile = jest.fn((name, data, callback) => {
|
|
dataToWrite = data;
|
|
callback();
|
|
});
|
|
|
|
MockDate.set('2018-01-14T11:17:40.712Z');
|
|
|
|
const callback = (a, b): void => {
|
|
expect(a).toBeNull();
|
|
expect(b).toBeTruthy();
|
|
expect(fs.writeFile).toHaveBeenCalled();
|
|
expect(dataToWrite.indexOf('usernotpresent')).not.toEqual(-1);
|
|
done();
|
|
};
|
|
wrapper.adduser('usernotpresent', 'somerandompassword', callback);
|
|
});
|
|
|
|
describe('addUser() error handling', () => {
|
|
test('sanityCheck should return an Error', (done) => {
|
|
jest.doMock('../src/utils.ts', () => {
|
|
return {
|
|
sanityCheck: (): Error => Error('some error'),
|
|
HtpasswdHashAlgorithm,
|
|
};
|
|
});
|
|
|
|
const HTPasswd = require('../src/htpasswd.ts').default;
|
|
const wrapper = new HTPasswd(config, stuff);
|
|
wrapper.adduser('sanityCheck', 'test', (sanity) => {
|
|
expect(sanity.message).toBeDefined();
|
|
expect(sanity.message).toMatch('some error');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('lockAndRead should return an Error', (done) => {
|
|
jest.doMock('../src/utils.ts', () => {
|
|
return {
|
|
sanityCheck: (): any => null,
|
|
lockAndRead: (_a, b): any => b(new Error('lock error')),
|
|
HtpasswdHashAlgorithm,
|
|
};
|
|
});
|
|
|
|
const HTPasswd = require('../src/htpasswd.ts').default;
|
|
const wrapper = new HTPasswd(config, stuff);
|
|
wrapper.adduser('lockAndRead', 'test', (sanity) => {
|
|
expect(sanity.message).toBeDefined();
|
|
expect(sanity.message).toMatch('lock error');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('addUserToHTPasswd should return an Error', (done) => {
|
|
jest.doMock('../src/utils.ts', () => {
|
|
return {
|
|
sanityCheck: (): any => null,
|
|
parseHTPasswd: (): void => {},
|
|
lockAndRead: (_a, b): any => b(null, ''),
|
|
unlockFile: (_a, b): any => b(),
|
|
HtpasswdHashAlgorithm,
|
|
};
|
|
});
|
|
|
|
const HTPasswd = require('../src/htpasswd.ts').default;
|
|
const wrapper = new HTPasswd(config, stuff);
|
|
wrapper.adduser('addUserToHTPasswd', 'test', () => {
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('writeFile should return an Error', (done) => {
|
|
jest.doMock('../src/utils.ts', () => {
|
|
return {
|
|
sanityCheck: (): any => null,
|
|
parseHTPasswd: (): void => {},
|
|
lockAndRead: (_a, b): any => b(null, ''),
|
|
addUserToHTPasswd: (): void => {},
|
|
HtpasswdHashAlgorithm,
|
|
};
|
|
});
|
|
jest.doMock('fs', () => {
|
|
const original = jest.requireActual('fs');
|
|
return {
|
|
...original,
|
|
writeFile: jest.fn((_name, _data, callback) => {
|
|
callback(new Error('write error'));
|
|
}),
|
|
};
|
|
});
|
|
|
|
const HTPasswd = require('../src/htpasswd.ts').default;
|
|
const wrapper = new HTPasswd(config, stuff);
|
|
wrapper.adduser('addUserToHTPasswd', 'test', (err) => {
|
|
expect(err).not.toBeNull();
|
|
expect(err.message).toMatch('write error');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('reload()', () => {
|
|
test('it should read the file and set the users', (done) => {
|
|
const output = { test: '$6FrCaT/v0dwE', username: '$66to3JK5RgZM' };
|
|
const callback = (): void => {
|
|
expect(wrapper.users).toEqual(output);
|
|
done();
|
|
};
|
|
wrapper.reload(callback);
|
|
});
|
|
|
|
test('reload should fails on check file', (done) => {
|
|
jest.doMock('fs', () => {
|
|
return {
|
|
stat: (_name, callback): void => {
|
|
callback(new Error('stat error'), null);
|
|
},
|
|
};
|
|
});
|
|
const callback = (err): void => {
|
|
expect(err).not.toBeNull();
|
|
expect(err.message).toMatch('stat error');
|
|
done();
|
|
};
|
|
|
|
const HTPasswd = require('../src/htpasswd.ts').default;
|
|
const wrapper = new HTPasswd(config, stuff);
|
|
wrapper.reload(callback);
|
|
});
|
|
|
|
test('reload times match', (done) => {
|
|
jest.doMock('fs', () => {
|
|
return {
|
|
stat: (_name, callback): void => {
|
|
callback(null, {
|
|
mtime: null,
|
|
});
|
|
},
|
|
};
|
|
});
|
|
const callback = (err): void => {
|
|
expect(err).toBeUndefined();
|
|
done();
|
|
};
|
|
|
|
const HTPasswd = require('../src/htpasswd.ts').default;
|
|
const wrapper = new HTPasswd(config, stuff);
|
|
wrapper.reload(callback);
|
|
});
|
|
|
|
test('reload should fails on read file', (done) => {
|
|
jest.doMock('fs', () => {
|
|
return {
|
|
stat: jest.requireActual('fs').stat,
|
|
readFile: (_name, _format, callback): void => {
|
|
callback(new Error('read error'), null);
|
|
},
|
|
};
|
|
});
|
|
const callback = (err): void => {
|
|
expect(err).not.toBeNull();
|
|
expect(err.message).toMatch('read error');
|
|
done();
|
|
};
|
|
|
|
const HTPasswd = require('../src/htpasswd.ts').default;
|
|
const wrapper = new HTPasswd(config, stuff);
|
|
wrapper.reload(callback);
|
|
});
|
|
});
|
|
});
|
|
|
|
test('changePassword - it should throw an error for user not found', (done) => {
|
|
const callback = (error, isSuccess): void => {
|
|
expect(error).not.toBeNull();
|
|
expect(error.message).toBe('User not found');
|
|
expect(isSuccess).toBeFalsy();
|
|
done();
|
|
};
|
|
wrapper.changePassword('usernotpresent', 'oldPassword', 'newPassword', callback);
|
|
});
|
|
|
|
test('changePassword - it should throw an error for wrong password', (done) => {
|
|
const callback = (error, isSuccess): void => {
|
|
expect(error).not.toBeNull();
|
|
expect(error.message).toBe('Invalid old Password');
|
|
expect(isSuccess).toBeFalsy();
|
|
done();
|
|
};
|
|
wrapper.changePassword('username', 'wrongPassword', 'newPassword', callback);
|
|
});
|
|
|
|
test('changePassword - it should change password', (done) => {
|
|
let dataToWrite;
|
|
// @ts-ignore
|
|
fs.writeFile = jest.fn((_name, data, callback) => {
|
|
dataToWrite = data;
|
|
callback();
|
|
});
|
|
const callback = (error, isSuccess): void => {
|
|
expect(error).toBeNull();
|
|
expect(isSuccess).toBeTruthy();
|
|
expect(fs.writeFile).toHaveBeenCalled();
|
|
expect(dataToWrite.indexOf('username')).not.toEqual(-1);
|
|
done();
|
|
};
|
|
wrapper.changePassword('username', 'password', 'newPassword', callback);
|
|
});
|
|
});
|