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

refactor: add OpenAPI schema to UI config controller (#1681)

This commit is contained in:
olav 2022-06-08 14:57:39 +02:00 committed by GitHub
parent cbffe0eda0
commit 09a6b578bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 327 additions and 34 deletions

View File

@ -18,10 +18,12 @@ import { patchesSchema } from './spec/patches-schema';
import { strategySchema } from './spec/strategy-schema'; import { strategySchema } from './spec/strategy-schema';
import { tagSchema } from './spec/tag-schema'; import { tagSchema } from './spec/tag-schema';
import { tagsSchema } from './spec/tags-schema'; import { tagsSchema } from './spec/tags-schema';
import { uiConfigSchema } from './spec/ui-config-schema';
import { updateFeatureSchema } from './spec/update-feature-schema'; import { updateFeatureSchema } from './spec/update-feature-schema';
import { updateStrategySchema } from './spec/update-strategy-schema'; import { updateStrategySchema } from './spec/update-strategy-schema';
import { variantSchema } from './spec/variant-schema'; import { variantSchema } from './spec/variant-schema';
import { variantsSchema } from './spec/variants-schema'; import { variantsSchema } from './spec/variants-schema';
import { versionSchema } from './spec/version-schema';
// Schemas must have $id property on the form "#/components/schemas/mySchema". // Schemas must have $id property on the form "#/components/schemas/mySchema".
export type SchemaId = typeof schemas[keyof typeof schemas]['$id']; export type SchemaId = typeof schemas[keyof typeof schemas]['$id'];
@ -57,10 +59,12 @@ export const schemas = {
strategySchema, strategySchema,
tagSchema, tagSchema,
tagsSchema, tagsSchema,
uiConfigSchema,
updateFeatureSchema, updateFeatureSchema,
updateStrategySchema, updateStrategySchema,
variantSchema, variantSchema,
variantsSchema, variantsSchema,
versionSchema,
}; };
export const createRequestSchema = ( export const createRequestSchema = (

View File

@ -0,0 +1,24 @@
import { validateSchema } from '../validate';
import { UiConfigSchema } from './ui-config-schema';
test('uiConfigSchema', () => {
const data: UiConfigSchema = {
slogan: 'a',
version: 'a',
unleashUrl: 'a',
baseUriPath: 'a',
disablePasswordAuth: false,
segmentValuesLimit: 0,
strategySegmentsLimit: 0,
versionInfo: {
current: {},
latest: {},
isLatest: true,
instanceId: 'a',
},
};
expect(
validateSchema('#/components/schemas/uiConfigSchema', data),
).toBeUndefined();
});

View File

@ -0,0 +1,76 @@
import { FromSchema } from 'json-schema-to-ts';
import { versionSchema } from './version-schema';
export const uiConfigSchema = {
$id: '#/components/schemas/uiConfigSchema',
type: 'object',
additionalProperties: false,
required: [
'version',
'unleashUrl',
'baseUriPath',
'versionInfo',
'disablePasswordAuth',
'segmentValuesLimit',
'strategySegmentsLimit',
],
properties: {
slogan: {
type: 'string',
},
name: {
type: 'string',
},
version: {
type: 'string',
},
unleashUrl: {
type: 'string',
},
baseUriPath: {
type: 'string',
},
disablePasswordAuth: {
type: 'boolean',
},
segmentValuesLimit: {
type: 'number',
},
strategySegmentsLimit: {
type: 'number',
},
flags: {
type: 'object',
additionalProperties: {
type: 'boolean',
},
},
links: {
type: 'array',
items: {
type: 'object',
},
},
authenticationType: {
type: 'string',
enum: [
'open-source',
'demo',
'enterprise',
'hosted',
'custom',
'none',
],
},
versionInfo: {
$ref: '#/components/schemas/versionSchema',
},
},
components: {
schemas: {
versionSchema,
},
},
} as const;
export type UiConfigSchema = FromSchema<typeof uiConfigSchema>;

View File

@ -0,0 +1,43 @@
import { FromSchema } from 'json-schema-to-ts';
export const versionSchema = {
$id: '#/components/schemas/versionSchema',
type: 'object',
additionalProperties: false,
required: ['current', 'latest', 'isLatest', 'instanceId'],
properties: {
current: {
type: 'object',
additionalProperties: false,
properties: {
oss: {
type: 'string',
},
enterprise: {
type: 'string',
},
},
},
latest: {
type: 'object',
additionalProperties: false,
properties: {
oss: {
type: 'string',
},
enterprise: {
type: 'string',
},
},
},
isLatest: {
type: 'boolean',
},
instanceId: {
type: 'string',
},
},
components: {},
} as const;
export type VersionSchema = FromSchema<typeof versionSchema>;

View File

@ -1,73 +1,91 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { IUnleashServices } from '../../types/services'; import { IUnleashServices } from '../../types/services';
import { IAuthType, IUIConfig, IUnleashConfig } from '../../types/option'; import { IAuthType, IUnleashConfig } from '../../types/option';
import version from '../../util/version'; import version from '../../util/version';
import Controller from '../controller'; import Controller from '../controller';
import VersionService, { IVersionHolder } from '../../services/version-service'; import VersionService from '../../services/version-service';
import SettingService from '../../services/setting-service'; import SettingService from '../../services/setting-service';
import { import {
simpleAuthKey, simpleAuthKey,
SimpleAuthSettings, SimpleAuthSettings,
} from '../../types/settings/simple-auth-settings'; } from '../../types/settings/simple-auth-settings';
import { NONE } from '../../types/permissions';
interface IUIConfigResponse extends IUIConfig { import { createResponseSchema } from '../../openapi';
version: string; import {
unleashUrl: string; uiConfigSchema,
baseUriPath: string; UiConfigSchema,
authenticationType?: IAuthType; } from '../../openapi/spec/ui-config-schema';
versionInfo: IVersionHolder; import { OpenApiService } from '../../services/openapi-service';
disablePasswordAuth: boolean;
segmentValuesLimit: number;
strategySegmentsLimit: number;
}
class ConfigController extends Controller { class ConfigController extends Controller {
private versionService: VersionService; private versionService: VersionService;
private settingService: SettingService; private settingService: SettingService;
private uiConfig: Omit< private readonly openApiService: OpenApiService;
IUIConfigResponse,
'versionInfo' | 'disablePasswordAuth'
>;
constructor( constructor(
config: IUnleashConfig, config: IUnleashConfig,
{ {
versionService, versionService,
settingService, settingService,
}: Pick<IUnleashServices, 'versionService' | 'settingService'>, openApiService,
}: Pick<
IUnleashServices,
'versionService' | 'settingService' | 'openApiService'
>,
) { ) {
super(config); super(config);
this.versionService = versionService; this.versionService = versionService;
this.settingService = settingService; this.settingService = settingService;
const authenticationType = this.openApiService = openApiService;
config.authentication && config.authentication.type;
this.uiConfig = { this.route({
...config.ui, method: 'get',
version, path: '',
unleashUrl: config.server.unleashUrl, handler: this.getUIConfig,
baseUriPath: config.server.baseUriPath, permission: NONE,
authenticationType, middleware: [
segmentValuesLimit: config.segmentValuesLimit, openApiService.validPath({
strategySegmentsLimit: config.strategySegmentsLimit, tags: ['admin'],
}; operationId: 'getUIConfig',
this.get('/', this.getUIConfig); responses: {
200: createResponseSchema('uiConfigSchema'),
},
}),
],
});
} }
async getUIConfig( async getUIConfig(
req: Request, req: Request,
res: Response<IUIConfigResponse>, res: Response<UiConfigSchema>,
): Promise<void> { ): Promise<void> {
const config = this.uiConfig;
const simpleAuthSettings = const simpleAuthSettings =
await this.settingService.get<SimpleAuthSettings>(simpleAuthKey); await this.settingService.get<SimpleAuthSettings>(simpleAuthKey);
const versionInfo = this.versionService.getVersionInfo();
const disablePasswordAuth = const disablePasswordAuth =
simpleAuthSettings?.disabled || simpleAuthSettings?.disabled ||
this.config.authentication.type == IAuthType.NONE; this.config.authentication.type == IAuthType.NONE;
res.json({ ...config, versionInfo, disablePasswordAuth });
const response: UiConfigSchema = {
...this.config.ui,
version,
unleashUrl: this.config.server.unleashUrl,
baseUriPath: this.config.server.baseUriPath,
authenticationType: this.config.authentication?.type,
segmentValuesLimit: this.config.segmentValuesLimit,
strategySegmentsLimit: this.config.strategySegmentsLimit,
versionInfo: this.versionService.getVersionInfo(),
disablePasswordAuth,
};
this.openApiService.respondWithValidation(
200,
res,
uiConfigSchema.$id,
response,
);
} }
} }
export default ConfigController; export default ConfigController;

View File

@ -147,6 +147,7 @@ export interface IUIConfig {
}, },
]; ];
} }
export interface ICspDomainOptions { export interface ICspDomainOptions {
defaultSrc?: string[]; defaultSrc?: string[];
fontSrc?: string[]; fontSrc?: string[];

View File

@ -455,6 +455,71 @@ Object {
], ],
"type": "object", "type": "object",
}, },
"uiConfigSchema": Object {
"additionalProperties": false,
"properties": Object {
"authenticationType": Object {
"enum": Array [
"open-source",
"demo",
"enterprise",
"hosted",
"custom",
"none",
],
"type": "string",
},
"baseUriPath": Object {
"type": "string",
},
"disablePasswordAuth": Object {
"type": "boolean",
},
"flags": Object {
"additionalProperties": Object {
"type": "boolean",
},
"type": "object",
},
"links": Object {
"items": Object {
"type": "object",
},
"type": "array",
},
"name": Object {
"type": "string",
},
"segmentValuesLimit": Object {
"type": "number",
},
"slogan": Object {
"type": "string",
},
"strategySegmentsLimit": Object {
"type": "number",
},
"unleashUrl": Object {
"type": "string",
},
"version": Object {
"type": "string",
},
"versionInfo": Object {
"$ref": "#/components/schemas/versionSchema",
},
},
"required": Array [
"version",
"unleashUrl",
"baseUriPath",
"versionInfo",
"disablePasswordAuth",
"segmentValuesLimit",
"strategySegmentsLimit",
],
"type": "object",
},
"updateFeatureSchema": Object { "updateFeatureSchema": Object {
"properties": Object { "properties": Object {
"archived": Object { "archived": Object {
@ -567,6 +632,48 @@ Object {
}, },
"type": "array", "type": "array",
}, },
"versionSchema": Object {
"additionalProperties": false,
"properties": Object {
"current": Object {
"additionalProperties": false,
"properties": Object {
"enterprise": Object {
"type": "string",
},
"oss": Object {
"type": "string",
},
},
"type": "object",
},
"instanceId": Object {
"type": "string",
},
"isLatest": Object {
"type": "boolean",
},
"latest": Object {
"additionalProperties": false,
"properties": Object {
"enterprise": Object {
"type": "string",
},
"oss": Object {
"type": "string",
},
},
"type": "object",
},
},
"required": Array [
"current",
"latest",
"isLatest",
"instanceId",
],
"type": "object",
},
}, },
"securitySchemes": Object { "securitySchemes": Object {
"apiKey": Object { "apiKey": Object {
@ -1676,6 +1783,26 @@ Object {
], ],
}, },
}, },
"/api/admin/ui-config": Object {
"get": Object {
"operationId": "getUIConfig",
"responses": Object {
"200": Object {
"content": Object {
"application/json": Object {
"schema": Object {
"$ref": "#/components/schemas/uiConfigSchema",
},
},
},
"description": "uiConfigSchema",
},
},
"tags": Array [
"admin",
],
},
},
}, },
"security": Array [ "security": Array [
Object { Object {