n8n
Version:
n8n Workflow Automation Tool
243 lines • 11.3 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkflowDependencyQueryService = void 0;
const db_1 = require("@n8n/db");
const di_1 = require("@n8n/di");
const permissions_1 = require("@n8n/permissions");
const typeorm_1 = require("@n8n/typeorm");
const credentials_finder_service_1 = require("../../credentials/credentials-finder.service");
const data_table_repository_1 = require("../../modules/data-table/data-table.repository");
const role_service_1 = require("../../services/role.service");
const workflow_finder_service_1 = require("../../workflows/workflow-finder.service");
let WorkflowDependencyQueryService = class WorkflowDependencyQueryService {
constructor(dependencyRepository, credentialsRepository, workflowRepository, dataTableRepository, workflowFinderService, credentialsFinderService, projectRelationRepository, roleService) {
this.dependencyRepository = dependencyRepository;
this.credentialsRepository = credentialsRepository;
this.workflowRepository = workflowRepository;
this.dataTableRepository = dataTableRepository;
this.workflowFinderService = workflowFinderService;
this.credentialsFinderService = credentialsFinderService;
this.projectRelationRepository = projectRelationRepository;
this.roleService = roleService;
}
async getDependencyCounts(resourceIds, resourceType, user) {
const loaded = await this.loadDepsForResources(resourceIds, resourceType, user);
if (!loaded)
return {};
const { accessibleInputIds, maps } = loaded;
const result = {};
for (const id of accessibleInputIds) {
result[id] = {
credentialId: maps.credMap.get(id)?.size ?? 0,
dataTableId: maps.dtMap.get(id)?.size ?? 0,
errorWorkflow: maps.errorWfMap.get(id)?.size ?? 0,
errorWorkflowParent: maps.errorWfParentMap.get(id)?.size ?? 0,
workflowCall: maps.subMap.get(id)?.size ?? 0,
workflowParent: maps.parentMap.get(id)?.size ?? 0,
};
}
return result;
}
async getResourceDependencies(resourceIds, resourceType, user) {
const loaded = await this.loadDepsForResources(resourceIds, resourceType, user);
if (!loaded)
return {};
const { accessibleInputIds, maps } = loaded;
const [accessibleWfIds, accessibleCredIds, accessibleDtIds] = await Promise.all([
this.filterByAccess([...maps.allWfIds], 'workflow', user),
this.filterByAccess([...maps.allCredIds], 'credential', user),
this.filterByAccess([...maps.allDtIds], 'dataTable', user),
]);
const [credentials, workflows, dataTables] = await Promise.all([
accessibleCredIds.length > 0
? this.credentialsRepository.find({
where: { id: (0, typeorm_1.In)(accessibleCredIds) },
select: ['id', 'name'],
})
: [],
accessibleWfIds.length > 0
? this.workflowRepository.find({
where: { id: (0, typeorm_1.In)(accessibleWfIds) },
select: ['id', 'name'],
})
: [],
accessibleDtIds.length > 0
? this.dataTableRepository.find({
where: { id: (0, typeorm_1.In)(accessibleDtIds) },
select: ['id', 'name', 'projectId'],
})
: [],
]);
const wfNames = new Map();
const credNames = new Map();
const dtNames = new Map();
for (const c of credentials)
credNames.set(c.id, c.name ?? c.id);
for (const w of workflows)
wfNames.set(w.id, w.name ?? w.id);
for (const dt of dataTables)
dtNames.set(dt.id, { name: dt.name ?? dt.id, projectId: dt.projectId });
return this.buildEnrichedResult(accessibleInputIds, maps, {
wfNames,
credNames,
dtNames,
});
}
async loadDepsForResources(resourceIds, resourceType, user) {
const accessibleInputIds = await this.filterByAccess(resourceIds, resourceType, user);
if (accessibleInputIds.length === 0)
return null;
const rawDeps = await this.dependencyRepository.find({
where: [
{
workflowId: (0, typeorm_1.In)(accessibleInputIds),
dependencyType: (0, typeorm_1.In)(['credentialId', 'dataTableId', 'errorWorkflow', 'workflowCall']),
},
{ dependencyKey: (0, typeorm_1.In)(accessibleInputIds) },
],
select: ['workflowId', 'dependencyType', 'dependencyKey'],
});
if (rawDeps.length === 0)
return null;
return { accessibleInputIds, maps: this.buildDepMaps(rawDeps) };
}
buildDepMaps(rawDeps) {
const credMap = new Map();
const dtMap = new Map();
const subMap = new Map();
const parentMap = new Map();
const errorWfMap = new Map();
const errorWfParentMap = new Map();
const allCredIds = new Set();
const allWfIds = new Set();
const allDtIds = new Set();
for (const dep of rawDeps) {
allWfIds.add(dep.workflowId);
switch (dep.dependencyType) {
case 'credentialId':
addToSet(credMap, dep.workflowId, dep.dependencyKey);
addToSet(parentMap, dep.dependencyKey, dep.workflowId);
allCredIds.add(dep.dependencyKey);
break;
case 'dataTableId':
addToSet(dtMap, dep.workflowId, dep.dependencyKey);
addToSet(parentMap, dep.dependencyKey, dep.workflowId);
allDtIds.add(dep.dependencyKey);
break;
case 'workflowCall':
addToSet(subMap, dep.workflowId, dep.dependencyKey);
addToSet(parentMap, dep.dependencyKey, dep.workflowId);
allWfIds.add(dep.dependencyKey);
break;
case 'errorWorkflow':
addToSet(errorWfMap, dep.workflowId, dep.dependencyKey);
addToSet(errorWfParentMap, dep.dependencyKey, dep.workflowId);
allWfIds.add(dep.dependencyKey);
break;
}
}
return {
credMap,
dtMap,
subMap,
parentMap,
errorWfMap,
errorWfParentMap,
allCredIds,
allWfIds,
allDtIds,
};
}
buildEnrichedResult(resourceIds, maps, accessMaps) {
const result = {};
for (const resourceId of resourceIds) {
const dependencies = [];
let inaccessibleCount = 0;
const resolve = (ids, nameMap, type) => {
for (const id of ids ?? []) {
const name = nameMap.get(id);
if (name !== undefined) {
dependencies.push({ id, name, type });
}
else {
inaccessibleCount++;
}
}
};
resolve(maps.subMap.get(resourceId), accessMaps.wfNames, 'workflowCall');
resolve(maps.parentMap.get(resourceId), accessMaps.wfNames, 'workflowParent');
resolve(maps.errorWfMap.get(resourceId), accessMaps.wfNames, 'errorWorkflow');
resolve(maps.errorWfParentMap.get(resourceId), accessMaps.wfNames, 'errorWorkflowParent');
resolve(maps.credMap.get(resourceId), accessMaps.credNames, 'credentialId');
for (const id of maps.dtMap.get(resourceId) ?? []) {
const dt = accessMaps.dtNames.get(id);
if (dt) {
dependencies.push({ id, name: dt.name, type: 'dataTableId', projectId: dt.projectId });
}
else {
inaccessibleCount++;
}
}
result[resourceId] = { dependencies, inaccessibleCount };
}
return result;
}
async filterByAccess(ids, resourceType, user) {
if (ids.length === 0)
return [];
switch (resourceType) {
case 'workflow': {
const accessible = await this.workflowFinderService.findWorkflowIdsWithScopeForUser(ids, user, ['workflow:read']);
return ids.filter((id) => accessible.has(id));
}
case 'credential': {
const accessible = await this.credentialsFinderService.findCredentialIdsWithScopeForUser(ids, user, ['credential:read']);
return ids.filter((id) => accessible.has(id));
}
case 'dataTable': {
return await this.filterDataTableIdsByAccess(ids, user);
}
}
}
async filterDataTableIdsByAccess(ids, user) {
if ((0, permissions_1.hasGlobalScope)(user, 'dataTable:listProject'))
return ids;
const dataTables = await this.dataTableRepository.find({
where: { id: (0, typeorm_1.In)(ids) },
select: ['id', 'projectId'],
});
const roles = await this.roleService.rolesWithScope('project', ['dataTable:listProject']);
const accessibleProjectIds = new Set(await this.projectRelationRepository.getAccessibleProjectsByRoles(user.id, roles));
return dataTables.filter((dt) => accessibleProjectIds.has(dt.projectId)).map((dt) => dt.id);
}
};
exports.WorkflowDependencyQueryService = WorkflowDependencyQueryService;
exports.WorkflowDependencyQueryService = WorkflowDependencyQueryService = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [db_1.WorkflowDependencyRepository,
db_1.CredentialsRepository,
db_1.WorkflowRepository,
data_table_repository_1.DataTableRepository,
workflow_finder_service_1.WorkflowFinderService,
credentials_finder_service_1.CredentialsFinderService,
db_1.ProjectRelationRepository,
role_service_1.RoleService])
], WorkflowDependencyQueryService);
function addToSet(map, key, val) {
let set = map.get(key);
if (!set) {
set = new Set();
map.set(key, set);
}
set.add(val);
}
//# sourceMappingURL=workflow-dependency-query.service.js.map