"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.clone = clone;
var _semver = _interopRequireDefault(require("semver"));
var _boom = _interopRequireDefault(require("@hapi/boom"));
var _ruleDataUtils = require("@kbn/rule-data-utils");
var _server = require("@kbn/core/server");
var _apmUtils = require("@kbn/apm-utils");
var _lib = require("../../lib");
var _authorization = require("../../authorization");
var _parse_duration = require("../../../common/parse_duration");
var _audit_events = require("../common/audit_events");
var _rule_execution_status = require("../../lib/rule_execution_status");
var _utils = require("../../saved_objects/migrations/utils");
var _lib2 = require("../lib");
/*
 * 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.
 */

async function clone(context, id, {
  newId
}) {
  var _context$auditLogger2;
  let ruleSavedObject;
  try {
    ruleSavedObject = await (0, _apmUtils.withSpan)({
      name: 'encryptedSavedObjectsClient.getDecryptedAsInternalUser',
      type: 'rules'
    }, () => context.encryptedSavedObjectsClient.getDecryptedAsInternalUser('alert', id, {
      namespace: context.namespace
    }));
  } catch (e) {
    // We'll skip invalidating the API key since we failed to load the decrypted saved object
    context.logger.error(`update(): Failed to load API key to invalidate on alert ${id}: ${e.message}`);
    // Still attempt to load the object using SOC
    ruleSavedObject = await (0, _apmUtils.withSpan)({
      name: 'unsecuredSavedObjectsClient.get',
      type: 'rules'
    }, () => context.unsecuredSavedObjectsClient.get('alert', id));
  }

  /*
   * As the time of the creation of this PR, security solution already have a clone/duplicate API
   * with some specific business logic so to avoid weird bugs, I prefer to exclude them from this
   * functionality until we resolve our difference
   */
  if ((0, _utils.isDetectionEngineAADRuleType)(ruleSavedObject) || ruleSavedObject.attributes.consumer === _ruleDataUtils.AlertConsumers.SIEM) {
    throw _boom.default.badRequest('The clone functionality is not enable for rule who belongs to security solution');
  }
  const ruleName = ruleSavedObject.attributes.name.indexOf('[Clone]') > 0 ? ruleSavedObject.attributes.name : `${ruleSavedObject.attributes.name} [Clone]`;
  const ruleId = newId !== null && newId !== void 0 ? newId : _server.SavedObjectsUtils.generateId();
  try {
    await (0, _apmUtils.withSpan)({
      name: 'authorization.ensureAuthorized',
      type: 'rules'
    }, () => context.authorization.ensureAuthorized({
      ruleTypeId: ruleSavedObject.attributes.alertTypeId,
      consumer: ruleSavedObject.attributes.consumer,
      operation: _authorization.WriteOperations.Create,
      entity: _authorization.AlertingAuthorizationEntity.Rule
    }));
  } catch (error) {
    var _context$auditLogger;
    (_context$auditLogger = context.auditLogger) === null || _context$auditLogger === void 0 ? void 0 : _context$auditLogger.log((0, _audit_events.ruleAuditEvent)({
      action: _audit_events.RuleAuditAction.CREATE,
      savedObject: {
        type: 'alert',
        id
      },
      error
    }));
    throw error;
  }
  context.ruleTypeRegistry.ensureRuleTypeEnabled(ruleSavedObject.attributes.alertTypeId);
  // Throws an error if alert type isn't registered
  const ruleType = context.ruleTypeRegistry.get(ruleSavedObject.attributes.alertTypeId);
  const username = await context.getUserName();
  const createTime = Date.now();
  const lastRunTimestamp = new Date();
  const legacyId = _semver.default.lt(context.kibanaVersion, '8.0.0') ? id : null;
  const apiKeyAttributes = await (0, _lib2.createNewAPIKeySet)(context, {
    id: ruleType.id,
    ruleName,
    username,
    shouldUpdateApiKey: ruleSavedObject.attributes.enabled,
    errorMessage: 'Error creating rule: could not create API key'
  });
  const rawRule = {
    ...ruleSavedObject.attributes,
    name: ruleName,
    ...apiKeyAttributes,
    legacyId,
    createdBy: username,
    updatedBy: username,
    createdAt: new Date(createTime).toISOString(),
    updatedAt: new Date(createTime).toISOString(),
    snoozeSchedule: [],
    muteAll: false,
    mutedInstanceIds: [],
    executionStatus: (0, _rule_execution_status.getRuleExecutionStatusPendingAttributes)(lastRunTimestamp.toISOString()),
    monitoring: (0, _lib.getDefaultMonitoring)(lastRunTimestamp.toISOString()),
    revision: 0,
    scheduledTaskId: null,
    running: false
  };
  (_context$auditLogger2 = context.auditLogger) === null || _context$auditLogger2 === void 0 ? void 0 : _context$auditLogger2.log((0, _audit_events.ruleAuditEvent)({
    action: _audit_events.RuleAuditAction.CREATE,
    outcome: 'unknown',
    savedObject: {
      type: 'alert',
      id
    }
  }));
  return await (0, _apmUtils.withSpan)({
    name: 'createRuleSavedObject',
    type: 'rules'
  }, () => (0, _lib2.createRuleSavedObject)(context, {
    intervalInMs: (0, _parse_duration.parseDuration)(rawRule.schedule.interval),
    rawRule,
    references: ruleSavedObject.references,
    ruleId
  }));
}