"use strict";
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.MultiKeyringWebCrypto = exports.MultiKeyringNode = void 0;
const immutable_class_1 = require("./immutable_class");
const keyring_1 = require("./keyring");
const needs_1 = require("./needs");
class MultiKeyringNode extends keyring_1.KeyringNode {
    generator;
    children;
    constructor(input) {
        super();
        decorateProperties(this, keyring_1.KeyringNode, input);
    }
    _onEncrypt = buildPrivateOnEncrypt();
    _onDecrypt = buildPrivateOnDecrypt();
}
exports.MultiKeyringNode = MultiKeyringNode;
(0, immutable_class_1.immutableClass)(MultiKeyringNode);
class MultiKeyringWebCrypto extends keyring_1.KeyringWebCrypto {
    constructor(input) {
        super();
        decorateProperties(this, keyring_1.KeyringWebCrypto, input);
    }
    _onEncrypt = buildPrivateOnEncrypt();
    _onDecrypt = buildPrivateOnDecrypt();
}
exports.MultiKeyringWebCrypto = MultiKeyringWebCrypto;
(0, immutable_class_1.immutableClass)(MultiKeyringWebCrypto);
function decorateProperties(obj, BaseKeyring, { generator, children = [] }) {
    /* Precondition: MultiKeyring must have keyrings. */
    (0, needs_1.needs)(generator || children.length, 'Noop MultiKeyring is not supported.');
    /* Precondition: generator must be a Keyring. */
    (0, needs_1.needs)(!!generator === generator instanceof BaseKeyring, 'Generator must be a Keyring');
    /* Precondition: All children must be Keyrings. */
    (0, needs_1.needs)(children.every((kr) => kr instanceof BaseKeyring), 'Child must be a Keyring');
    (0, immutable_class_1.readOnlyProperty)(obj, 'children', Object.freeze(children.slice()));
    (0, immutable_class_1.readOnlyProperty)(obj, 'generator', generator);
}
function buildPrivateOnEncrypt() {
    return async function _onEncrypt(material) {
        /* Precondition: Only Keyrings explicitly designated as generators can generate material.
         * Technically, the precondition below will handle this.
         * Since if I do not have an unencrypted data key,
         * and I do not have a generator,
         * then generated.hasUnencryptedDataKey === false will throw.
         * But this is a much more meaningful error.
         */
        (0, needs_1.needs)(!material.hasUnencryptedDataKey ? this.generator : true, 'Only Keyrings explicitly designated as generators can generate material.');
        const generated = this.generator
            ? await this.generator.onEncrypt(material)
            : material;
        /* Precondition: A Generator Keyring *must* ensure generated material. */
        (0, needs_1.needs)(generated.hasUnencryptedDataKey, 'Generator Keyring has not generated material.');
        /* By default this is a serial operation.  A keyring _may_ perform an expensive operation
         * or create resource constraints such that encrypting with multiple keyrings could
         * fail in unexpected ways.
         * Additionally, "downstream" keyrings may make choices about the EncryptedDataKeys they
         * append based on already appended EDK's.
         */
        for (const keyring of this.children) {
            await keyring.onEncrypt(generated);
        }
        // Keyrings are required to not create new EncryptionMaterial instances, but
        // only append EncryptedDataKey.  Therefore the generated material has all
        // the data I want.
        return generated;
    };
}
function buildPrivateOnDecrypt() {
    return async function _onDecrypt(material, encryptedDataKeys) {
        const children = this.children.slice();
        if (this.generator)
            children.unshift(this.generator);
        const childKeyringErrors = [];
        for (const keyring of children) {
            /* Check for early return (Postcondition): Do not attempt to decrypt once I have a valid key. */
            if (material.hasValidKey())
                return material;
            try {
                await keyring.onDecrypt(material, encryptedDataKeys);
            }
            catch (e) {
                /* Failures onDecrypt should not short-circuit the process
                 * If the caller does not have access they may have access
                 * through another Keyring.
                 */
                childKeyringErrors.push({ errPlus: e });
            }
        }
        /* Postcondition: A child keyring must provide a valid data key or no child keyring must have raised an error.
         * If I have a data key,
         * decrypt errors can be ignored.
         * However, if I was unable to decrypt a data key AND I have errors,
         * these errors should bubble up.
         * Otherwise, the only error customers will see is that
         * the material does not have an unencrypted data key.
         * So I return a concatenated Error message
         */
        (0, needs_1.needs)(material.hasValidKey() ||
            (!material.hasValidKey() && !childKeyringErrors.length), childKeyringErrors.reduce((m, e, i) => `${m} Error #${i + 1} \n ${e.errPlus.stack} \n`, 'Unable to decrypt data key and one or more child keyrings had an error. \n '));
        return material;
    };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGlfa2V5cmluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tdWx0aV9rZXlyaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxvRUFBb0U7QUFDcEUsc0NBQXNDOzs7QUFFdEMsdURBQW9FO0FBQ3BFLHVDQUFrRTtBQU9sRSxtQ0FBK0I7QUFLL0IsTUFBYSxnQkFDWCxTQUFRLHFCQUFXO0lBR0gsU0FBUyxDQUFjO0lBQ3ZCLFFBQVEsQ0FBNkI7SUFDckQsWUFBWSxLQUE0QztRQUN0RCxLQUFLLEVBQUUsQ0FBQTtRQUNQLGtCQUFrQixDQUFDLElBQUksRUFBRSxxQkFBVyxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQzlDLENBQUM7SUFDRCxVQUFVLEdBQUcscUJBQXFCLEVBQXNCLENBQUE7SUFDeEQsVUFBVSxHQUFHLHFCQUFxQixFQUFzQixDQUFBO0NBQ3pEO0FBWkQsNENBWUM7QUFDRCxJQUFBLGdDQUFjLEVBQUMsZ0JBQWdCLENBQUMsQ0FBQTtBQUVoQyxNQUFhLHFCQUNYLFNBQVEsMEJBQWdCO0lBTXhCLFlBQVksS0FBaUQ7UUFDM0QsS0FBSyxFQUFFLENBQUE7UUFDUCxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsMEJBQWdCLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFDbkQsQ0FBQztJQUNELFVBQVUsR0FBRyxxQkFBcUIsRUFBMkIsQ0FBQTtJQUM3RCxVQUFVLEdBQUcscUJBQXFCLEVBQTJCLENBQUE7Q0FDOUQ7QUFiRCxzREFhQztBQUNELElBQUEsZ0NBQWMsRUFBQyxxQkFBcUIsQ0FBQyxDQUFBO0FBRXJDLFNBQVMsa0JBQWtCLENBQ3pCLEdBQW9CLEVBQ3BCLFdBQWdCLEVBQ2hCLEVBQUUsU0FBUyxFQUFFLFFBQVEsR0FBRyxFQUFFLEVBQXdCO0lBRWxELG9EQUFvRDtJQUNwRCxJQUFBLGFBQUssRUFBQyxTQUFTLElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxxQ0FBcUMsQ0FBQyxDQUFBO0lBQzFFLGdE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