1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-19 01:17:18 +02:00

refactor: rename proxy to frontend api (#6502)

This commit is contained in:
Mateusz Kwasniewski 2024-03-11 17:30:46 +01:00 committed by GitHub
parent b4454053e8
commit 1f374ea20e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 203 additions and 201 deletions

View File

@ -1,4 +1,4 @@
import { IFeatureToggleClient } from '../types';
import { IFeatureToggleClient } from '../../types';
export interface IClientFeatureToggleReadModel {
getAll(): Promise<Record<string, Record<string, IFeatureToggleClient>>>;

View File

@ -1,11 +1,15 @@
import { Knex } from 'knex';
import { IFeatureToggleClient, IStrategyConfig, PartialDeep } from '../types';
import { ensureStringValue, mapValues } from '../util';
import { Db } from '../db/db';
import FeatureToggleStore from '../features/feature-toggle/feature-toggle-store';
import {
IFeatureToggleClient,
IStrategyConfig,
PartialDeep,
} from '../../types';
import { ensureStringValue, mapValues } from '../../util';
import { Db } from '../../db/db';
import FeatureToggleStore from '../feature-toggle/feature-toggle-store';
import Raw = Knex.Raw;
import metricsHelper from '../util/metrics-helper';
import { DB_TIME } from '../metric-events';
import metricsHelper from '../../util/metrics-helper';
import { DB_TIME } from '../../metric-events';
import EventEmitter from 'events';
import { IClientFeatureToggleReadModel } from './client-feature-toggle-read-model-type';

View File

@ -1,30 +1,30 @@
import { ProxyService } from './proxy-service';
import { SegmentReadModel } from '../features/segment/segment-read-model';
import ClientMetricsServiceV2 from '../features/metrics/client-metrics/metrics-service-v2';
import SettingService from '../services/setting-service';
import SettingStore from '../db/setting-store';
import { FrontendApiService } from './frontend-api-service';
import { SegmentReadModel } from '../segment/segment-read-model';
import ClientMetricsServiceV2 from '../metrics/client-metrics/metrics-service-v2';
import SettingService from '../../services/setting-service';
import SettingStore from '../../db/setting-store';
import {
createEventsService,
createFakeEventsService,
createFakeFeatureToggleService,
createFeatureToggleService,
} from '../features';
import ConfigurationRevisionService from '../features/feature-toggle/configuration-revision-service';
} from '../index';
import ConfigurationRevisionService from '../feature-toggle/configuration-revision-service';
import { GlobalFrontendApiCache } from './global-frontend-api-cache';
import ClientFeatureToggleReadModel from './client-feature-toggle-read-model';
import { FakeSegmentReadModel } from '../features/segment/fake-segment-read-model';
import FakeSettingStore from '../../test/fixtures/fake-setting-store';
import { FakeSegmentReadModel } from '../segment/fake-segment-read-model';
import FakeSettingStore from '../../../test/fixtures/fake-setting-store';
import FakeClientFeatureToggleReadModel from './fake-client-feature-toggle-read-model';
import { IUnleashConfig } from '../types';
import { Db } from '../db/db';
import { IUnleashConfig } from '../../types';
import { Db } from '../../db/db';
export const createProxyService = (
export const createFrontendApiService = (
db: Db,
config: IUnleashConfig,
// client metrics service needs to be shared because it uses in-memory cache
clientMetricsServiceV2: ClientMetricsServiceV2,
configurationRevisionService: ConfigurationRevisionService,
): ProxyService => {
): FrontendApiService => {
const segmentReadModel = new SegmentReadModel(db);
const settingStore = new SettingStore(db, config.getLogger);
const eventService = createEventsService(db, config);
@ -45,7 +45,7 @@ export const createProxyService = (
clientFeatureToggleReadModel,
configurationRevisionService,
);
return new ProxyService(
return new FrontendApiService(
config,
{ segmentReadModel },
{
@ -58,11 +58,11 @@ export const createProxyService = (
);
};
export const createFakeProxyService = (
export const createFakeFrontendApiService = (
config: IUnleashConfig,
clientMetricsServiceV2: ClientMetricsServiceV2,
configurationRevisionService: ConfigurationRevisionService,
): ProxyService => {
): FrontendApiService => {
const segmentReadModel = new FakeSegmentReadModel();
const settingStore = new FakeSettingStore();
const eventService = createFakeEventsService(config);
@ -80,7 +80,7 @@ export const createFakeProxyService = (
clientFeatureToggleReadModel,
configurationRevisionService,
);
return new ProxyService(
return new FrontendApiService(
config,
{ segmentReadModel },
{

View File

@ -1,4 +1,4 @@
import { IFeatureToggleClient } from '../types';
import { IFeatureToggleClient } from '../../types';
import { IClientFeatureToggleReadModel } from './client-feature-toggle-read-model-type';
export default class FakeClientFeatureToggleReadModel

View File

@ -1,8 +1,8 @@
import { Request, Response } from 'express';
import Controller from '../routes/controller';
import { IUnleashConfig, IUnleashServices, NONE } from '../types';
import { Logger } from '../logger';
import { IApiUser } from '../types/api-user';
import Controller from '../../routes/controller';
import { IUnleashConfig, IUnleashServices, NONE } from '../../types';
import { Logger } from '../../logger';
import { IApiUser } from '../../types/api-user';
import {
ClientMetricsSchema,
createRequestSchema,
@ -13,12 +13,12 @@ import {
ProxyFeatureSchema,
proxyFeaturesSchema,
ProxyFeaturesSchema,
} from '../openapi';
} from '../../openapi';
import { Context } from 'unleash-client';
import { enrichContextWithIp } from './index';
import { corsOriginMiddleware } from '../middleware';
import NotImplementedError from '../error/not-implemented-error';
import NotFoundError from '../error/notfound-error';
import { corsOriginMiddleware } from '../../middleware';
import NotImplementedError from '../../error/not-implemented-error';
import NotFoundError from '../../error/notfound-error';
import rateLimit from 'express-rate-limit';
import { minutesToMilliseconds } from 'date-fns';
import isEqual from 'lodash.isequal';
@ -34,7 +34,7 @@ interface ApiUserRequest<
type Services = Pick<
IUnleashServices,
'settingService' | 'proxyService' | 'openApiService'
'settingService' | 'frontendApiService' | 'openApiService'
>;
export default class FrontendAPIController extends Controller {
@ -44,7 +44,7 @@ export default class FrontendAPIController extends Controller {
constructor(config: IUnleashConfig, services: Services) {
super(config);
this.logger = config.getLogger('proxy-api/index.ts');
this.logger = config.getLogger('frontend-api-controller.ts');
this.services = services;
// Support CORS requests for the frontend endpoints.
@ -54,7 +54,7 @@ export default class FrontendAPIController extends Controller {
this.route({
method: 'get',
path: '',
handler: this.getProxyFeatures,
handler: this.getFrontendApiFeatures,
permission: NONE,
middleware: [
this.services.openApiService.validPath({
@ -89,7 +89,7 @@ export default class FrontendAPIController extends Controller {
this.route({
method: 'post',
path: '/client/metrics',
handler: this.registerProxyMetrics,
handler: this.registerFrontendApiMetrics,
permission: NONE,
middleware: [
this.services.openApiService.validPath({
@ -117,7 +117,7 @@ export default class FrontendAPIController extends Controller {
this.route({
method: 'post',
path: '/client/register',
handler: this.registerProxyClient,
handler: this.registerFrontendApiClient,
permission: NONE,
middleware: [
this.services.openApiService.validPath({
@ -168,7 +168,7 @@ export default class FrontendAPIController extends Controller {
res.status(error.statusCode).json(error);
}
private async getProxyFeatures(
private async getFrontendApiFeatures(
req: ApiUserRequest,
res: Response<ProxyFeaturesSchema>,
) {
@ -179,11 +179,11 @@ export default class FrontendAPIController extends Controller {
let newToggles: ProxyFeatureSchema[] = [];
if (this.config.flagResolver.isEnabled('globalFrontendApiCache')) {
[toggles, newToggles] = await Promise.all([
this.services.proxyService.getProxyFeatures(
this.services.frontendApiService.getFrontendApiFeatures(
req.user,
FrontendAPIController.createContext(req),
),
this.services.proxyService.getNewProxyFeatures(
this.services.frontendApiService.getNewFrontendApiFeatures(
req.user,
FrontendAPIController.createContext(req),
),
@ -199,10 +199,11 @@ export default class FrontendAPIController extends Controller {
);
}
} else {
toggles = await this.services.proxyService.getProxyFeatures(
req.user,
FrontendAPIController.createContext(req),
);
toggles =
await this.services.frontendApiService.getFrontendApiFeatures(
req.user,
FrontendAPIController.createContext(req),
);
}
const returnedToggles = this.config.flagResolver.isEnabled(
@ -221,7 +222,7 @@ export default class FrontendAPIController extends Controller {
);
}
private async registerProxyMetrics(
private async registerFrontendApiMetrics(
req: ApiUserRequest<unknown, unknown, ClientMetricsSchema>,
res: Response,
) {
@ -234,7 +235,7 @@ export default class FrontendAPIController extends Controller {
return;
}
await this.services.proxyService.registerProxyMetrics(
await this.services.frontendApiService.registerFrontendApiMetrics(
req.user,
req.body,
req.ip,
@ -242,7 +243,7 @@ export default class FrontendAPIController extends Controller {
res.sendStatus(200);
}
private async registerProxyClient(
private async registerFrontendApiClient(
req: ApiUserRequest<unknown, unknown, ProxyClientSchema>,
res: Response<string>,
) {

View File

@ -5,10 +5,10 @@ import {
EnhancedFeatureInterface,
FeatureInterface,
} from 'unleash-client/lib/feature';
import { IApiUser } from '../types/api-user';
import { IUnleashConfig } from '../types';
import { IApiUser } from '../../types/api-user';
import { IUnleashConfig } from '../../types';
import { UnleashEvents } from 'unleash-client';
import { Logger } from '../logger';
import { Logger } from '../../logger';
import { GlobalFrontendApiCache } from './global-frontend-api-cache';
type Config = Pick<IUnleashConfig, 'getLogger'>;

View File

@ -1,25 +1,24 @@
import { IUnleashConfig, IUnleashServices, IUnleashStores } from '../types';
import { Logger } from '../logger';
import { ClientMetricsSchema, ProxyFeatureSchema } from '../openapi';
import ApiUser, { IApiUser } from '../types/api-user';
import { IUnleashConfig, IUnleashServices, IUnleashStores } from '../../types';
import { Logger } from '../../logger';
import { ClientMetricsSchema, ProxyFeatureSchema } from '../../openapi';
import ApiUser, { IApiUser } from '../../types/api-user';
import {
Context,
InMemStorageProvider,
Unleash,
UnleashEvents,
} from 'unleash-client';
import { ApiTokenType } from '../types/models/api-token';
import { ApiTokenType } from '../../types/models/api-token';
import {
FrontendSettings,
frontendSettingsKey,
} from '../types/settings/frontend-settings';
import { validateOrigins } from '../util';
import { BadDataError, InvalidTokenError } from '../error';
import { PROXY_REPOSITORY_CREATED } from '../metric-events';
import { ProxyRepository } from './index';
} from '../../types/settings/frontend-settings';
import { validateOrigins } from '../../util';
import { BadDataError, InvalidTokenError } from '../../error';
import { PROXY_REPOSITORY_CREATED } from '../../metric-events';
import { FrontendApiRepository } from './frontend-api-repository';
import { GlobalFrontendApiCache } from './global-frontend-api-cache';
import isEqual from 'lodash.isequal';
import { ProxyRepository } from './proxy-repository';
export type Config = Pick<
IUnleashConfig,
@ -36,7 +35,7 @@ export type Services = Pick<
| 'configurationRevisionService'
>;
export class ProxyService {
export class FrontendApiService {
private readonly config: Config;
private readonly logger: Logger;
@ -50,7 +49,7 @@ export class ProxyService {
/**
* This is intentionally a Promise because we want to be able to await
* until the client (which might be being created by a different request) is ready
* Check this test that fails if we don't use a Promise: src/test/e2e/api/proxy/proxy.concurrency.e2e.test.ts
* Check this test that fails if we don't use a Promise: frontend-api.concurrency.e2e.test.ts
*/
private readonly clients: Map<ApiUser['secret'], Promise<Unleash>> =
new Map();
@ -66,17 +65,17 @@ export class ProxyService {
globalFrontendApiCache: GlobalFrontendApiCache,
) {
this.config = config;
this.logger = config.getLogger('services/proxy-service.ts');
this.logger = config.getLogger('services/frontend-api-service.ts');
this.stores = stores;
this.services = services;
this.globalFrontendApiCache = globalFrontendApiCache;
}
async getProxyFeatures(
async getFrontendApiFeatures(
token: IApiUser,
context: Context,
): Promise<ProxyFeatureSchema[]> {
const client = await this.clientForProxyToken(token);
const client = await this.clientForFrontendApiToken(token);
const definitions = client.getFeatureToggleDefinitions() || [];
const sessionId = context.sessionId || String(Math.random());
@ -98,30 +97,11 @@ export class ProxyService {
}));
}
async compareToggleDefinitions(token: IApiUser) {
const oldClient = await this.clientForProxyToken(token);
const oldDefinitions = oldClient.getFeatureToggleDefinitions() || [];
const newClient = await this.newClientForProxyToken(token);
const newDefinitions = newClient.getFeatureToggleDefinitions() || [];
if (
!isEqual(
oldDefinitions.sort((a, b) => a.name.localeCompare(b.name)),
newDefinitions.sort((a, b) => a.name.localeCompare(b.name)),
)
) {
this.logger.warn(
`old features definitions and new features definitions are different. Old definitions count ${oldDefinitions.length}, new count ${newDefinitions.length}`,
);
}
}
async getNewProxyFeatures(
async getNewFrontendApiFeatures(
token: IApiUser,
context: Context,
): Promise<ProxyFeatureSchema[]> {
const client = await this.newClientForProxyToken(token);
const client = await this.newClientForFrontendApiToken(token);
const definitions = client.getFeatureToggleDefinitions() || [];
const sessionId = context.sessionId || String(Math.random());
@ -144,12 +124,12 @@ export class ProxyService {
}));
}
async registerProxyMetrics(
async registerFrontendApiMetrics(
token: IApiUser,
metrics: ClientMetricsSchema,
ip: string,
): Promise<void> {
ProxyService.assertExpectedTokenType(token);
FrontendApiService.assertExpectedTokenType(token);
const environment =
this.services.clientMetricsServiceV2.resolveMetricsEnvironment(
@ -166,12 +146,12 @@ export class ProxyService {
);
}
private async clientForProxyToken(token: IApiUser): Promise<Unleash> {
ProxyService.assertExpectedTokenType(token);
private async clientForFrontendApiToken(token: IApiUser): Promise<Unleash> {
FrontendApiService.assertExpectedTokenType(token);
let client = this.clients.get(token.secret);
if (!client) {
client = this.createClientForProxyToken(token);
client = this.createClientForFrontendApiToken(token);
this.clients.set(token.secret, client);
this.config.eventBus.emit(PROXY_REPOSITORY_CREATED);
}
@ -179,12 +159,14 @@ export class ProxyService {
return client;
}
private async newClientForProxyToken(token: IApiUser): Promise<Unleash> {
ProxyService.assertExpectedTokenType(token);
private async newClientForFrontendApiToken(
token: IApiUser,
): Promise<Unleash> {
FrontendApiService.assertExpectedTokenType(token);
let newClient = this.newClients.get(token.secret);
if (!newClient) {
newClient = this.createNewClientForProxyToken(token);
newClient = this.createNewClientForFrontendApiToken(token);
this.newClients.set(token.secret, newClient);
// TODO: do we need this twice?
// this.config.eventBus.emit(PROXY_REPOSITORY_CREATED);
@ -193,7 +175,9 @@ export class ProxyService {
return newClient;
}
private async createClientForProxyToken(token: IApiUser): Promise<Unleash> {
private async createClientForFrontendApiToken(
token: IApiUser,
): Promise<Unleash> {
const repository = new ProxyRepository(
this.config,
this.stores,
@ -219,7 +203,7 @@ export class ProxyService {
return client;
}
private async createNewClientForProxyToken(
private async createNewClientForFrontendApiToken(
token: IApiUser,
): Promise<Unleash> {
const repository = new FrontendApiRepository(
@ -228,7 +212,7 @@ export class ProxyService {
token,
);
const client = new Unleash({
appName: 'proxy',
appName: 'frontend-api',
url: 'unused',
storageProvider: new InMemStorageProvider(),
disableMetrics: true,
@ -246,7 +230,7 @@ export class ProxyService {
return client;
}
async deleteClientForProxyToken(secret: string): Promise<void> {
async deleteClientForFrontendApiToken(secret: string): Promise<void> {
const clientPromise = this.clients.get(secret);
if (clientPromise) {
const client = await clientPromise;

View File

@ -1,8 +1,11 @@
import { IUnleashTest, setupAppWithAuth } from '../../helpers/test-helper';
import dbInit, { ITestDb } from '../../helpers/database-init';
import getLogger from '../../../fixtures/no-logger';
import { randomId } from '../../../../lib/util';
import { ApiTokenType } from '../../../../lib/types/models/api-token';
import {
IUnleashTest,
setupAppWithAuth,
} from '../../../test/e2e/helpers/test-helper';
import dbInit, { ITestDb } from '../../../test/e2e/helpers/database-init';
import getLogger from '../../../test/fixtures/no-logger';
import { randomId } from '../../util';
import { ApiTokenType } from '../../types/models/api-token';
let app: IUnleashTest;
let db: ITestDb;
@ -25,7 +28,7 @@ beforeAll(async () => {
});
afterEach(() => {
app.services.proxyService.stopAll();
app.services.frontendApiService.stopAll();
jest.clearAllMocks();
});

View File

@ -1,21 +1,24 @@
import { IUnleashTest, setupAppWithAuth } from '../../helpers/test-helper';
import dbInit, { ITestDb } from '../../helpers/database-init';
import getLogger from '../../../fixtures/no-logger';
import { randomId } from '../../../../lib/util';
import {
IUnleashTest,
setupAppWithAuth,
} from '../../../test/e2e/helpers/test-helper';
import dbInit, { ITestDb } from '../../../test/e2e/helpers/database-init';
import getLogger from '../../../test/fixtures/no-logger';
import { randomId } from '../../util';
import {
ApiTokenType,
IApiToken,
IApiTokenCreate,
} from '../../../../lib/types/models/api-token';
} from '../../types/models/api-token';
import { startOfHour } from 'date-fns';
import {
FEATURE_UPDATED,
IConstraint,
IStrategyConfig,
SYSTEM_USER,
} from '../../../../lib/types';
import { ProxyRepository } from '../../../../lib/proxy';
import { Logger } from '../../../../lib/logger';
} from '../../types';
import { ProxyRepository } from './index';
import { Logger } from '../../logger';
let app: IUnleashTest;
let db: ITestDb;
@ -32,7 +35,7 @@ beforeAll(async () => {
});
afterEach(() => {
app.services.proxyService.stopAll();
app.services.frontendApiService.stopAll();
jest.clearAllMocks();
});

View File

@ -2,8 +2,8 @@ import {
GlobalFrontendApiCache,
GlobalFrontendApiCacheState,
} from './global-frontend-api-cache';
import noLogger from '../../test/fixtures/no-logger';
import { FakeSegmentReadModel } from '../features/segment/fake-segment-read-model';
import noLogger from '../../../test/fixtures/no-logger';
import { FakeSegmentReadModel } from '../segment/fake-segment-read-model';
import FakeClientFeatureToggleReadModel from './fake-client-feature-toggle-read-model';
import EventEmitter from 'events';
import {
@ -11,8 +11,8 @@ import {
IFeatureToggleClient,
IFlagResolver,
ISegment,
} from '../types';
import { UPDATE_REVISION } from '../features/feature-toggle/configuration-revision-service';
} from '../../types';
import { UPDATE_REVISION } from '../feature-toggle/configuration-revision-service';
const state = async (
cache: GlobalFrontendApiCache,

View File

@ -1,19 +1,19 @@
import EventEmitter from 'events';
import { Segment } from 'unleash-client/lib/strategy/strategy';
import { FeatureInterface } from 'unleash-client/lib/feature';
import { IApiUser } from '../types/api-user';
import { IApiUser } from '../../types/api-user';
import {
IFeatureToggleClient,
ISegmentReadModel,
IUnleashConfig,
} from '../types';
} from '../../types';
import {
mapFeatureForClient,
mapSegmentsForClient,
} from '../features/playground/offline-unleash-client';
import { ALL_ENVS } from '../util/constants';
import { Logger } from '../logger';
import { UPDATE_REVISION } from '../features/feature-toggle/configuration-revision-service';
} from '../playground/offline-unleash-client';
import { ALL_ENVS } from '../../util/constants';
import { Logger } from '../../logger';
import { UPDATE_REVISION } from '../feature-toggle/configuration-revision-service';
import { IClientFeatureToggleReadModel } from './client-feature-toggle-read-model-type';
type Config = Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>;

View File

@ -5,19 +5,19 @@ import {
EnhancedFeatureInterface,
FeatureInterface,
} from 'unleash-client/lib/feature';
import { IApiUser } from '../types/api-user';
import { IUnleashConfig, IUnleashServices, IUnleashStores } from '../types';
import { IApiUser } from '../../types/api-user';
import { IUnleashConfig, IUnleashServices, IUnleashStores } from '../../types';
import {
mapFeaturesForClient,
mapSegmentsForClient,
} from '../features/playground/offline-unleash-client';
import { ALL_ENVS } from '../util/constants';
} from '../playground/offline-unleash-client';
import { ALL_ENVS } from '../../util/constants';
import { UnleashEvents } from 'unleash-client';
import { Logger } from '../logger';
import { Logger } from '../../logger';
import ConfigurationRevisionService, {
UPDATE_REVISION,
} from '../features/feature-toggle/configuration-revision-service';
import { PROXY_FEATURES_FOR_TOKEN_TIME } from '../metric-events';
} from '../feature-toggle/configuration-revision-service';
import { PROXY_FEATURES_FOR_TOKEN_TIME } from '../../metric-events';
type Config = Pick<IUnleashConfig, 'getLogger' | 'frontendApi' | 'eventBus'>;
@ -28,6 +28,7 @@ type Services = Pick<
'featureToggleServiceV2' | 'configurationRevisionService'
>;
// TODO: remove after finished migration to global frontend api cache
export class ProxyRepository
extends EventEmitter
implements RepositoryInterface

View File

@ -1,11 +1,11 @@
import { ProxyService, Config } from './proxy-service';
import { FrontendApiService, Config } from './frontend-api-service';
import { GlobalFrontendApiCache } from './global-frontend-api-cache';
import { IApiUser } from '../types';
import { IApiUser } from '../../types';
import { FeatureInterface } from 'unleash-client/lib/feature';
import noLogger from '../../test/fixtures/no-logger';
import { ApiTokenType } from '../types/models/api-token';
import noLogger from '../../../test/fixtures/no-logger';
import { ApiTokenType } from '../../types/models/api-token';
test('proxy service fetching features from global cache', async () => {
test('frontend api service fetching features from global cache', async () => {
const irrelevant = {} as any;
const globalFrontendApiCache = {
getToggles(_: IApiUser): FeatureInterface[] {
@ -38,14 +38,14 @@ test('proxy service fetching features from global cache', async () => {
) as FeatureInterface;
},
} as GlobalFrontendApiCache;
const proxyService = new ProxyService(
const frontendApiService = new FrontendApiService(
{ getLogger: noLogger } as unknown as Config,
irrelevant,
irrelevant,
globalFrontendApiCache,
);
const features = await proxyService.getNewProxyFeatures(
const features = await frontendApiService.getNewFrontendApiFeatures(
{
projects: ['irrelevant'],
environment: 'irrelevant',

View File

@ -28,7 +28,7 @@ export const scheduleServices = async (
eventService,
versionService,
lastSeenService,
proxyService,
frontendApiService,
clientMetricsServiceV2,
} = services;
@ -126,7 +126,7 @@ export const scheduleServices = async (
);
schedulerService.schedule(
proxyService.fetchFrontendSettings.bind(proxyService),
frontendApiService.fetchFrontendSettings.bind(frontendApiService),
minutesToMilliseconds(2),
'fetchFrontendSettings',
0,

View File

@ -6,7 +6,7 @@ export * from './addons';
export * from './db';
export * from './middleware';
export * from './openapi';
export * from './proxy';
export * from './features/frontend-api';
export * from './routes';
export * from './services';
export * from './types';

View File

@ -4,7 +4,11 @@ import { createTestConfig } from '../../test/config/test-config';
import FakeEventStore from '../../test/fixtures/fake-event-store';
import { randomId } from '../util/random-id';
import FakeProjectStore from '../../test/fixtures/fake-project-store';
import { EventService, ProxyService, SettingService } from '../../lib/services';
import {
EventService,
FrontendApiService,
SettingService,
} from '../../lib/services';
import { ISettingStore } from '../../lib/types';
import { frontendSettingsKey } from '../../lib/types/settings/frontend-settings';
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';
@ -12,7 +16,7 @@ import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';
const TEST_USER_ID = -9999;
const createSettingService = (
frontendApiOrigins: string[],
): { proxyService: ProxyService; settingStore: ISettingStore } => {
): { frontendApiService: FrontendApiService; settingStore: ISettingStore } => {
const config = createTestConfig({ frontendApiOrigins });
const stores = {
@ -30,7 +34,7 @@ const createSettingService = (
return {
//@ts-ignore
proxyService: new ProxyService(config, stores, services),
frontendApiService: new FrontendApiService(config, stores, services),
settingStore: stores.settingStore,
};
};
@ -47,10 +51,10 @@ test('resolveOrigin', () => {
});
test('corsOriginMiddleware origin validation', async () => {
const { proxyService } = createSettingService([]);
const { frontendApiService } = createSettingService([]);
const userName = randomId();
await expect(() =>
proxyService.setFrontendSettings(
frontendApiService.setFrontendSettings(
{ frontendApiOrigins: ['a'] },
userName,
TEST_USER_ID,
@ -59,84 +63,84 @@ test('corsOriginMiddleware origin validation', async () => {
});
test('corsOriginMiddleware without config', async () => {
const { proxyService, settingStore } = createSettingService([]);
const { frontendApiService, settingStore } = createSettingService([]);
const userName = randomId();
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: [],
});
await proxyService.setFrontendSettings(
await frontendApiService.setFrontendSettings(
{ frontendApiOrigins: [] },
userName,
TEST_USER_ID,
);
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: [],
});
await proxyService.setFrontendSettings(
await frontendApiService.setFrontendSettings(
{ frontendApiOrigins: ['*'] },
userName,
TEST_USER_ID,
);
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: ['*'],
});
await settingStore.delete(frontendSettingsKey);
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: [],
});
});
test('corsOriginMiddleware with config', async () => {
const { proxyService, settingStore } = createSettingService(['*']);
const { frontendApiService, settingStore } = createSettingService(['*']);
const userName = randomId();
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: ['*'],
});
await proxyService.setFrontendSettings(
await frontendApiService.setFrontendSettings(
{ frontendApiOrigins: [] },
userName,
TEST_USER_ID,
);
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: [],
});
await proxyService.setFrontendSettings(
await frontendApiService.setFrontendSettings(
{ frontendApiOrigins: ['https://example.com', 'https://example.org'] },
userName,
TEST_USER_ID,
);
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: ['https://example.com', 'https://example.org'],
});
await settingStore.delete(frontendSettingsKey);
expect(await proxyService.getFrontendSettings(false)).toEqual({
expect(await frontendApiService.getFrontendSettings(false)).toEqual({
frontendApiOrigins: ['*'],
});
});
test('corsOriginMiddleware with caching enabled', async () => {
const { proxyService } = createSettingService([]);
const { frontendApiService } = createSettingService([]);
const userName = randomId();
expect(await proxyService.getFrontendSettings()).toEqual({
expect(await frontendApiService.getFrontendSettings()).toEqual({
frontendApiOrigins: [],
});
//setting
await proxyService.setFrontendSettings(
await frontendApiService.setFrontendSettings(
{ frontendApiOrigins: ['*'] },
userName,
TEST_USER_ID,
);
//still get cached value
expect(await proxyService.getFrontendSettings()).toEqual({
expect(await frontendApiService.getFrontendSettings()).toEqual({
frontendApiOrigins: [],
});
await proxyService.fetchFrontendSettings(); // called by the scheduler service
await frontendApiService.fetchFrontendSettings(); // called by the scheduler service
const settings = await proxyService.getFrontendSettings();
const settings = await frontendApiService.getFrontendSettings();
expect(settings).toEqual({
frontendApiOrigins: ['*'],

View File

@ -16,13 +16,13 @@ export const resolveOrigin = (allowedOrigins: string[]): string | string[] => {
// Check the request's Origin header against a list of allowed origins.
// The list may include '*', which `cors` does not support natively.
export const corsOriginMiddleware = (
{ proxyService }: Pick<IUnleashServices, 'proxyService'>,
{ frontendApiService }: Pick<IUnleashServices, 'frontendApiService'>,
config: IUnleashConfig,
): RequestHandler => {
const corsFunc = cors(async (req, callback) => {
try {
const { frontendApiOrigins = [] } =
await proxyService.getFrontendSettings();
await frontendApiService.getFrontendSettings();
callback(null, {
origin: resolveOrigin(frontendApiOrigins),
maxAge: config.accessControlMaxAge,

View File

@ -41,7 +41,7 @@ import {
emptyResponse,
getStandardResponses,
} from '../../openapi/util/standard-responses';
import { ProxyService } from '../../proxy/proxy-service';
import { FrontendApiService } from '../../features/frontend-api/frontend-api-service';
import { extractUserId, extractUsername } from '../../util';
import { OperationDeniedError } from '../../error';
@ -121,7 +121,7 @@ export class ApiTokenController extends Controller {
private accessService: AccessService;
private proxyService: ProxyService;
private frontendApiService: FrontendApiService;
private openApiService: OpenApiService;
@ -134,20 +134,20 @@ export class ApiTokenController extends Controller {
{
apiTokenService,
accessService,
proxyService,
frontendApiService,
openApiService,
}: Pick<
IUnleashServices,
| 'apiTokenService'
| 'accessService'
| 'proxyService'
| 'frontendApiService'
| 'openApiService'
>,
) {
super(config);
this.apiTokenService = apiTokenService;
this.accessService = accessService;
this.proxyService = proxyService;
this.frontendApiService = frontendApiService;
this.openApiService = openApiService;
this.flagResolver = config.flagResolver;
this.logger = config.getLogger('api-token-controller.js');
@ -411,7 +411,7 @@ export class ApiTokenController extends Controller {
extractUsername(req),
req.user.id,
);
await this.proxyService.deleteClientForProxyToken(token);
await this.frontendApiService.deleteClientForFrontendApiToken(token);
res.status(200).end();
}

View File

@ -24,7 +24,7 @@ import { extractUsername } from '../../util/extract-user';
import NotFoundError from '../../error/notfound-error';
import { SetUiConfigSchema } from '../../openapi/spec/set-ui-config-schema';
import { createRequestSchema } from '../../openapi/util/create-request-schema';
import { ProxyService } from '../../services';
import { FrontendApiService } from '../../services';
import MaintenanceService from '../../features/maintenance/maintenance-service';
import memoizee from 'memoizee';
import { minutesToMilliseconds } from 'date-fns';
@ -35,7 +35,7 @@ class ConfigController extends Controller {
private settingService: SettingService;
private proxyService: ProxyService;
private frontendApiService: FrontendApiService;
private emailService: EmailService;
@ -54,7 +54,7 @@ class ConfigController extends Controller {
settingService,
emailService,
openApiService,
proxyService,
frontendApiService,
maintenanceService,
clientInstanceService,
}: Pick<
@ -63,7 +63,7 @@ class ConfigController extends Controller {
| 'settingService'
| 'emailService'
| 'openApiService'
| 'proxyService'
| 'frontendApiService'
| 'maintenanceService'
| 'clientInstanceService'
>,
@ -73,7 +73,7 @@ class ConfigController extends Controller {
this.settingService = settingService;
this.emailService = emailService;
this.openApiService = openApiService;
this.proxyService = proxyService;
this.frontendApiService = frontendApiService;
this.maintenanceService = maintenanceService;
this.clientInstanceService = clientInstanceService;
this.usesOldEdgeFunction = memoizee(
@ -136,7 +136,7 @@ class ConfigController extends Controller {
maintenanceMode,
usesOldEdge,
] = await Promise.all([
this.proxyService.getFrontendSettings(false),
this.frontendApiService.getFrontendSettings(false),
this.settingService.get<SimpleAuthSettings>(simpleAuthSettingsKey),
this.maintenanceService.isMaintenanceMode(),
this.usesOldEdgeFunction(),
@ -190,7 +190,7 @@ class ConfigController extends Controller {
res: Response<string>,
): Promise<void> {
if (req.body.frontendSettings) {
await this.proxyService.setFrontendSettings(
await this.frontendApiService.setFrontendSettings(
req.body.frontendSettings,
extractUsername(req),
req.user.id,

View File

@ -25,7 +25,7 @@ import {
ApiTokenService,
OpenApiService,
ProjectService,
ProxyService,
FrontendApiService,
} from '../../../services';
import { extractUserId, extractUsername } from '../../../util';
import { IAuthRequest } from '../../unleash-types';
@ -48,7 +48,7 @@ export class ProjectApiTokenController extends Controller {
private accessService: AccessService;
private proxyService: ProxyService;
private frontendApiService: FrontendApiService;
private openApiService: OpenApiService;
@ -61,14 +61,14 @@ export class ProjectApiTokenController extends Controller {
{
apiTokenService,
accessService,
proxyService,
frontendApiService,
openApiService,
projectService,
}: Pick<
IUnleashServices,
| 'apiTokenService'
| 'accessService'
| 'proxyService'
| 'frontendApiService'
| 'openApiService'
| 'projectService'
>,
@ -76,7 +76,7 @@ export class ProjectApiTokenController extends Controller {
super(config);
this.apiTokenService = apiTokenService;
this.accessService = accessService;
this.proxyService = proxyService;
this.frontendApiService = frontendApiService;
this.openApiService = openApiService;
this.projectService = projectService;
this.logger = config.getLogger('project-api-token-controller.js');
@ -226,7 +226,9 @@ export class ProjectApiTokenController extends Controller {
extractUsername(req),
user.id,
);
await this.proxyService.deleteClientForProxyToken(token);
await this.frontendApiService.deleteClientForFrontendApiToken(
token,
);
res.status(200).end();
} else if (!storedToken) {
res.status(404).end();

View File

@ -9,7 +9,7 @@ import { AdminApi } from './admin-api';
import ClientApi from './client-api';
import { HealthCheckController } from './health-check';
import FrontendAPIController from '../proxy/proxy-controller';
import FrontendAPIController from '../features/frontend-api/frontend-api-controller';
import EdgeController from './edge-api';
import { PublicInviteController } from './public-invite';
import { Db } from '../db/db';

View File

@ -31,7 +31,7 @@ import { OpenApiService } from './openapi-service';
import { ClientSpecService } from './client-spec-service';
import { PlaygroundService } from '../features/playground/playground-service';
import { GroupService } from './group-service';
import { ProxyService } from '../proxy/proxy-service';
import { FrontendApiService } from '../features/frontend-api/frontend-api-service';
import EdgeService from './edge-service';
import PatService from './pat-service';
import { PublicSignupTokenService } from './public-signup-token-service';
@ -112,9 +112,9 @@ import { InactiveUsersService } from '../users/inactive/inactive-users-service';
import { SegmentReadModel } from '../features/segment/segment-read-model';
import { FakeSegmentReadModel } from '../features/segment/fake-segment-read-model';
import {
createFakeProxyService,
createProxyService,
} from '../proxy/createProxyService';
createFakeFrontendApiService,
createFrontendApiService,
} from '../features/frontend-api/createFrontendApiService';
export const createServices = (
stores: IUnleashStores,
@ -295,14 +295,14 @@ export const createServices = (
? createClientFeatureToggleService(db, config)
: createFakeClientFeatureToggleService(config);
const proxyService = db
? createProxyService(
const frontendApiService = db
? createFrontendApiService(
db,
config,
clientMetricsServiceV2,
configurationRevisionService,
)
: createFakeProxyService(
: createFakeFrontendApiService(
config,
clientMetricsServiceV2,
configurationRevisionService,
@ -373,7 +373,7 @@ export const createServices = (
clientSpecService,
playgroundService,
groupService,
proxyService,
frontendApiService,
edgeService,
patService,
publicSignupTokenService,
@ -428,7 +428,7 @@ export {
ClientSpecService,
PlaygroundService,
GroupService,
ProxyService,
FrontendApiService,
EdgeService,
PatService,
PublicSignupTokenService,

View File

@ -28,7 +28,7 @@ import { OpenApiService } from '../services/openapi-service';
import { ClientSpecService } from '../services/client-spec-service';
import { PlaygroundService } from '../features/playground/playground-service';
import { GroupService } from '../services/group-service';
import { ProxyService } from '../proxy/proxy-service';
import { FrontendApiService } from '../features/frontend-api/frontend-api-service';
import EdgeService from '../services/edge-service';
import PatService from '../services/pat-service';
import { PublicSignupTokenService } from '../services/public-signup-token-service';
@ -76,7 +76,7 @@ export interface IUnleashServices {
projectHealthService: ProjectHealthService;
projectService: ProjectService;
playgroundService: PlaygroundService;
proxyService: ProxyService;
frontendApiService: FrontendApiService;
publicSignupTokenService: PublicSignupTokenService;
resetTokenService: ResetTokenService;
sessionService: SessionService;

View File

@ -57,7 +57,7 @@ test('gets ui config with disablePasswordAuth', async () => {
test('gets ui config with frontendSettings', async () => {
const frontendApiOrigins = ['https://example.net'];
await app.services.proxyService.setFrontendSettings(
await app.services.frontendApiService.setFrontendSettings(
{ frontendApiOrigins },
randomId(),
-9999,