"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.find = find;
var _boom = _interopRequireDefault(require("@hapi/boom"));
var _lodash = require("lodash");
var _esQuery = require("@kbn/es-query");
var _ruleDataUtils = require("@kbn/rule-data-utils");
var _authorization = require("../../authorization");
var _audit_events = require("../common/audit_events");
var _common = require("../common");
var _mapped_params_utils = require("../common/mapped_params_utils");
var _constants = require("../common/constants");
var _get_alert_from_raw = require("../lib/get_alert_from_raw");
var _lib = 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 find(context, {
  options: {
    fields,
    filterConsumers,
    ...options
  } = {},
  excludeFromPublicApi = false,
  includeSnoozeData = false
} = {}) {
  var _ref;
  let authorizationTuple;
  try {
    authorizationTuple = await context.authorization.getFindAuthorizationFilter(_authorization.AlertingAuthorizationEntity.Rule, _constants.alertingAuthorizationFilterOpts, (0, _lodash.isEmpty)(filterConsumers) ? undefined : new Set(filterConsumers));
  } 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.FIND,
      error
    }));
    throw error;
  }
  const {
    filter: authorizationFilter,
    ensureRuleTypeIsAuthorized
  } = authorizationTuple;
  const filterKueryNode = (0, _common.buildKueryNodeFilter)(options.filter);
  let sortField = (0, _common.mapSortField)(options.sortField);
  if (excludeFromPublicApi) {
    try {
      (0, _common.validateOperationOnAttributes)(filterKueryNode, sortField, options.searchFields, context.fieldsToExcludeFromPublicApi);
    } catch (error) {
      throw _boom.default.badRequest(`Error find rules: ${error.message}`);
    }
  }
  sortField = (0, _common.mapSortField)((0, _mapped_params_utils.getModifiedField)(options.sortField));

  // Generate new modified search and search fields, translating certain params properties
  // to mapped_params. Thus, allowing for sort/search/filtering on params.
  // We do the modifcation after the validate check to make sure the public API does not
  // use the mapped_params in their queries.
  options = {
    ...options,
    ...(options.searchFields && {
      searchFields: (0, _mapped_params_utils.getModifiedSearchFields)(options.searchFields)
    }),
    ...(options.search && {
      search: (0, _mapped_params_utils.getModifiedSearch)(options.searchFields, options.search)
    })
  };

  // Modifies kuery node AST to translate params filter and the filter value to mapped_params.
  // This translation is done in place, and therefore is not a pure function.
  if (filterKueryNode) {
    (0, _mapped_params_utils.modifyFilterKueryNode)({
      astFilter: filterKueryNode
    });
  }
  const {
    page,
    per_page: perPage,
    total,
    saved_objects: data
  } = await context.unsecuredSavedObjectsClient.find({
    ...options,
    sortField,
    filter: (_ref = authorizationFilter && filterKueryNode ? _esQuery.nodeBuilder.and([filterKueryNode, authorizationFilter]) : authorizationFilter) !== null && _ref !== void 0 ? _ref : filterKueryNode,
    fields: fields ? (0, _common.includeFieldsRequiredForAuthentication)(fields) : fields,
    type: 'alert'
  });
  const siemRules = [];
  const authorizedData = data.map(({
    id,
    attributes,
    references
  }) => {
    try {
      ensureRuleTypeIsAuthorized(attributes.alertTypeId, attributes.consumer, _authorization.AlertingAuthorizationEntity.Rule);
    } catch (error) {
      var _context$auditLogger2;
      (_context$auditLogger2 = context.auditLogger) === null || _context$auditLogger2 === void 0 ? void 0 : _context$auditLogger2.log((0, _audit_events.ruleAuditEvent)({
        action: _audit_events.RuleAuditAction.FIND,
        savedObject: {
          type: 'alert',
          id
        },
        error
      }));
      throw error;
    }
    const rule = (0, _get_alert_from_raw.getAlertFromRaw)(context, id, attributes.alertTypeId, fields ? (0, _lodash.pick)(attributes, fields) : attributes, references, false, excludeFromPublicApi, includeSnoozeData);

    // collect SIEM rule for further formatting legacy actions
    if (attributes.consumer === _ruleDataUtils.AlertConsumers.SIEM) {
      siemRules.push(rule);
    }
    return rule;
  });
  authorizedData.forEach(({
    id
  }) => {
    var _context$auditLogger3;
    return (_context$auditLogger3 = context.auditLogger) === null || _context$auditLogger3 === void 0 ? void 0 : _context$auditLogger3.log((0, _audit_events.ruleAuditEvent)({
      action: _audit_events.RuleAuditAction.FIND,
      savedObject: {
        type: 'alert',
        id
      }
    }));
  });

  // format legacy actions for SIEM rules, if there any
  if (siemRules.length) {
    const formattedRules = await (0, _lib.formatLegacyActions)(siemRules, {
      savedObjectsClient: context.unsecuredSavedObjectsClient,
      logger: context.logger
    });
    const formattedRulesMap = formattedRules.reduce((acc, rule) => {
      acc[rule.id] = rule;
      return acc;
    }, {});
    return {
      page,
      perPage,
      total,
      // replace siem formatted rules
      data: authorizedData.map(rule => {
        var _formattedRulesMap$ru;
        return (_formattedRulesMap$ru = formattedRulesMap[rule.id]) !== null && _formattedRulesMap$ru !== void 0 ? _formattedRulesMap$ru : rule;
      })
    };
  }
  return {
    page,
    perPage,
    total,
    data: authorizedData
  };
}