mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
Feat: OpenAPI controller - Bootstrap UI (#1773)
* rename bootstrap ui controller * sort openapi schema imports * add bootstrap ui json schema * test bootstrap ui schema * openapi bootstrap ui route * fix: bootstrap ui schema type * bootstrap ui e2e test * simplify bootstrap-ui testing mock * fix: update after review
This commit is contained in:
parent
a607dea284
commit
2729999bed
@ -1,118 +1,120 @@
|
||||
import { OpenAPIV3 } from 'openapi-types';
|
||||
import { addonParameterSchema } from './spec/addon-parameter-schema';
|
||||
import { addonSchema } from './spec/addon-schema';
|
||||
import { addonsSchema } from './spec/addons-schema';
|
||||
import { addonTypeSchema } from './spec/addon-type-schema';
|
||||
import { apiTokenSchema } from './spec/api-token-schema';
|
||||
import { apiTokensSchema } from './spec/api-tokens-schema';
|
||||
import { applicationSchema } from './spec/application-schema';
|
||||
import { applicationsSchema } from './spec/applications-schema';
|
||||
import { bootstrapUiSchema } from './spec/bootstrap-ui-schema';
|
||||
import { changePasswordSchema } from './spec/change-password-schema';
|
||||
import { clientApplicationSchema } from './spec/client-application-schema';
|
||||
import { clientFeatureSchema } from './spec/client-feature-schema';
|
||||
import { clientFeaturesQuerySchema } from './spec/client-features-query-schema';
|
||||
import { clientFeaturesSchema } from './spec/client-features-schema';
|
||||
import { clientMetricsSchema } from './spec/client-metrics-schema';
|
||||
import { clientVariantSchema } from './spec/client-variant-schema';
|
||||
import { cloneFeatureSchema } from './spec/clone-feature-schema';
|
||||
import { constraintSchema } from './spec/constraint-schema';
|
||||
import { contextFieldSchema } from './spec/context-field-schema';
|
||||
import { contextFieldsSchema } from './spec/context-fields-schema';
|
||||
import { createApiTokenSchema } from './spec/create-api-token-schema';
|
||||
import { createFeatureSchema } from './spec/create-feature-schema';
|
||||
import { createUserSchema } from './spec/create-user-schema';
|
||||
import { createFeatureStrategySchema } from './spec/create-feature-strategy-schema';
|
||||
import { createUserSchema } from './spec/create-user-schema';
|
||||
import { dateSchema } from './spec/date-schema';
|
||||
import { emailSchema } from './spec/email-schema';
|
||||
import { environmentSchema } from './spec/environment-schema';
|
||||
import { environmentsSchema } from './spec/environments-schema';
|
||||
import { eventSchema } from './spec/event-schema';
|
||||
import { eventsSchema } from './spec/events-schema';
|
||||
import { exportParametersSchema } from './spec/export-parameters-schema';
|
||||
import { featureEnvironmentMetricsSchema } from './spec/feature-environment-metrics-schema';
|
||||
import { featureEnvironmentSchema } from './spec/feature-environment-schema';
|
||||
import { featureEventsSchema } from './spec/feature-events-schema';
|
||||
import { featureMetricsSchema } from './spec/feature-metrics-schema';
|
||||
import { featureSchema } from './spec/feature-schema';
|
||||
import { featuresSchema } from './spec/features-schema';
|
||||
import { featureStrategySchema } from './spec/feature-strategy-schema';
|
||||
import { featureStrategySegmentSchema } from './spec/feature-strategy-segment-schema';
|
||||
import { featureTagSchema } from './spec/feature-tag-schema';
|
||||
import { featureTypeSchema } from './spec/feature-type-schema';
|
||||
import { featureTypesSchema } from './spec/feature-types-schema';
|
||||
import { featureUsageSchema } from './spec/feature-usage-schema';
|
||||
import { featureVariantsSchema } from './spec/feature-variants-schema';
|
||||
import { featuresSchema } from './spec/features-schema';
|
||||
import { feedbackSchema } from './spec/feedback-schema';
|
||||
import { healthCheckSchema } from './spec/health-check-schema';
|
||||
import { healthOverviewSchema } from './spec/health-overview-schema';
|
||||
import { healthReportSchema } from './spec/health-report-schema';
|
||||
import { idSchema } from './spec/id-schema';
|
||||
import { legalValueSchema } from './spec/legal-value-schema';
|
||||
import { loginSchema } from './spec/login-schema';
|
||||
import { idSchema } from './spec/id-schema';
|
||||
import { mapValues } from '../util/map-values';
|
||||
import { nameSchema } from './spec/name-schema';
|
||||
import { meSchema } from './spec/me-schema';
|
||||
import { nameSchema } from './spec/name-schema';
|
||||
import { omitKeys } from '../util/omit-keys';
|
||||
import { overrideSchema } from './spec/override-schema';
|
||||
import { parametersSchema } from './spec/parameters-schema';
|
||||
import { passwordSchema } from './spec/password-schema';
|
||||
import { patchSchema } from './spec/patch-schema';
|
||||
import { patchesSchema } from './spec/patches-schema';
|
||||
import { patchSchema } from './spec/patch-schema';
|
||||
import { permissionSchema } from './spec/permission-schema';
|
||||
import { projectEnvironmentSchema } from './spec/project-environment-schema';
|
||||
import { projectSchema } from './spec/project-schema';
|
||||
import { projectsSchema } from './spec/projects-schema';
|
||||
import { resetPasswordSchema } from './spec/reset-password-schema';
|
||||
import { roleSchema } from './spec/role-schema';
|
||||
import { segmentSchema } from './spec/segment-schema';
|
||||
import { sortOrderSchema } from './spec/sort-order-schema';
|
||||
import { splashSchema } from './spec/splash-schema';
|
||||
import { stateSchema } from './spec/state-schema';
|
||||
import { strategiesSchema } from './spec/strategies-schema';
|
||||
import { strategySchema } from './spec/strategy-schema';
|
||||
import { tagSchema } from './spec/tag-schema';
|
||||
import { tagsSchema } from './spec/tags-schema';
|
||||
import { tagTypeSchema } from './spec/tag-type-schema';
|
||||
import { tagTypesSchema } from './spec/tag-types-schema';
|
||||
import { tagWithVersionSchema } from './spec/tag-with-version-schema';
|
||||
import { tokenUserSchema } from './spec/token-user-schema';
|
||||
import { uiConfigSchema } from './spec/ui-config-schema';
|
||||
import { updateApiTokenSchema } from './spec/update-api-token-schema';
|
||||
import { updateFeatureSchema } from './spec/update-feature-schema';
|
||||
import { updateFeatureStrategySchema } from './spec/update-feature-strategy-schema';
|
||||
import { updateApiTokenSchema } from './spec/update-api-token-schema';
|
||||
import { updateTagTypeSchema } from './spec/update-tag-type-schema';
|
||||
import { upsertContextFieldSchema } from './spec/upsert-context-field-schema';
|
||||
import { updateUserSchema } from './spec/update-user-schema';
|
||||
import { upsertContextFieldSchema } from './spec/upsert-context-field-schema';
|
||||
import { upsertStrategySchema } from './spec/upsert-strategy-schema';
|
||||
import { userSchema } from './spec/user-schema';
|
||||
import { usersSchema } from './spec/users-schema';
|
||||
import { usersSearchSchema } from './spec/users-search-schema';
|
||||
import { validatePasswordSchema } from './spec/validate-password-schema';
|
||||
import { validateTagTypeSchema } from './spec/validate-tag-type-schema';
|
||||
import { variantSchema } from './spec/variant-schema';
|
||||
import { variantsSchema } from './spec/variants-schema';
|
||||
import { versionSchema } from './spec/version-schema';
|
||||
import { featureEnvironmentMetricsSchema } from './spec/feature-environment-metrics-schema';
|
||||
import { featureUsageSchema } from './spec/feature-usage-schema';
|
||||
import { featureMetricsSchema } from './spec/feature-metrics-schema';
|
||||
import { addonSchema } from './spec/addon-schema';
|
||||
import { addonsSchema } from './spec/addons-schema';
|
||||
import { addonParameterSchema } from './spec/addon-parameter-schema';
|
||||
import { addonTypeSchema } from './spec/addon-type-schema';
|
||||
import { applicationSchema } from './spec/application-schema';
|
||||
import { applicationsSchema } from './spec/applications-schema';
|
||||
import { tagWithVersionSchema } from './spec/tag-with-version-schema';
|
||||
import { tokenUserSchema } from './spec/token-user-schema';
|
||||
import { changePasswordSchema } from './spec/change-password-schema';
|
||||
import { validatePasswordSchema } from './spec/validate-password-schema';
|
||||
import { resetPasswordSchema } from './spec/reset-password-schema';
|
||||
import { featureStrategySegmentSchema } from './spec/feature-strategy-segment-schema';
|
||||
import { segmentSchema } from './spec/segment-schema';
|
||||
import { stateSchema } from './spec/state-schema';
|
||||
import { featureTagSchema } from './spec/feature-tag-schema';
|
||||
import { exportParametersSchema } from './spec/export-parameters-schema';
|
||||
import { emailSchema } from './spec/email-schema';
|
||||
import { strategySchema } from './spec/strategy-schema';
|
||||
import { strategiesSchema } from './spec/strategies-schema';
|
||||
import { upsertStrategySchema } from './spec/upsert-strategy-schema';
|
||||
import { clientFeaturesQuerySchema } from './spec/client-features-query-schema';
|
||||
import { clientFeatureSchema } from './spec/client-feature-schema';
|
||||
import { clientFeaturesSchema } from './spec/client-features-schema';
|
||||
import { eventSchema } from './spec/event-schema';
|
||||
import { eventsSchema } from './spec/events-schema';
|
||||
import { featureEventsSchema } from './spec/feature-events-schema';
|
||||
import { clientApplicationSchema } from './spec/client-application-schema';
|
||||
import { clientMetricsSchema } from './spec/client-metrics-schema';
|
||||
import { dateSchema } from './spec/date-schema';
|
||||
import { clientVariantSchema } from './spec/client-variant-schema';
|
||||
import { IServerOption } from '../types';
|
||||
import { URL } from 'url';
|
||||
|
||||
// All schemas in `openapi/spec` should be listed here.
|
||||
export const schemas = {
|
||||
addonParameterSchema,
|
||||
addonSchema,
|
||||
addonsSchema,
|
||||
addonTypeSchema,
|
||||
addonParameterSchema,
|
||||
apiTokenSchema,
|
||||
apiTokensSchema,
|
||||
applicationSchema,
|
||||
applicationsSchema,
|
||||
clientApplicationSchema,
|
||||
clientMetricsSchema,
|
||||
cloneFeatureSchema,
|
||||
clientFeatureSchema,
|
||||
clientFeaturesSchema,
|
||||
clientVariantSchema,
|
||||
clientFeaturesQuerySchema,
|
||||
bootstrapUiSchema,
|
||||
changePasswordSchema,
|
||||
clientApplicationSchema,
|
||||
clientFeatureSchema,
|
||||
clientFeaturesQuerySchema,
|
||||
clientFeaturesSchema,
|
||||
clientMetricsSchema,
|
||||
clientVariantSchema,
|
||||
cloneFeatureSchema,
|
||||
constraintSchema,
|
||||
contextFieldSchema,
|
||||
contextFieldsSchema,
|
||||
@ -127,33 +129,33 @@ export const schemas = {
|
||||
eventSchema,
|
||||
eventsSchema,
|
||||
exportParametersSchema,
|
||||
featureEnvironmentSchema,
|
||||
featureEnvironmentMetricsSchema,
|
||||
featureEnvironmentSchema,
|
||||
featureEventsSchema,
|
||||
featureSchema,
|
||||
featureMetricsSchema,
|
||||
featureUsageSchema,
|
||||
featureSchema,
|
||||
featuresSchema,
|
||||
featureStrategySchema,
|
||||
featureStrategySegmentSchema,
|
||||
featureTagSchema,
|
||||
featureTypeSchema,
|
||||
featureTypesSchema,
|
||||
featureUsageSchema,
|
||||
featureVariantsSchema,
|
||||
featuresSchema,
|
||||
feedbackSchema,
|
||||
healthCheckSchema,
|
||||
healthOverviewSchema,
|
||||
healthReportSchema,
|
||||
idSchema,
|
||||
legalValueSchema,
|
||||
loginSchema,
|
||||
nameSchema,
|
||||
idSchema,
|
||||
meSchema,
|
||||
nameSchema,
|
||||
overrideSchema,
|
||||
parametersSchema,
|
||||
passwordSchema,
|
||||
patchSchema,
|
||||
patchesSchema,
|
||||
patchSchema,
|
||||
permissionSchema,
|
||||
projectEnvironmentSchema,
|
||||
projectSchema,
|
||||
@ -167,24 +169,24 @@ export const schemas = {
|
||||
strategiesSchema,
|
||||
strategySchema,
|
||||
tagSchema,
|
||||
tagWithVersionSchema,
|
||||
tagsSchema,
|
||||
tagTypeSchema,
|
||||
tagTypesSchema,
|
||||
tagWithVersionSchema,
|
||||
tokenUserSchema,
|
||||
uiConfigSchema,
|
||||
updateApiTokenSchema,
|
||||
updateFeatureSchema,
|
||||
updateFeatureStrategySchema,
|
||||
updateApiTokenSchema,
|
||||
updateTagTypeSchema,
|
||||
updateUserSchema,
|
||||
upsertContextFieldSchema,
|
||||
upsertStrategySchema,
|
||||
validatePasswordSchema,
|
||||
validateTagTypeSchema,
|
||||
updateUserSchema,
|
||||
userSchema,
|
||||
usersSchema,
|
||||
usersSearchSchema,
|
||||
validatePasswordSchema,
|
||||
validateTagTypeSchema,
|
||||
variantSchema,
|
||||
variantsSchema,
|
||||
versionSchema,
|
||||
|
157
src/lib/openapi/spec/bootstrap-ui-schema.test.ts
Normal file
157
src/lib/openapi/spec/bootstrap-ui-schema.test.ts
Normal file
@ -0,0 +1,157 @@
|
||||
import { validateSchema } from '../validate';
|
||||
import { BootstrapUiSchema } from './bootstrap-ui-schema';
|
||||
|
||||
test('bootstrapUiSchema', () => {
|
||||
const data: BootstrapUiSchema = {
|
||||
uiConfig: {
|
||||
flags: { E: true },
|
||||
authenticationType: 'open-source',
|
||||
unleashUrl: 'http://localhost:4242',
|
||||
version: '4.14.0-beta.0',
|
||||
baseUriPath: '',
|
||||
versionInfo: {
|
||||
current: { oss: '4.14.0-beta.0', enterprise: '' },
|
||||
latest: {},
|
||||
isLatest: true,
|
||||
instanceId: '51c9190a-4ff5-4f47-b73a-7aebe06f9331',
|
||||
},
|
||||
},
|
||||
user: {
|
||||
isAPI: false,
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/21232f297a57a5a743894a0e4a801fc3?size=42&default=retro',
|
||||
seenAt: '2022-06-27T12:19:15.838Z',
|
||||
loginAttempts: 0,
|
||||
createdAt: '2022-04-08T10:59:25.072Z',
|
||||
permissions: [
|
||||
{ permission: 'READ_API_TOKEN' },
|
||||
{
|
||||
project: 'default',
|
||||
environment: 'staging',
|
||||
permission: 'CREATE_FEATURE_STRATEGY',
|
||||
},
|
||||
{
|
||||
project: 'default',
|
||||
environment: 'staging',
|
||||
permission: 'UPDATE_FEATURE_STRATEGY',
|
||||
},
|
||||
{ project: 'default', permission: 'UPDATE_FEATURE' },
|
||||
],
|
||||
},
|
||||
email: false,
|
||||
context: [
|
||||
{
|
||||
name: 'appName',
|
||||
description: 'Allows you to constrain on application name',
|
||||
stickiness: false,
|
||||
sortOrder: 2,
|
||||
legalValues: [],
|
||||
createdAt: '2022-04-08T10:59:24.374Z',
|
||||
},
|
||||
{
|
||||
name: 'currentTime',
|
||||
description: '',
|
||||
stickiness: false,
|
||||
sortOrder: 10,
|
||||
legalValues: [],
|
||||
createdAt: '2022-05-18T08:15:18.917Z',
|
||||
},
|
||||
{
|
||||
name: 'environment',
|
||||
description:
|
||||
'Allows you to constrain on application environment',
|
||||
stickiness: false,
|
||||
sortOrder: 0,
|
||||
legalValues: [],
|
||||
createdAt: '2022-04-08T10:59:24.374Z',
|
||||
},
|
||||
{
|
||||
name: 'userId',
|
||||
description: 'Allows you to constrain on userId',
|
||||
stickiness: false,
|
||||
sortOrder: 1,
|
||||
legalValues: [],
|
||||
createdAt: '2022-04-08T10:59:24.374Z',
|
||||
},
|
||||
],
|
||||
featureTypes: [
|
||||
{
|
||||
id: 'release',
|
||||
name: 'Release',
|
||||
description:
|
||||
'Release feature toggles are used to release new features.',
|
||||
lifetimeDays: 40,
|
||||
},
|
||||
{
|
||||
id: 'experiment',
|
||||
name: 'Experiment',
|
||||
description:
|
||||
'Experiment feature toggles are used to test and verify multiple different versions of a feature.',
|
||||
lifetimeDays: 40,
|
||||
},
|
||||
{
|
||||
id: 'operational',
|
||||
name: 'Operational',
|
||||
description:
|
||||
'Operational feature toggles are used to control aspects of a rollout.',
|
||||
lifetimeDays: 7,
|
||||
},
|
||||
],
|
||||
tagTypes: [
|
||||
{
|
||||
name: 'simple',
|
||||
description: 'Used to simplify filtering of features',
|
||||
icon: '#',
|
||||
},
|
||||
{ name: 'hashtag', description: '', icon: null },
|
||||
],
|
||||
strategies: [
|
||||
{
|
||||
displayName: 'Standard',
|
||||
name: 'default',
|
||||
editable: false,
|
||||
description:
|
||||
'The standard strategy is strictly on / off for your entire userbase.',
|
||||
parameters: [],
|
||||
deprecated: false,
|
||||
},
|
||||
{
|
||||
displayName: null,
|
||||
name: 'gradualRolloutRandom',
|
||||
editable: true,
|
||||
description:
|
||||
'Randomly activate the feature toggle. No stickiness.',
|
||||
parameters: [
|
||||
{
|
||||
name: 'percentage',
|
||||
type: 'percentage',
|
||||
description: '',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
deprecated: true,
|
||||
},
|
||||
],
|
||||
projects: [
|
||||
{
|
||||
name: 'Default',
|
||||
id: 'default',
|
||||
description: 'Default project',
|
||||
health: 74,
|
||||
featureCount: 10,
|
||||
memberCount: 3,
|
||||
updatedAt: '2022-06-28T17:33:53.963Z',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(
|
||||
validateSchema('#/components/schemas/bootstrapUiSchema', {}),
|
||||
).not.toBeUndefined();
|
||||
|
||||
expect(
|
||||
validateSchema('#/components/schemas/bootstrapUiSchema', data),
|
||||
).toBeUndefined();
|
||||
});
|
94
src/lib/openapi/spec/bootstrap-ui-schema.ts
Normal file
94
src/lib/openapi/spec/bootstrap-ui-schema.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { uiConfigSchema } from './ui-config-schema';
|
||||
import { userSchema } from './user-schema';
|
||||
import { permissionSchema } from './permission-schema';
|
||||
import { featureTypeSchema } from './feature-type-schema';
|
||||
import { tagTypeSchema } from './tag-type-schema';
|
||||
import { contextFieldSchema } from './context-field-schema';
|
||||
import { strategySchema } from './strategy-schema';
|
||||
import { projectSchema } from './project-schema';
|
||||
import { versionSchema } from './version-schema';
|
||||
import { legalValueSchema } from './legal-value-schema';
|
||||
|
||||
export const bootstrapUiSchema = {
|
||||
$id: '#/components/schemas/bootstrapUiSchema',
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: [
|
||||
'uiConfig',
|
||||
'user',
|
||||
'email',
|
||||
'context',
|
||||
'featureTypes',
|
||||
'tagTypes',
|
||||
'strategies',
|
||||
'projects',
|
||||
],
|
||||
properties: {
|
||||
uiConfig: {
|
||||
$ref: '#/components/schemas/uiConfigSchema',
|
||||
},
|
||||
user: {
|
||||
type: 'object',
|
||||
required: [...userSchema.required],
|
||||
properties: {
|
||||
...userSchema.properties,
|
||||
permissions: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/permissionSchema',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
email: {
|
||||
type: 'boolean',
|
||||
},
|
||||
context: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/contextFieldSchema',
|
||||
},
|
||||
},
|
||||
featureTypes: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/featureTypeSchema',
|
||||
},
|
||||
},
|
||||
tagTypes: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/tagTypeSchema',
|
||||
},
|
||||
},
|
||||
strategies: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/strategySchema',
|
||||
},
|
||||
},
|
||||
projects: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/projectSchema',
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
uiConfigSchema,
|
||||
userSchema,
|
||||
permissionSchema,
|
||||
contextFieldSchema,
|
||||
featureTypeSchema,
|
||||
tagTypeSchema,
|
||||
strategySchema,
|
||||
projectSchema,
|
||||
versionSchema,
|
||||
legalValueSchema,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export type BootstrapUiSchema = FromSchema<typeof bootstrapUiSchema>;
|
@ -14,6 +14,7 @@ export const tagTypeSchema = {
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
},
|
||||
},
|
||||
components: {},
|
||||
|
@ -5,15 +5,7 @@ export const uiConfigSchema = {
|
||||
$id: '#/components/schemas/uiConfigSchema',
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: [
|
||||
'version',
|
||||
'unleashUrl',
|
||||
'baseUriPath',
|
||||
'versionInfo',
|
||||
'disablePasswordAuth',
|
||||
'segmentValuesLimit',
|
||||
'strategySegmentsLimit',
|
||||
],
|
||||
required: ['version', 'unleashUrl', 'baseUriPath', 'versionInfo'],
|
||||
properties: {
|
||||
slogan: {
|
||||
type: 'string',
|
||||
|
63
src/lib/routes/admin-api/bootstrap-ui.test.ts
Normal file
63
src/lib/routes/admin-api/bootstrap-ui.test.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import supertest from 'supertest';
|
||||
import { createTestConfig } from '../../../test/config/test-config';
|
||||
import { randomId } from '../../util/random-id';
|
||||
|
||||
import createStores from '../../../test/fixtures/store';
|
||||
import getApp from '../../app';
|
||||
import { createServices } from '../../services';
|
||||
const uiConfig = {
|
||||
headerBackground: 'red',
|
||||
slogan: 'hello',
|
||||
};
|
||||
|
||||
async function getSetup() {
|
||||
const base = `/random${randomId()}`;
|
||||
const config = createTestConfig({
|
||||
server: { baseUriPath: base },
|
||||
ui: uiConfig,
|
||||
});
|
||||
const stores = createStores();
|
||||
const services = createServices(stores, config);
|
||||
|
||||
const app = await getApp(config, stores, services);
|
||||
|
||||
return {
|
||||
base,
|
||||
request: supertest(app),
|
||||
destroy: () => {
|
||||
services.versionService.destroy();
|
||||
services.clientInstanceService.destroy();
|
||||
services.apiTokenService.destroy();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let request;
|
||||
let base;
|
||||
let destroy;
|
||||
|
||||
beforeEach(async () => {
|
||||
const setup = await getSetup();
|
||||
request = setup.request;
|
||||
base = setup.base;
|
||||
destroy = setup.destroy;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
destroy();
|
||||
});
|
||||
|
||||
test('should get ui config', async () => {
|
||||
const { body } = await request
|
||||
.get(`${base}/api/admin/ui-bootstrap`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200);
|
||||
|
||||
expect(body.uiConfig.slogan).toEqual('hello');
|
||||
expect(body.email).toEqual(false);
|
||||
expect(body.user).toHaveProperty('permissions');
|
||||
expect(body.context).toBeInstanceOf(Array);
|
||||
expect(body.tagTypes).toBeInstanceOf(Array);
|
||||
expect(body.strategies).toBeInstanceOf(Array);
|
||||
expect(body.projects).toBeInstanceOf(Array);
|
||||
});
|
@ -19,8 +19,20 @@ import { ITagType } from '../../types/stores/tag-type-store';
|
||||
import { IStrategy } from '../../types/stores/strategy-store';
|
||||
import { IProject } from '../../types/model';
|
||||
import { IUserPermission } from '../../types/stores/access-store';
|
||||
import { OpenApiService } from '../../services/openapi-service';
|
||||
import { NONE } from '../../types/permissions';
|
||||
import { createResponseSchema } from '../../openapi';
|
||||
import {
|
||||
BootstrapUiSchema,
|
||||
bootstrapUiSchema,
|
||||
} from '../../openapi/spec/bootstrap-ui-schema';
|
||||
import { serializeDates } from '../../types/serialize-dates';
|
||||
|
||||
class BootstrapController extends Controller {
|
||||
/**
|
||||
* Provides admin UI configuration.
|
||||
* Not to be confused with SDK bootstrapping.
|
||||
*/
|
||||
class BootstrapUIController extends Controller {
|
||||
private logger: Logger;
|
||||
|
||||
private accessService: AccessService;
|
||||
@ -39,6 +51,8 @@ class BootstrapController extends Controller {
|
||||
|
||||
private versionService: VersionService;
|
||||
|
||||
private openApiService: OpenApiService;
|
||||
|
||||
constructor(
|
||||
config: IUnleashConfig,
|
||||
{
|
||||
@ -50,6 +64,7 @@ class BootstrapController extends Controller {
|
||||
emailService,
|
||||
versionService,
|
||||
featureTypeService,
|
||||
openApiService,
|
||||
}: Pick<
|
||||
IUnleashServices,
|
||||
| 'contextService'
|
||||
@ -60,6 +75,7 @@ class BootstrapController extends Controller {
|
||||
| 'emailService'
|
||||
| 'versionService'
|
||||
| 'featureTypeService'
|
||||
| 'openApiService'
|
||||
>,
|
||||
) {
|
||||
super(config);
|
||||
@ -71,15 +87,30 @@ class BootstrapController extends Controller {
|
||||
this.featureTypeService = featureTypeService;
|
||||
this.emailService = emailService;
|
||||
this.versionService = versionService;
|
||||
this.openApiService = openApiService;
|
||||
|
||||
this.logger = config.getLogger(
|
||||
'routes/admin-api/bootstrap-controller.ts',
|
||||
);
|
||||
|
||||
this.get('/', this.bootstrap);
|
||||
this.logger = config.getLogger('routes/admin-api/bootstrap-ui.ts');
|
||||
this.route({
|
||||
method: 'get',
|
||||
path: '',
|
||||
handler: this.bootstrap,
|
||||
permission: NONE,
|
||||
middleware: [
|
||||
openApiService.validPath({
|
||||
tags: ['other'],
|
||||
operationId: 'getBootstrapUiData',
|
||||
responses: {
|
||||
202: createResponseSchema('bootstrapUiSchema'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async bootstrap(req: AuthedRequest, res: Response): Promise<void> {
|
||||
async bootstrap(
|
||||
req: AuthedRequest,
|
||||
res: Response<BootstrapUiSchema>,
|
||||
): Promise<void> {
|
||||
const jobs: [
|
||||
Promise<IContextField[]>,
|
||||
Promise<IFeatureType[]>,
|
||||
@ -117,18 +148,26 @@ class BootstrapController extends Controller {
|
||||
versionInfo,
|
||||
};
|
||||
|
||||
res.json({
|
||||
uiConfig,
|
||||
user: { ...req.user, permissions: userPermissions },
|
||||
email: this.emailService.isEnabled(),
|
||||
context,
|
||||
featureTypes,
|
||||
tagTypes,
|
||||
strategies,
|
||||
projects,
|
||||
});
|
||||
this.openApiService.respondWithValidation(
|
||||
200,
|
||||
res,
|
||||
bootstrapUiSchema.$id,
|
||||
{
|
||||
uiConfig,
|
||||
user: {
|
||||
...serializeDates(req.user),
|
||||
permissions: userPermissions,
|
||||
},
|
||||
email: this.emailService.isEnabled(),
|
||||
context: serializeDates(context),
|
||||
featureTypes,
|
||||
tagTypes,
|
||||
strategies,
|
||||
projects: serializeDates(projects),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BootstrapController;
|
||||
module.exports = BootstrapController;
|
||||
export default BootstrapUIController;
|
||||
module.exports = BootstrapUIController;
|
@ -12,7 +12,7 @@ import UserController from './user';
|
||||
import ConfigController from './config';
|
||||
import { ContextController } from './context';
|
||||
import ClientMetricsController from './client-metrics';
|
||||
import BootstrapController from './bootstrap';
|
||||
import BootstrapUIController from './bootstrap-ui';
|
||||
import StateController from './state';
|
||||
import TagController from './tag';
|
||||
import TagTypeController from './tag-type';
|
||||
@ -65,7 +65,7 @@ class AdminApi extends Controller {
|
||||
);
|
||||
this.app.use(
|
||||
'/ui-bootstrap',
|
||||
new BootstrapController(config, services).router,
|
||||
new BootstrapUIController(config, services).router,
|
||||
);
|
||||
this.app.use(
|
||||
'/context',
|
||||
|
@ -293,6 +293,111 @@ Object {
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"bootstrapUiSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
"context": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/contextFieldSchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"email": Object {
|
||||
"type": "boolean",
|
||||
},
|
||||
"featureTypes": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/featureTypeSchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"projects": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/projectSchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"strategies": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/strategySchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"tagTypes": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/tagTypeSchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"uiConfig": Object {
|
||||
"$ref": "#/components/schemas/uiConfigSchema",
|
||||
},
|
||||
"user": Object {
|
||||
"properties": Object {
|
||||
"createdAt": Object {
|
||||
"format": "date-time",
|
||||
"type": "string",
|
||||
},
|
||||
"email": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"emailSent": Object {
|
||||
"type": "boolean",
|
||||
},
|
||||
"id": Object {
|
||||
"type": "number",
|
||||
},
|
||||
"imageUrl": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"inviteLink": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"isAPI": Object {
|
||||
"type": "boolean",
|
||||
},
|
||||
"loginAttempts": Object {
|
||||
"type": "number",
|
||||
},
|
||||
"name": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"permissions": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/permissionSchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"rootRole": Object {
|
||||
"type": "number",
|
||||
},
|
||||
"seenAt": Object {
|
||||
"format": "date-time",
|
||||
"nullable": true,
|
||||
"type": "string",
|
||||
},
|
||||
"username": Object {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": Array [
|
||||
"id",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
"required": Array [
|
||||
"uiConfig",
|
||||
"user",
|
||||
"email",
|
||||
"context",
|
||||
"featureTypes",
|
||||
"tagTypes",
|
||||
"strategies",
|
||||
"projects",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
"changePasswordSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
@ -1962,6 +2067,7 @@ Object {
|
||||
"type": "string",
|
||||
},
|
||||
"icon": Object {
|
||||
"nullable": true,
|
||||
"type": "string",
|
||||
},
|
||||
"name": Object {
|
||||
@ -2122,9 +2228,6 @@ Object {
|
||||
"unleashUrl",
|
||||
"baseUriPath",
|
||||
"versionInfo",
|
||||
"disablePasswordAuth",
|
||||
"segmentValuesLimit",
|
||||
"strategySegmentsLimit",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
@ -5167,6 +5270,26 @@ If the provided project does not exist, the list of events will be empty.",
|
||||
],
|
||||
},
|
||||
},
|
||||
"/api/admin/ui-bootstrap": Object {
|
||||
"get": Object {
|
||||
"operationId": "getBootstrapUiData",
|
||||
"responses": Object {
|
||||
"202": Object {
|
||||
"content": Object {
|
||||
"application/json": Object {
|
||||
"schema": Object {
|
||||
"$ref": "#/components/schemas/bootstrapUiSchema",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "bootstrapUiSchema",
|
||||
},
|
||||
},
|
||||
"tags": Array [
|
||||
"other",
|
||||
],
|
||||
},
|
||||
},
|
||||
"/api/admin/ui-config": Object {
|
||||
"get": Object {
|
||||
"operationId": "getUIConfig",
|
||||
|
Loading…
Reference in New Issue
Block a user