"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
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 __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
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.CredentialsOverwrites = void 0;
const backend_common_1 = require("@n8n/backend-common");
const config_1 = require("@n8n/config");
const db_1 = require("@n8n/db");
const decorators_1 = require("@n8n/decorators");
const di_1 = require("@n8n/di");
const n8n_core_1 = require("n8n-core");
const n8n_workflow_1 = require("n8n-workflow");
const credential_types_1 = require("./credential-types");
const static_auth_service_1 = require("./services/static-auth-service");
const CREDENTIALS_OVERWRITE_KEY = 'credentialsOverwrite';
let CredentialsOverwrites = class CredentialsOverwrites {
    constructor(globalConfig, credentialTypes, logger, settings, cipher) {
        this.globalConfig = globalConfig;
        this.credentialTypes = credentialTypes;
        this.logger = logger;
        this.settings = settings;
        this.cipher = cipher;
        this.overwriteData = {};
        this.resolvedTypes = [];
        this.reloading = false;
    }
    async init() {
        const data = this.globalConfig.credentials.overwrite.data;
        if (data) {
            this.logger.debug('Loading overwrite credentials from static envvar');
            const overwriteData = (0, n8n_workflow_1.jsonParse)(data, {
                errorMessage: 'The credentials-overwrite is not valid JSON.',
            });
            this.setPlainData(overwriteData);
        }
        const persistence = this.globalConfig.credentials.overwrite.persistence;
        if (persistence) {
            this.logger.debug('Loading overwrite credentials from database');
            await this.loadOverwriteDataFromDB(false);
        }
    }
    async reloadOverwriteCredentials() {
        await this.loadOverwriteDataFromDB(true);
    }
    async loadOverwriteDataFromDB(reloadFrontend) {
        if (this.reloading)
            return;
        try {
            this.reloading = true;
            this.logger.debug('Loading overwrite credentials from DB');
            const data = await this.settings.findByKey(CREDENTIALS_OVERWRITE_KEY);
            if (data) {
                const decryptedData = this.cipher.decrypt(data.value);
                const overwriteData = (0, n8n_workflow_1.jsonParse)(decryptedData, {
                    errorMessage: 'The credentials-overwrite is not valid JSON.',
                });
                await this.setData(overwriteData, false, reloadFrontend);
            }
        }
        catch (error) {
            this.logger.error('Error loading overwrite credentials', { error });
        }
        finally {
            this.reloading = false;
        }
    }
    async broadcastReloadOverwriteCredentialsCommand() {
        const { Publisher } = await Promise.resolve().then(() => __importStar(require('./scaling/pubsub/publisher.service')));
        await di_1.Container.get(Publisher).publishCommand({ command: 'reload-overwrite-credentials' });
    }
    async saveOverwriteDataToDB(overwriteData, broadcast = true) {
        const data = this.cipher.encrypt(JSON.stringify(overwriteData));
        const setting = this.settings.create({
            key: CREDENTIALS_OVERWRITE_KEY,
            value: data,
            loadOnStartup: false,
        });
        await this.settings.save(setting);
        if (broadcast) {
            await this.broadcastReloadOverwriteCredentialsCommand();
        }
    }
    getOverwriteEndpointMiddleware() {
        const { endpointAuthToken } = this.globalConfig.credentials.overwrite;
        return static_auth_service_1.StaticAuthService.getStaticAuthMiddleware(endpointAuthToken);
    }
    setPlainData(overwriteData) {
        this.resolvedTypes.length = 0;
        this.overwriteData = overwriteData;
        for (const type in overwriteData) {
            const overwrites = this.getOverwrites(type);
            if (overwrites && Object.keys(overwrites).length) {
                this.overwriteData[type] = overwrites;
            }
        }
    }
    async setData(overwriteData, storeInDb = true, reloadFrontend = true) {
        this.setPlainData(overwriteData);
        if (storeInDb && this.globalConfig.credentials.overwrite.persistence) {
            await this.saveOverwriteDataToDB(overwriteData, true);
        }
        if (reloadFrontend) {
            await this.reloadFrontendService();
        }
    }
    async reloadFrontendService() {
        const { FrontendService } = await Promise.resolve().then(() => __importStar(require('./services/frontend.service')));
        await di_1.Container.get(FrontendService)?.generateTypes();
    }
    applyOverwrite(type, data) {
        const overwrites = this.get(type);
        if (overwrites === undefined) {
            return data;
        }
        if (this.globalConfig.credentials.overwrite?.skipTypes?.includes(type)) {
            const isFieldCustomized = (key) => {
                const storedValue = data[key];
                return (storedValue !== null &&
                    storedValue !== undefined &&
                    storedValue !== '' &&
                    storedValue !== overwrites[key]);
            };
            if (Object.keys(overwrites).some(isFieldCustomized)) {
                return data;
            }
        }
        const returnData = (0, n8n_workflow_1.deepCopy)(data);
        for (const key of Object.keys(overwrites)) {
            if ([null, undefined, ''].includes(returnData[key])) {
                returnData[key] = overwrites[key];
            }
        }
        return returnData;
    }
    getOverwrites(type) {
        if (this.resolvedTypes.includes(type)) {
            return this.overwriteData[type];
        }
        if (!this.credentialTypes.recognizes(type)) {
            this.logger.warn(`Unknown credential type ${type} in Credential overwrites`);
            return;
        }
        const credentialTypeData = this.credentialTypes.getByName(type);
        if (credentialTypeData.extends === undefined) {
            this.resolvedTypes.push(type);
            return this.overwriteData[type];
        }
        const overwrites = {};
        for (const credentialsTypeName of credentialTypeData.extends) {
            Object.assign(overwrites, this.getOverwrites(credentialsTypeName));
        }
        if (this.overwriteData[type] !== undefined) {
            Object.assign(overwrites, this.overwriteData[type]);
        }
        this.resolvedTypes.push(type);
        return overwrites;
    }
    get(name) {
        const parentTypes = this.credentialTypes.getParentTypes(name);
        const entries = [name, ...parentTypes]
            .reverse()
            .map((type) => this.overwriteData[type])
            .filter((type) => !!type);
        if (entries.length === 0)
            return undefined;
        return entries.reduce((acc, current) => Object.assign(acc, current), {});
    }
    getAll() {
        return this.overwriteData;
    }
};
exports.CredentialsOverwrites = CredentialsOverwrites;
__decorate([
    (0, decorators_1.OnPubSubEvent)('reload-overwrite-credentials'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], CredentialsOverwrites.prototype, "reloadOverwriteCredentials", null);
exports.CredentialsOverwrites = CredentialsOverwrites = __decorate([
    (0, di_1.Service)(),
    __metadata("design:paramtypes", [config_1.GlobalConfig,
        credential_types_1.CredentialTypes,
        backend_common_1.Logger,
        db_1.SettingsRepository,
        n8n_core_1.Cipher])
], CredentialsOverwrites);
//# sourceMappingURL=credentials-overwrites.js.map