import _ from 'lodash'; import { Config as AppConfig } from '@verdaccio/config'; import { setup } from '@verdaccio/logger'; import { IAuth } from '@verdaccio/dev-types'; import { Config } from '@verdaccio/types'; import { ROLES } from '@verdaccio/dev-commons'; import { getInternalError } from '@verdaccio/commons-api'; import { Auth } from '../src'; import { authProfileConf, authPluginFailureConf, authPluginPassThrougConf } from './helper/plugin'; setup([]); describe('AuthTest', () => { test('should be defined', () => { const config: Config = new AppConfig(_.cloneDeep(authProfileConf)); 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)); 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(_.cloneDeep(authPluginFailureConf)); 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(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)); 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)); 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)); 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)); 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); } }); }); }) });