import ActiveDirectory from 'activedirectory2'; import { HTTP_STATUS } from '@verdaccio/core'; import ActiveDirectoryPlugin, { NotAuthMessage } from '../src/active-directory'; // eslint-disable-next-line jest/no-mocks-import import logger from './__mocks__/Logger'; describe('Active Directory Plugin', () => { let adPlugin; let adPluginSingleGroup; let adPluginMultiGroups; const config = { url: 'ldap://localhost', baseDN: 'dc=local,dc=host', domainSuffix: 'local.host', }; const configSingleGroup = { ...config, groupName: 'singleGroup', }; const configMultiGroups = { ...config, groupName: ['group1', 'group2', 'group3'], }; beforeAll(() => { adPlugin = new ActiveDirectoryPlugin(config, { logger }); adPluginSingleGroup = new ActiveDirectoryPlugin(configSingleGroup, { logger }); adPluginMultiGroups = new ActiveDirectoryPlugin(configMultiGroups, { logger }); }); beforeEach(() => { jest.resetModules(); }); test('get error when connection fails', (done) => { const errorMessage = 'Unknown error'; ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(errorMessage, undefined)); adPlugin.authenticate('', '', (error, authUser) => { expect(ActiveDirectory.prototype.authenticate).toHaveBeenCalled(); expect(logger.warn).toHaveBeenCalled(); expect(error.code).toBe(HTTP_STATUS.INTERNAL_ERROR); expect(error.message).toBe(errorMessage); expect(authUser).toBeUndefined(); done(); }); }); test('get error when not authenticated satisfactory', (done) => { ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, false)); adPlugin.authenticate('', '', (error, authUser) => { expect(ActiveDirectory.prototype.authenticate).toHaveBeenCalled(); expect(logger.warn).toHaveBeenCalledWith(NotAuthMessage); expect(error.code).toBe(HTTP_STATUS.UNAUTHORIZED); expect(error.message).toBe(NotAuthMessage); expect(authUser).toBeUndefined(); done(); }); }); test('connect satisfactory without groups', (done) => { const user = 'user'; const password = 'password'; ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, true)); adPlugin.authenticate(user, password, (error, authUser) => { expect(ActiveDirectory.prototype.authenticate).toHaveBeenCalled(); expect(logger.info).toHaveBeenCalled(); expect(error).toBeNull(); expect(authUser).toStrictEqual([user]); done(); }); }); test('get error when getting groups for user', (done) => { const errorMessage = 'Unknown error retrieving groups'; ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, true)); ActiveDirectory.prototype.getGroupMembershipForUser = jest.fn((_, cb) => cb(errorMessage as unknown as object, null) ) as jest.Mock; adPluginSingleGroup.authenticate('', '', (error, authUser) => { expect(ActiveDirectory.prototype.authenticate).toHaveBeenCalled(); expect(ActiveDirectory.prototype.getGroupMembershipForUser).toHaveBeenCalled(); expect(logger.warn).toHaveBeenCalled(); expect(error.code).toBe(HTTP_STATUS.INTERNAL_ERROR); expect(error.message).toBe(errorMessage); expect(authUser).toBeUndefined(); done(); }); }); test('get error when user groups do not match', (done) => { const user = 'user'; const password = 'password'; ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, true)); ActiveDirectory.prototype.getGroupMembershipForUser = jest.fn((_, cb) => cb(null, [{ cn: 'notMatchGroup' }]) ) as jest.Mock; adPluginSingleGroup.authenticate(user, password, (error, authUser) => { expect(ActiveDirectory.prototype.authenticate).toHaveBeenCalled(); expect(ActiveDirectory.prototype.getGroupMembershipForUser).toHaveBeenCalled(); expect(logger.warn).toHaveBeenCalled(); expect(error.code).toBe(HTTP_STATUS.FORBIDDEN); expect(error.message).toBe( `AD - User ${user} is not member of group(s): ${configSingleGroup.groupName}` ); expect(authUser).toBeUndefined(); done(); }); }); test('connect satisfactory when connection has only one group defined', (done) => { const { groupName } = configSingleGroup; const user = 'user'; const password = 'password'; ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, true)); ActiveDirectory.prototype.getGroupMembershipForUser = jest.fn((_, cb) => cb(null, [{ cn: groupName }]) ) as jest.Mock; adPluginSingleGroup.authenticate(user, password, (error, authUser) => { expect(ActiveDirectory.prototype.authenticate).toHaveBeenCalled(); expect(ActiveDirectory.prototype.getGroupMembershipForUser).toHaveBeenCalled(); expect(logger.info).toHaveBeenCalled(); expect(error).toBeNull(); expect(authUser).toStrictEqual([groupName, user]); done(); }); }); test('connect satisfactory when connection has multiple groups defined', (done) => { const [, group2, group3] = configMultiGroups.groupName; const user = 'user'; const password = 'password'; ActiveDirectory.prototype.authenticate = jest.fn((_1, _2, cb) => cb(null, true)); ActiveDirectory.prototype.getGroupMembershipForUser = jest.fn((_, cb) => cb(null, [{ cn: group2 }, { dn: group3 }]) ) as jest.Mock; adPluginMultiGroups.authenticate(user, password, (error, authUser) => { expect(ActiveDirectory.prototype.authenticate).toHaveBeenCalled(); expect(ActiveDirectory.prototype.getGroupMembershipForUser).toHaveBeenCalled(); expect(logger.info).toHaveBeenCalled(); expect(error).toBeNull(); expect(authUser).toStrictEqual([group2, group3, user]); done(); }); }); });