UNPKG

n8n

Version:

n8n Workflow Automation Tool

202 lines • 10 kB
"use strict"; 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.FavoritesService = void 0; const di_1 = require("@n8n/di"); const db_1 = require("@n8n/db"); const permissions_1 = require("@n8n/permissions"); const typeorm_1 = require("@n8n/typeorm"); const user_favorite_repository_1 = require("./database/repositories/user-favorite.repository"); const bad_request_error_1 = require("../../errors/response-errors/bad-request.error"); const not_found_error_1 = require("../../errors/response-errors/not-found.error"); const data_table_repository_1 = require("../../modules/data-table/data-table.repository"); const idsOfType = (favorites, type) => favorites.filter((f) => f.resourceType === type).map((f) => f.resourceId); const enrichWithName = (fav, name) => name === undefined ? [] : [{ ...fav, resourceName: name }]; const enrichWithMeta = (fav, meta) => meta === undefined ? [] : [{ ...fav, resourceName: meta.name, resourceProjectId: meta.projectId }]; let FavoritesService = class FavoritesService { constructor(userFavoriteRepository, workflowRepository, projectRepository, sharedWorkflowRepository, dataTableRepository, folderRepository) { this.userFavoriteRepository = userFavoriteRepository; this.workflowRepository = workflowRepository; this.projectRepository = projectRepository; this.sharedWorkflowRepository = sharedWorkflowRepository; this.dataTableRepository = dataTableRepository; this.folderRepository = folderRepository; this.MAX_FAVORITES = 200; } async getEnrichedFavorites(user) { const favorites = await this.userFavoriteRepository.findByUser(user.id); if (favorites.length === 0) return []; const ids = { workflow: idsOfType(favorites, 'workflow'), project: idsOfType(favorites, 'project'), dataTable: idsOfType(favorites, 'dataTable'), folder: idsOfType(favorites, 'folder'), }; const accessibleProjects = await this.projectRepository.getAccessibleProjects(user.id); const accessibleProjectIds = new Set(accessibleProjects.map((p) => p.id)); const [workflowNames, projectNames, dataTableMeta, folderMeta] = await Promise.all([ this.enrichWorkflowFavorites(user, ids.workflow, accessibleProjectIds), this.enrichProjectFavorites(user, ids.project, accessibleProjects), this.enrichDataTableFavorites(user, ids.dataTable, accessibleProjectIds), this.enrichFolderFavorites(user, ids.folder, accessibleProjectIds), ]); return favorites.flatMap((fav) => { switch (fav.resourceType) { case 'workflow': return enrichWithName(fav, workflowNames.get(fav.resourceId)); case 'project': return enrichWithName(fav, projectNames.get(fav.resourceId)); case 'dataTable': return enrichWithMeta(fav, dataTableMeta.get(fav.resourceId)); case 'folder': return enrichWithMeta(fav, folderMeta.get(fav.resourceId)); default: return []; } }); } async enrichWorkflowFavorites(user, workflowIds, accessibleProjectIds) { const result = new Map(); if (workflowIds.length === 0) return result; const hasGlobalAccess = (0, permissions_1.hasGlobalScope)(user, 'workflow:read'); if (!hasGlobalAccess && accessibleProjectIds.size === 0) return result; const [workflows, sharedWorkflows] = await Promise.all([ this.workflowRepository.findByIds(workflowIds, { fields: ['id', 'name'] }), hasGlobalAccess ? Promise.resolve([]) : this.sharedWorkflowRepository.find({ select: { workflowId: true }, where: { workflowId: (0, typeorm_1.In)(workflowIds), projectId: (0, typeorm_1.In)([...accessibleProjectIds]) }, }), ]); const accessibleIds = hasGlobalAccess ? new Set(workflows.map((wf) => wf.id)) : new Set(sharedWorkflows.map((sw) => sw.workflowId)); for (const wf of workflows) { if (accessibleIds.has(wf.id)) result.set(wf.id, wf.name); } return result; } async enrichProjectFavorites(user, projectFavoriteIds, accessibleProjects) { const result = new Map(accessibleProjects.map((p) => [p.id, p.name ?? ''])); if (projectFavoriteIds.length === 0) return result; if (!(0, permissions_1.hasGlobalScope)(user, 'project:read')) return result; const missingIds = projectFavoriteIds.filter((id) => !result.has(id)); if (missingIds.length === 0) return result; const additional = await this.projectRepository.find({ where: { id: (0, typeorm_1.In)(missingIds) }, select: { id: true, name: true }, }); for (const p of additional) { result.set(p.id, p.name ?? ''); } return result; } async enrichDataTableFavorites(user, dataTableIds, accessibleProjectIds) { const result = new Map(); if (dataTableIds.length === 0) return result; const hasGlobalAccess = (0, permissions_1.hasGlobalScope)(user, 'dataTable:read'); const dataTables = await this.dataTableRepository.find({ where: { id: (0, typeorm_1.In)(dataTableIds) } }); for (const dt of dataTables) { if (hasGlobalAccess || accessibleProjectIds.has(dt.projectId)) { result.set(dt.id, { name: dt.name, projectId: dt.projectId }); } } return result; } async enrichFolderFavorites(user, folderIds, accessibleProjectIds) { const result = new Map(); if (folderIds.length === 0) return result; const hasGlobalAccess = (0, permissions_1.hasGlobalScope)(user, 'folder:read'); const folders = await this.folderRepository.find({ where: { id: (0, typeorm_1.In)(folderIds) }, relations: { homeProject: true }, }); for (const folder of folders) { const projectId = folder.homeProject?.id; if (projectId && (hasGlobalAccess || accessibleProjectIds.has(projectId))) { result.set(folder.id, { name: folder.name, projectId }); } } return result; } async addFavorite(userId, resourceId, resourceType) { const existing = await this.userFavoriteRepository.findOne({ where: { userId, resourceId, resourceType }, }); if (existing) return existing; await this.assertResourceExists(resourceId, resourceType); const count = await this.userFavoriteRepository.count({ where: { userId } }); if (count >= this.MAX_FAVORITES) { throw new bad_request_error_1.BadRequestError(`Favorites limit of ${this.MAX_FAVORITES} reached`); } const favorite = this.userFavoriteRepository.create({ userId, resourceId, resourceType }); return await this.userFavoriteRepository.save(favorite); } async assertResourceExists(resourceId, resourceType) { let exists; switch (resourceType) { case 'workflow': exists = await this.workflowRepository.existsBy({ id: resourceId }); break; case 'project': exists = await this.projectRepository.existsBy({ id: resourceId }); break; case 'dataTable': exists = await this.dataTableRepository.existsBy({ id: resourceId }); break; case 'folder': exists = await this.folderRepository.existsBy({ id: resourceId }); break; } if (!exists) { throw new not_found_error_1.NotFoundError(`${resourceType} with id "${resourceId}" not found`); } } async removeFavorite(userId, resourceId, resourceType) { const favorite = await this.userFavoriteRepository.findOne({ where: { userId, resourceId, resourceType }, }); if (!favorite) { throw new not_found_error_1.NotFoundError('Favorite not found'); } await this.userFavoriteRepository.remove(favorite); } async deleteByResource(resourceId, resourceType) { await this.userFavoriteRepository.deleteByResourceId(resourceId, resourceType); } async deleteByResourceIds(resourceIds, resourceType) { await this.userFavoriteRepository.deleteByResourceIds(resourceIds, resourceType); } }; exports.FavoritesService = FavoritesService; exports.FavoritesService = FavoritesService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [user_favorite_repository_1.UserFavoriteRepository, db_1.WorkflowRepository, db_1.ProjectRepository, db_1.SharedWorkflowRepository, data_table_repository_1.DataTableRepository, db_1.FolderRepository]) ], FavoritesService); //# sourceMappingURL=favorites.service.js.map