From 912324885273b219d2cae07793e024c9e1de6cba Mon Sep 17 00:00:00 2001 From: Ben Hesseldieck Date: Fri, 15 Jul 2022 15:41:52 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=9B=A0=20refactor=20authAgent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cli/test/integration/credentials.test.ts | 74 ++++++++----------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/packages/cli/test/integration/credentials.test.ts b/packages/cli/test/integration/credentials.test.ts index a37bc51e36771..1b778c39e5897 100644 --- a/packages/cli/test/integration/credentials.test.ts +++ b/packages/cli/test/integration/credentials.test.ts @@ -1,9 +1,11 @@ import express from 'express'; import { UserSettings } from 'n8n-core'; +import type { SuperAgentTest } from 'supertest'; import { Db } from '../../src'; import { RESPONSE_ERROR_MESSAGES } from '../../src/constants'; import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity'; import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; import { randomCredentialPayload, randomName, randomString } from './shared/random'; import * as testDb from './shared/testDb'; import type { SaveCredentialFunction } from './shared/types'; @@ -16,6 +18,7 @@ let testDbName = ''; let globalOwnerRole: Role; let globalMemberRole: Role; let saveCredential: SaveCredentialFunction; +let authAgent: (user: User) => SuperAgentTest; beforeAll(async () => { app = await utils.initTestServer({ @@ -33,6 +36,8 @@ beforeAll(async () => { saveCredential = testDb.affixRoleToSaveCredential(credentialOwnerRole); + authAgent = utils.createAuthAgent(app); + utils.initTestLogger(); utils.initTestTelemetry(); }); @@ -48,10 +53,9 @@ afterAll(async () => { test('POST /credentials should create cred', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const payload = randomCredentialPayload(); - const response = await authOwnerAgent.post('/credentials').send(payload); + const response = await authAgent(ownerShell).post('/credentials').send(payload); expect(response.statusCode).toBe(200); @@ -80,7 +84,7 @@ test('POST /credentials should create cred', async () => { test('POST /credentials should fail with invalid inputs', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerAgent = authAgent(ownerShell); await Promise.all( INVALID_PAYLOADS.map(async (invalidPayload) => { @@ -95,9 +99,8 @@ test('POST /credentials should fail with missing encryption key', async () => { mock.mockRejectedValue(new Error(RESPONSE_ERROR_MESSAGES.NO_ENCRYPTION_KEY)); const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerAgent.post('/credentials').send(randomCredentialPayload()); + const response = await authAgent(ownerShell).post('/credentials').send(randomCredentialPayload()); expect(response.statusCode).toBe(500); @@ -106,7 +109,7 @@ test('POST /credentials should fail with missing encryption key', async () => { test('POST /credentials should ignore ID in payload', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerAgent = authAgent(ownerShell); const firstResponse = await authOwnerAgent .post('/credentials') @@ -123,10 +126,9 @@ test('POST /credentials should ignore ID in payload', async () => { test('DELETE /credentials/:id should delete owned cred for owner', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); - const response = await authOwnerAgent.delete(`/credentials/${savedCredential.id}`); + const response = await authAgent(ownerShell).delete(`/credentials/${savedCredential.id}`); expect(response.statusCode).toBe(200); expect(response.body).toEqual({ data: true }); @@ -142,11 +144,10 @@ test('DELETE /credentials/:id should delete owned cred for owner', async () => { test('DELETE /credentials/:id should delete non-owned cred for owner', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const member = await testDb.createUser({ globalRole: globalMemberRole }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: member }); - const response = await authOwnerAgent.delete(`/credentials/${savedCredential.id}`); + const response = await authAgent(ownerShell).delete(`/credentials/${savedCredential.id}`); expect(response.statusCode).toBe(200); expect(response.body).toEqual({ data: true }); @@ -162,10 +163,9 @@ test('DELETE /credentials/:id should delete non-owned cred for owner', async () test('DELETE /credentials/:id should delete owned cred for member', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: member }); - const response = await authMemberAgent.delete(`/credentials/${savedCredential.id}`); + const response = await authAgent(member).delete(`/credentials/${savedCredential.id}`); expect(response.statusCode).toBe(200); expect(response.body).toEqual({ data: true }); @@ -182,10 +182,9 @@ test('DELETE /credentials/:id should delete owned cred for member', async () => test('DELETE /credentials/:id should not delete non-owned cred for member', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); - const response = await authMemberAgent.delete(`/credentials/${savedCredential.id}`); + const response = await authAgent(member).delete(`/credentials/${savedCredential.id}`); expect(response.statusCode).toBe(404); @@ -200,20 +199,18 @@ test('DELETE /credentials/:id should not delete non-owned cred for member', asyn test('DELETE /credentials/:id should fail if cred not found', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerAgent.delete('/credentials/123'); + const response = await authAgent(ownerShell).delete('/credentials/123'); expect(response.statusCode).toBe(404); }); test('PATCH /credentials/:id should update owned cred for owner', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); const patchPayload = randomCredentialPayload(); - const response = await authOwnerAgent + const response = await authAgent(ownerShell) .patch(`/credentials/${savedCredential.id}`) .send(patchPayload); @@ -243,12 +240,11 @@ test('PATCH /credentials/:id should update owned cred for owner', async () => { test('PATCH /credentials/:id should update non-owned cred for owner', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const member = await testDb.createUser({ globalRole: globalMemberRole }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: member }); const patchPayload = randomCredentialPayload(); - const response = await authOwnerAgent + const response = await authAgent(ownerShell) .patch(`/credentials/${savedCredential.id}`) .send(patchPayload); @@ -278,11 +274,10 @@ test('PATCH /credentials/:id should update non-owned cred for owner', async () = test('PATCH /credentials/:id should update owned cred for member', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: member }); const patchPayload = randomCredentialPayload(); - const response = await authMemberAgent + const response = await authAgent(member) .patch(`/credentials/${savedCredential.id}`) .send(patchPayload); @@ -313,11 +308,10 @@ test('PATCH /credentials/:id should update owned cred for member', async () => { test('PATCH /credentials/:id should not update non-owned cred for member', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); const patchPayload = randomCredentialPayload(); - const response = await authMemberAgent + const response = await authAgent(member) .patch(`/credentials/${savedCredential.id}`) .send(patchPayload); @@ -330,7 +324,7 @@ test('PATCH /credentials/:id should not update non-owned cred for member', async test('PATCH /credentials/:id should fail with invalid inputs', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerAgent = authAgent(ownerShell); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); await Promise.all( @@ -346,9 +340,10 @@ test('PATCH /credentials/:id should fail with invalid inputs', async () => { test('PATCH /credentials/:id should fail if cred not found', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerAgent.patch('/credentials/123').send(randomCredentialPayload()); + const response = await authAgent(ownerShell) + .patch('/credentials/123') + .send(randomCredentialPayload()); expect(response.statusCode).toBe(404); }); @@ -358,9 +353,8 @@ test('PATCH /credentials/:id should fail with missing encryption key', async () mock.mockRejectedValue(new Error(RESPONSE_ERROR_MESSAGES.NO_ENCRYPTION_KEY)); const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerAgent.post('/credentials').send(randomCredentialPayload()); + const response = await authAgent(ownerShell).post('/credentials').send(randomCredentialPayload()); expect(response.statusCode).toBe(500); @@ -369,7 +363,6 @@ test('PATCH /credentials/:id should fail with missing encryption key', async () test('GET /credentials should retrieve all creds for owner', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); for (let i = 0; i < 3; i++) { await saveCredential(randomCredentialPayload(), { user: ownerShell }); @@ -379,7 +372,7 @@ test('GET /credentials should retrieve all creds for owner', async () => { await saveCredential(randomCredentialPayload(), { user: member }); - const response = await authOwnerAgent.get('/credentials'); + const response = await authAgent(ownerShell).get('/credentials'); expect(response.statusCode).toBe(200); expect(response.body.data.length).toBe(4); // 3 owner + 1 member @@ -398,13 +391,12 @@ test('GET /credentials should retrieve all creds for owner', async () => { test('GET /credentials should retrieve owned creds for member', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); for (let i = 0; i < 3; i++) { await saveCredential(randomCredentialPayload(), { user: member }); } - const response = await authMemberAgent.get('/credentials'); + const response = await authAgent(member).get('/credentials'); expect(response.statusCode).toBe(200); expect(response.body.data.length).toBe(3); @@ -424,13 +416,12 @@ test('GET /credentials should retrieve owned creds for member', async () => { test('GET /credentials should not retrieve non-owned creds for member', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); for (let i = 0; i < 3; i++) { await saveCredential(randomCredentialPayload(), { user: ownerShell }); } - const response = await authMemberAgent.get('/credentials'); + const response = await authAgent(member).get('/credentials'); expect(response.statusCode).toBe(200); expect(response.body.data.length).toBe(0); // owner's creds not returned @@ -438,7 +429,7 @@ test('GET /credentials should not retrieve non-owned creds for member', async () test('GET /credentials/:id should retrieve owned cred for owner', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerAgent = authAgent(ownerShell); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); const firstResponse = await authOwnerAgent.get(`/credentials/${savedCredential.id}`); @@ -463,7 +454,7 @@ test('GET /credentials/:id should retrieve owned cred for owner', async () => { test('GET /credentials/:id should retrieve owned cred for member', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); + const authMemberAgent = authAgent(member); const savedCredential = await saveCredential(randomCredentialPayload(), { user: member }); const firstResponse = await authMemberAgent.get(`/credentials/${savedCredential.id}`); @@ -490,10 +481,9 @@ test('GET /credentials/:id should retrieve owned cred for member', async () => { test('GET /credentials/:id should not retrieve non-owned cred for member', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); - const response = await authMemberAgent.get(`/credentials/${savedCredential.id}`); + const response = await authAgent(member).get(`/credentials/${savedCredential.id}`); expect(response.statusCode).toBe(404); expect(response.body.data).toBeUndefined(); // owner's cred not returned @@ -501,13 +491,12 @@ test('GET /credentials/:id should not retrieve non-owned cred for member', async test('GET /credentials/:id should fail with missing encryption key', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const savedCredential = await saveCredential(randomCredentialPayload(), { user: ownerShell }); const mock = jest.spyOn(UserSettings, 'getEncryptionKey'); mock.mockRejectedValue(new Error(RESPONSE_ERROR_MESSAGES.NO_ENCRYPTION_KEY)); - const response = await authOwnerAgent + const response = await authAgent(ownerShell) .get(`/credentials/${savedCredential.id}`) .query({ includeData: true }); @@ -518,9 +507,8 @@ test('GET /credentials/:id should fail with missing encryption key', async () => test('GET /credentials/:id should return 404 if cred not found', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authMemberAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authMemberAgent.get('/credentials/789'); + const response = await authAgent(ownerShell).get('/credentials/789'); expect(response.statusCode).toBe(404); }); From 006fdc5a7a146bef4d914f96dc53bd750c18aecb Mon Sep 17 00:00:00 2001 From: Ben Hesseldieck Date: Fri, 15 Jul 2022 16:00:28 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=9B=A0=20refactor=20authAgent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cli/test/integration/auth.api.test.ts | 34 +++++------ packages/cli/test/integration/auth.mw.test.ts | 14 +++-- packages/cli/test/integration/me.api.test.ts | 60 +++++++++---------- .../cli/test/integration/shared/constants.ts | 1 - 4 files changed, 53 insertions(+), 56 deletions(-) diff --git a/packages/cli/test/integration/auth.api.test.ts b/packages/cli/test/integration/auth.api.test.ts index 9ae08f60c0c26..95c4cd2e94635 100644 --- a/packages/cli/test/integration/auth.api.test.ts +++ b/packages/cli/test/integration/auth.api.test.ts @@ -1,14 +1,15 @@ import express = require('express'); +import type { SuperAgentTest } from 'supertest'; import validator from 'validator'; - -import config = require('../../config'); -import * as utils from './shared/utils'; -import { LOGGED_OUT_RESPONSE_BODY } from './shared/constants'; +import config from '../../config'; import { Db } from '../../src'; +import { AUTH_COOKIE_NAME } from '../../src/constants'; import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; +import { LOGGED_OUT_RESPONSE_BODY } from './shared/constants'; import { randomValidPassword } from './shared/random'; import * as testDb from './shared/testDb'; -import { AUTH_COOKIE_NAME } from '../../src/constants'; +import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -16,6 +17,7 @@ let app: express.Application; let testDbName = ''; let globalOwnerRole: Role; let globalMemberRole: Role; +let authAgent: (user: User) => SuperAgentTest; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['auth'], applyAuth: true }); @@ -24,6 +26,9 @@ beforeAll(async () => { globalOwnerRole = await testDb.getGlobalOwnerRole(); globalMemberRole = await testDb.getGlobalMemberRole(); + + authAgent = utils.createAuthAgent(app); + utils.initTestLogger(); utils.initTestTelemetry(); }); @@ -109,9 +114,7 @@ test('GET /login should return cookie if UM is disabled', async () => { { value: JSON.stringify(false) }, ); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - - const response = await authOwnerShellAgent.get('/login'); + const response = await authAgent(ownerShell).get('/login'); expect(response.statusCode).toBe(200); @@ -133,9 +136,8 @@ test('GET /login should return 401 Unauthorized if invalid cookie', async () => test('GET /login should return logged-in owner shell', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authMemberAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authMemberAgent.get('/login'); + const response = await authAgent(ownerShell).get('/login'); expect(response.statusCode).toBe(200); @@ -170,9 +172,8 @@ test('GET /login should return logged-in owner shell', async () => { test('GET /login should return logged-in member shell', async () => { const memberShell = await testDb.createUserShell(globalMemberRole); - const authMemberAgent = utils.createAgent(app, { auth: true, user: memberShell }); - const response = await authMemberAgent.get('/login'); + const response = await authAgent(memberShell).get('/login'); expect(response.statusCode).toBe(200); @@ -207,9 +208,8 @@ test('GET /login should return logged-in member shell', async () => { test('GET /login should return logged-in owner', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const response = await authOwnerAgent.get('/login'); + const response = await authAgent(owner).get('/login'); expect(response.statusCode).toBe(200); @@ -244,9 +244,8 @@ test('GET /login should return logged-in owner', async () => { test('GET /login should return logged-in member', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const response = await authMemberAgent.get('/login'); + const response = await authAgent(member).get('/login'); expect(response.statusCode).toBe(200); @@ -281,9 +280,8 @@ test('GET /login should return logged-in member', async () => { test('POST /logout should log user out', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const response = await authOwnerAgent.post('/logout'); + const response = await authAgent(owner).post('/logout'); expect(response.statusCode).toBe(200); expect(response.body).toEqual(LOGGED_OUT_RESPONSE_BODY); diff --git a/packages/cli/test/integration/auth.mw.test.ts b/packages/cli/test/integration/auth.mw.test.ts index 6652c23b26455..458e5c2cee031 100644 --- a/packages/cli/test/integration/auth.mw.test.ts +++ b/packages/cli/test/integration/auth.mw.test.ts @@ -1,20 +1,23 @@ import express from 'express'; +import type { SuperAgentTest } from 'supertest'; import request from 'supertest'; +import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; import { REST_PATH_SEGMENT, - ROUTES_REQUIRING_AUTHORIZATION, ROUTES_REQUIRING_AUTHENTICATION, + ROUTES_REQUIRING_AUTHORIZATION, } from './shared/constants'; -import * as utils from './shared/utils'; import * as testDb from './shared/testDb'; -import type { Role } from '../../src/databases/entities/Role'; +import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; let globalMemberRole: Role; +let authAgent: (user: User) => SuperAgentTest; beforeAll(async () => { app = await utils.initTestServer({ @@ -26,6 +29,8 @@ beforeAll(async () => { globalMemberRole = await testDb.getGlobalMemberRole(); + authAgent = utils.createAuthAgent(app); + utils.initTestLogger(); utils.initTestTelemetry(); }); @@ -49,8 +54,7 @@ ROUTES_REQUIRING_AUTHORIZATION.forEach(async (route) => { test(`${route} should return 403 Forbidden for member`, async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const response = await authMemberAgent[method](endpoint); + const response = await authAgent(member)[method](endpoint); expect(response.statusCode).toBe(403); }); diff --git a/packages/cli/test/integration/me.api.test.ts b/packages/cli/test/integration/me.api.test.ts index 37371953723a5..fbab3780b8893 100644 --- a/packages/cli/test/integration/me.api.test.ts +++ b/packages/cli/test/integration/me.api.test.ts @@ -1,12 +1,13 @@ import express from 'express'; -import validator from 'validator'; +import type { SuperAgentTest } from 'supertest'; import { IsNull } from 'typeorm'; +import validator from 'validator'; import config from '../../config'; -import * as utils from './shared/utils'; -import { SUCCESS_RESPONSE_BODY } from './shared/constants'; import { Db } from '../../src'; import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; +import { SUCCESS_RESPONSE_BODY } from './shared/constants'; import { randomApiKey, randomEmail, @@ -15,6 +16,7 @@ import { randomValidPassword, } from './shared/random'; import * as testDb from './shared/testDb'; +import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -22,6 +24,7 @@ let app: express.Application; let testDbName = ''; let globalOwnerRole: Role; let globalMemberRole: Role; +let authAgent: (user: User) => SuperAgentTest; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['me'], applyAuth: true }); @@ -30,6 +33,9 @@ beforeAll(async () => { globalOwnerRole = await testDb.getGlobalOwnerRole(); globalMemberRole = await testDb.getGlobalMemberRole(); + + authAgent = utils.createAuthAgent(app); + utils.initTestLogger(); utils.initTestTelemetry(); }); @@ -45,9 +51,8 @@ describe('Owner shell', () => { test('GET /me should return sanitized owner shell', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerShellAgent.get('/me'); + const response = await authAgent(ownerShell).get('/me'); expect(response.statusCode).toBe(200); @@ -79,7 +84,7 @@ describe('Owner shell', () => { test('PATCH /me should succeed with valid inputs', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerShellAgent = authAgent(ownerShell); for (const validPayload of VALID_PATCH_ME_PAYLOADS) { const response = await authOwnerShellAgent.patch('/me').send(validPayload); @@ -121,7 +126,7 @@ describe('Owner shell', () => { test('PATCH /me should fail with invalid inputs', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerShellAgent = authAgent(ownerShell); for (const invalidPayload of INVALID_PATCH_ME_PAYLOADS) { const response = await authOwnerShellAgent.patch('/me').send(invalidPayload); @@ -136,7 +141,7 @@ describe('Owner shell', () => { test('PATCH /me/password should fail for shell', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerShellAgent = authAgent(ownerShell); const validPasswordPayload = { currentPassword: randomValidPassword(), @@ -168,7 +173,7 @@ describe('Owner shell', () => { test('POST /me/survey should succeed with valid inputs', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerShellAgent = authAgent(ownerShell); const validPayloads = [SURVEY, {}]; @@ -188,9 +193,8 @@ describe('Owner shell', () => { test('POST /me/api-key should create an api key', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerShellAgent.post('/me/api-key'); + const response = await authAgent(ownerShell).post('/me/api-key'); expect(response.statusCode).toBe(200); expect(response.body.data.apiKey).toBeDefined(); @@ -206,9 +210,8 @@ describe('Owner shell', () => { test('GET /me/api-key should fetch the api key', async () => { let ownerShell = await testDb.createUserShell(globalOwnerRole); ownerShell = await testDb.addApiKey(ownerShell); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerShellAgent.get('/me/api-key'); + const response = await authAgent(ownerShell).get('/me/api-key'); expect(response.statusCode).toBe(200); expect(response.body.data.apiKey).toEqual(ownerShell.apiKey); @@ -217,9 +220,8 @@ describe('Owner shell', () => { test('DELETE /me/api-key should fetch the api key', async () => { let ownerShell = await testDb.createUserShell(globalOwnerRole); ownerShell = await testDb.addApiKey(ownerShell); - const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerShellAgent.delete('/me/api-key'); + const response = await authAgent(ownerShell).delete('/me/api-key'); expect(response.statusCode).toBe(200); @@ -247,9 +249,8 @@ describe('Member', () => { test('GET /me should return sanitized member', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const response = await authMemberAgent.get('/me'); + const response = await authAgent(member).get('/me'); expect(response.statusCode).toBe(200); @@ -281,7 +282,7 @@ describe('Member', () => { test('PATCH /me should succeed with valid inputs', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); + const authMemberAgent = authAgent(member); for (const validPayload of VALID_PATCH_ME_PAYLOADS) { const response = await authMemberAgent.patch('/me').send(validPayload); @@ -323,7 +324,7 @@ describe('Member', () => { test('PATCH /me should fail with invalid inputs', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); + const authMemberAgent = authAgent(member); for (const invalidPayload of INVALID_PATCH_ME_PAYLOADS) { const response = await authMemberAgent.patch('/me').send(invalidPayload); @@ -342,14 +343,13 @@ describe('Member', () => { password: memberPassword, globalRole: globalMemberRole, }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const validPayload = { currentPassword: memberPassword, newPassword: randomValidPassword(), }; - const response = await authMemberAgent.patch('/me/password').send(validPayload); + const response = await authAgent(member).patch('/me/password').send(validPayload); expect(response.statusCode).toBe(200); expect(response.body).toEqual(SUCCESS_RESPONSE_BODY); @@ -360,7 +360,7 @@ describe('Member', () => { test('PATCH /me/password should fail with invalid inputs', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); + const authMemberAgent = authAgent(member); for (const payload of INVALID_PASSWORD_PAYLOADS) { const response = await authMemberAgent.patch('/me/password').send(payload); @@ -379,7 +379,7 @@ describe('Member', () => { test('POST /me/survey should succeed with valid inputs', async () => { const member = await testDb.createUser({ globalRole: globalMemberRole }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); + const authMemberAgent = authAgent(member); const validPayloads = [SURVEY, {}]; @@ -399,9 +399,8 @@ describe('Member', () => { globalRole: globalMemberRole, apiKey: randomApiKey(), }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const response = await authMemberAgent.post('/me/api-key'); + const response = await authAgent(member).post('/me/api-key'); expect(response.statusCode).toBe(200); expect(response.body.data.apiKey).toBeDefined(); @@ -417,9 +416,8 @@ describe('Member', () => { globalRole: globalMemberRole, apiKey: randomApiKey(), }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const response = await authMemberAgent.get('/me/api-key'); + const response = await authAgent(member).get('/me/api-key'); expect(response.statusCode).toBe(200); expect(response.body.data.apiKey).toEqual(member.apiKey); @@ -430,9 +428,8 @@ describe('Member', () => { globalRole: globalMemberRole, apiKey: randomApiKey(), }); - const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const response = await authMemberAgent.delete('/me/api-key'); + const response = await authAgent(member).delete('/me/api-key'); expect(response.statusCode).toBe(200); @@ -453,9 +450,8 @@ describe('Owner', () => { test('GET /me should return sanitized owner', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const response = await authOwnerAgent.get('/me'); + const response = await authAgent(owner).get('/me'); expect(response.statusCode).toBe(200); @@ -487,7 +483,7 @@ describe('Owner', () => { test('PATCH /me should succeed with valid inputs', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const authOwnerAgent = authAgent(owner); for (const validPayload of VALID_PATCH_ME_PAYLOADS) { const response = await authOwnerAgent.patch('/me').send(validPayload); diff --git a/packages/cli/test/integration/shared/constants.ts b/packages/cli/test/integration/shared/constants.ts index d68ef00e1e89c..4a5e7a4b8f67b 100644 --- a/packages/cli/test/integration/shared/constants.ts +++ b/packages/cli/test/integration/shared/constants.ts @@ -58,7 +58,6 @@ export const MAPPING_TABLES_TO_CLEAR: Record = { Tag: ['workflows_tags'], }; - /** * Name of the connection used for creating and dropping a Postgres DB * for each suite test run. From ca4a307182459ac2ddc4f693529142ecee735dbb Mon Sep 17 00:00:00 2001 From: Ben Hesseldieck Date: Fri, 15 Jul 2022 16:07:38 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=9B=A0=20refactor=20authAgent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cli/test/integration/owner.api.test.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/cli/test/integration/owner.api.test.ts b/packages/cli/test/integration/owner.api.test.ts index c5899fce338b8..245cc4dda091b 100644 --- a/packages/cli/test/integration/owner.api.test.ts +++ b/packages/cli/test/integration/owner.api.test.ts @@ -1,23 +1,26 @@ import express from 'express'; +import type { SuperAgentTest } from 'supertest'; import validator from 'validator'; -import * as utils from './shared/utils'; -import * as testDb from './shared/testDb'; -import { Db } from '../../src'; import config from '../../config'; +import { Db } from '../../src'; +import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; import { randomEmail, + randomInvalidPassword, randomName, randomValidPassword, - randomInvalidPassword, } from './shared/random'; -import type { Role } from '../../src/databases/entities/Role'; +import * as testDb from './shared/testDb'; +import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; let globalOwnerRole: Role; +let authAgent: (user: User) => SuperAgentTest; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['owner'], applyAuth: true }); @@ -25,6 +28,9 @@ beforeAll(async () => { testDbName = initResult.testDbName; globalOwnerRole = await testDb.getGlobalOwnerRole(); + + authAgent = utils.createAuthAgent(app); + utils.initTestLogger(); utils.initTestTelemetry(); }); @@ -43,7 +49,6 @@ afterAll(async () => { test('POST /owner should create owner and enable isInstanceOwnerSetUp', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const newOwnerData = { email: randomEmail(), @@ -52,7 +57,7 @@ test('POST /owner should create owner and enable isInstanceOwnerSetUp', async () password: randomValidPassword(), }; - const response = await authOwnerAgent.post('/owner').send(newOwnerData); + const response = await authAgent(ownerShell).post('/owner').send(newOwnerData); expect(response.statusCode).toBe(200); @@ -96,7 +101,6 @@ test('POST /owner should create owner and enable isInstanceOwnerSetUp', async () test('POST /owner should create owner with lowercased email', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const newOwnerData = { email: randomEmail().toUpperCase(), @@ -105,7 +109,7 @@ test('POST /owner should create owner with lowercased email', async () => { password: randomValidPassword(), }; - const response = await authOwnerAgent.post('/owner').send(newOwnerData); + const response = await authAgent(ownerShell).post('/owner').send(newOwnerData); expect(response.statusCode).toBe(200); @@ -120,7 +124,7 @@ test('POST /owner should create owner with lowercased email', async () => { test('POST /owner should fail with invalid inputs', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const authOwnerAgent = authAgent(ownerShell); await Promise.all( INVALID_POST_OWNER_PAYLOADS.map(async (invalidPayload) => { @@ -132,9 +136,8 @@ test('POST /owner should fail with invalid inputs', async () => { test('POST /owner/skip-setup should persist skipping setup to the DB', async () => { const ownerShell = await testDb.createUserShell(globalOwnerRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerAgent.post('/owner/skip-setup').send(); + const response = await authAgent(ownerShell).post('/owner/skip-setup').send(); expect(response.statusCode).toBe(200); From 1916b2c0d63d9d98a12522da2b3d84a1ab68cc74 Mon Sep 17 00:00:00 2001 From: Ben Hesseldieck Date: Fri, 15 Jul 2022 16:21:33 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=9B=A0=20refactor=20authAgent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cli/test/integration/users.api.test.ts | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/packages/cli/test/integration/users.api.test.ts b/packages/cli/test/integration/users.api.test.ts index 77f7cd36bce8b..6279d185d7959 100644 --- a/packages/cli/test/integration/users.api.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -1,23 +1,24 @@ import express from 'express'; -import validator from 'validator'; import { v4 as uuid } from 'uuid'; +import validator from 'validator'; -import { Db } from '../../src'; +import type { SuperAgentTest } from 'supertest'; import config from '../../config'; +import { Db } from '../../src'; +import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity'; +import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; +import { WorkflowEntity } from '../../src/databases/entities/WorkflowEntity'; +import { compareHash } from '../../src/UserManagement/UserManagementHelper'; import { SUCCESS_RESPONSE_BODY } from './shared/constants'; import { randomEmail, - randomValidPassword, - randomName, randomInvalidPassword, + randomName, + randomValidPassword, } from './shared/random'; -import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity'; -import { WorkflowEntity } from '../../src/databases/entities/WorkflowEntity'; -import type { Role } from '../../src/databases/entities/Role'; -import type { User } from '../../src/databases/entities/User'; -import * as utils from './shared/utils'; import * as testDb from './shared/testDb'; -import { compareHash } from '../../src/UserManagement/UserManagementHelper'; +import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); jest.mock('../../src/UserManagement/email/NodeMailer'); @@ -28,6 +29,7 @@ let globalMemberRole: Role; let globalOwnerRole: Role; let workflowOwnerRole: Role; let credentialOwnerRole: Role; +let authAgent: (user: User) => SuperAgentTest; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['users'], applyAuth: true }); @@ -46,6 +48,8 @@ beforeAll(async () => { workflowOwnerRole = fetchedWorkflowOwnerRole; credentialOwnerRole = fetchedCredentialOwnerRole; + authAgent = utils.createAuthAgent(app); + utils.initTestTelemetry(); utils.initTestLogger(); }); @@ -69,11 +73,10 @@ afterAll(async () => { test('GET /users should return all users', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); await testDb.createUser({ globalRole: globalMemberRole }); - const response = await authOwnerAgent.get('/users'); + const response = await authAgent(owner).get('/users'); expect(response.statusCode).toBe(200); expect(response.body.data.length).toBe(2); @@ -109,7 +112,6 @@ test('GET /users should return all users', async () => { test('DELETE /users/:id should delete the user', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); const userToDelete = await testDb.createUser({ globalRole: globalMemberRole }); @@ -147,7 +149,7 @@ test('DELETE /users/:id should delete the user', async () => { credentials: savedCredential, }); - const response = await authOwnerAgent.delete(`/users/${userToDelete.id}`); + const response = await authAgent(owner).delete(`/users/${userToDelete.id}`); expect(response.statusCode).toBe(200); expect(response.body).toEqual(SUCCESS_RESPONSE_BODY); @@ -178,9 +180,8 @@ test('DELETE /users/:id should delete the user', async () => { test('DELETE /users/:id should fail to delete self', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const response = await authOwnerAgent.delete(`/users/${owner.id}`); + const response = await authAgent(owner).delete(`/users/${owner.id}`); expect(response.statusCode).toBe(400); @@ -190,11 +191,10 @@ test('DELETE /users/:id should fail to delete self', async () => { test('DELETE /users/:id should fail if user to delete is transferee', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); const { id: idToDelete } = await testDb.createUser({ globalRole: globalMemberRole }); - const response = await authOwnerAgent.delete(`/users/${idToDelete}`).query({ + const response = await authAgent(owner).delete(`/users/${idToDelete}`).query({ transferId: idToDelete, }); @@ -206,7 +206,6 @@ test('DELETE /users/:id should fail if user to delete is transferee', async () = test('DELETE /users/:id with transferId should perform transfer', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); const userToDelete = await Db.collections.User.save({ id: uuid(), @@ -253,7 +252,7 @@ test('DELETE /users/:id with transferId should perform transfer', async () => { credentials: savedCredential, }); - const response = await authOwnerAgent.delete(`/users/${userToDelete.id}`).query({ + const response = await authAgent(owner).delete(`/users/${userToDelete.id}`).query({ transferId: owner.id, }); @@ -278,11 +277,10 @@ test('DELETE /users/:id with transferId should perform transfer', async () => { test('GET /resolve-signup-token should validate invite token', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); const memberShell = await testDb.createUserShell(globalMemberRole); - const response = await authOwnerAgent + const response = await authAgent(owner) .get('/resolve-signup-token') .query({ inviterId: owner.id }) .query({ inviteeId: memberShell.id }); @@ -300,7 +298,7 @@ test('GET /resolve-signup-token should validate invite token', async () => { test('GET /resolve-signup-token should fail with invalid inputs', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const authOwnerAgent = authAgent(owner); const { id: inviteeId } = await testDb.createUser({ globalRole: globalMemberRole }); @@ -467,20 +465,22 @@ test('POST /users/:id should fail with already accepted invite', async () => { test('POST /users should fail if emailing is not set up', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const response = await authOwnerAgent.post('/users').send([{ email: randomEmail() }]); + const response = await authAgent(owner) + .post('/users') + .send([{ email: randomEmail() }]); expect(response.statusCode).toBe(500); }); test('POST /users should fail if user management is disabled', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); config.set('userManagement.disabled', true); - const response = await authOwnerAgent.post('/users').send([{ email: randomEmail() }]); + const response = await authAgent(owner) + .post('/users') + .send([{ email: randomEmail() }]); expect(response.statusCode).toBe(500); }); @@ -489,7 +489,6 @@ test('POST /users should email invites and create user shells but ignore existin const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const member = await testDb.createUser({ globalRole: globalMemberRole }); const memberShell = await testDb.createUserShell(globalMemberRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); config.set('userManagement.emails.mode', 'smtp'); @@ -497,7 +496,7 @@ test('POST /users should email invites and create user shells but ignore existin const payload = testEmails.map((e) => ({ email: e })); - const response = await authOwnerAgent.post('/users').send(payload); + const response = await authAgent(owner).post('/users').send(payload); expect(response.statusCode).toBe(200); @@ -530,7 +529,7 @@ test('POST /users should email invites and create user shells but ignore existin test('POST /users should fail with invalid inputs', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const authOwnerAgent = authAgent(owner); config.set('userManagement.emails.mode', 'smtp'); @@ -555,11 +554,10 @@ test('POST /users should fail with invalid inputs', async () => { test('POST /users should ignore an empty payload', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); config.set('userManagement.emails.mode', 'smtp'); - const response = await authOwnerAgent.post('/users').send([]); + const response = await authAgent(owner).post('/users').send([]); const { data } = response.body; From f96a0715a617cf693c738e89b2d9cfb27fcd99b7 Mon Sep 17 00:00:00 2001 From: Ben Hesseldieck Date: Fri, 15 Jul 2022 16:24:04 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=91=95=20fix=20ts=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cli/test/integration/credentials.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/cli/test/integration/credentials.test.ts b/packages/cli/test/integration/credentials.test.ts index 1b778c39e5897..8327c0c1eac42 100644 --- a/packages/cli/test/integration/credentials.test.ts +++ b/packages/cli/test/integration/credentials.test.ts @@ -63,14 +63,14 @@ test('POST /credentials should create cred', async () => { expect(name).toBe(payload.name); expect(type).toBe(payload.type); - expect(nodesAccess[0].nodeType).toBe(payload.nodesAccess[0].nodeType); + expect(nodesAccess[0].nodeType).toBe(payload.nodesAccess![0].nodeType); expect(encryptedData).not.toBe(payload.data); const credential = await Db.collections.Credentials.findOneOrFail(id); expect(credential.name).toBe(payload.name); expect(credential.type).toBe(payload.type); - expect(credential.nodesAccess[0].nodeType).toBe(payload.nodesAccess[0].nodeType); + expect(credential.nodesAccess[0].nodeType).toBe(payload.nodesAccess![0].nodeType); expect(credential.data).not.toBe(payload.data); const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ @@ -220,14 +220,14 @@ test('PATCH /credentials/:id should update owned cred for owner', async () => { expect(name).toBe(patchPayload.name); expect(type).toBe(patchPayload.type); - expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); + expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess![0].nodeType); expect(encryptedData).not.toBe(patchPayload.data); const credential = await Db.collections.Credentials.findOneOrFail(id); expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); - expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); + expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess![0].nodeType); expect(credential.data).not.toBe(patchPayload.data); const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ @@ -254,14 +254,14 @@ test('PATCH /credentials/:id should update non-owned cred for owner', async () = expect(name).toBe(patchPayload.name); expect(type).toBe(patchPayload.type); - expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); + expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess![0].nodeType); expect(encryptedData).not.toBe(patchPayload.data); const credential = await Db.collections.Credentials.findOneOrFail(id); expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); - expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); + expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess![0].nodeType); expect(credential.data).not.toBe(patchPayload.data); const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ @@ -287,14 +287,14 @@ test('PATCH /credentials/:id should update owned cred for member', async () => { expect(name).toBe(patchPayload.name); expect(type).toBe(patchPayload.type); - expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); + expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess![0].nodeType); expect(encryptedData).not.toBe(patchPayload.data); const credential = await Db.collections.Credentials.findOneOrFail(id); expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); - expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); + expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess![0].nodeType); expect(credential.data).not.toBe(patchPayload.data); const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ From 94c4e3165d6e7e680a650a51560ea839222b5a18 Mon Sep 17 00:00:00 2001 From: Ben Hesseldieck Date: Wed, 20 Jul 2022 16:49:01 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=90=98=20add=20migration=20for=20mysq?= =?UTF-8?q?l=20and=20postgres=20+=20add=20AuthAgent=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...57062385367-CreateCredentialsEditorRole.ts | 23 +++++++++++++++++++ .../src/databases/migrations/mysqldb/index.ts | 6 +++-- ...57062385367-CreateCredentialsEditorRole.ts | 23 +++++++++++++++++++ .../databases/migrations/postgresdb/index.ts | 4 +++- .../cli/test/integration/auth.api.test.ts | 5 ++-- packages/cli/test/integration/auth.mw.test.ts | 5 ++-- .../test/integration/credentials.ee.test.ts | 10 ++++---- .../cli/test/integration/credentials.test.ts | 6 ++--- packages/cli/test/integration/me.api.test.ts | 5 ++-- .../cli/test/integration/owner.api.test.ts | 5 ++-- .../cli/test/integration/shared/types.d.ts | 3 +++ .../cli/test/integration/users.api.test.ts | 4 ++-- 12 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 packages/cli/src/databases/migrations/mysqldb/1657062385367-CreateCredentialsEditorRole.ts create mode 100644 packages/cli/src/databases/migrations/postgresdb/1657062385367-CreateCredentialsEditorRole.ts diff --git a/packages/cli/src/databases/migrations/mysqldb/1657062385367-CreateCredentialsEditorRole.ts b/packages/cli/src/databases/migrations/mysqldb/1657062385367-CreateCredentialsEditorRole.ts new file mode 100644 index 0000000000000..d92f3529b899a --- /dev/null +++ b/packages/cli/src/databases/migrations/mysqldb/1657062385367-CreateCredentialsEditorRole.ts @@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; +import config from '../../../../config'; + +export class CreateCredentialsEditorRole1657062385367 implements MigrationInterface { + name = 'CreateCredentialsEditorRole1657062385367'; + + public async up(queryRunner: QueryRunner): Promise { + const tablePrefix = config.getEnv('database.tablePrefix'); + + await queryRunner.query(` + INSERT INTO ${tablePrefix}role (name, scope) + VALUES ("editor", "credential"); + `); + } + + public async down(queryRunner: QueryRunner): Promise { + const tablePrefix = config.getEnv('database.tablePrefix'); + + await queryRunner.query(` + DELETE FROM ${tablePrefix}role WHERE name='editor' AND scope='credential'; + `); + } +} diff --git a/packages/cli/src/databases/migrations/mysqldb/index.ts b/packages/cli/src/databases/migrations/mysqldb/index.ts index 31993d41cd603..72e10b0ddf9c4 100644 --- a/packages/cli/src/databases/migrations/mysqldb/index.ts +++ b/packages/cli/src/databases/migrations/mysqldb/index.ts @@ -1,11 +1,11 @@ import { InitialMigration1588157391238 } from './1588157391238-InitialMigration'; import { WebhookModel1592447867632 } from './1592447867632-WebhookModel'; import { CreateIndexStoppedAt1594902918301 } from './1594902918301-CreateIndexStoppedAt'; -import { AddWebhookId1611149998770 } from './1611149998770-AddWebhookId'; import { MakeStoppedAtNullable1607431743767 } from './1607431743767-MakeStoppedAtNullable'; +import { AddWebhookId1611149998770 } from './1611149998770-AddWebhookId'; import { ChangeDataSize1615306975123 } from './1615306975123-ChangeDataSize'; -import { ChangeCredentialDataSize1620729500000 } from './1620729500000-ChangeCredentialDataSize'; import { CreateTagEntity1617268711084 } from './1617268711084-CreateTagEntity'; +import { ChangeCredentialDataSize1620729500000 } from './1620729500000-ChangeCredentialDataSize'; import { UniqueWorkflowNames1620826335440 } from './1620826335440-UniqueWorkflowNames'; import { CertifyCorrectCollation1623936588000 } from './1623936588000-CertifyCorrectCollation'; import { AddWaitColumnId1626183952959 } from './1626183952959-AddWaitColumn'; @@ -15,6 +15,7 @@ import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserMan import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail'; import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings'; import { AddAPIKeyColumn1652905585850 } from './1652905585850-AddAPIKeyColumn'; +import { CreateCredentialsEditorRole1657062385367 } from './1657062385367-CreateCredentialsEditorRole'; export const mysqlMigrations = [ InitialMigration1588157391238, @@ -34,4 +35,5 @@ export const mysqlMigrations = [ LowerCaseUserEmail1648740597343, AddUserSettings1652367743993, AddAPIKeyColumn1652905585850, + CreateCredentialsEditorRole1657062385367, ]; diff --git a/packages/cli/src/databases/migrations/postgresdb/1657062385367-CreateCredentialsEditorRole.ts b/packages/cli/src/databases/migrations/postgresdb/1657062385367-CreateCredentialsEditorRole.ts new file mode 100644 index 0000000000000..b90dfdfc43afe --- /dev/null +++ b/packages/cli/src/databases/migrations/postgresdb/1657062385367-CreateCredentialsEditorRole.ts @@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; +import config from '../../../../config'; + +export class CreateCredentialsEditorRole1657062385367 implements MigrationInterface { + name = 'CreateCredentialsEditorRole1657062385367'; + + public async up(queryRunner: QueryRunner): Promise { + const tablePrefix = config.getEnv('database.tablePrefix'); + + await queryRunner.query(` + INSERT INTO ${tablePrefix}role (name, scope) + VALUES ('editor', 'credential'); + `); + } + + public async down(queryRunner: QueryRunner): Promise { + const tablePrefix = config.getEnv('database.tablePrefix'); + + await queryRunner.query(` + DELETE FROM ${tablePrefix}role WHERE name='editor' AND scope='credential'; + `); + } +} diff --git a/packages/cli/src/databases/migrations/postgresdb/index.ts b/packages/cli/src/databases/migrations/postgresdb/index.ts index 30cc17b873cd8..6de2647bcb0ba 100644 --- a/packages/cli/src/databases/migrations/postgresdb/index.ts +++ b/packages/cli/src/databases/migrations/postgresdb/index.ts @@ -1,8 +1,8 @@ import { InitialMigration1587669153312 } from './1587669153312-InitialMigration'; import { WebhookModel1589476000887 } from './1589476000887-WebhookModel'; import { CreateIndexStoppedAt1594828256133 } from './1594828256133-CreateIndexStoppedAt'; -import { AddWebhookId1611144599516 } from './1611144599516-AddWebhookId'; import { MakeStoppedAtNullable1607431743768 } from './1607431743768-MakeStoppedAtNullable'; +import { AddWebhookId1611144599516 } from './1611144599516-AddWebhookId'; import { CreateTagEntity1617270242566 } from './1617270242566-CreateTagEntity'; import { UniqueWorkflowNames1620824779533 } from './1620824779533-UniqueWorkflowNames'; import { AddwaitTill1626176912946 } from './1626176912946-AddwaitTill'; @@ -13,6 +13,7 @@ import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserMan import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail'; import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings'; import { AddAPIKeyColumn1652905585850 } from './1652905585850-AddAPIKeyColumn'; +import { CreateCredentialsEditorRole1657062385367 } from './1657062385367-CreateCredentialsEditorRole'; export const postgresMigrations = [ InitialMigration1587669153312, @@ -30,4 +31,5 @@ export const postgresMigrations = [ LowerCaseUserEmail1648740597343, AddUserSettings1652367743993, AddAPIKeyColumn1652905585850, + CreateCredentialsEditorRole1657062385367, ]; diff --git a/packages/cli/test/integration/auth.api.test.ts b/packages/cli/test/integration/auth.api.test.ts index 95c4cd2e94635..fc266b06d35cc 100644 --- a/packages/cli/test/integration/auth.api.test.ts +++ b/packages/cli/test/integration/auth.api.test.ts @@ -1,14 +1,13 @@ import express = require('express'); -import type { SuperAgentTest } from 'supertest'; import validator from 'validator'; import config from '../../config'; import { Db } from '../../src'; import { AUTH_COOKIE_NAME } from '../../src/constants'; import type { Role } from '../../src/databases/entities/Role'; -import type { User } from '../../src/databases/entities/User'; import { LOGGED_OUT_RESPONSE_BODY } from './shared/constants'; import { randomValidPassword } from './shared/random'; import * as testDb from './shared/testDb'; +import type { AuthAgent } from './shared/types'; import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -17,7 +16,7 @@ let app: express.Application; let testDbName = ''; let globalOwnerRole: Role; let globalMemberRole: Role; -let authAgent: (user: User) => SuperAgentTest; +let authAgent: AuthAgent; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['auth'], applyAuth: true }); diff --git a/packages/cli/test/integration/auth.mw.test.ts b/packages/cli/test/integration/auth.mw.test.ts index 458e5c2cee031..5dd130f1b6d8b 100644 --- a/packages/cli/test/integration/auth.mw.test.ts +++ b/packages/cli/test/integration/auth.mw.test.ts @@ -1,15 +1,14 @@ import express from 'express'; -import type { SuperAgentTest } from 'supertest'; import request from 'supertest'; import type { Role } from '../../src/databases/entities/Role'; -import type { User } from '../../src/databases/entities/User'; import { REST_PATH_SEGMENT, ROUTES_REQUIRING_AUTHENTICATION, ROUTES_REQUIRING_AUTHORIZATION, } from './shared/constants'; import * as testDb from './shared/testDb'; +import type { AuthAgent } from './shared/types'; import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -17,7 +16,7 @@ jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; let globalMemberRole: Role; -let authAgent: (user: User) => SuperAgentTest; +let authAgent: AuthAgent; beforeAll(async () => { app = await utils.initTestServer({ diff --git a/packages/cli/test/integration/credentials.ee.test.ts b/packages/cli/test/integration/credentials.ee.test.ts index 5ad13fe21bc13..d625c6a486b2a 100644 --- a/packages/cli/test/integration/credentials.ee.test.ts +++ b/packages/cli/test/integration/credentials.ee.test.ts @@ -1,12 +1,10 @@ import express from 'express'; -import type { SuperAgentTest } from 'supertest'; import config from '../../config'; import { Db } from '../../src'; import type { Role } from '../../src/databases/entities/Role'; -import type { User } from '../../src/databases/entities/User'; import { randomCredentialPayload } from './shared/random'; import * as testDb from './shared/testDb'; -import type { SaveCredentialFunction } from './shared/types'; +import type { AuthAgent, SaveCredentialFunction } from './shared/types'; import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -17,7 +15,7 @@ let globalOwnerRole: Role; let globalMemberRole: Role; let credentialOwnerRole: Role; let saveCredential: SaveCredentialFunction; -let authAgent: (user: User) => SuperAgentTest; +let authAgent: AuthAgent; beforeAll(async () => { app = await utils.initTestServer({ @@ -159,7 +157,7 @@ test('POST /credentials/:id/share should respond 400 for non-existing sharee', a const response = await authAgent(owner) .post(`/credentials/${savedCredential.id}/share`) - .send({ shareeId: 'abc' }); + .send({ shareeId: 'bce38a11-5e45-4d1c-a9ee-36e4a20ab0fc' }); expect(response.statusCode).toBe(400); }); @@ -236,7 +234,7 @@ test('DELETE /credentials/:id/share should be idempotent', async () => { const unshareNonExistent = await authAgent(owner) .delete(`/credentials/${savedCredential.id}/share`) - .send({ shareeId: 'abc' }); + .send({ shareeId: 'bce38a11-5e45-4d1c-a9ee-36e4a20ab0fc' }); expect(unshareNonExistent.statusCode).toBe(200); }); diff --git a/packages/cli/test/integration/credentials.test.ts b/packages/cli/test/integration/credentials.test.ts index 8327c0c1eac42..28c9302d22b9e 100644 --- a/packages/cli/test/integration/credentials.test.ts +++ b/packages/cli/test/integration/credentials.test.ts @@ -1,14 +1,12 @@ import express from 'express'; import { UserSettings } from 'n8n-core'; -import type { SuperAgentTest } from 'supertest'; import { Db } from '../../src'; import { RESPONSE_ERROR_MESSAGES } from '../../src/constants'; import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity'; import type { Role } from '../../src/databases/entities/Role'; -import type { User } from '../../src/databases/entities/User'; import { randomCredentialPayload, randomName, randomString } from './shared/random'; import * as testDb from './shared/testDb'; -import type { SaveCredentialFunction } from './shared/types'; +import type { AuthAgent, SaveCredentialFunction } from './shared/types'; import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -18,7 +16,7 @@ let testDbName = ''; let globalOwnerRole: Role; let globalMemberRole: Role; let saveCredential: SaveCredentialFunction; -let authAgent: (user: User) => SuperAgentTest; +let authAgent: AuthAgent; beforeAll(async () => { app = await utils.initTestServer({ diff --git a/packages/cli/test/integration/me.api.test.ts b/packages/cli/test/integration/me.api.test.ts index fbab3780b8893..8e2ad67c964da 100644 --- a/packages/cli/test/integration/me.api.test.ts +++ b/packages/cli/test/integration/me.api.test.ts @@ -1,12 +1,10 @@ import express from 'express'; -import type { SuperAgentTest } from 'supertest'; import { IsNull } from 'typeorm'; import validator from 'validator'; import config from '../../config'; import { Db } from '../../src'; import type { Role } from '../../src/databases/entities/Role'; -import type { User } from '../../src/databases/entities/User'; import { SUCCESS_RESPONSE_BODY } from './shared/constants'; import { randomApiKey, @@ -16,6 +14,7 @@ import { randomValidPassword, } from './shared/random'; import * as testDb from './shared/testDb'; +import type { AuthAgent } from './shared/types'; import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -24,7 +23,7 @@ let app: express.Application; let testDbName = ''; let globalOwnerRole: Role; let globalMemberRole: Role; -let authAgent: (user: User) => SuperAgentTest; +let authAgent: AuthAgent; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['me'], applyAuth: true }); diff --git a/packages/cli/test/integration/owner.api.test.ts b/packages/cli/test/integration/owner.api.test.ts index 245cc4dda091b..ae7e2f1e5369a 100644 --- a/packages/cli/test/integration/owner.api.test.ts +++ b/packages/cli/test/integration/owner.api.test.ts @@ -1,11 +1,9 @@ import express from 'express'; -import type { SuperAgentTest } from 'supertest'; import validator from 'validator'; import config from '../../config'; import { Db } from '../../src'; import type { Role } from '../../src/databases/entities/Role'; -import type { User } from '../../src/databases/entities/User'; import { randomEmail, randomInvalidPassword, @@ -13,6 +11,7 @@ import { randomValidPassword, } from './shared/random'; import * as testDb from './shared/testDb'; +import type { AuthAgent } from './shared/types'; import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -20,7 +19,7 @@ jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; let globalOwnerRole: Role; -let authAgent: (user: User) => SuperAgentTest; +let authAgent: AuthAgent; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['owner'], applyAuth: true }); diff --git a/packages/cli/test/integration/shared/types.d.ts b/packages/cli/test/integration/shared/types.d.ts index 1b31e598a4783..3e92738908160 100644 --- a/packages/cli/test/integration/shared/types.d.ts +++ b/packages/cli/test/integration/shared/types.d.ts @@ -1,4 +1,5 @@ import type { ICredentialDataDecryptedObject, ICredentialNodeAccess } from 'n8n-workflow'; +import type { SuperAgentTest } from 'supertest'; import type { ICredentialsDb, IDatabaseCollections } from '../../../src'; import type { CredentialsEntity } from '../../../src/databases/entities/CredentialsEntity'; import type { User } from '../../../src/databases/entities/User'; @@ -10,6 +11,8 @@ export type MappingName = keyof typeof MAPPING_TABLES; export type ApiPath = 'internal' | 'public'; +export type AuthAgent = (user: User) => SuperAgentTest; + type EndpointGroup = | 'me' | 'users' diff --git a/packages/cli/test/integration/users.api.test.ts b/packages/cli/test/integration/users.api.test.ts index 6279d185d7959..4b9a73cac74cf 100644 --- a/packages/cli/test/integration/users.api.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -2,7 +2,6 @@ import express from 'express'; import { v4 as uuid } from 'uuid'; import validator from 'validator'; -import type { SuperAgentTest } from 'supertest'; import config from '../../config'; import { Db } from '../../src'; import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity'; @@ -18,6 +17,7 @@ import { randomValidPassword, } from './shared/random'; import * as testDb from './shared/testDb'; +import type { AuthAgent } from './shared/types'; import * as utils from './shared/utils'; jest.mock('../../src/telemetry'); @@ -29,7 +29,7 @@ let globalMemberRole: Role; let globalOwnerRole: Role; let workflowOwnerRole: Role; let credentialOwnerRole: Role; -let authAgent: (user: User) => SuperAgentTest; +let authAgent: AuthAgent; beforeAll(async () => { app = await utils.initTestServer({ endpointGroups: ['users'], applyAuth: true });