"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.PolicyWatcher = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _coreSavedObjectsServer = require("@kbn/core-saved-objects-server");
var _lodash = require("lodash");
var _common = require("../../common");
var _agent_policy_config = require("../../common/services/agent_policy_config");
var _agent_policy = require("./agent_policy");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

class PolicyWatcher {
  constructor(soStart, esStart, logger) {
    (0, _defineProperty2.default)(this, "logger", void 0);
    (0, _defineProperty2.default)(this, "esClient", void 0);
    (0, _defineProperty2.default)(this, "subscription", void 0);
    (0, _defineProperty2.default)(this, "soStart", void 0);
    this.esClient = esStart.client.asInternalUser;
    this.logger = logger;
    this.soStart = soStart;
  }

  /**
   * The policy watcher is not called as part of a HTTP request chain, where the
   * request-scoped SOClient could be passed down. It is called via license observable
   * changes. We are acting as the 'system' in response to license changes, so we are
   * intentionally using the system user here. Be very aware of what you are using this
   * client to do
   */
  makeInternalSOClient(soStart) {
    const fakeRequest = {
      headers: {},
      getBasePath: () => '',
      path: '/',
      route: {
        settings: {}
      },
      url: {
        href: {}
      },
      raw: {
        req: {
          url: '/'
        }
      }
    };
    return soStart.getScopedClient(fakeRequest, {
      excludedExtensions: [_coreSavedObjectsServer.SECURITY_EXTENSION_ID]
    });
  }
  start(licenseService) {
    var _licenseService$getLi;
    this.subscription = (_licenseService$getLi = licenseService.getLicenseInformation$()) === null || _licenseService$getLi === void 0 ? void 0 : _licenseService$getLi.subscribe(this.watch.bind(this));
  }
  stop() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
  async watch(license) {
    let page = 1;
    let response;
    do {
      try {
        response = await _agent_policy.agentPolicyService.list(this.makeInternalSOClient(this.soStart), {
          page: page++,
          perPage: 100,
          kuery: _common.AGENT_POLICY_SAVED_OBJECT_TYPE
        });
      } catch (e) {
        this.logger.warn(`Unable to verify agent policies in line with license change: failed to fetch agent policies: ${e.message}`);
        return;
      }
      const updatedPolicyIds = [];
      for (const policy of response.items) {
        let updatePolicy = (0, _lodash.pick)(policy, ['is_protected']);
        try {
          if (!(0, _agent_policy_config.isAgentPolicyValidForLicense)(updatePolicy, license)) {
            updatePolicy = (0, _agent_policy_config.unsetAgentPolicyAccordingToLicenseLevel)(updatePolicy, license);
            try {
              this.logger.info('Updating agent policies per license change');
              await _agent_policy.agentPolicyService.update(this.makeInternalSOClient(this.soStart), this.esClient, policy.id, updatePolicy);
              // accumulate list of policies updated
              updatedPolicyIds.push(policy.id);
            } catch (e) {
              // try again for transient issues
              try {
                await _agent_policy.agentPolicyService.update(this.makeInternalSOClient(this.soStart), this.esClient, policy.id, updatePolicy);
              } catch (ee) {
                this.logger.warn(`Unable to remove platinum features from agent policy ${policy.id}`);
                this.logger.warn(ee);
              }
            }
          }
        } catch (error) {
          this.logger.warn(`Failure while attempting to verify features for agent policy [${policy.id}]`);
          this.logger.warn(error);
        }
      }
      this.logger.info(`Agent policies updated by license change: [${updatedPolicyIds.join()}]`);
    } while (response.page * response.perPage < response.total);
  }
}
exports.PolicyWatcher = PolicyWatcher;