From ca81e14d6397652e8157b45249f485f485f2a9ba Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Wed, 28 Aug 2024 12:19:57 +0000 Subject: [PATCH] feat: write PATCH /v1/admin/apps/:appKey/config --- .../api/v1/admin/apps/update-config.ee.js | 24 +++++ .../v1/admin/apps/update-config.ee.test.js | 91 +++++++++++++++++++ .../src/routes/api/v1/admin/apps.ee.js | 9 ++ 3 files changed, 124 insertions(+) create mode 100644 packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.js create mode 100644 packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.test.js diff --git a/packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.js b/packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.js new file mode 100644 index 00000000..0467d573 --- /dev/null +++ b/packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.js @@ -0,0 +1,24 @@ +import { renderObject } from '../../../../../helpers/renderer.js'; +import AppConfig from '../../../../../models/app-config.js'; + +export default async (request, response) => { + const appConfig = await AppConfig.query() + .findOne({ + key: request.params.appKey, + }) + .throwIfNotFound(); + + await appConfig.$query().patchAndFetch(appConfigParams(request)); + + renderObject(response, appConfig); +}; + +const appConfigParams = (request) => { + const { allowCustomConnection, shared, disabled } = request.body; + + return { + allowCustomConnection, + shared, + disabled, + }; +}; diff --git a/packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.test.js b/packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.test.js new file mode 100644 index 00000000..d89e0dc0 --- /dev/null +++ b/packages/backend/src/controllers/api/v1/admin/apps/update-config.ee.test.js @@ -0,0 +1,91 @@ +import { vi, describe, it, expect, beforeEach } from 'vitest'; +import request from 'supertest'; + +import app from '../../../../../app.js'; +import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js'; +import { createUser } from '../../../../../../test/factories/user.js'; +import { createRole } from '../../../../../../test/factories/role.js'; +import createAppConfigMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/create-config.js'; +import { createAppConfig } from '../../../../../../test/factories/app-config.js'; +import * as license from '../../../../../helpers/license.ee.js'; + +describe('PATCH /api/v1/admin/apps/:appKey/config', () => { + let currentUser, adminRole, token; + + beforeEach(async () => { + vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true); + + adminRole = await createRole({ key: 'admin' }); + currentUser = await createUser({ roleId: adminRole.id }); + + token = await createAuthTokenByUserId(currentUser.id); + }); + + it('should return updated app config', async () => { + const appConfig = { + key: 'gitlab', + allowCustomConnection: true, + shared: true, + disabled: false, + }; + + await createAppConfig(appConfig); + + const newAppConfigValues = { + shared: false, + disabled: true, + allowCustomConnection: false, + }; + + const response = await request(app) + .patch('/api/v1/admin/apps/gitlab/config') + .set('Authorization', token) + .send(newAppConfigValues) + .expect(200); + + const expectedPayload = createAppConfigMock({ + ...newAppConfigValues, + key: 'gitlab', + }); + + expect(response.body).toMatchObject(expectedPayload); + }); + + it('should return not found response for unexisting app config', async () => { + const appConfig = { + shared: false, + disabled: true, + allowCustomConnection: false, + }; + + await request(app) + .patch('/api/v1/admin/apps/gitlab/config') + .set('Authorization', token) + .send(appConfig) + .expect(404); + }); + + it('should return HTTP 422 for already existing app config', async () => { + const appConfig = { + key: 'gitlab', + allowCustomConnection: true, + shared: true, + disabled: false, + }; + + await createAppConfig(appConfig); + + const response = await request(app) + .patch('/api/v1/admin/apps/gitlab/config') + .set('Authorization', token) + .send({ + disabled: 'invalid value type', + }) + .expect(422); + + expect(response.body.meta.type).toEqual('ModelValidation'); + expect(response.body.errors).toMatchObject({ + disabled: ['must be boolean'], + }); + }); +}); diff --git a/packages/backend/src/routes/api/v1/admin/apps.ee.js b/packages/backend/src/routes/api/v1/admin/apps.ee.js index 71f9cfee..c476d2ff 100644 --- a/packages/backend/src/routes/api/v1/admin/apps.ee.js +++ b/packages/backend/src/routes/api/v1/admin/apps.ee.js @@ -3,6 +3,7 @@ import { authenticateUser } from '../../../../helpers/authentication.js'; import { authorizeAdmin } from '../../../../helpers/authorization.js'; import { checkIsEnterprise } from '../../../../helpers/check-is-enterprise.js'; import createConfigAction from '../../../../controllers/api/v1/admin/apps/create-config.ee.js'; +import updateConfigAction from '../../../../controllers/api/v1/admin/apps/update-config.ee.js'; import getAuthClientsAction from '../../../../controllers/api/v1/admin/apps/get-auth-clients.ee.js'; import getAuthClientAction from '../../../../controllers/api/v1/admin/apps/get-auth-client.ee.js'; import createAuthClientAction from '../../../../controllers/api/v1/admin/apps/create-auth-client.ee.js'; @@ -18,6 +19,14 @@ router.post( createConfigAction ); +router.patch( + '/:appKey/config', + authenticateUser, + authorizeAdmin, + checkIsEnterprise, + updateConfigAction +); + router.get( '/:appKey/auth-clients', authenticateUser,