mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	task: enabled in OSS. (#8856)
Hardcode project and environment names to filter by when OSS
This commit is contained in:
		
							parent
							
								
									a454e14f28
								
							
						
					
					
						commit
						663b169c46
					
				@ -85,6 +85,7 @@ exports[`should create default config 1`] = `
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "inlineSegmentConstraints": true,
 | 
					  "inlineSegmentConstraints": true,
 | 
				
			||||||
  "isEnterprise": false,
 | 
					  "isEnterprise": false,
 | 
				
			||||||
 | 
					  "isOss": false,
 | 
				
			||||||
  "listen": {
 | 
					  "listen": {
 | 
				
			||||||
    "host": undefined,
 | 
					    "host": undefined,
 | 
				
			||||||
    "port": 4242,
 | 
					    "port": 4242,
 | 
				
			||||||
 | 
				
			|||||||
@ -620,6 +620,10 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
 | 
				
			|||||||
        Boolean(options.enterpriseVersion) &&
 | 
					        Boolean(options.enterpriseVersion) &&
 | 
				
			||||||
        ui.environment?.toLowerCase() !== 'pro';
 | 
					        ui.environment?.toLowerCase() !== 'pro';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const isTest = process.env.NODE_ENV === 'test';
 | 
				
			||||||
 | 
					    const isOss = isTest
 | 
				
			||||||
 | 
					        ? options.isOss || false
 | 
				
			||||||
 | 
					        : !isEnterprise && ui.environment !== 'pro';
 | 
				
			||||||
    const metricsRateLimiting = loadMetricsRateLimitingConfig(options);
 | 
					    const metricsRateLimiting = loadMetricsRateLimitingConfig(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const rateLimiting = loadRateLimitingConfig(options);
 | 
					    const rateLimiting = loadRateLimitingConfig(options);
 | 
				
			||||||
@ -760,6 +764,7 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
 | 
				
			|||||||
        publicFolder: options.publicFolder,
 | 
					        publicFolder: options.publicFolder,
 | 
				
			||||||
        disableScheduler: options.disableScheduler,
 | 
					        disableScheduler: options.disableScheduler,
 | 
				
			||||||
        isEnterprise: isEnterprise,
 | 
					        isEnterprise: isEnterprise,
 | 
				
			||||||
 | 
					        isOss: isOss,
 | 
				
			||||||
        metricsRateLimiting,
 | 
					        metricsRateLimiting,
 | 
				
			||||||
        rateLimiting,
 | 
					        rateLimiting,
 | 
				
			||||||
        feedbackUriPath,
 | 
					        feedbackUriPath,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,13 +3,14 @@ import type {
 | 
				
			|||||||
    FeatureEnvironmentKey,
 | 
					    FeatureEnvironmentKey,
 | 
				
			||||||
    IFeatureEnvironmentStore,
 | 
					    IFeatureEnvironmentStore,
 | 
				
			||||||
} from '../types/stores/feature-environment-store';
 | 
					} from '../types/stores/feature-environment-store';
 | 
				
			||||||
import type { Logger, LogProvider } from '../logger';
 | 
					import type { Logger } from '../logger';
 | 
				
			||||||
import metricsHelper from '../util/metrics-helper';
 | 
					import metricsHelper from '../util/metrics-helper';
 | 
				
			||||||
import { DB_TIME } from '../metric-events';
 | 
					import { DB_TIME } from '../metric-events';
 | 
				
			||||||
import type { IFeatureEnvironment, IVariant } from '../types/model';
 | 
					import type { IFeatureEnvironment, IVariant } from '../types/model';
 | 
				
			||||||
import NotFoundError from '../error/notfound-error';
 | 
					import NotFoundError from '../error/notfound-error';
 | 
				
			||||||
import { v4 as uuidv4 } from 'uuid';
 | 
					import { v4 as uuidv4 } from 'uuid';
 | 
				
			||||||
import type { Db } from './db';
 | 
					import type { Db } from './db';
 | 
				
			||||||
 | 
					import type { IUnleashConfig } from '../types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const T = {
 | 
					const T = {
 | 
				
			||||||
    featureEnvs: 'feature_environments',
 | 
					    featureEnvs: 'feature_environments',
 | 
				
			||||||
@ -36,7 +37,12 @@ export class FeatureEnvironmentStore implements IFeatureEnvironmentStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private readonly timer: Function;
 | 
					    private readonly timer: Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(db: Db, eventBus: EventEmitter, getLogger: LogProvider) {
 | 
					    private readonly isOss: boolean;
 | 
				
			||||||
 | 
					    constructor(
 | 
				
			||||||
 | 
					        db: Db,
 | 
				
			||||||
 | 
					        eventBus: EventEmitter,
 | 
				
			||||||
 | 
					        { getLogger, isOss }: Pick<IUnleashConfig, 'getLogger' | 'isOss'>,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
        this.db = db;
 | 
					        this.db = db;
 | 
				
			||||||
        this.logger = getLogger('feature-environment-store.ts');
 | 
					        this.logger = getLogger('feature-environment-store.ts');
 | 
				
			||||||
        this.timer = (action) =>
 | 
					        this.timer = (action) =>
 | 
				
			||||||
@ -44,6 +50,7 @@ export class FeatureEnvironmentStore implements IFeatureEnvironmentStore {
 | 
				
			|||||||
                store: 'feature-environments',
 | 
					                store: 'feature-environments',
 | 
				
			||||||
                action,
 | 
					                action,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					        this.isOss = isOss;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async delete({
 | 
					    async delete({
 | 
				
			||||||
@ -96,11 +103,30 @@ export class FeatureEnvironmentStore implements IFeatureEnvironmentStore {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    addOssFilterIfNeeded(queryBuilder) {
 | 
				
			||||||
 | 
					        if (this.isOss) {
 | 
				
			||||||
 | 
					            return queryBuilder
 | 
				
			||||||
 | 
					                .join(
 | 
				
			||||||
 | 
					                    'environments',
 | 
				
			||||||
 | 
					                    'environments.name',
 | 
				
			||||||
 | 
					                    '=',
 | 
				
			||||||
 | 
					                    `${T.featureEnvs}.environment`,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .whereIn('environments.name', [
 | 
				
			||||||
 | 
					                    'default',
 | 
				
			||||||
 | 
					                    'development',
 | 
				
			||||||
 | 
					                    'production',
 | 
				
			||||||
 | 
					                ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return queryBuilder;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async getAll(query?: Object): Promise<IFeatureEnvironment[]> {
 | 
					    async getAll(query?: Object): Promise<IFeatureEnvironment[]> {
 | 
				
			||||||
        let rows = this.db(T.featureEnvs);
 | 
					        let rows = this.db(T.featureEnvs);
 | 
				
			||||||
        if (query) {
 | 
					        if (query) {
 | 
				
			||||||
            rows = rows.where(query);
 | 
					            rows = rows.where(query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        this.addOssFilterIfNeeded(rows);
 | 
				
			||||||
        return (await rows).map((r) => ({
 | 
					        return (await rows).map((r) => ({
 | 
				
			||||||
            enabled: r.enabled,
 | 
					            enabled: r.enabled,
 | 
				
			||||||
            featureName: r.feature_name,
 | 
					            featureName: r.feature_name,
 | 
				
			||||||
@ -119,6 +145,7 @@ export class FeatureEnvironmentStore implements IFeatureEnvironmentStore {
 | 
				
			|||||||
        if (environment) {
 | 
					        if (environment) {
 | 
				
			||||||
            rows = rows.where({ environment });
 | 
					            rows = rows.where({ environment });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        this.addOssFilterIfNeeded(rows);
 | 
				
			||||||
        return (await rows).map((r) => ({
 | 
					        return (await rows).map((r) => ({
 | 
				
			||||||
            enabled: r.enabled,
 | 
					            enabled: r.enabled,
 | 
				
			||||||
            featureName: r.feature_name,
 | 
					            featureName: r.feature_name,
 | 
				
			||||||
 | 
				
			|||||||
@ -94,12 +94,7 @@ export const createStores = (
 | 
				
			|||||||
        settingStore: new SettingStore(db, getLogger),
 | 
					        settingStore: new SettingStore(db, getLogger),
 | 
				
			||||||
        userStore: new UserStore(db, getLogger, config.flagResolver),
 | 
					        userStore: new UserStore(db, getLogger, config.flagResolver),
 | 
				
			||||||
        accountStore: new AccountStore(db, getLogger),
 | 
					        accountStore: new AccountStore(db, getLogger),
 | 
				
			||||||
        projectStore: new ProjectStore(
 | 
					        projectStore: new ProjectStore(db, eventBus, config),
 | 
				
			||||||
            db,
 | 
					 | 
				
			||||||
            eventBus,
 | 
					 | 
				
			||||||
            getLogger,
 | 
					 | 
				
			||||||
            config.flagResolver,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        tagStore: new TagStore(db, eventBus, getLogger),
 | 
					        tagStore: new TagStore(db, eventBus, getLogger),
 | 
				
			||||||
        tagTypeStore: new TagTypeStore(db, eventBus, getLogger),
 | 
					        tagTypeStore: new TagTypeStore(db, eventBus, getLogger),
 | 
				
			||||||
        addonStore: new AddonStore(db, eventBus, getLogger),
 | 
					        addonStore: new AddonStore(db, eventBus, getLogger),
 | 
				
			||||||
@ -122,15 +117,14 @@ export const createStores = (
 | 
				
			|||||||
        clientFeatureToggleStore: new FeatureToggleClientStore(
 | 
					        clientFeatureToggleStore: new FeatureToggleClientStore(
 | 
				
			||||||
            db,
 | 
					            db,
 | 
				
			||||||
            eventBus,
 | 
					            eventBus,
 | 
				
			||||||
            getLogger,
 | 
					            config,
 | 
				
			||||||
            config.flagResolver,
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        environmentStore: new EnvironmentStore(db, eventBus, getLogger),
 | 
					        environmentStore: new EnvironmentStore(db, eventBus, config),
 | 
				
			||||||
        featureTagStore: new FeatureTagStore(db, eventBus, getLogger),
 | 
					        featureTagStore: new FeatureTagStore(db, eventBus, getLogger),
 | 
				
			||||||
        featureEnvironmentStore: new FeatureEnvironmentStore(
 | 
					        featureEnvironmentStore: new FeatureEnvironmentStore(
 | 
				
			||||||
            db,
 | 
					            db,
 | 
				
			||||||
            eventBus,
 | 
					            eventBus,
 | 
				
			||||||
            getLogger,
 | 
					            config,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        userSplashStore: new UserSplashStore(db, eventBus, getLogger),
 | 
					        userSplashStore: new UserSplashStore(db, eventBus, getLogger),
 | 
				
			||||||
        roleStore: new RoleStore(db, eventBus, getLogger),
 | 
					        roleStore: new RoleStore(db, eventBus, getLogger),
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ export const createAccessService = (
 | 
				
			|||||||
    const groupStore = new GroupStore(db);
 | 
					    const groupStore = new GroupStore(db);
 | 
				
			||||||
    const accountStore = new AccountStore(db, getLogger);
 | 
					    const accountStore = new AccountStore(db, getLogger);
 | 
				
			||||||
    const roleStore = new RoleStore(db, eventBus, getLogger);
 | 
					    const roleStore = new RoleStore(db, eventBus, getLogger);
 | 
				
			||||||
    const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
 | 
					    const environmentStore = new EnvironmentStore(db, eventBus, config);
 | 
				
			||||||
    const accessStore = new AccessStore(db, eventBus, getLogger);
 | 
					    const accessStore = new AccessStore(db, eventBus, getLogger);
 | 
				
			||||||
    const eventService = createEventsService(db, config);
 | 
					    const eventService = createEventsService(db, config);
 | 
				
			||||||
    const groupService = new GroupService(
 | 
					    const groupService = new GroupService(
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ export const createApiTokenService = (
 | 
				
			|||||||
        getLogger,
 | 
					        getLogger,
 | 
				
			||||||
        config.flagResolver,
 | 
					        config.flagResolver,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
 | 
					    const environmentStore = new EnvironmentStore(db, eventBus, config);
 | 
				
			||||||
    const eventService = createEventsService(db, config);
 | 
					    const eventService = createEventsService(db, config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return new ApiTokenService(
 | 
					    return new ApiTokenService(
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { Knex } from 'knex';
 | 
					import { Knex } from 'knex';
 | 
				
			||||||
import metricsHelper from '../../util/metrics-helper';
 | 
					import metricsHelper from '../../util/metrics-helper';
 | 
				
			||||||
import { DB_TIME } from '../../metric-events';
 | 
					import { DB_TIME } from '../../metric-events';
 | 
				
			||||||
import type { Logger, LogProvider } from '../../logger';
 | 
					import type { Logger } from '../../logger';
 | 
				
			||||||
import type {
 | 
					import type {
 | 
				
			||||||
    IFeatureToggleClient,
 | 
					    IFeatureToggleClient,
 | 
				
			||||||
    IFeatureToggleClientStore,
 | 
					    IFeatureToggleClientStore,
 | 
				
			||||||
@ -9,6 +9,7 @@ import type {
 | 
				
			|||||||
    IFlagResolver,
 | 
					    IFlagResolver,
 | 
				
			||||||
    IStrategyConfig,
 | 
					    IStrategyConfig,
 | 
				
			||||||
    ITag,
 | 
					    ITag,
 | 
				
			||||||
 | 
					    IUnleashConfig,
 | 
				
			||||||
    PartialDeep,
 | 
					    PartialDeep,
 | 
				
			||||||
} from '../../types';
 | 
					} from '../../types';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -46,11 +47,16 @@ export default class FeatureToggleClientStore
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private flagResolver: IFlagResolver;
 | 
					    private flagResolver: IFlagResolver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly isOss: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        db: Db,
 | 
					        db: Db,
 | 
				
			||||||
        eventBus: EventEmitter,
 | 
					        eventBus: EventEmitter,
 | 
				
			||||||
        getLogger: LogProvider,
 | 
					        {
 | 
				
			||||||
        flagResolver: IFlagResolver,
 | 
					            getLogger,
 | 
				
			||||||
 | 
					            flagResolver,
 | 
				
			||||||
 | 
					            isOss,
 | 
				
			||||||
 | 
					        }: Pick<IUnleashConfig, 'getLogger' | 'flagResolver' | 'isOss'>,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        this.db = db;
 | 
					        this.db = db;
 | 
				
			||||||
        this.logger = getLogger('feature-toggle-client-store.ts');
 | 
					        this.logger = getLogger('feature-toggle-client-store.ts');
 | 
				
			||||||
@ -60,6 +66,7 @@ export default class FeatureToggleClientStore
 | 
				
			|||||||
                action,
 | 
					                action,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        this.flagResolver = flagResolver;
 | 
					        this.flagResolver = flagResolver;
 | 
				
			||||||
 | 
					        this.isOss = isOss;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private async getAll({
 | 
					    private async getAll({
 | 
				
			||||||
@ -72,7 +79,6 @@ export default class FeatureToggleClientStore
 | 
				
			|||||||
        const isPlayground = requestType === 'playground';
 | 
					        const isPlayground = requestType === 'playground';
 | 
				
			||||||
        const environment = featureQuery?.environment || DEFAULT_ENV;
 | 
					        const environment = featureQuery?.environment || DEFAULT_ENV;
 | 
				
			||||||
        const stopTimer = this.timer(`getAllBy${requestType}`);
 | 
					        const stopTimer = this.timer(`getAllBy${requestType}`);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        let selectColumns = [
 | 
					        let selectColumns = [
 | 
				
			||||||
            'features.name as name',
 | 
					            'features.name as name',
 | 
				
			||||||
            'features.description as description',
 | 
					            'features.description as description',
 | 
				
			||||||
@ -103,6 +109,10 @@ export default class FeatureToggleClientStore
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let query = this.db('features')
 | 
					        let query = this.db('features')
 | 
				
			||||||
            .modify(FeatureToggleStore.filterByArchived, archived)
 | 
					            .modify(FeatureToggleStore.filterByArchived, archived)
 | 
				
			||||||
 | 
					            .modify(
 | 
				
			||||||
 | 
					                FeatureToggleStore.filterByProjectsAccessibleByOss,
 | 
				
			||||||
 | 
					                this.isOss,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
            .leftJoin(
 | 
					            .leftJoin(
 | 
				
			||||||
                this.db('feature_strategies')
 | 
					                this.db('feature_strategies')
 | 
				
			||||||
                    .select('*')
 | 
					                    .select('*')
 | 
				
			||||||
 | 
				
			|||||||
@ -10,13 +10,10 @@ export const createClientFeatureToggleService = (
 | 
				
			|||||||
    db: Db,
 | 
					    db: Db,
 | 
				
			||||||
    config: IUnleashConfig,
 | 
					    config: IUnleashConfig,
 | 
				
			||||||
): ClientFeatureToggleService => {
 | 
					): ClientFeatureToggleService => {
 | 
				
			||||||
    const { getLogger, eventBus, flagResolver } = config;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const featureToggleClientStore = new FeatureToggleClientStore(
 | 
					    const featureToggleClientStore = new FeatureToggleClientStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
        eventBus,
 | 
					        config.eventBus,
 | 
				
			||||||
        getLogger,
 | 
					        config,
 | 
				
			||||||
        flagResolver,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const segmentReadModel = new SegmentReadModel(db);
 | 
					    const segmentReadModel = new SegmentReadModel(db);
 | 
				
			||||||
@ -26,7 +23,7 @@ export const createClientFeatureToggleService = (
 | 
				
			|||||||
            clientFeatureToggleStore: featureToggleClientStore,
 | 
					            clientFeatureToggleStore: featureToggleClientStore,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        segmentReadModel,
 | 
					        segmentReadModel,
 | 
				
			||||||
        { getLogger, flagResolver },
 | 
					        config,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return clientFeatureToggleService;
 | 
					    return clientFeatureToggleService;
 | 
				
			||||||
@ -35,8 +32,6 @@ export const createClientFeatureToggleService = (
 | 
				
			|||||||
export const createFakeClientFeatureToggleService = (
 | 
					export const createFakeClientFeatureToggleService = (
 | 
				
			||||||
    config: IUnleashConfig,
 | 
					    config: IUnleashConfig,
 | 
				
			||||||
): ClientFeatureToggleService => {
 | 
					): ClientFeatureToggleService => {
 | 
				
			||||||
    const { getLogger, flagResolver } = config;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const fakeClientFeatureToggleStore = new FakeClientFeatureToggleStore();
 | 
					    const fakeClientFeatureToggleStore = new FakeClientFeatureToggleStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const fakeSegmentReadModel = new FakeSegmentReadModel();
 | 
					    const fakeSegmentReadModel = new FakeSegmentReadModel();
 | 
				
			||||||
@ -46,7 +41,7 @@ export const createFakeClientFeatureToggleService = (
 | 
				
			|||||||
            clientFeatureToggleStore: fakeClientFeatureToggleStore,
 | 
					            clientFeatureToggleStore: fakeClientFeatureToggleStore,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        fakeSegmentReadModel,
 | 
					        fakeSegmentReadModel,
 | 
				
			||||||
        { getLogger, flagResolver },
 | 
					        config,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return clientFeatureToggleService;
 | 
					    return clientFeatureToggleService;
 | 
				
			||||||
 | 
				
			|||||||
@ -150,12 +150,7 @@ export const deferredExportImportTogglesService = (
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
        const tagStore = new TagStore(db, eventBus, getLogger);
 | 
					        const tagStore = new TagStore(db, eventBus, getLogger);
 | 
				
			||||||
        const tagTypeStore = new TagTypeStore(db, eventBus, getLogger);
 | 
					        const tagTypeStore = new TagTypeStore(db, eventBus, getLogger);
 | 
				
			||||||
        const projectStore = new ProjectStore(
 | 
					        const projectStore = new ProjectStore(db, eventBus, config);
 | 
				
			||||||
            db,
 | 
					 | 
				
			||||||
            eventBus,
 | 
					 | 
				
			||||||
            getLogger,
 | 
					 | 
				
			||||||
            flagResolver,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        const featureTagStore = new FeatureTagStore(db, eventBus, getLogger);
 | 
					        const featureTagStore = new FeatureTagStore(db, eventBus, getLogger);
 | 
				
			||||||
        const strategyStore = new StrategyStore(db, getLogger);
 | 
					        const strategyStore = new StrategyStore(db, getLogger);
 | 
				
			||||||
        const contextFieldStore = new ContextFieldStore(
 | 
					        const contextFieldStore = new ContextFieldStore(
 | 
				
			||||||
@ -172,7 +167,7 @@ export const deferredExportImportTogglesService = (
 | 
				
			|||||||
        const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
					        const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
				
			||||||
            db,
 | 
					            db,
 | 
				
			||||||
            eventBus,
 | 
					            eventBus,
 | 
				
			||||||
            getLogger,
 | 
					            config,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        const eventStore = new EventStore(db, getLogger);
 | 
					        const eventStore = new EventStore(db, getLogger);
 | 
				
			||||||
        const accessService = createAccessService(db, config);
 | 
					        const accessService = createAccessService(db, config);
 | 
				
			||||||
 | 
				
			|||||||
@ -19,11 +19,11 @@ export const createFeatureLifecycleService =
 | 
				
			|||||||
        const { eventBus, getLogger } = config;
 | 
					        const { eventBus, getLogger } = config;
 | 
				
			||||||
        const eventStore = new EventStore(db, getLogger);
 | 
					        const eventStore = new EventStore(db, getLogger);
 | 
				
			||||||
        const featureLifecycleStore = new FeatureLifecycleStore(db);
 | 
					        const featureLifecycleStore = new FeatureLifecycleStore(db);
 | 
				
			||||||
        const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
 | 
					        const environmentStore = new EnvironmentStore(db, eventBus, config);
 | 
				
			||||||
        const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
					        const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
				
			||||||
            db,
 | 
					            db,
 | 
				
			||||||
            eventBus,
 | 
					            eventBus,
 | 
				
			||||||
            getLogger,
 | 
					            config,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        const eventService = createEventsService(db, config);
 | 
					        const eventService = createEventsService(db, config);
 | 
				
			||||||
        const featureLifecycleService = new FeatureLifecycleService(
 | 
					        const featureLifecycleService = new FeatureLifecycleService(
 | 
				
			||||||
 | 
				
			|||||||
@ -80,19 +80,13 @@ export const createFeatureToggleService = (
 | 
				
			|||||||
    const featureToggleClientStore = new FeatureToggleClientStore(
 | 
					    const featureToggleClientStore = new FeatureToggleClientStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
        eventBus,
 | 
					        eventBus,
 | 
				
			||||||
        getLogger,
 | 
					        config,
 | 
				
			||||||
        flagResolver,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    const projectStore = new ProjectStore(
 | 
					 | 
				
			||||||
        db,
 | 
					 | 
				
			||||||
        eventBus,
 | 
					 | 
				
			||||||
        getLogger,
 | 
					 | 
				
			||||||
        flagResolver,
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					    const projectStore = new ProjectStore(db, eventBus, config);
 | 
				
			||||||
    const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
					    const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
        eventBus,
 | 
					        eventBus,
 | 
				
			||||||
        getLogger,
 | 
					        config,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const contextFieldStore = new ContextFieldStore(
 | 
					    const contextFieldStore = new ContextFieldStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
@ -105,7 +99,7 @@ export const createFeatureToggleService = (
 | 
				
			|||||||
    const accessStore = new AccessStore(db, eventBus, getLogger);
 | 
					    const accessStore = new AccessStore(db, eventBus, getLogger);
 | 
				
			||||||
    const featureTagStore = new FeatureTagStore(db, eventBus, getLogger);
 | 
					    const featureTagStore = new FeatureTagStore(db, eventBus, getLogger);
 | 
				
			||||||
    const roleStore = new RoleStore(db, eventBus, getLogger);
 | 
					    const roleStore = new RoleStore(db, eventBus, getLogger);
 | 
				
			||||||
    const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
 | 
					    const environmentStore = new EnvironmentStore(db, eventBus, config);
 | 
				
			||||||
    const eventService = createEventsService(db, config);
 | 
					    const eventService = createEventsService(db, config);
 | 
				
			||||||
    const groupService = new GroupService(
 | 
					    const groupService = new GroupService(
 | 
				
			||||||
        { groupStore, accountStore },
 | 
					        { groupStore, accountStore },
 | 
				
			||||||
 | 
				
			|||||||
@ -439,6 +439,16 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
 | 
				
			|||||||
            : queryBuilder.whereNull('archived_at');
 | 
					            : queryBuilder.whereNull('archived_at');
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static filterByProjectsAccessibleByOss: Knex.QueryCallbackWithArgs = (
 | 
				
			||||||
 | 
					        queryBuilder: Knex.QueryBuilder,
 | 
				
			||||||
 | 
					        isOss: boolean,
 | 
				
			||||||
 | 
					    ) => {
 | 
				
			||||||
 | 
					        if (isOss) {
 | 
				
			||||||
 | 
					            return queryBuilder.andWhere('project', '=', 'default');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return queryBuilder;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rowToFeature(row: FeaturesTable): FeatureToggle {
 | 
					    rowToFeature(row: FeaturesTable): FeatureToggle {
 | 
				
			||||||
        if (!row) {
 | 
					        if (!row) {
 | 
				
			||||||
            throw new NotFoundError('No feature flag found');
 | 
					            throw new NotFoundError('No feature flag found');
 | 
				
			||||||
 | 
				
			|||||||
@ -58,13 +58,8 @@ export const createInstanceStatsService = (db: Db, config: IUnleashConfig) => {
 | 
				
			|||||||
        flagResolver,
 | 
					        flagResolver,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const userStore = new UserStore(db, getLogger, flagResolver);
 | 
					    const userStore = new UserStore(db, getLogger, flagResolver);
 | 
				
			||||||
    const projectStore = new ProjectStore(
 | 
					    const projectStore = new ProjectStore(db, eventBus, config);
 | 
				
			||||||
        db,
 | 
					    const environmentStore = new EnvironmentStore(db, eventBus, config);
 | 
				
			||||||
        eventBus,
 | 
					 | 
				
			||||||
        getLogger,
 | 
					 | 
				
			||||||
        flagResolver,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
 | 
					 | 
				
			||||||
    const strategyStore = new StrategyStore(db, getLogger);
 | 
					    const strategyStore = new StrategyStore(db, getLogger);
 | 
				
			||||||
    const contextFieldStore = new ContextFieldStore(
 | 
					    const contextFieldStore = new ContextFieldStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
 | 
				
			|||||||
@ -21,21 +21,16 @@ export const createEnvironmentService =
 | 
				
			|||||||
        const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
					        const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
				
			||||||
            db,
 | 
					            db,
 | 
				
			||||||
            eventBus,
 | 
					            eventBus,
 | 
				
			||||||
            getLogger,
 | 
					            config,
 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        const projectStore = new ProjectStore(
 | 
					 | 
				
			||||||
            db,
 | 
					 | 
				
			||||||
            eventBus,
 | 
					 | 
				
			||||||
            getLogger,
 | 
					 | 
				
			||||||
            flagResolver,
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					        const projectStore = new ProjectStore(db, eventBus, config);
 | 
				
			||||||
        const featureStrategiesStore = new FeatureStrategiesStore(
 | 
					        const featureStrategiesStore = new FeatureStrategiesStore(
 | 
				
			||||||
            db,
 | 
					            db,
 | 
				
			||||||
            eventBus,
 | 
					            eventBus,
 | 
				
			||||||
            getLogger,
 | 
					            getLogger,
 | 
				
			||||||
            flagResolver,
 | 
					            flagResolver,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
 | 
					        const environmentStore = new EnvironmentStore(db, eventBus, config);
 | 
				
			||||||
        const eventService = createEventsService(db, config);
 | 
					        const eventService = createEventsService(db, config);
 | 
				
			||||||
        return new EnvironmentService(
 | 
					        return new EnvironmentService(
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import type EventEmitter from 'events';
 | 
					import type EventEmitter from 'events';
 | 
				
			||||||
import type { Db } from '../../db/db';
 | 
					import type { Db } from '../../db/db';
 | 
				
			||||||
import type { Logger, LogProvider } from '../../logger';
 | 
					import type { Logger } from '../../logger';
 | 
				
			||||||
import metricsHelper from '../../util/metrics-helper';
 | 
					import metricsHelper from '../../util/metrics-helper';
 | 
				
			||||||
import { DB_TIME } from '../../metric-events';
 | 
					import { DB_TIME } from '../../metric-events';
 | 
				
			||||||
import type {
 | 
					import type {
 | 
				
			||||||
@ -12,6 +12,7 @@ import NotFoundError from '../../error/notfound-error';
 | 
				
			|||||||
import type { IEnvironmentStore } from './environment-store-type';
 | 
					import type { IEnvironmentStore } from './environment-store-type';
 | 
				
			||||||
import { snakeCaseKeys } from '../../util/snakeCase';
 | 
					import { snakeCaseKeys } from '../../util/snakeCase';
 | 
				
			||||||
import type { CreateFeatureStrategySchema } from '../../openapi';
 | 
					import type { CreateFeatureStrategySchema } from '../../openapi';
 | 
				
			||||||
 | 
					import type { IUnleashConfig } from '../../types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IEnvironmentsTable {
 | 
					interface IEnvironmentsTable {
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
@ -104,11 +105,18 @@ export default class EnvironmentStore implements IEnvironmentStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private db: Db;
 | 
					    private db: Db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private isOss: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private timer: (string) => any;
 | 
					    private timer: (string) => any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(db: Db, eventBus: EventEmitter, getLogger: LogProvider) {
 | 
					    constructor(
 | 
				
			||||||
 | 
					        db: Db,
 | 
				
			||||||
 | 
					        eventBus: EventEmitter,
 | 
				
			||||||
 | 
					        { getLogger, isOss }: Pick<IUnleashConfig, 'getLogger' | 'isOss'>,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
        this.db = db;
 | 
					        this.db = db;
 | 
				
			||||||
        this.logger = getLogger('db/environment-store.ts');
 | 
					        this.logger = getLogger('db/environment-store.ts');
 | 
				
			||||||
 | 
					        this.isOss = isOss;
 | 
				
			||||||
        this.timer = (action) =>
 | 
					        this.timer = (action) =>
 | 
				
			||||||
            metricsHelper.wrapTimer(eventBus, DB_TIME, {
 | 
					            metricsHelper.wrapTimer(eventBus, DB_TIME, {
 | 
				
			||||||
                store: 'environment',
 | 
					                store: 'environment',
 | 
				
			||||||
@ -148,9 +156,15 @@ export default class EnvironmentStore implements IEnvironmentStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    async get(key: string): Promise<IEnvironment> {
 | 
					    async get(key: string): Promise<IEnvironment> {
 | 
				
			||||||
        const stopTimer = this.timer('get');
 | 
					        const stopTimer = this.timer('get');
 | 
				
			||||||
        const row = await this.db<IEnvironmentsTable>(TABLE)
 | 
					        let keyQuery = this.db<IEnvironmentsTable>(TABLE).where({ name: key });
 | 
				
			||||||
            .where({ name: key })
 | 
					        if (this.isOss) {
 | 
				
			||||||
            .first();
 | 
					            keyQuery = keyQuery.whereIn('name', [
 | 
				
			||||||
 | 
					                'default',
 | 
				
			||||||
 | 
					                'development',
 | 
				
			||||||
 | 
					                'production',
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const row = await keyQuery.first();
 | 
				
			||||||
        stopTimer();
 | 
					        stopTimer();
 | 
				
			||||||
        if (row) {
 | 
					        if (row) {
 | 
				
			||||||
            return mapRow(row);
 | 
					            return mapRow(row);
 | 
				
			||||||
@ -169,6 +183,9 @@ export default class EnvironmentStore implements IEnvironmentStore {
 | 
				
			|||||||
        if (query) {
 | 
					        if (query) {
 | 
				
			||||||
            qB = qB.where(query);
 | 
					            qB = qB.where(query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.isOss) {
 | 
				
			||||||
 | 
					            qB = qB.whereIn('name', ['default', 'development', 'production']);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const rows = await qB;
 | 
					        const rows = await qB;
 | 
				
			||||||
        stopTimer();
 | 
					        stopTimer();
 | 
				
			||||||
        return rows.map(mapRow);
 | 
					        return rows.map(mapRow);
 | 
				
			||||||
@ -196,6 +213,9 @@ export default class EnvironmentStore implements IEnvironmentStore {
 | 
				
			|||||||
        if (query) {
 | 
					        if (query) {
 | 
				
			||||||
            qB = qB.where(query);
 | 
					            qB = qB.where(query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.isOss) {
 | 
				
			||||||
 | 
					            qB = qB.whereIn('name', ['default', 'development', 'production']);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const rows = await qB;
 | 
					        const rows = await qB;
 | 
				
			||||||
        stopTimer();
 | 
					        stopTimer();
 | 
				
			||||||
        return rows.map(mapRowWithCounts);
 | 
					        return rows.map(mapRowWithCounts);
 | 
				
			||||||
@ -230,6 +250,13 @@ export default class EnvironmentStore implements IEnvironmentStore {
 | 
				
			|||||||
        if (query) {
 | 
					        if (query) {
 | 
				
			||||||
            qB = qB.where(query);
 | 
					            qB = qB.where(query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.isOss) {
 | 
				
			||||||
 | 
					            qB = qB.whereIn('environments.name', [
 | 
				
			||||||
 | 
					                'default',
 | 
				
			||||||
 | 
					                'production',
 | 
				
			||||||
 | 
					                'development',
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const rows = await qB;
 | 
					        const rows = await qB;
 | 
				
			||||||
        stopTimer();
 | 
					        stopTimer();
 | 
				
			||||||
 | 
				
			|||||||
@ -16,12 +16,7 @@ export const createProjectInsightsService = (
 | 
				
			|||||||
    config: IUnleashConfig,
 | 
					    config: IUnleashConfig,
 | 
				
			||||||
): ProjectInsightsService => {
 | 
					): ProjectInsightsService => {
 | 
				
			||||||
    const { eventBus, getLogger, flagResolver } = config;
 | 
					    const { eventBus, getLogger, flagResolver } = config;
 | 
				
			||||||
    const projectStore = new ProjectStore(
 | 
					    const projectStore = new ProjectStore(db, eventBus, config);
 | 
				
			||||||
        db,
 | 
					 | 
				
			||||||
        eventBus,
 | 
					 | 
				
			||||||
        getLogger,
 | 
					 | 
				
			||||||
        flagResolver,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    const featureToggleStore = new FeatureToggleStore(
 | 
					    const featureToggleStore = new FeatureToggleStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
        eventBus,
 | 
					        eventBus,
 | 
				
			||||||
 | 
				
			|||||||
@ -24,12 +24,7 @@ export const createProjectStatusService = (
 | 
				
			|||||||
    config: IUnleashConfig,
 | 
					    config: IUnleashConfig,
 | 
				
			||||||
): ProjectStatusService => {
 | 
					): ProjectStatusService => {
 | 
				
			||||||
    const eventStore = new EventStore(db, config.getLogger);
 | 
					    const eventStore = new EventStore(db, config.getLogger);
 | 
				
			||||||
    const projectStore = new ProjectStore(
 | 
					    const projectStore = new ProjectStore(db, config.eventBus, config);
 | 
				
			||||||
        db,
 | 
					 | 
				
			||||||
        config.eventBus,
 | 
					 | 
				
			||||||
        config.getLogger,
 | 
					 | 
				
			||||||
        config.flagResolver,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    const apiTokenStore = new ApiTokenStore(
 | 
					    const apiTokenStore = new ApiTokenStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
        config.eventBus,
 | 
					        config.eventBus,
 | 
				
			||||||
 | 
				
			|||||||
@ -63,12 +63,7 @@ export const createProjectService = (
 | 
				
			|||||||
): ProjectService => {
 | 
					): ProjectService => {
 | 
				
			||||||
    const { eventBus, getLogger, flagResolver } = config;
 | 
					    const { eventBus, getLogger, flagResolver } = config;
 | 
				
			||||||
    const eventStore = new EventStore(db, getLogger);
 | 
					    const eventStore = new EventStore(db, getLogger);
 | 
				
			||||||
    const projectStore = new ProjectStore(
 | 
					    const projectStore = new ProjectStore(db, eventBus, config);
 | 
				
			||||||
        db,
 | 
					 | 
				
			||||||
        eventBus,
 | 
					 | 
				
			||||||
        getLogger,
 | 
					 | 
				
			||||||
        flagResolver,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    const projectOwnersReadModel = new ProjectOwnersReadModel(db);
 | 
					    const projectOwnersReadModel = new ProjectOwnersReadModel(db);
 | 
				
			||||||
    const projectFlagCreatorsReadModel = new ProjectFlagCreatorsReadModel(db);
 | 
					    const projectFlagCreatorsReadModel = new ProjectFlagCreatorsReadModel(db);
 | 
				
			||||||
    const groupStore = new GroupStore(db);
 | 
					    const groupStore = new GroupStore(db);
 | 
				
			||||||
@ -79,11 +74,11 @@ export const createProjectService = (
 | 
				
			|||||||
        flagResolver,
 | 
					        flagResolver,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const accountStore = new AccountStore(db, getLogger);
 | 
					    const accountStore = new AccountStore(db, getLogger);
 | 
				
			||||||
    const environmentStore = new EnvironmentStore(db, eventBus, getLogger);
 | 
					    const environmentStore = new EnvironmentStore(db, eventBus, config);
 | 
				
			||||||
    const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
					    const featureEnvironmentStore = new FeatureEnvironmentStore(
 | 
				
			||||||
        db,
 | 
					        db,
 | 
				
			||||||
        eventBus,
 | 
					        eventBus,
 | 
				
			||||||
        getLogger,
 | 
					        config,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const projectStatsStore = new ProjectStatsStore(db, eventBus, getLogger);
 | 
					    const projectStatsStore = new ProjectStatsStore(db, eventBus, getLogger);
 | 
				
			||||||
    const accessService: AccessService = createAccessService(db, config);
 | 
					    const accessService: AccessService = createAccessService(db, config);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import type { Logger, LogProvider } from '../../logger';
 | 
					import type { Logger } from '../../logger';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import NotFoundError from '../../error/notfound-error';
 | 
					import NotFoundError from '../../error/notfound-error';
 | 
				
			||||||
import type {
 | 
					import type {
 | 
				
			||||||
@ -8,6 +8,7 @@ import type {
 | 
				
			|||||||
    IProjectApplication,
 | 
					    IProjectApplication,
 | 
				
			||||||
    IProjectApplications,
 | 
					    IProjectApplications,
 | 
				
			||||||
    IProjectUpdate,
 | 
					    IProjectUpdate,
 | 
				
			||||||
 | 
					    IUnleashConfig,
 | 
				
			||||||
    ProjectMode,
 | 
					    ProjectMode,
 | 
				
			||||||
} from '../../types';
 | 
					} from '../../types';
 | 
				
			||||||
import type {
 | 
					import type {
 | 
				
			||||||
@ -72,11 +73,16 @@ class ProjectStore implements IProjectStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private timer: Function;
 | 
					    private timer: Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private isOss: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        db: Db,
 | 
					        db: Db,
 | 
				
			||||||
        eventBus: EventEmitter,
 | 
					        eventBus: EventEmitter,
 | 
				
			||||||
        getLogger: LogProvider,
 | 
					        {
 | 
				
			||||||
        flagResolver: IFlagResolver,
 | 
					            getLogger,
 | 
				
			||||||
 | 
					            flagResolver,
 | 
				
			||||||
 | 
					            isOss,
 | 
				
			||||||
 | 
					        }: Pick<IUnleashConfig, 'getLogger' | 'flagResolver' | 'isOss'>,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        this.db = db;
 | 
					        this.db = db;
 | 
				
			||||||
        this.logger = getLogger('project-store.ts');
 | 
					        this.logger = getLogger('project-store.ts');
 | 
				
			||||||
@ -86,6 +92,7 @@ class ProjectStore implements IProjectStore {
 | 
				
			|||||||
                action,
 | 
					                action,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        this.flagResolver = flagResolver;
 | 
					        this.flagResolver = flagResolver;
 | 
				
			||||||
 | 
					        this.isOss = isOss;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
 | 
					    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
 | 
				
			||||||
@ -122,6 +129,9 @@ class ProjectStore implements IProjectStore {
 | 
				
			|||||||
            .orderBy('name', 'asc');
 | 
					            .orderBy('name', 'asc');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        projects = projects.where(`${TABLE}.archived_at`, null);
 | 
					        projects = projects.where(`${TABLE}.archived_at`, null);
 | 
				
			||||||
 | 
					        if (this.isOss) {
 | 
				
			||||||
 | 
					            projects = projects.where('id', 'default');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const rows = await projects;
 | 
					        const rows = await projects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -143,6 +143,7 @@ export interface IUnleashOptions {
 | 
				
			|||||||
    metricsRateLimiting?: Partial<IMetricsRateLimiting>;
 | 
					    metricsRateLimiting?: Partial<IMetricsRateLimiting>;
 | 
				
			||||||
    dailyMetricsStorageDays?: number;
 | 
					    dailyMetricsStorageDays?: number;
 | 
				
			||||||
    rateLimiting?: Partial<IRateLimiting>;
 | 
					    rateLimiting?: Partial<IRateLimiting>;
 | 
				
			||||||
 | 
					    isOss?: boolean;
 | 
				
			||||||
    resourceLimits?: Partial<
 | 
					    resourceLimits?: Partial<
 | 
				
			||||||
        Pick<
 | 
					        Pick<
 | 
				
			||||||
            ResourceLimitsSchema,
 | 
					            ResourceLimitsSchema,
 | 
				
			||||||
@ -273,6 +274,7 @@ export interface IUnleashConfig {
 | 
				
			|||||||
    publicFolder?: string;
 | 
					    publicFolder?: string;
 | 
				
			||||||
    disableScheduler?: boolean;
 | 
					    disableScheduler?: boolean;
 | 
				
			||||||
    isEnterprise: boolean;
 | 
					    isEnterprise: boolean;
 | 
				
			||||||
 | 
					    isOss: boolean;
 | 
				
			||||||
    rateLimiting: IRateLimiting;
 | 
					    rateLimiting: IRateLimiting;
 | 
				
			||||||
    feedbackUriPath?: string;
 | 
					    feedbackUriPath?: string;
 | 
				
			||||||
    openAIAPIKey?: string;
 | 
					    openAIAPIKey?: string;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										68
									
								
								src/test/e2e/api/admin/environment-oss.e2e.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/test/e2e/api/admin/environment-oss.e2e.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					import {
 | 
				
			||||||
 | 
					    type IUnleashTest,
 | 
				
			||||||
 | 
					    setupAppWithCustomConfig,
 | 
				
			||||||
 | 
					} from '../../helpers/test-helper';
 | 
				
			||||||
 | 
					import dbInit, { type ITestDb } from '../../helpers/database-init';
 | 
				
			||||||
 | 
					import getLogger from '../../../fixtures/no-logger';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let app: IUnleashTest;
 | 
				
			||||||
 | 
					let db: ITestDb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					beforeAll(async () => {
 | 
				
			||||||
 | 
					    db = await dbInit('environment_api_is_oss_serial', getLogger, {
 | 
				
			||||||
 | 
					        isOss: true,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    app = await setupAppWithCustomConfig(
 | 
				
			||||||
 | 
					        db.stores,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            experimental: {
 | 
				
			||||||
 | 
					                flags: {
 | 
				
			||||||
 | 
					                    strictSchemaValidation: true,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            isOss: true,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        db.rawDatabase,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    await db.stores.environmentStore.create({
 | 
				
			||||||
 | 
					        name: 'development',
 | 
				
			||||||
 | 
					        type: 'development',
 | 
				
			||||||
 | 
					        enabled: true,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    await db.stores.environmentStore.create({
 | 
				
			||||||
 | 
					        name: 'production',
 | 
				
			||||||
 | 
					        type: 'production',
 | 
				
			||||||
 | 
					        enabled: true,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    await db.stores.environmentStore.create({
 | 
				
			||||||
 | 
					        name: 'customenvironment',
 | 
				
			||||||
 | 
					        type: 'production',
 | 
				
			||||||
 | 
					        enabled: true,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    await db.stores.environmentStore.create({
 | 
				
			||||||
 | 
					        name: 'customenvironment2',
 | 
				
			||||||
 | 
					        type: 'production',
 | 
				
			||||||
 | 
					        enabled: true,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    await db.stores.environmentStore.create({
 | 
				
			||||||
 | 
					        name: 'customenvironment3',
 | 
				
			||||||
 | 
					        type: 'production',
 | 
				
			||||||
 | 
					        enabled: true,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					afterAll(async () => {
 | 
				
			||||||
 | 
					    await app.destroy();
 | 
				
			||||||
 | 
					    await db.destroy();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test('querying environments in OSS only returns environments that are included in oss', async () => {
 | 
				
			||||||
 | 
					    await app.request
 | 
				
			||||||
 | 
					        .get('/api/admin/environments')
 | 
				
			||||||
 | 
					        .expect(200)
 | 
				
			||||||
 | 
					        .expect((res) => {
 | 
				
			||||||
 | 
					            expect(res.body.environments).toHaveLength(3);
 | 
				
			||||||
 | 
					            const names = res.body.environments.map((env) => env.name);
 | 
				
			||||||
 | 
					            expect(names).toEqual(['default', 'development', 'production']);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										82
									
								
								src/test/e2e/api/client/feature-oss.e2e.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/test/e2e/api/client/feature-oss.e2e.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					import getLogger from '../../../fixtures/no-logger';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    type IUnleashTest,
 | 
				
			||||||
 | 
					    setupAppWithCustomConfig,
 | 
				
			||||||
 | 
					} from '../../helpers/test-helper';
 | 
				
			||||||
 | 
					import dbInit from '../../helpers/database-init';
 | 
				
			||||||
 | 
					import type { ITestDb } from '../../helpers/database-init';
 | 
				
			||||||
 | 
					import type { IAuditUser, IUser } from '../../../../lib/types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let app: IUnleashTest;
 | 
				
			||||||
 | 
					let db: ITestDb;
 | 
				
			||||||
 | 
					let testUser: IUser;
 | 
				
			||||||
 | 
					const auditUser = {
 | 
				
			||||||
 | 
					    username: 'audituser',
 | 
				
			||||||
 | 
					    id: -42,
 | 
				
			||||||
 | 
					    ip: 'localhost',
 | 
				
			||||||
 | 
					} as IAuditUser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let userIndex = 0;
 | 
				
			||||||
 | 
					const createUser = async (role?: number) => {
 | 
				
			||||||
 | 
					    const name = `User ${userIndex}`;
 | 
				
			||||||
 | 
					    const email = `user-${userIndex}@getunleash.io`;
 | 
				
			||||||
 | 
					    userIndex++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const { userStore } = db.stores;
 | 
				
			||||||
 | 
					    return userStore.insert({ name, email });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					beforeAll(async () => {
 | 
				
			||||||
 | 
					    db = await dbInit('feature_api_client_is_oss', getLogger, { isOss: true });
 | 
				
			||||||
 | 
					    app = await setupAppWithCustomConfig(
 | 
				
			||||||
 | 
					        db.stores,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            experimental: {
 | 
				
			||||||
 | 
					                flags: {
 | 
				
			||||||
 | 
					                    strictSchemaValidation: true,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            isOss: true,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        db.rawDatabase,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    testUser = await createUser();
 | 
				
			||||||
 | 
					    await app.services.projectService.createProject(
 | 
				
			||||||
 | 
					        { id: 'secondproject', name: 'Second project not returned when oss' },
 | 
				
			||||||
 | 
					        testUser,
 | 
				
			||||||
 | 
					        auditUser,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    await app.services.featureToggleService.createFeatureToggle(
 | 
				
			||||||
 | 
					        'secondproject',
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            name: 'my.feature.toggle',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        auditUser,
 | 
				
			||||||
 | 
					        true,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    await app.services.featureToggleService.createFeatureToggle(
 | 
				
			||||||
 | 
					        'default',
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            name: 'my.default.toggle',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        auditUser,
 | 
				
			||||||
 | 
					        true,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					afterAll(async () => {
 | 
				
			||||||
 | 
					    await app.destroy();
 | 
				
			||||||
 | 
					    await db.destroy();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('OSS downgrade', () => {
 | 
				
			||||||
 | 
					    test('features created in projects other than default is not visible in client endpoint', async () => {
 | 
				
			||||||
 | 
					        return app.request
 | 
				
			||||||
 | 
					            .get('/api/client/features')
 | 
				
			||||||
 | 
					            .expect('Content-Type', /json/)
 | 
				
			||||||
 | 
					            .expect(200)
 | 
				
			||||||
 | 
					            .expect((res) => {
 | 
				
			||||||
 | 
					                expect(res.body.features).toHaveLength(1);
 | 
				
			||||||
 | 
					                expect(res.body.features[0].name).toBe('my.default.toggle');
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user