mirror of
https://github.com/n8n-io/n8n.git
synced 2026-07-28 11:35:03 +02:00
109 lines
3.3 KiB
TypeScript
109 lines
3.3 KiB
TypeScript
import { testDb, getPersonalProject } from '@n8n/backend-test-utils';
|
|
import type { User } from '@n8n/db';
|
|
import { Container } from '@n8n/di';
|
|
|
|
import { DataTableRepository } from '@/modules/data-table/data-table.repository';
|
|
import { toTableName } from '@/modules/data-table/utils/sql-utils';
|
|
|
|
import { createDataTable } from './shared/db/data-tables';
|
|
import { createMember, createOwner } from './shared/db/users';
|
|
import type { SuperAgentTest } from './shared/types';
|
|
import * as utils from './shared/utils/';
|
|
|
|
const testServer = utils.setupTestServer({
|
|
endpointGroups: ['users'],
|
|
enabledFeatures: ['feat:advancedPermissions'],
|
|
modules: ['data-table'],
|
|
});
|
|
|
|
/** Returns true if the physical `data_table_user_<id>` table still exists in the DB. */
|
|
const physicalTableExists = async (dataTableId: string) => {
|
|
const dataTableRepository = Container.get(DataTableRepository);
|
|
const queryRunner = dataTableRepository.manager.connection.createQueryRunner();
|
|
try {
|
|
const table = await queryRunner.getTable(toTableName(dataTableId));
|
|
return table !== undefined;
|
|
} finally {
|
|
await queryRunner.release();
|
|
}
|
|
};
|
|
|
|
describe('DELETE /users/:id with data tables', () => {
|
|
let owner: User;
|
|
let ownerAgent: SuperAgentTest;
|
|
|
|
beforeAll(async () => {
|
|
await testDb.truncate(['User']);
|
|
|
|
owner = await createOwner();
|
|
ownerAgent = testServer.authAgentFor(owner);
|
|
});
|
|
|
|
test('should drop the physical data table when deleting a user without transfer', async () => {
|
|
//
|
|
// ARRANGE
|
|
//
|
|
const member = await createMember();
|
|
const memberPersonalProject = await getPersonalProject(member);
|
|
|
|
const dataTable = await createDataTable(memberPersonalProject, {
|
|
name: 'ID Documents',
|
|
columns: [{ name: 'document', type: 'string' }],
|
|
data: [{ document: 'passport' }],
|
|
});
|
|
|
|
expect(await physicalTableExists(dataTable.id)).toBe(true);
|
|
|
|
//
|
|
// ACT
|
|
//
|
|
await ownerAgent.delete(`/users/${member.id}`).expect(200);
|
|
|
|
//
|
|
// ASSERT
|
|
//
|
|
const dataTableRepository = Container.get(DataTableRepository);
|
|
|
|
// metadata row is gone ...
|
|
await expect(dataTableRepository.findOneBy({ id: dataTable.id })).resolves.toBeNull();
|
|
// ... and the physical table is dropped, not orphaned
|
|
expect(await physicalTableExists(dataTable.id)).toBe(false);
|
|
});
|
|
|
|
test('should transfer the data table to the transferee project when deleting a user with transfer', async () => {
|
|
//
|
|
// ARRANGE
|
|
//
|
|
const [member, transferee] = await Promise.all([createMember(), createMember()]);
|
|
const [memberPersonalProject, transfereePersonalProject] = await Promise.all([
|
|
getPersonalProject(member),
|
|
getPersonalProject(transferee),
|
|
]);
|
|
|
|
const dataTable = await createDataTable(memberPersonalProject, {
|
|
name: 'Employee Onboarding',
|
|
columns: [{ name: 'name', type: 'string' }],
|
|
data: [{ name: 'Ada' }],
|
|
});
|
|
|
|
//
|
|
// ACT
|
|
//
|
|
await ownerAgent
|
|
.delete(`/users/${member.id}`)
|
|
.query({ transferId: transfereePersonalProject.id })
|
|
.expect(200);
|
|
|
|
//
|
|
// ASSERT
|
|
//
|
|
const dataTableRepository = Container.get(DataTableRepository);
|
|
|
|
// data table now belongs to the transferee's personal project ...
|
|
const transferred = await dataTableRepository.findOneBy({ id: dataTable.id });
|
|
expect(transferred?.projectId).toBe(transfereePersonalProject.id);
|
|
// ... and its physical table is preserved with its rows intact
|
|
expect(await physicalTableExists(dataTable.id)).toBe(true);
|
|
});
|
|
});
|