n8n/packages/cli/test/integration/services/project.service.test.ts

203 lines
4.9 KiB
TypeScript

import { ProjectService } from '@/services/project.service';
import * as testDb from '../shared/test-db';
import Container from 'typedi';
import { createMember } from '../shared/db/users';
import { ProjectRepository } from '@/databases/repositories/project.repository';
import { ProjectRelationRepository } from '@/databases/repositories/project-relation.repository';
import type { ProjectRole } from '@/databases/entities/project-relation';
import type { Scope } from '@n8n/permissions';
let projectRepository: ProjectRepository;
let projectService: ProjectService;
let projectRelationRepository: ProjectRelationRepository;
beforeAll(async () => {
await testDb.init();
projectRepository = Container.get(ProjectRepository);
projectService = Container.get(ProjectService);
projectRelationRepository = Container.get(ProjectRelationRepository);
});
afterAll(async () => {
await testDb.terminate();
});
afterEach(async () => {
await testDb.truncate(['User']);
});
describe('ProjectService', () => {
describe('addUser', () => {
it.each([
'project:viewer',
'project:admin',
'project:editor',
'project:personalOwner',
] as ProjectRole[])(
'creates a relation between the user and the project using the role %s',
async (role) => {
//
// ARRANGE
//
const member = await createMember();
const project = await projectRepository.save(
projectRepository.create({
name: 'Team Project',
type: 'team',
}),
);
//
// ACT
//
await projectService.addUser(project.id, member.id, role);
//
// ASSERT
//
await projectRelationRepository.findOneOrFail({
where: { userId: member.id, projectId: project.id, role },
});
},
);
it('changes the role the user has in the project if the user is already part of the project, instead of creating a new relationship', async () => {
//
// ARRANGE
//
const member = await createMember();
const project = await projectRepository.save(
projectRepository.create({
name: 'Team Project',
type: 'team',
}),
);
await projectService.addUser(project.id, member.id, 'project:viewer');
await projectRelationRepository.findOneOrFail({
where: { userId: member.id, projectId: project.id, role: 'project:viewer' },
});
//
// ACT
//
await projectService.addUser(project.id, member.id, 'project:admin');
//
// ASSERT
//
const relationships = await projectRelationRepository.find({
where: { userId: member.id, projectId: project.id },
});
expect(relationships).toHaveLength(1);
expect(relationships[0]).toHaveProperty('role', 'project:admin');
});
});
describe('getProjectWithScope', () => {
it.each([
{ role: 'project:admin', scope: 'workflow:list' },
{ role: 'project:admin', scope: 'workflow:create' },
] as Array<{
role: ProjectRole;
scope: Scope;
}>)(
'should return the project if the user has the role $role and wants the scope $scope',
async ({ role, scope }) => {
//
// ARRANGE
//
const projectOwner = await createMember();
const project = await projectRepository.save(
projectRepository.create({
name: 'Team Project',
type: 'team',
}),
);
await projectService.addUser(project.id, projectOwner.id, role);
//
// ACT
//
const projectFromService = await projectService.getProjectWithScope(
projectOwner,
project.id,
[scope],
);
//
// ASSERT
//
if (projectFromService === null) {
fail('Expected projectFromService not to be null');
}
expect(project.id).toBe(projectFromService.id);
},
);
it.each([
{ role: 'project:viewer', scope: 'workflow:create' },
{ role: 'project:viewer', scope: 'credential:create' },
] as Array<{
role: ProjectRole;
scope: Scope;
}>)(
'should return the project if the user has the role $role and wants the scope $scope',
async ({ role, scope }) => {
//
// ARRANGE
//
const projectViewer = await createMember();
const project = await projectRepository.save(
projectRepository.create({
name: 'Team Project',
type: 'team',
}),
);
await projectService.addUser(project.id, projectViewer.id, role);
//
// ACT
//
const projectFromService = await projectService.getProjectWithScope(
projectViewer,
project.id,
[scope],
);
//
// ASSERT
//
expect(projectFromService).toBeNull();
},
);
it('should not return the project if the user is not part of it', async () => {
//
// ARRANGE
//
const member = await createMember();
const project = await projectRepository.save(
projectRepository.create({
name: 'Team Project',
type: 'team',
}),
);
//
// ACT
//
const projectFromService = await projectService.getProjectWithScope(member, project.id, [
'workflow:list',
]);
//
// ASSERT
//
expect(projectFromService).toBeNull();
});
});
});