UNPKG

n8n

Version:

n8n Workflow Automation Tool

118 lines • 6.25 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.CredentialConnectionStatusService = void 0; const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const permissions_1 = require("@n8n/permissions"); const role_service_1 = require("../../../services/role.service"); const constants_1 = require("../constants"); const dynamic_credential_user_entry_1 = require("../database/entities/dynamic-credential-user-entry"); const dynamic_credential_user_entry_repository_1 = require("../database/repositories/dynamic-credential-user-entry.repository"); const CREDENTIAL_RETAIN_SCOPE = 'credential:connect'; const keyOf = (pair) => `${pair.credentialId}|${pair.userId}`; let CredentialConnectionStatusService = class CredentialConnectionStatusService { constructor(repository, userRepository, sharedCredentialsRepository, roleService, projectRelationRepository) { this.repository = repository; this.userRepository = userRepository; this.sharedCredentialsRepository = sharedCredentialsRepository; this.roleService = roleService; this.projectRelationRepository = projectRelationRepository; } async findConnectedCredentialIds(userId, credentialIds) { if (credentialIds.length === 0) return new Set(); const rows = await this.repository.find({ select: ['credentialId'], where: { userId, resolverId: constants_1.SYSTEM_RESOLVER_ID, credentialId: (0, db_1.In)(credentialIds), }, }); return new Set(rows.map((row) => row.credentialId)); } async deleteMyConnection(userId, credentialId) { const result = await this.repository.delete({ userId, credentialId, resolverId: constants_1.SYSTEM_RESOLVER_ID, }); return result.affected ?? 0; } async countConnectedUsers(credentialId) { return await this.repository.countBy({ credentialId }); } async deleteAllUserEntries(credentialId, em) { const manager = em ?? this.repository.manager; await manager.delete(dynamic_credential_user_entry_1.DynamicCredentialUserEntry, { credentialId }); } async cleanupOrphanedEntriesForUsers(userIds, em, credentialId) { if (userIds.length === 0) return; const manager = em ?? this.repository.manager; const entries = await manager.find(dynamic_credential_user_entry_1.DynamicCredentialUserEntry, { select: ['credentialId', 'userId'], where: { userId: (0, db_1.In)(userIds), ...(credentialId ? { credentialId } : {}) }, }); if (entries.length === 0) return; const pairs = entries.map((e) => ({ credentialId: e.credentialId, userId: e.userId })); await this.deleteOrphanedPairs(pairs, manager); } async cleanupOrphanedEntriesForProjects(credentialId, projectIds, em) { if (projectIds.length === 0) return; const manager = em ?? this.repository.manager; const members = await manager.findBy(this.projectRelationRepository.target, { projectId: (0, db_1.In)(projectIds), }); const userIds = [...new Set(members.map((m) => m.userId))]; await this.cleanupOrphanedEntriesForUsers(userIds, em, credentialId); } async deleteOrphanedPairs(pairs, em) { if (pairs.length === 0) return; const uniquePairs = [...new Map(pairs.map((p) => [keyOf(p), p])).values()]; const users = await em.find(this.userRepository.target, { where: { id: (0, db_1.In)(uniquePairs.map((p) => p.userId)) }, relations: { role: { scopes: true } }, }); const userById = new Map(users.map((u) => [u.id, u])); const pairsToCheck = uniquePairs.filter((p) => userById.has(p.userId)); let projectRetainedKeys = new Set(); if (pairsToCheck.length > 0) { const validCredRoles = await this.roleService.rolesWithScope('credential', CREDENTIAL_RETAIN_SCOPE, em); const projectRetained = await this.sharedCredentialsRepository.findPairsWithCredentialAccess(pairsToCheck, CREDENTIAL_RETAIN_SCOPE, validCredRoles, em); projectRetainedKeys = new Set(projectRetained.map(keyOf)); } const toDelete = this.selectOrphanedPairs(uniquePairs, userById, projectRetainedKeys); if (toDelete.length > 0) { await this.repository.deleteByPairs(toDelete, em); } } selectOrphanedPairs(pairs, userById, projectRetainedKeys) { return pairs.filter((pair) => { const user = userById.get(pair.userId); if (!user) return true; if ((0, permissions_1.hasGlobalScope)(user, CREDENTIAL_RETAIN_SCOPE)) return false; return !projectRetainedKeys.has(keyOf(pair)); }); } }; exports.CredentialConnectionStatusService = CredentialConnectionStatusService; exports.CredentialConnectionStatusService = CredentialConnectionStatusService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [dynamic_credential_user_entry_repository_1.DynamicCredentialUserEntryRepository, db_1.UserRepository, db_1.SharedCredentialsRepository, role_service_1.RoleService, db_1.ProjectRelationRepository]) ], CredentialConnectionStatusService); //# sourceMappingURL=credential-connection-status.service.js.map