mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
feat: Disable password based login (#1046)
This commit will introduce a new setting used to disbaled simple password based authention. The setting itself is an enterprise setting.
This commit is contained in:
parent
9e73ed8f47
commit
4fb1bcb524
@ -3,15 +3,31 @@ import { IUnleashServices } from '../../types/services';
|
|||||||
import { IUnleashConfig } from '../../types/option';
|
import { IUnleashConfig } from '../../types/option';
|
||||||
import version from '../../util/version';
|
import version from '../../util/version';
|
||||||
|
|
||||||
const Controller = require('../controller');
|
import Controller from '../controller';
|
||||||
|
import VersionService from '../../services/version-service';
|
||||||
|
import SettingService from '../../services/setting-service';
|
||||||
|
import {
|
||||||
|
simpleAuthKey,
|
||||||
|
SimpleAuthSettings,
|
||||||
|
} from '../../types/settings/simple-auth-settings';
|
||||||
|
|
||||||
class ConfigController extends Controller {
|
class ConfigController extends Controller {
|
||||||
|
private versionService: VersionService;
|
||||||
|
|
||||||
|
private settingService: SettingService;
|
||||||
|
|
||||||
|
private uiConfig: any;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
{ versionService }: Pick<IUnleashServices, 'versionService'>,
|
{
|
||||||
|
versionService,
|
||||||
|
settingService,
|
||||||
|
}: Pick<IUnleashServices, 'versionService' | 'settingService'>,
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.versionService = versionService;
|
this.versionService = versionService;
|
||||||
|
this.settingService = settingService;
|
||||||
const authenticationType =
|
const authenticationType =
|
||||||
config.authentication && config.authentication.type;
|
config.authentication && config.authentication.type;
|
||||||
this.uiConfig = {
|
this.uiConfig = {
|
||||||
@ -26,13 +42,12 @@ class ConfigController extends Controller {
|
|||||||
|
|
||||||
async getUIConfig(req: Request, res: Response): Promise<void> {
|
async getUIConfig(req: Request, res: Response): Promise<void> {
|
||||||
const config = this.uiConfig;
|
const config = this.uiConfig;
|
||||||
if (this.versionService) {
|
const simpleAuthSettings =
|
||||||
const versionInfo = this.versionService.getVersionInfo();
|
await this.settingService.get<SimpleAuthSettings>(simpleAuthKey);
|
||||||
res.json({ ...config, versionInfo });
|
|
||||||
} else {
|
const versionInfo = this.versionService.getVersionInfo();
|
||||||
res.json(config);
|
const disablePasswordAuth = simpleAuthSettings?.disabled;
|
||||||
}
|
res.json({ ...config, versionInfo, disablePasswordAuth });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default ConfigController;
|
export default ConfigController;
|
||||||
module.exports = ConfigController;
|
|
||||||
|
@ -24,6 +24,7 @@ import { IAuthRequest } from './routes/unleash-types';
|
|||||||
import * as permissions from './types/permissions';
|
import * as permissions from './types/permissions';
|
||||||
import * as eventType from './types/events';
|
import * as eventType from './types/events';
|
||||||
import { RoleName } from './types/model';
|
import { RoleName } from './types/model';
|
||||||
|
import { SimpleAuthSettings } from './types/settings/simple-auth-settings';
|
||||||
|
|
||||||
async function createApp(
|
async function createApp(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
@ -177,4 +178,5 @@ export type {
|
|||||||
IUser,
|
IUser,
|
||||||
IUnleashServices,
|
IUnleashServices,
|
||||||
IAuthRequest,
|
IAuthRequest,
|
||||||
|
SimpleAuthSettings,
|
||||||
};
|
};
|
||||||
|
@ -47,15 +47,16 @@ export const createServices = (
|
|||||||
const tagTypeService = new TagTypeService(stores, config);
|
const tagTypeService = new TagTypeService(stores, config);
|
||||||
const addonService = new AddonService(stores, config, tagTypeService);
|
const addonService = new AddonService(stores, config, tagTypeService);
|
||||||
const sessionService = new SessionService(stores, config);
|
const sessionService = new SessionService(stores, config);
|
||||||
|
const settingService = new SettingService(stores, config);
|
||||||
const userService = new UserService(stores, config, {
|
const userService = new UserService(stores, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
const versionService = new VersionService(stores, config);
|
const versionService = new VersionService(stores, config);
|
||||||
const healthService = new HealthService(stores, config);
|
const healthService = new HealthService(stores, config);
|
||||||
const settingService = new SettingService(stores, config);
|
|
||||||
const userFeedbackService = new UserFeedbackService(stores, config);
|
const userFeedbackService = new UserFeedbackService(stores, config);
|
||||||
const featureToggleServiceV2 = new FeatureToggleServiceV2(stores, config);
|
const featureToggleServiceV2 = new FeatureToggleServiceV2(stores, config);
|
||||||
const environmentService = new EnvironmentService(stores, config);
|
const environmentService = new EnvironmentService(stores, config);
|
||||||
|
@ -16,7 +16,7 @@ export default class SettingService {
|
|||||||
this.settingStore = settingStore;
|
this.settingStore = settingStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: string): Promise<object> {
|
async get<T>(id: string): Promise<T> {
|
||||||
return this.settingStore.get(id);
|
return this.settingStore.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ import SessionService from './session-service';
|
|||||||
import FakeSessionStore from '../../test/fixtures/fake-session-store';
|
import FakeSessionStore from '../../test/fixtures/fake-session-store';
|
||||||
import User from '../types/user';
|
import User from '../types/user';
|
||||||
import FakeResetTokenStore from '../../test/fixtures/fake-reset-token-store';
|
import FakeResetTokenStore from '../../test/fixtures/fake-reset-token-store';
|
||||||
|
import SettingService from './setting-service';
|
||||||
|
import FakeSettingStore from '../../test/fixtures/fake-setting-store';
|
||||||
|
|
||||||
const config: IUnleashConfig = createTestConfig();
|
const config: IUnleashConfig = createTestConfig();
|
||||||
|
|
||||||
@ -28,12 +30,17 @@ test('Should create new user', async () => {
|
|||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
const user = await service.createUser(
|
const user = await service.createUser(
|
||||||
{
|
{
|
||||||
@ -63,12 +70,17 @@ test('Should create default user', async () => {
|
|||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
|
|
||||||
await service.initAdminUser();
|
await service.initAdminUser();
|
||||||
@ -90,12 +102,17 @@ test('Should be a valid password', async () => {
|
|||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
|
|
||||||
const valid = service.validatePassword('this is a strong password!');
|
const valid = service.validatePassword('this is a strong password!');
|
||||||
@ -115,12 +132,17 @@ test('Password must be at least 10 chars', async () => {
|
|||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
expect(() => service.validatePassword('admin')).toThrow(
|
expect(() => service.validatePassword('admin')).toThrow(
|
||||||
'The password must be at least 10 characters long.',
|
'The password must be at least 10 characters long.',
|
||||||
@ -142,12 +164,17 @@ test('The password must contain at least one uppercase letter.', async () => {
|
|||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(() => service.validatePassword('qwertyabcde')).toThrowError(
|
expect(() => service.validatePassword('qwertyabcde')).toThrowError(
|
||||||
@ -171,12 +198,17 @@ test('The password must contain at least one number', async () => {
|
|||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(() => service.validatePassword('qwertyabcdE')).toThrowError(
|
expect(() => service.validatePassword('qwertyabcdE')).toThrowError(
|
||||||
@ -199,12 +231,17 @@ test('The password must contain at least one special character', async () => {
|
|||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(() => service.validatePassword('qwertyabcdE2')).toThrowError(
|
expect(() => service.validatePassword('qwertyabcdE2')).toThrowError(
|
||||||
@ -227,12 +264,17 @@ test('Should be a valid password with special chars', async () => {
|
|||||||
const emailService = new EmailService(config.email, config.getLogger);
|
const emailService = new EmailService(config.email, config.getLogger);
|
||||||
const sessionStore = new FakeSessionStore();
|
const sessionStore = new FakeSessionStore();
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const service = new UserService({ userStore, eventStore }, config, {
|
const service = new UserService({ userStore, eventStore }, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
|
|
||||||
const valid = service.validatePassword('this is a strong password!');
|
const valid = service.validatePassword('this is a strong password!');
|
||||||
|
@ -21,6 +21,9 @@ import { USER_UPDATED, USER_CREATED, USER_DELETED } from '../types/events';
|
|||||||
import { IEventStore } from '../types/stores/event-store';
|
import { IEventStore } from '../types/stores/event-store';
|
||||||
import { IUserSearch, IUserStore } from '../types/stores/user-store';
|
import { IUserSearch, IUserStore } from '../types/stores/user-store';
|
||||||
import { RoleName } from '../types/model';
|
import { RoleName } from '../types/model';
|
||||||
|
import SettingService from './setting-service';
|
||||||
|
import { SimpleAuthSettings } from '../server-impl';
|
||||||
|
import { simpleAuthKey } from '../types/settings/simple-auth-settings';
|
||||||
|
|
||||||
const systemUser = new User({ id: -1, username: 'system' });
|
const systemUser = new User({ id: -1, username: 'system' });
|
||||||
|
|
||||||
@ -77,6 +80,8 @@ class UserService {
|
|||||||
|
|
||||||
private emailService: EmailService;
|
private emailService: EmailService;
|
||||||
|
|
||||||
|
private settingService: SettingService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
stores: Pick<IUnleashStores, 'userStore' | 'eventStore'>,
|
stores: Pick<IUnleashStores, 'userStore' | 'eventStore'>,
|
||||||
{
|
{
|
||||||
@ -88,6 +93,7 @@ class UserService {
|
|||||||
resetTokenService: ResetTokenService;
|
resetTokenService: ResetTokenService;
|
||||||
emailService: EmailService;
|
emailService: EmailService;
|
||||||
sessionService: SessionService;
|
sessionService: SessionService;
|
||||||
|
settingService: SettingService;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
this.logger = getLogger('service/user-service.js');
|
this.logger = getLogger('service/user-service.js');
|
||||||
@ -97,6 +103,7 @@ class UserService {
|
|||||||
this.resetTokenService = services.resetTokenService;
|
this.resetTokenService = services.resetTokenService;
|
||||||
this.emailService = services.emailService;
|
this.emailService = services.emailService;
|
||||||
this.sessionService = services.sessionService;
|
this.sessionService = services.sessionService;
|
||||||
|
this.settingService = services.settingService;
|
||||||
if (authentication && authentication.createAdminUser) {
|
if (authentication && authentication.createAdminUser) {
|
||||||
process.nextTick(() => this.initAdminUser());
|
process.nextTick(() => this.initAdminUser());
|
||||||
}
|
}
|
||||||
@ -241,6 +248,16 @@ class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loginUser(usernameOrEmail: string, password: string): Promise<IUser> {
|
async loginUser(usernameOrEmail: string, password: string): Promise<IUser> {
|
||||||
|
const settings = await this.settingService.get<SimpleAuthSettings>(
|
||||||
|
simpleAuthKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (settings && settings.disabled) {
|
||||||
|
throw new Error(
|
||||||
|
'Logging in with username/password has been disabled.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const idQuery = isEmail(usernameOrEmail)
|
const idQuery = isEmail(usernameOrEmail)
|
||||||
? { email: usernameOrEmail }
|
? { email: usernameOrEmail }
|
||||||
: { username: usernameOrEmail };
|
: { username: usernameOrEmail };
|
||||||
|
@ -2,6 +2,7 @@ interface IBaseOptions {
|
|||||||
type: string;
|
type: string;
|
||||||
path: string;
|
path: string;
|
||||||
message: string;
|
message: string;
|
||||||
|
defaultHidden?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IOptions extends IBaseOptions {
|
interface IOptions extends IBaseOptions {
|
||||||
@ -15,13 +16,22 @@ class AuthenticationRequired {
|
|||||||
|
|
||||||
private message: string;
|
private message: string;
|
||||||
|
|
||||||
|
private defaultHidden: boolean;
|
||||||
|
|
||||||
private options?: IBaseOptions[];
|
private options?: IBaseOptions[];
|
||||||
|
|
||||||
constructor({ type, path, message, options }: IOptions) {
|
constructor({
|
||||||
|
type,
|
||||||
|
path,
|
||||||
|
message,
|
||||||
|
options,
|
||||||
|
defaultHidden = false,
|
||||||
|
}: IOptions) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
this.defaultHidden = defaultHidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
src/lib/types/settings/simple-auth-settings.ts
Normal file
4
src/lib/types/settings/simple-auth-settings.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const simpleAuthKey = 'unleash.auth.simple';
|
||||||
|
export interface SimpleAuthSettings {
|
||||||
|
disabled: boolean;
|
||||||
|
}
|
@ -6,6 +6,6 @@ export interface ISettingInsert {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ISettingStore extends Store<any, string> {
|
export interface ISettingStore extends Store<any, string> {
|
||||||
insert(name: string, content: any): Promise<void>;
|
insert<T>(name: string, content: T): Promise<void>;
|
||||||
updateRow(name: string, content: any): Promise<void>;
|
updateRow(name: string, content: any): Promise<void>;
|
||||||
}
|
}
|
||||||
|
37
src/test/e2e/api/admin/config.e2e.test.ts
Normal file
37
src/test/e2e/api/admin/config.e2e.test.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import dbInit, { ITestDb } from '../../helpers/database-init';
|
||||||
|
import { setupApp } from '../../helpers/test-helper';
|
||||||
|
import getLogger from '../../../fixtures/no-logger';
|
||||||
|
import { simpleAuthKey } from '../../../../lib/types/settings/simple-auth-settings';
|
||||||
|
|
||||||
|
let db: ITestDb;
|
||||||
|
let app;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
db = await dbInit('config_api_serial', getLogger);
|
||||||
|
app = await setupApp(db.stores);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await app.destroy();
|
||||||
|
await db.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('gets ui config', async () => {
|
||||||
|
const { body } = await app.request
|
||||||
|
.get('/api/admin/ui-config')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
expect(body.unleashUrl).toBe('http://localhost:4242');
|
||||||
|
expect(body.version).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('gets ui config with disablePasswordAuth', async () => {
|
||||||
|
await db.stores.settingStore.insert(simpleAuthKey, { disabled: true });
|
||||||
|
const { body } = await app.request
|
||||||
|
.get('/api/admin/ui-config')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
expect(body.disablePasswordAuth).toBe(true);
|
||||||
|
});
|
@ -13,6 +13,8 @@ import { EmailService } from '../../../../lib/services/email-service';
|
|||||||
import SessionStore from '../../../../lib/db/session-store';
|
import SessionStore from '../../../../lib/db/session-store';
|
||||||
import SessionService from '../../../../lib/services/session-service';
|
import SessionService from '../../../../lib/services/session-service';
|
||||||
import { RoleName } from '../../../../lib/types/model';
|
import { RoleName } from '../../../../lib/types/model';
|
||||||
|
import SettingService from '../../../../lib/services/setting-service';
|
||||||
|
import FakeSettingStore from '../../../fixtures/fake-setting-store';
|
||||||
|
|
||||||
let app;
|
let app;
|
||||||
let stores;
|
let stores;
|
||||||
@ -53,11 +55,16 @@ beforeAll(async () => {
|
|||||||
config.getLogger,
|
config.getLogger,
|
||||||
);
|
);
|
||||||
const sessionService = new SessionService({ sessionStore }, config);
|
const sessionService = new SessionService({ sessionStore }, config);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
userService = new UserService(stores, config, {
|
userService = new UserService(stores, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
resetTokenService = new ResetTokenService(stores, config);
|
resetTokenService = new ResetTokenService(stores, config);
|
||||||
const adminRole = await accessService.getRootRole(RoleName.ADMIN);
|
const adminRole = await accessService.getRootRole(RoleName.ADMIN);
|
||||||
|
@ -9,6 +9,8 @@ import { createTestConfig } from '../../config/test-config';
|
|||||||
import SessionService from '../../../lib/services/session-service';
|
import SessionService from '../../../lib/services/session-service';
|
||||||
import InvalidTokenError from '../../../lib/error/invalid-token-error';
|
import InvalidTokenError from '../../../lib/error/invalid-token-error';
|
||||||
import { IUser } from '../../../lib/types/user';
|
import { IUser } from '../../../lib/types/user';
|
||||||
|
import SettingService from '../../../lib/services/setting-service';
|
||||||
|
import FakeSettingStore from '../../fixtures/fake-setting-store';
|
||||||
|
|
||||||
const config: IUnleashConfig = createTestConfig();
|
const config: IUnleashConfig = createTestConfig();
|
||||||
|
|
||||||
@ -28,12 +30,17 @@ beforeAll(async () => {
|
|||||||
resetTokenService = new ResetTokenService(stores, config);
|
resetTokenService = new ResetTokenService(stores, config);
|
||||||
sessionService = new SessionService(stores, config);
|
sessionService = new SessionService(stores, config);
|
||||||
const emailService = new EmailService(undefined, config.getLogger);
|
const emailService = new EmailService(undefined, config.getLogger);
|
||||||
|
const settingService = new SettingService(
|
||||||
|
{ settingStore: new FakeSettingStore() },
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
userService = new UserService(stores, config, {
|
userService = new UserService(stores, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
|
|
||||||
adminUser = await userService.createUser({
|
adminUser = await userService.createUser({
|
||||||
|
@ -10,6 +10,8 @@ import SessionService from '../../../lib/services/session-service';
|
|||||||
import NotFoundError from '../../../lib/error/notfound-error';
|
import NotFoundError from '../../../lib/error/notfound-error';
|
||||||
import { IRole } from '../../../lib/types/stores/access-store';
|
import { IRole } from '../../../lib/types/stores/access-store';
|
||||||
import { RoleName } from '../../../lib/types/model';
|
import { RoleName } from '../../../lib/types/model';
|
||||||
|
import SettingService from '../../../lib/services/setting-service';
|
||||||
|
import { simpleAuthKey } from '../../../lib/types/settings/simple-auth-settings';
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
let stores;
|
let stores;
|
||||||
@ -27,12 +29,14 @@ beforeAll(async () => {
|
|||||||
const resetTokenService = new ResetTokenService(stores, config);
|
const resetTokenService = new ResetTokenService(stores, config);
|
||||||
const emailService = new EmailService(undefined, config.getLogger);
|
const emailService = new EmailService(undefined, config.getLogger);
|
||||||
sessionService = new SessionService(stores, config);
|
sessionService = new SessionService(stores, config);
|
||||||
|
const settingService = new SettingService(stores, config);
|
||||||
|
|
||||||
userService = new UserService(stores, config, {
|
userService = new UserService(stores, config, {
|
||||||
accessService,
|
accessService,
|
||||||
resetTokenService,
|
resetTokenService,
|
||||||
emailService,
|
emailService,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
settingService,
|
||||||
});
|
});
|
||||||
userStore = stores.userStore;
|
userStore = stores.userStore;
|
||||||
const rootRoles = await accessService.getRootRoles();
|
const rootRoles = await accessService.getRootRoles();
|
||||||
@ -93,6 +97,22 @@ test('should create user with password', async () => {
|
|||||||
expect(user.username).toBe('test');
|
expect(user.username).toBe('test');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should not login user if simple auth is disabled', async () => {
|
||||||
|
await db.stores.settingStore.insert(simpleAuthKey, { disabled: true });
|
||||||
|
|
||||||
|
await userService.createUser({
|
||||||
|
username: 'test_no_pass',
|
||||||
|
password: 'A very strange P4ssw0rd_',
|
||||||
|
rootRole: adminRole.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(async () => {
|
||||||
|
await userService.loginUser('test_no_pass', 'A very strange P4ssw0rd_');
|
||||||
|
}).rejects.toThrowError(
|
||||||
|
'Logging in with username/password has been disabled.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('should login for user _without_ password', async () => {
|
test('should login for user _without_ password', async () => {
|
||||||
const email = 'some@test.com';
|
const email = 'some@test.com';
|
||||||
await userService.createUser({
|
await userService.createUser({
|
||||||
|
3
src/test/fixtures/fake-setting-store.ts
vendored
3
src/test/fixtures/fake-setting-store.ts
vendored
@ -1,5 +1,4 @@
|
|||||||
import { ISettingStore } from '../../lib/types/stores/settings-store';
|
import { ISettingStore } from '../../lib/types/stores/settings-store';
|
||||||
import NotFoundError from '../../lib/error/notfound-error';
|
|
||||||
|
|
||||||
export default class FakeSettingStore implements ISettingStore {
|
export default class FakeSettingStore implements ISettingStore {
|
||||||
settings: Map<string, any> = new Map();
|
settings: Map<string, any> = new Map();
|
||||||
@ -23,7 +22,7 @@ export default class FakeSettingStore implements ISettingStore {
|
|||||||
if (setting) {
|
if (setting) {
|
||||||
return setting;
|
return setting;
|
||||||
}
|
}
|
||||||
throw new NotFoundError(`Could not find setting with key ${key}`);
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAll(): Promise<any[]> {
|
async getAll(): Promise<any[]> {
|
||||||
|
Loading…
Reference in New Issue
Block a user