import _ from 'lodash'; import { IAuth } from '@verdaccio/auth'; import { Config as AppConfig, ROLES } from '@verdaccio/config'; import { errorUtils } from '@verdaccio/core'; import { setup } from '@verdaccio/logger'; import { Config } from '@verdaccio/types'; import { Auth } from '../src'; import { authPluginFailureConf, authPluginPassThrougConf, authProfileConf } from './helper/plugin'; setup([]); describe('AuthTest', () => { test('should be defined', () => { const config: Config = new AppConfig(_.cloneDeep(authProfileConf)); config.checkSecretKey('12345'); const auth: IAuth = new Auth(config); expect(auth).toBeDefined(); }); describe('test authenticate method', () => { describe('test authenticate states', () => { test('should be a success login', () => { const config: Config = new AppConfig(_.cloneDeep(authProfileConf)); config.checkSecretKey('12345'); const auth: IAuth = new Auth(config); expect(auth).toBeDefined(); const callback = jest.fn(); const groups = ['test']; auth.authenticate('foo', 'bar', callback); expect(callback).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledWith(null, { groups: [ 'test', ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL, ], name: 'foo', real_groups: groups, }); }); test('should be a fail on login', () => { const config: Config = new AppConfig(authPluginFailureConf); config.checkSecretKey('12345'); const auth: IAuth = new Auth(config); expect(auth).toBeDefined(); const callback = jest.fn(); auth.authenticate('foo', 'bar', callback); expect(callback).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledWith(errorUtils.getInternalError()); }); }); // plugins are free to send whatever they want, so, we need to test some scenarios // that might make break the request // the @ts-ignore below are intended describe('test authenticate out of control inputs from plugins', () => { test('should skip falsy values', () => { const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf)); config.checkSecretKey('12345'); const auth: IAuth = new Auth(config); expect(auth).toBeDefined(); const callback = jest.fn(); let index = 0; // as defined by https://developer.mozilla.org/en-US/docs/Glossary/Falsy for (const value of [false, 0, '', null, undefined, NaN]) { // @ts-ignore auth.authenticate(null, value, callback); const call = callback.mock.calls[index++]; expect(call[0]).toBeDefined(); expect(call[1]).toBeUndefined(); } }); test('should error truthy non-array', () => { const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf)); config.checkSecretKey('12345'); const auth: IAuth = new Auth(config); expect(auth).toBeDefined(); const callback = jest.fn(); for (const value of [true, 1, 'test', {}]) { expect(function () { // @ts-ignore auth.authenticate(null, value, callback); }).toThrow(TypeError); expect(callback).not.toHaveBeenCalled(); } }); test('should skip empty array', () => { const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf)); config.checkSecretKey('12345'); const auth: IAuth = new Auth(config); expect(auth).toBeDefined(); const callback = jest.fn(); const value = []; // @ts-ignore auth.authenticate(null, value, callback); expect(callback.mock.calls).toHaveLength(1); expect(callback.mock.calls[0][0]).toBeDefined(); expect(callback.mock.calls[0][1]).toBeUndefined(); }); test('should accept valid array', () => { const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf)); config.checkSecretKey('12345'); const auth: IAuth = new Auth(config); expect(auth).toBeDefined(); const callback = jest.fn(); let index = 0; for (const value of [[''], ['1'], ['0'], ['000']]) { // @ts-ignore auth.authenticate(null, value, callback); const call = callback.mock.calls[index++]; expect(call[0]).toBeNull(); expect(call[1].real_groups).toBe(value); } }); }); }); });