'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _stringify = require('babel-runtime/core-js/json/stringify');

var _stringify2 = _interopRequireDefault(_stringify);

var _promise = require('babel-runtime/core-js/promise');

var _promise2 = _interopRequireDefault(_promise);

var _keys = require('babel-runtime/core-js/object/keys');

var _keys2 = _interopRequireDefault(_keys);

var _regenerator = require('babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

require('source-map-support/register');

var _awsSdk = require('aws-sdk');

var AWS = _interopRequireWildcard(_awsSdk);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var proxy = require('proxy-agent');
if (process.env.AWS_PROXY) {
    AWS.config.update({
        httpOptions: {
            agent: proxy(process.env.AWS_PROXY)
        }
    });
}

var KmsUtils = function () {
    function KmsUtils() {
        (0, _classCallCheck3.default)(this, KmsUtils);

        this.KMS = new AWS.KMS({ region: process.env.GTM_AWS_REGION });
        this.primeStore();
        console.info('KmsUtils created');
    }

    (0, _createClass3.default)(KmsUtils, [{
        key: 'decrypt',
        value: function () {
            var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(encrypted) {
                var _this = this;

                return _regenerator2.default.wrap(function _callee$(_context) {
                    while (1) {
                        switch (_context.prev = _context.next) {
                            case 0:
                                if (!encrypted) {
                                    _context.next = 18;
                                    break;
                                }

                                if (process.env.GTM_AWS_KMS_KEY_ID) {
                                    _context.next = 7;
                                    break;
                                }

                                this.logger.warn('no encryption key configured, using raw values');
                                this.setDecrypted(encrypted, encrypted);
                                return _context.abrupt('return', encrypted);

                            case 7:
                                this.logger.info('decrypting: ' + encrypted);

                                if (!this.hasDecrypted(encrypted)) {
                                    _context.next = 11;
                                    break;
                                }

                                this.logger.info('returning stored decrypted value');
                                return _context.abrupt('return', this.getDecrypted(encrypted));

                            case 11:
                                _context.prev = 11;
                                return _context.abrupt('return', this.KMS.decrypt({ CiphertextBlob: new Buffer(encrypted, 'base64') }).promise().then(function (data) {
                                    _this.logger.info('storing decrypted result.');
                                    var decrypted = data.Plaintext.toString();
                                    _this.setDecrypted(encrypted, decrypted);
                                    return decrypted;
                                }));

                            case 15:
                                _context.prev = 15;
                                _context.t0 = _context['catch'](11);

                                this.logger.error(_context.t0);

                            case 18:
                            case 'end':
                                return _context.stop();
                        }
                    }
                }, _callee, this, [[11, 15]]);
            }));

            function decrypt(_x) {
                return _ref.apply(this, arguments);
            }

            return decrypt;
        }()
    }, {
        key: 'primeStore',
        value: function () {
            var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
                var _this2 = this;

                var promises;
                return _regenerator2.default.wrap(function _callee2$(_context2) {
                    while (1) {
                        switch (_context2.prev = _context2.next) {
                            case 0:
                                this.logger.info('priming decrypted var store');
                                promises = [];

                                (0, _keys2.default)(process.env).forEach(function (key) {
                                    if (key.startsWith('GTM_CRYPT_')) {
                                        promises.push(_this2.decrypt(process.env[key]));
                                        _this2.logger.info('decrypting value of ' + key);
                                    }
                                });
                                return _context2.abrupt('return', _promise2.default.all(promises));

                            case 4:
                            case 'end':
                                return _context2.stop();
                        }
                    }
                }, _callee2, this);
            }));

            function primeStore() {
                return _ref2.apply(this, arguments);
            }

            return primeStore;
        }()
    }, {
        key: 'hasDecrypted',
        value: function hasDecrypted(encrypted) {
            return (0, _keys2.default)(this.store).includes(encrypted);
        }
    }, {
        key: 'getDecrypted',
        value: function () {
            var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(encrypted) {
                return _regenerator2.default.wrap(function _callee3$(_context3) {
                    while (1) {
                        switch (_context3.prev = _context3.next) {
                            case 0:
                                if (!this.hasDecrypted(encrypted)) {
                                    _context3.next = 4;
                                    break;
                                }

                                return _context3.abrupt('return', this.store[encrypted]);

                            case 4:
                                this.logger.info('returning newly decrypted value');
                                _context3.next = 7;
                                return this.decrypt(encrypted).catch(function (e) {
                                    console.error('failed to decrypt ' + encrypted + '.  error: ' + (0, _stringify2.default)(e));
                                });

                            case 7:
                                return _context3.abrupt('return', _context3.sent);

                            case 8:
                            case 'end':
                                return _context3.stop();
                        }
                    }
                }, _callee3, this);
            }));

            function getDecrypted(_x2) {
                return _ref3.apply(this, arguments);
            }

            return getDecrypted;
        }()
    }, {
        key: 'setDecrypted',
        value: function setDecrypted(encrypted, decrypted) {
            this.store[encrypted] = decrypted;
        }
    }, {
        key: 'logger',
        get: function get() {
            if (!this._logger) this._logger = console;
            return this._logger;
        },
        set: function set(log) {
            if (log) this._logger = log;
        }
    }, {
        key: 'store',
        get: function get() {
            if (!this._store) this._store = {};
            return this._store;
        }
    }]);
    return KmsUtils;
}();

exports.default = new KmsUtils();