From e52fcd11e06256a6158a0fe321a322d0259c5bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Mon, 26 May 2025 10:22:16 +0100 Subject: [PATCH] chore!: remove deprecated POST ui-config endpoint (#10027) https://linear.app/unleash/issue/2-3472/remove-post-apiadminui-config-deprecated-in-690 Removes POST `/api/admin/ui-config` which was deprecated in v6.9. Also cleans up related code. --- .../frontend-api/frontend-api-service.ts | 16 --------- .../middleware/cors-origin-middleware.test.ts | 34 ++++-------------- src/lib/openapi/spec/index.ts | 1 - src/lib/openapi/spec/set-ui-config-schema.ts | 28 --------------- src/lib/routes/admin-api/config.ts | 36 ------------------- src/test/e2e/api/admin/config.e2e.test.ts | 33 ++--------------- .../using-unleash/troubleshooting/cors.md | 4 +-- 7 files changed, 11 insertions(+), 141 deletions(-) delete mode 100644 src/lib/openapi/spec/set-ui-config-schema.ts diff --git a/src/lib/features/frontend-api/frontend-api-service.ts b/src/lib/features/frontend-api/frontend-api-service.ts index 09581f9dee..cc17714ff6 100644 --- a/src/lib/features/frontend-api/frontend-api-service.ts +++ b/src/lib/features/frontend-api/frontend-api-service.ts @@ -215,22 +215,6 @@ export class FrontendApiService { } } - async setFrontendSettings( - value: FrontendSettings, - auditUser: IAuditUser, - ): Promise { - const error = validateOrigins(value.frontendApiOrigins); - if (error) { - throw new BadDataError(error); - } - await this.services.settingService.insert( - frontendSettingsKey, - value, - auditUser, - false, - ); - } - async setFrontendCorsSettings( value: FrontendSettings['frontendApiOrigins'], auditUser: IAuditUser, diff --git a/src/lib/middleware/cors-origin-middleware.test.ts b/src/lib/middleware/cors-origin-middleware.test.ts index d79333c9d9..d7e20faec7 100644 --- a/src/lib/middleware/cors-origin-middleware.test.ts +++ b/src/lib/middleware/cors-origin-middleware.test.ts @@ -2,7 +2,6 @@ import { resolveOrigin } from './cors-origin-middleware.js'; import FakeSettingStore from '../../test/fixtures/fake-setting-store.js'; import { createTestConfig } from '../../test/config/test-config.js'; import FakeEventStore from '../../test/fixtures/fake-event-store.js'; -import { randomId } from '../util/random-id.js'; import FakeProjectStore from '../../test/fixtures/fake-project-store.js'; import { FrontendApiService, @@ -56,32 +55,21 @@ test('resolveOrigin', () => { test('corsOriginMiddleware origin validation', async () => { const { frontendApiService } = createSettingService([]); - const userName = randomId(); await expect(() => - frontendApiService.setFrontendSettings( - { frontendApiOrigins: ['a'] }, - TEST_AUDIT_USER, - ), + frontendApiService.setFrontendCorsSettings(['a'], TEST_AUDIT_USER), ).rejects.toThrow('Invalid origin: a'); }); test('corsOriginMiddleware without config', async () => { const { frontendApiService, settingStore } = createSettingService([]); - const userName = randomId(); expect(await frontendApiService.getFrontendSettings(false)).toEqual({ frontendApiOrigins: [], }); - await frontendApiService.setFrontendSettings( - { frontendApiOrigins: [] }, - TEST_AUDIT_USER, - ); + await frontendApiService.setFrontendCorsSettings([], TEST_AUDIT_USER); expect(await frontendApiService.getFrontendSettings(false)).toEqual({ frontendApiOrigins: [], }); - await frontendApiService.setFrontendSettings( - { frontendApiOrigins: ['*'] }, - TEST_AUDIT_USER, - ); + await frontendApiService.setFrontendCorsSettings(['*'], TEST_AUDIT_USER); expect(await frontendApiService.getFrontendSettings(false)).toEqual({ frontendApiOrigins: ['*'], }); @@ -93,19 +81,15 @@ test('corsOriginMiddleware without config', async () => { test('corsOriginMiddleware with config', async () => { const { frontendApiService, settingStore } = createSettingService(['*']); - const userName = randomId(); expect(await frontendApiService.getFrontendSettings(false)).toEqual({ frontendApiOrigins: ['*'], }); - await frontendApiService.setFrontendSettings( - { frontendApiOrigins: [] }, - TEST_AUDIT_USER, - ); + await frontendApiService.setFrontendCorsSettings([], TEST_AUDIT_USER); expect(await frontendApiService.getFrontendSettings(false)).toEqual({ frontendApiOrigins: [], }); - await frontendApiService.setFrontendSettings( - { frontendApiOrigins: ['https://example.com', 'https://example.org'] }, + await frontendApiService.setFrontendCorsSettings( + ['https://example.com', 'https://example.org'], TEST_AUDIT_USER, ); expect(await frontendApiService.getFrontendSettings(false)).toEqual({ @@ -120,16 +104,12 @@ test('corsOriginMiddleware with config', async () => { test('corsOriginMiddleware with caching enabled', async () => { const { frontendApiService } = createSettingService([]); - const userName = randomId(); expect(await frontendApiService.getFrontendSettings()).toEqual({ frontendApiOrigins: [], }); //setting - await frontendApiService.setFrontendSettings( - { frontendApiOrigins: ['*'] }, - TEST_AUDIT_USER, - ); + await frontendApiService.setFrontendCorsSettings(['*'], TEST_AUDIT_USER); //still get cached value expect(await frontendApiService.getFrontendSettings()).toEqual({ diff --git a/src/lib/openapi/spec/index.ts b/src/lib/openapi/spec/index.ts index dfb942b408..6e48e00126 100644 --- a/src/lib/openapi/spec/index.ts +++ b/src/lib/openapi/spec/index.ts @@ -184,7 +184,6 @@ export * from './segment-strategies-schema.js'; export * from './segments-schema.js'; export * from './set-cors-schema.js'; export * from './set-strategy-sort-order-schema.js'; -export * from './set-ui-config-schema.js'; export * from './sort-order-schema.js'; export * from './splash-request-schema.js'; export * from './splash-response-schema.js'; diff --git a/src/lib/openapi/spec/set-ui-config-schema.ts b/src/lib/openapi/spec/set-ui-config-schema.ts deleted file mode 100644 index 4d8df4e8f2..0000000000 --- a/src/lib/openapi/spec/set-ui-config-schema.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { FromSchema } from 'json-schema-to-ts'; - -export const setUiConfigSchema = { - $id: '#/components/schemas/setUiConfigSchema', - type: 'object', - additionalProperties: false, - description: 'Unleash configuration settings affect the admin UI.', - properties: { - frontendSettings: { - type: 'object', - description: 'Settings related to the front-end API.', - additionalProperties: false, - required: ['frontendApiOrigins'], - properties: { - frontendApiOrigins: { - description: - 'The list of origins that the front-end API should accept requests from.', - example: ['*'], - type: 'array', - items: { type: 'string' }, - }, - }, - }, - }, - components: {}, -} as const; - -export type SetUiConfigSchema = FromSchema; diff --git a/src/lib/routes/admin-api/config.ts b/src/lib/routes/admin-api/config.ts index 47467480fe..c4feb6c6c7 100644 --- a/src/lib/routes/admin-api/config.ts +++ b/src/lib/routes/admin-api/config.ts @@ -21,7 +21,6 @@ import type { EmailService } from '../../services/email-service.js'; import { emptyResponse } from '../../openapi/util/standard-responses.js'; import type { IAuthRequest } from '../unleash-types.js'; import NotFoundError from '../../error/notfound-error.js'; -import type { SetUiConfigSchema } from '../../openapi/spec/set-ui-config-schema.js'; import type { SetCorsSchema } from '../../openapi/spec/set-cors-schema.js'; import { createRequestSchema } from '../../openapi/util/create-request-schema.js'; import type { @@ -103,25 +102,6 @@ class ConfigController extends Controller { ], }); - this.route({ - method: 'post', - path: '', - handler: this.setUiConfig, - permission: ADMIN, - middleware: [ - openApiService.validPath({ - tags: ['Admin UI'], - summary: 'Set UI configuration', - description: - 'Deprecated. Use `./cors` instead. Sets the UI configuration for this Unleash instance.', - operationId: 'setUiConfig', - requestBody: createRequestSchema('setUiConfigSchema'), - responses: { 200: emptyResponse }, - deprecated: true, - }), - ], - }); - this.route({ method: 'post', path: '/cors', @@ -210,22 +190,6 @@ class ConfigController extends Controller { ); } - async setUiConfig( - req: IAuthRequest, - res: Response, - ): Promise { - if (req.body.frontendSettings) { - await this.frontendApiService.setFrontendSettings( - req.body.frontendSettings, - req.audit, - ); - res.sendStatus(204); - return; - } - - throw new NotFoundError(); - } - async setCors( req: IAuthRequest, res: Response, diff --git a/src/test/e2e/api/admin/config.e2e.test.ts b/src/test/e2e/api/admin/config.e2e.test.ts index 3baec92a32..5501f44c05 100644 --- a/src/test/e2e/api/admin/config.e2e.test.ts +++ b/src/test/e2e/api/admin/config.e2e.test.ts @@ -58,8 +58,8 @@ test('gets ui config with disablePasswordAuth', async () => { test('gets ui config with frontendSettings', async () => { const frontendApiOrigins = ['https://example.net']; - await app.services.frontendApiService.setFrontendSettings( - { frontendApiOrigins }, + await app.services.frontendApiService.setFrontendCorsSettings( + frontendApiOrigins, TEST_AUDIT_USER, ); await app.request @@ -71,35 +71,6 @@ test('gets ui config with frontendSettings', async () => { ); }); -test('sets ui config with frontendSettings', async () => { - const frontendApiOrigins = ['https://example.org']; - await app.request - .get('/api/admin/ui-config') - .expect('Content-Type', /json/) - .expect(200) - .expect((res) => expect(res.body.frontendApiOrigins).toEqual(['*'])); - await app.request - .post('/api/admin/ui-config') - .send({ frontendSettings: { frontendApiOrigins: [] } }) - .expect(204); - await app.request - .get('/api/admin/ui-config') - .expect('Content-Type', /json/) - .expect(200) - .expect((res) => expect(res.body.frontendApiOrigins).toEqual([])); - await app.request - .post('/api/admin/ui-config') - .send({ frontendSettings: { frontendApiOrigins } }) - .expect(204); - await app.request - .get('/api/admin/ui-config') - .expect('Content-Type', /json/) - .expect(200) - .expect((res) => - expect(res.body.frontendApiOrigins).toEqual(frontendApiOrigins), - ); -}); - describe('maxSessionsCount', () => { beforeEach(async () => { // prevent memoization of session count diff --git a/website/docs/using-unleash/troubleshooting/cors.md b/website/docs/using-unleash/troubleshooting/cors.md index 57f1e217f2..f604b6b3b5 100644 --- a/website/docs/using-unleash/troubleshooting/cors.md +++ b/website/docs/using-unleash/troubleshooting/cors.md @@ -2,5 +2,5 @@ title: My requests are being blocked by CORS --- -1. Make sure you've configured CORS access in Unleash admin UI settings as defined in the [Unleash CORS Policy docs](/reference/front-end-api#configure-cross-origin-resource-sharing-cors). These settings can be changed in the Unleash Dashboard under **Settings -> CORS Origins** or by using the [API](/reference/api/unleash/set-ui-config). Allowing all origins (using a single asterisk) will address this matter and is a great starting point when troubleshooting the behavior. -1. When receiving "**No 'Access-Control-Policy' header is present on the requested resource**", using the command `curl -I https:///` will allow us to verify that the response includes the header `Access-Control-Allow-Origin: *`. \ No newline at end of file +1. Make sure you've configured CORS access in Unleash admin UI settings as defined in the [Unleash CORS Policy docs](/reference/front-end-api#configure-cross-origin-resource-sharing-cors). These settings can be changed in the Unleash Dashboard under **Settings -> CORS Origins** or by using the [API](/reference/api/unleash/set-cors). Allowing all origins (using a single asterisk) will address this matter and is a great starting point when troubleshooting the behavior. +1. When receiving "**No 'Access-Control-Policy' header is present on the requested resource**", using the command `curl -I https:///` will allow us to verify that the response includes the header `Access-Control-Allow-Origin: *`.