From 64049bd546886e384bbc36f78f093c8578f2c01b Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 14 Mar 2024 15:46:08 +0100 Subject: [PATCH] feat: Implement get role mappings API endpoint --- .../get-role-mappings.ee.js | 14 +++++ .../get-role-mappings.ee.test.js | 51 +++++++++++++++++++ .../api/v1/admin/saml-auth-providers.ee.js | 9 ++++ packages/backend/src/serializers/index.js | 2 + .../src/serializers/role-mapping.ee.js | 10 ++++ .../backend/test/factories/role-mapping.js | 16 ++++++ .../get-role-mappings.ee.js | 23 +++++++++ 7 files changed, 125 insertions(+) create mode 100644 packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js create mode 100644 packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.test.js create mode 100644 packages/backend/src/serializers/role-mapping.ee.js create mode 100644 packages/backend/test/factories/role-mapping.js create mode 100644 packages/backend/test/mocks/rest/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js diff --git a/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js b/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js new file mode 100644 index 00000000..2f7a377f --- /dev/null +++ b/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js @@ -0,0 +1,14 @@ +import { renderObject } from '../../../../../helpers/renderer.js'; +import SamlAuthProvider from '../../../../../models/saml-auth-provider.ee.js'; + +export default async (request, response) => { + const samlAuthProvider = await SamlAuthProvider.query() + .findById(request.params.samlAuthProviderId) + .throwIfNotFound(); + + const roleMappings = await samlAuthProvider + .$relatedQuery('samlAuthProvidersRoleMappings') + .orderBy('remote_role_name', 'asc'); + + renderObject(response, roleMappings); +}; diff --git a/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.test.js b/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.test.js new file mode 100644 index 00000000..10ca9f33 --- /dev/null +++ b/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.test.js @@ -0,0 +1,51 @@ +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 { createRole } from '../../../../../../test/factories/role.js'; +import { createUser } from '../../../../../../test/factories/user.js'; +import { createSamlAuthProvider } from '../../../../../../test/factories/saml-auth-provider.ee.js'; +import { createRoleMapping } from '../../../../../../test/factories/role-mapping.js'; +import getRoleMappingsMock from '../../../../../../test/mocks/rest/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js'; +import * as license from '../../../../../helpers/license.ee.js'; + +describe('GET /api/v1/admin/saml-auth-providers/:samlAuthProviderId/role-mappings', () => { + let roleMappingOne, roleMappingTwo, samlAuthProvider, currentUser, token; + + beforeEach(async () => { + const role = await createRole({ key: 'admin' }); + currentUser = await createUser({ roleId: role.id }); + + samlAuthProvider = await createSamlAuthProvider(); + + roleMappingOne = await createRoleMapping({ + samlAuthProviderId: samlAuthProvider.id, + remoteRoleName: 'Admin', + }); + + roleMappingTwo = await createRoleMapping({ + samlAuthProviderId: samlAuthProvider.id, + remoteRoleName: 'User', + }); + + token = createAuthTokenByUserId(currentUser.id); + }); + + it('should return role mappings', async () => { + vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true); + + const response = await request(app) + .get( + `/api/v1/admin/saml-auth-providers/${samlAuthProvider.id}/role-mappings` + ) + .set('Authorization', token) + .expect(200); + + const expectedPayload = await getRoleMappingsMock([ + roleMappingOne, + roleMappingTwo, + ]); + + expect(response.body).toEqual(expectedPayload); + }); +}); diff --git a/packages/backend/src/routes/api/v1/admin/saml-auth-providers.ee.js b/packages/backend/src/routes/api/v1/admin/saml-auth-providers.ee.js index e13771a1..586f4a6f 100644 --- a/packages/backend/src/routes/api/v1/admin/saml-auth-providers.ee.js +++ b/packages/backend/src/routes/api/v1/admin/saml-auth-providers.ee.js @@ -5,6 +5,7 @@ import { authorizeAdmin } from '../../../../helpers/authorization.js'; import { checkIsEnterprise } from '../../../../helpers/check-is-enterprise.js'; import getSamlAuthProvidersAction from '../../../../controllers/api/v1/admin/saml-auth-providers/get-saml-auth-providers.ee.js'; import getSamlAuthProviderAction from '../../../../controllers/api/v1/admin/saml-auth-providers/get-saml-auth-provider.ee.js'; +import getRoleMappingsAction from '../../../../controllers/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js'; const router = Router(); @@ -24,4 +25,12 @@ router.get( asyncHandler(getSamlAuthProviderAction) ); +router.get( + '/:samlAuthProviderId/role-mappings', + authenticateUser, + authorizeAdmin, + checkIsEnterprise, + asyncHandler(getRoleMappingsAction) +); + export default router; diff --git a/packages/backend/src/serializers/index.js b/packages/backend/src/serializers/index.js index 7d6445ab..28b98e1e 100644 --- a/packages/backend/src/serializers/index.js +++ b/packages/backend/src/serializers/index.js @@ -3,6 +3,7 @@ import roleSerializer from './role.js'; import permissionSerializer from './permission.js'; import adminSamlAuthProviderSerializer from './admin-saml-auth-provider.ee.js'; import samlAuthProviderSerializer from './saml-auth-provider.ee.js'; +import samlAuthProviderRoleMappingSerializer from './role-mapping.ee.js'; import appAuthClientSerializer from './app-auth-client.js'; import appConfigSerializer from './app-config.js'; import flowSerializer from './flow.js'; @@ -22,6 +23,7 @@ const serializers = { Permission: permissionSerializer, AdminSamlAuthProvider: adminSamlAuthProviderSerializer, SamlAuthProvider: samlAuthProviderSerializer, + SamlAuthProvidersRoleMapping: samlAuthProviderRoleMappingSerializer, AppAuthClient: appAuthClientSerializer, AppConfig: appConfigSerializer, Flow: flowSerializer, diff --git a/packages/backend/src/serializers/role-mapping.ee.js b/packages/backend/src/serializers/role-mapping.ee.js new file mode 100644 index 00000000..cb2f9ed1 --- /dev/null +++ b/packages/backend/src/serializers/role-mapping.ee.js @@ -0,0 +1,10 @@ +const roleMappingSerializer = (roleMapping) => { + return { + id: roleMapping.id, + samlAuthProviderId: roleMapping.samlAuthProviderId, + roleId: roleMapping.roleId, + remoteRoleName: roleMapping.remoteRoleName, + }; +}; + +export default roleMappingSerializer; diff --git a/packages/backend/test/factories/role-mapping.js b/packages/backend/test/factories/role-mapping.js new file mode 100644 index 00000000..e9d37fcc --- /dev/null +++ b/packages/backend/test/factories/role-mapping.js @@ -0,0 +1,16 @@ +import { createRole } from './role.js'; +import { createSamlAuthProvider } from './saml-auth-provider.ee.js'; +import SamlAuthProviderRoleMapping from '../../src/models/saml-auth-providers-role-mapping.ee.js'; + +export const createRoleMapping = async (params = {}) => { + params.roleId = params?.roleId || (await createRole()).id; + params.samlAuthProviderId = + params?.samlAuthProviderId || (await createSamlAuthProvider()).id; + + params.remoteRoleName = params?.remoteRoleName || 'User'; + + const samlAuthProviderRoleMapping = + await SamlAuthProviderRoleMapping.query().insertAndFetch(params); + + return samlAuthProviderRoleMapping; +}; diff --git a/packages/backend/test/mocks/rest/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js b/packages/backend/test/mocks/rest/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js new file mode 100644 index 00000000..66fdf08a --- /dev/null +++ b/packages/backend/test/mocks/rest/api/v1/admin/saml-auth-providers/get-role-mappings.ee.js @@ -0,0 +1,23 @@ +const getRoleMappingsMock = async (roleMappings) => { + const data = roleMappings.map((roleMapping) => { + return { + id: roleMapping.id, + samlAuthProviderId: roleMapping.samlAuthProviderId, + roleId: roleMapping.roleId, + remoteRoleName: roleMapping.remoteRoleName, + }; + }); + + return { + data: data, + meta: { + count: data.length, + currentPage: null, + isArray: true, + totalPages: null, + type: 'SamlAuthProvidersRoleMapping', + }, + }; +}; + +export default getRoleMappingsMock;