Кирилл

Вечкасов

Статьи
Наши курсы

Кирилл

Вечкасов

>

>

Клонирование Credentials

Автоматический перенос credentials между n8n

У меня стоит 2 версии n8n где пишу скрипты и есть версия куда я перемещаю уже сформированные сценарии которые запускаются один раз и больше я их особо не трогаю. Так вот, мне надоело каждый раз копировать доступы (credentials) между n8n верями и я написал простой триггер для PostgresSQL базы который автоматически копирует или обновляет триггеры на "боевой" версии n8n.

Предварительная настройка

Обе копии должны работать с одним ключем шифрования и он должен быть обязательно выставлен в окружении .env файле n8n среды. У меня он прописан таким образом:
N8N_ENCRYPTION_KEY=Kp9mX2vL8nQ4rT1231231aZ3bC5dE7fG9hJ0iK2lM4

Если у вас n8n на бегет, то файл лежит тут:
/opt/beget/n8n/.env

Но опять же, скрипт работает если n8n у вас лежат в одной БД и у одного пользователя есть доступ сразу к двум БД одновременно.

Скрипт авто-копирования доступов

Запускаете данный скрипт в БД откуда требуется копировать данные автоматически, а вместо n8n_fire вы прописываете название БД в которую хотите копировать доступы. Вместо kirill.vech@gmail.com прописываете email пользователя которому будет выдаваться доступ к credentials в "боевой" версии n8n.

-- === Функция синхронизации (INSERT / UPDATE) ===
CREATE OR REPLACE FUNCTION sync_credential_to_fire()
RETURNS trigger AS $$
DECLARE
    target_db TEXT := 'n8n_fire';                           -- Целевая база
    target_user_email TEXT := 'kirill.vech@gmail.com';      -- Владелец
    target_project_id TEXT;
BEGIN
    -- Проверяем наличие dblink
    PERFORM 1 FROM pg_extension WHERE extname='dblink';
    IF NOT FOUND THEN
        EXECUTE 'CREATE EXTENSION IF NOT EXISTS dblink';
    END IF;

    -- Получаем projectId пользователя по email
    BEGIN
        SELECT id INTO target_project_id
        FROM dblink(
            format('dbname=%I', target_db),
            format(
                $q$
                SELECT p."id"
                FROM project p
                JOIN project_relation pr ON pr."projectId" = p."id"
                JOIN "user" u ON u."id" = pr."userId"
                WHERE u."email" = %L
                ORDER BY p."createdAt" ASC
                LIMIT 1
                $q$,
                target_user_email
            )
        ) AS proj("id" text)
        LIMIT 1;
    EXCEPTION WHEN OTHERS THEN
        RAISE NOTICE '❌ Ошибка при получении project_id: %', SQLERRM;
        RETURN NEW;
    END;

    IF target_project_id IS NULL THEN
        RAISE NOTICE '⚠️ Проект не найден для пользователя % в %', target_user_email, target_db;
        RETURN NEW;
    END IF;

    -- Копируем или обновляем credential
    BEGIN
        PERFORM dblink_exec(
            format('dbname=%I', target_db),
            format(
                $q$
                INSERT INTO credentials_entity ("id","name","data","type","createdAt","updatedAt","isManaged")
                VALUES (%L,%L,%L,%L,%L,%L,%L)
                ON CONFLICT ("id") DO UPDATE
                SET "name"=EXCLUDED."name",
                    "data"=EXCLUDED."data",
                    "type"=EXCLUDED."type",
                    "updatedAt"=EXCLUDED."updatedAt",
                    "isManaged"=EXCLUDED."isManaged";
                $q$,
                NEW."id",NEW."name",NEW."data",NEW."type",
                NEW."createdAt",NEW."updatedAt",NEW."isManaged"
            )
        );
    EXCEPTION WHEN OTHERS THEN
        RAISE NOTICE '❌ Ошибка при копировании credential %: %', NEW."id", SQLERRM;
        RETURN NEW;
    END;

    -- Добавляем доступ на проект пользователя
    BEGIN
        PERFORM dblink_exec(
            format('dbname=%I', target_db),
            format(
                $q$
                INSERT INTO shared_credentials ("credentialsId","projectId","role","createdAt","updatedAt")
                VALUES (%L,%L,'owner',NOW(),NOW())
                ON CONFLICT DO NOTHING;
                $q$,
                NEW."id",target_project_id
            )
        );
    EXCEPTION WHEN OTHERS THEN
        RAISE NOTICE '❌ Ошибка при создании shared_credentials для %: %', NEW."id", SQLERRM;
    END;

    RAISE NOTICE '✅ Credential % синхронизирован и расшарен для проекта %', NEW."id", target_project_id;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;


-- === Пересоздаём только один триггер (без delete) ===
DROP TRIGGER IF EXISTS trg_sync_credentials_to_fire ON credentials_entity;

CREATE TRIGGER trg_sync_credentials_to_fire
AFTER INSERT OR UPDATE
ON credentials_entity
FOR EACH ROW
EXECUTE FUNCTION sync_credential_to_fire();

Мои соц. сети

Подписывайся на мой Telegram-канал — там регулярно публикую фишки по n8n, кейсы по рекламе и практичные решения для бизнеса.