mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-04 18:49:20 +02:00
fix(core): Fix folders file overwrite for admin on push (#20813)
This commit is contained in:
parent
fde49fec4f
commit
4a3e7d7aec
|
|
@ -1,5 +1,6 @@
|
|||
import type { SourceControlledFile } from '@n8n/api-types';
|
||||
import type {
|
||||
Folder,
|
||||
FolderRepository,
|
||||
Project,
|
||||
ProjectRepository,
|
||||
|
|
@ -57,6 +58,7 @@ describe('SourceControlExportService', () => {
|
|||
);
|
||||
|
||||
const fsWriteFile = jest.spyOn(fsp, 'writeFile');
|
||||
const fsReadFile = jest.spyOn(fsp, 'readFile');
|
||||
|
||||
beforeEach(() => jest.clearAllMocks());
|
||||
|
||||
|
|
@ -273,6 +275,63 @@ describe('SourceControlExportService', () => {
|
|||
expect(result.count).toBe(0);
|
||||
expect(result.files).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should not duplicate folders on push', async () => {
|
||||
// Arrange
|
||||
const newFolders = [
|
||||
{
|
||||
id: 'folder-id',
|
||||
name: 'Folder Name',
|
||||
parentFolderId: null,
|
||||
homeProject: { id: 'project-id' },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
} as Folder,
|
||||
];
|
||||
folderRepository.find.mockResolvedValue(newFolders);
|
||||
workflowRepository.find.mockResolvedValue([mock()]);
|
||||
const existingFolders = [
|
||||
{
|
||||
id: 'folder-id',
|
||||
name: 'Folder Name',
|
||||
parentFolderId: null,
|
||||
homeProjectId: 'project-id',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
},
|
||||
];
|
||||
fsReadFile.mockResolvedValue(
|
||||
JSON.stringify({
|
||||
folders: existingFolders,
|
||||
}),
|
||||
);
|
||||
|
||||
// Act
|
||||
const result = await service.exportFoldersToWorkFolder(globalAdminContext);
|
||||
|
||||
// Assert
|
||||
// new json file should contain only the new folders
|
||||
expect(fsWriteFile).toHaveBeenCalledWith(
|
||||
'/mock/n8n/git/folders.json',
|
||||
JSON.stringify(
|
||||
{
|
||||
folders: newFolders.map((f) => ({
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
parentFolderId: f.parentFolderId,
|
||||
homeProjectId: f.homeProject.id,
|
||||
createdAt: f.createdAt.toISOString(),
|
||||
updatedAt: f.updatedAt.toISOString(),
|
||||
})),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
expect(result.count).toBe(1);
|
||||
expect(result.files).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('exportVariablesToWorkFolder', () => {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import { UnexpectedError, type ICredentialDataDecryptedObject } from 'n8n-workfl
|
|||
import { rm as fsRm, writeFile as fsWriteFile } from 'node:fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
import { VariablesService } from '../variables/variables.service.ee';
|
||||
import {
|
||||
SOURCE_CONTROL_CREDENTIAL_EXPORT_FOLDER,
|
||||
SOURCE_CONTROL_GIT_FOLDER,
|
||||
|
|
@ -40,14 +39,15 @@ import {
|
|||
stringContainsExpression,
|
||||
} from './source-control-helper.ee';
|
||||
import { SourceControlScopedService } from './source-control-scoped.service';
|
||||
import { VariablesService } from '../variables/variables.service.ee';
|
||||
import type { ExportResult } from './types/export-result';
|
||||
import type { ExportableCredential } from './types/exportable-credential';
|
||||
import { ExportableProject } from './types/exportable-project';
|
||||
import type { ExportableWorkflow } from './types/exportable-workflow';
|
||||
import type { RemoteResourceOwner } from './types/resource-owner';
|
||||
import type { SourceControlContext } from './types/source-control-context';
|
||||
|
||||
import { formatWorkflow } from '@/workflows/workflow.formatter';
|
||||
import { ExportableProject } from './types/exportable-project';
|
||||
|
||||
@Service()
|
||||
export class SourceControlExportService {
|
||||
|
|
@ -269,7 +269,7 @@ export class SourceControlExportService {
|
|||
// keep all folders that are not accessible by the current user
|
||||
// if allowedProjects is undefined, all folders are accessible by the current user
|
||||
const foldersToKeepUnchanged = context.hasAccessToAllProjects()
|
||||
? existingFolders.folders
|
||||
? []
|
||||
: existingFolders.folders.filter((folder) => {
|
||||
return !allowedProjects.some((project) => project.id === folder.homeProjectId);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user