From d2c8f5a75c3d03692a89eaa083c05b403298a22b Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 27 Nov 2024 16:47:50 +0300 Subject: [PATCH 1/5] test: Add test for config method of saml auth providers --- .../src/models/saml-auth-provider.ee.test.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/backend/src/models/saml-auth-provider.ee.test.js b/packages/backend/src/models/saml-auth-provider.ee.test.js index 2f94f44e..d241058c 100644 --- a/packages/backend/src/models/saml-auth-provider.ee.test.js +++ b/packages/backend/src/models/saml-auth-provider.ee.test.js @@ -81,4 +81,28 @@ describe('SamlAuthProvider model', () => { 'https://example.com/saml/logout' ); }); + + it('config should return the correct configuration object', () => { + const samlAuthProvider = new SamlAuthProvider(); + + samlAuthProvider.certificate = 'sample-certificate'; + samlAuthProvider.signatureAlgorithm = 'sha256'; + samlAuthProvider.entryPoint = 'https://example.com/saml'; + samlAuthProvider.issuer = 'sample-issuer'; + + vi.spyOn(appConfig, 'baseUrl', 'get').mockReturnValue( + 'https://automatisch.io' + ); + + const expectedConfig = { + callbackUrl: 'https://automatisch.io/login/saml/sample-issuer/callback', + cert: 'sample-certificate', + entryPoint: 'https://example.com/saml', + issuer: 'sample-issuer', + signatureAlgorithm: 'sha256', + logoutUrl: 'https://example.com/saml', + }; + + expect(samlAuthProvider.config).toStrictEqual(expectedConfig); + }); }); From d896238f23054f26b5ad0842f2e62b8a83e05ed0 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 27 Nov 2024 16:59:49 +0300 Subject: [PATCH 2/5] test: Implement generateLogoutRequestBody test for saml auth provider model --- .../src/models/saml-auth-provider.ee.test.js | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/backend/src/models/saml-auth-provider.ee.test.js b/packages/backend/src/models/saml-auth-provider.ee.test.js index d241058c..a07e0e71 100644 --- a/packages/backend/src/models/saml-auth-provider.ee.test.js +++ b/packages/backend/src/models/saml-auth-provider.ee.test.js @@ -1,4 +1,5 @@ import { vi, describe, it, expect } from 'vitest'; +import { v4 as uuidv4 } from 'uuid'; import SamlAuthProvider from '../models/saml-auth-provider.ee'; import RoleMapping from '../models/role-mapping.ee'; import Identity from './identity.ee'; @@ -105,4 +106,41 @@ describe('SamlAuthProvider model', () => { expect(samlAuthProvider.config).toStrictEqual(expectedConfig); }); + + it('generateLogoutRequestBody should return a correctly encoded SAML logout request', () => { + vi.mock('uuid', () => ({ + v4: vi.fn(), + })); + + const samlAuthProvider = new SamlAuthProvider(); + + samlAuthProvider.entryPoint = 'https://example.com/saml'; + samlAuthProvider.issuer = 'sample-issuer'; + + const mockUuid = '123e4567-e89b-12d3-a456-426614174000'; + uuidv4.mockReturnValue(mockUuid); + + const sessionId = 'test-session-id'; + + const logoutRequest = samlAuthProvider.generateLogoutRequestBody(sessionId); + + const expectedLogoutRequest = ` + + + sample-issuer + test-session-id + + `; + + const expectedEncodedRequest = Buffer.from(expectedLogoutRequest).toString( + 'base64' + ); + + expect(logoutRequest).toBe(expectedEncodedRequest); + }); }); From b26e2ecf2e7eea340cd6c209fa0ad91069d2120b Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 27 Nov 2024 17:04:37 +0300 Subject: [PATCH 3/5] test: Add tests for terminateRemoteSession method --- .../src/models/saml-auth-provider.ee.test.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/packages/backend/src/models/saml-auth-provider.ee.test.js b/packages/backend/src/models/saml-auth-provider.ee.test.js index a07e0e71..61fbe414 100644 --- a/packages/backend/src/models/saml-auth-provider.ee.test.js +++ b/packages/backend/src/models/saml-auth-provider.ee.test.js @@ -2,6 +2,7 @@ import { vi, describe, it, expect } from 'vitest'; import { v4 as uuidv4 } from 'uuid'; import SamlAuthProvider from '../models/saml-auth-provider.ee'; import RoleMapping from '../models/role-mapping.ee'; +import axios from '../helpers/axios-with-proxy.js'; import Identity from './identity.ee'; import Base from './base'; import appConfig from '../config/app'; @@ -143,4 +144,42 @@ describe('SamlAuthProvider model', () => { expect(logoutRequest).toBe(expectedEncodedRequest); }); + + it('terminateRemoteSession should send the correct POST request and return the response', async () => { + vi.mock('../helpers/axios-with-proxy.js', () => ({ + default: { + post: vi.fn(), + }, + })); + + const samlAuthProvider = new SamlAuthProvider(); + + samlAuthProvider.entryPoint = 'https://example.com/saml'; + samlAuthProvider.generateLogoutRequestBody = vi + .fn() + .mockReturnValue('mockEncodedLogoutRequest'); + + const sessionId = 'test-session-id'; + + const mockResponse = { data: 'Logout Successful' }; + axios.post.mockResolvedValue(mockResponse); + + const response = await samlAuthProvider.terminateRemoteSession(sessionId); + + expect(samlAuthProvider.generateLogoutRequestBody).toHaveBeenCalledWith( + sessionId + ); + + expect(axios.post).toHaveBeenCalledWith( + 'https://example.com/saml', + 'SAMLRequest=mockEncodedLogoutRequest', + { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + } + ); + + expect(response).toBe(mockResponse); + }); }); From 6e97e023c91d8e817df82ca07faf6162ca7679ba Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 27 Nov 2024 17:19:24 +0300 Subject: [PATCH 4/5] test: Add tests for updateRoleMappings method for saml auth provider --- .../src/models/saml-auth-provider.ee.js | 26 +++++----- .../src/models/saml-auth-provider.ee.test.js | 48 ++++++++++++++++++- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/packages/backend/src/models/saml-auth-provider.ee.js b/packages/backend/src/models/saml-auth-provider.ee.js index 44f6f15e..4eb588ec 100644 --- a/packages/backend/src/models/saml-auth-provider.ee.js +++ b/packages/backend/src/models/saml-auth-provider.ee.js @@ -133,24 +133,22 @@ class SamlAuthProvider extends Base { } async updateRoleMappings(roleMappings) { - return await SamlAuthProvider.transaction(async (trx) => { - await this.$relatedQuery('roleMappings', trx).delete(); + await this.$relatedQuery('roleMappings').delete(); - if (isEmpty(roleMappings)) { - return []; - } + if (isEmpty(roleMappings)) { + return []; + } - const roleMappingsData = roleMappings.map((roleMapping) => ({ - ...roleMapping, - samlAuthProviderId: this.id, - })); + const roleMappingsData = roleMappings.map((roleMapping) => ({ + ...roleMapping, + samlAuthProviderId: this.id, + })); - const newRoleMappings = await RoleMapping.query(trx).insertAndFetch( - roleMappingsData - ); + const newRoleMappings = await RoleMapping.query().insertAndFetch( + roleMappingsData + ); - return newRoleMappings; - }); + return newRoleMappings; } } diff --git a/packages/backend/src/models/saml-auth-provider.ee.test.js b/packages/backend/src/models/saml-auth-provider.ee.test.js index 61fbe414..10a0abb0 100644 --- a/packages/backend/src/models/saml-auth-provider.ee.test.js +++ b/packages/backend/src/models/saml-auth-provider.ee.test.js @@ -1,4 +1,4 @@ -import { vi, describe, it, expect } from 'vitest'; +import { vi, beforeEach, describe, it, expect } from 'vitest'; import { v4 as uuidv4 } from 'uuid'; import SamlAuthProvider from '../models/saml-auth-provider.ee'; import RoleMapping from '../models/role-mapping.ee'; @@ -6,6 +6,9 @@ import axios from '../helpers/axios-with-proxy.js'; import Identity from './identity.ee'; import Base from './base'; import appConfig from '../config/app'; +import { createSamlAuthProvider } from '../../test/factories/saml-auth-provider.ee.js'; +import { createRoleMapping } from '../../test/factories/role-mapping.js'; +import { createRole } from '../../test/factories/role.js'; describe('SamlAuthProvider model', () => { it('tableName should return correct name', () => { @@ -182,4 +185,47 @@ describe('SamlAuthProvider model', () => { expect(response).toBe(mockResponse); }); + + describe('updateRoleMappings', () => { + let samlAuthProvider; + + beforeEach(async () => { + samlAuthProvider = await createSamlAuthProvider(); + }); + + it('should remove all existing role mappings', async () => { + await createRoleMapping({ + samlAuthProviderId: samlAuthProvider.id, + remoteRoleName: 'Admin', + }); + + await createRoleMapping({ + samlAuthProviderId: samlAuthProvider.id, + remoteRoleName: 'User', + }); + + await samlAuthProvider.updateRoleMappings([]); + + const roleMappings = await samlAuthProvider.$relatedQuery('roleMappings'); + expect(roleMappings).toStrictEqual([]); + }); + + it('should return the updated role mappings when new ones are provided', async () => { + const adminRole = await createRole({ name: 'Admin' }); + const userRole = await createRole({ name: 'User' }); + + const newRoleMappings = [ + { remoteRoleName: 'Admin', roleId: adminRole.id }, + { remoteRoleName: 'User', roleId: userRole.id }, + ]; + + const result = await samlAuthProvider.updateRoleMappings(newRoleMappings); + + const refetchedRoleMappings = await samlAuthProvider.$relatedQuery( + 'roleMappings' + ); + + expect(result).toStrictEqual(refetchedRoleMappings); + }); + }); }); From 3346c1425551ff18824aec1d1131c2e21f01584f Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 28 Nov 2024 15:30:32 +0300 Subject: [PATCH 5/5] refactor: Remove redundant test case after removing transaction --- .../update-role-mappings.ee.test.js | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/update-role-mappings.ee.test.js b/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/update-role-mappings.ee.test.js index 523b17ac..a3c12c0f 100644 --- a/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/update-role-mappings.ee.test.js +++ b/packages/backend/src/controllers/api/v1/admin/saml-auth-providers/update-role-mappings.ee.test.js @@ -149,34 +149,4 @@ describe('PATCH /api/v1/admin/saml-auth-providers/:samlAuthProviderId/role-mappi .send(roleMappings) .expect(404); }); - - it('should not delete existing role mapping when error thrown', async () => { - const roleMappings = [ - { - roleId: userRole.id, - remoteRoleName: { - invalid: 'data', - }, - }, - ]; - - const roleMappingsBeforeRequest = await samlAuthProvider.$relatedQuery( - 'roleMappings' - ); - - await request(app) - .patch( - `/api/v1/admin/saml-auth-providers/${samlAuthProvider.id}/role-mappings` - ) - .set('Authorization', token) - .send(roleMappings) - .expect(422); - - const roleMappingsAfterRequest = await samlAuthProvider.$relatedQuery( - 'roleMappings' - ); - - expect(roleMappingsBeforeRequest).toStrictEqual(roleMappingsAfterRequest); - expect(roleMappingsAfterRequest.length).toBe(2); - }); });