diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index 87ac7096e5a35..b1c877bb3db0e 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -250,7 +250,7 @@ const getPipeline = (filename: string, removeSteps = true) => { /^packages\/kbn-securitysolution-.*/, /^x-pack\/plugins\/alerting/, /^x-pack\/plugins\/data_views\/common/, - /^x-pack\/plugins\/lists/, + /^x-pack\/solutions\/security\/plugins\/lists/, /^x-pack\/plugins\/rule_registry\/common/, /^x-pack\/solutions\/security\/plugins\/security_solution/, /^x-pack\/solutions\/security\/plugins\/security_solution_ess/, @@ -306,10 +306,10 @@ const getPipeline = (filename: string, removeSteps = true) => { /^packages\/kbn-search-types/, /^packages\/kbn-securitysolution-.*/, /^src\/platform\/packages\/shared\/kbn-securitysolution-ecs/, - /^packages\/kbn-securitysolution-io-ts-alerting-types/, - /^packages\/kbn-securitysolution-io-ts-list-types/, - /^packages\/kbn-securitysolution-list-hooks/, - /^packages\/kbn-securitysolution-t-grid/, + /^x-pack\/solutions\/security\/packages\/kbn-securitysolution-io-ts-alerting-types/, + /^x-pack\/solutions\/security\/packages\/kbn-securitysolution-io-ts-list-types/, + /^x-pack\/solutions\/security\/packages\/kbn-securitysolution-list-hooks/, + /^x-pack\/solutions\/security\/packages\/kbn-securitysolution-t-grid/, /^packages\/kbn-ui-theme/, /^packages\/kbn-utility-types/, /^packages\/react/, @@ -335,7 +335,7 @@ const getPipeline = (filename: string, removeSteps = true) => { /^x-pack\/plugins\/cases/, /^x-pack\/plugins\/data_views\/common/, /^x-pack\/solutions\/security\/plugins\/elastic_assistant/, - /^x-pack\/plugins\/lists/, + /^x-pack\/solutions\/security\/plugins\/lists/, /^x-pack\/plugins\/rule_registry\/common/, /^x-pack\/solutions\/security\/plugins\/security_solution/, /^x-pack\/solutions\/security\/plugins\/security_solution_ess/, diff --git a/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh index db7131d127856..13bd0aaf7189a 100755 --- a/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh +++ b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh @@ -10,13 +10,13 @@ echo -e "\n[Security Solution OpenAPI Code Generation] OpenAPI Common Package\n" (cd packages/kbn-openapi-common && yarn openapi:generate) echo -e "\n[Security Solution OpenAPI Code Generation] Lists Common Package\n" -(cd packages/kbn-securitysolution-lists-common && yarn openapi:generate) +(cd x-pack/solutions/security/packages/kbn-securitysolution-lists-common && yarn openapi:generate) echo -e "\n[Security Solution OpenAPI Code Generation] Exceptions Common Package\n" -(cd packages/kbn-securitysolution-exceptions-common && yarn openapi:generate) +(cd x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common && yarn openapi:generate) echo -e "\n[Security Solution OpenAPI Code Generation] Endpoint Exceptions Common Package\n" -(cd packages/kbn-securitysolution-endpoint-exceptions-common && yarn openapi:generate) +(cd x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common && yarn openapi:generate) echo -e "\n[Security Solution OpenAPI Code Generation] Security Solution Plugin\n" (cd x-pack/solutions/security/plugins/security_solution && yarn openapi:generate) diff --git a/.buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh b/.buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh index 18d2c963b3c24..4dd23435e351d 100755 --- a/.buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh +++ b/.buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh @@ -16,13 +16,13 @@ echo -e "\n[Security Solution OpenAPI Bundling] Entity Analytics API\n" (cd x-pack/solutions/security/plugins/security_solution && yarn openapi:bundle:entity-analytics) echo -e "\n[Security Solution OpenAPI Bundling] Lists API\n" -(cd packages/kbn-securitysolution-lists-common && yarn openapi:bundle) +(cd x-pack/solutions/security/packages/kbn-securitysolution-lists-common && yarn openapi:bundle) echo -e "\n[Security Solution OpenAPI Bundling] Exceptions API\n" -(cd packages/kbn-securitysolution-exceptions-common && yarn openapi:bundle) +(cd x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common && yarn openapi:bundle) echo -e "\n[Security Solution OpenAPI Bundling] Endpoint Exceptions API\n" -(cd packages/kbn-securitysolution-endpoint-exceptions-common && yarn openapi:bundle) +(cd x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common && yarn openapi:bundle) echo -e "\n[Security Solution OpenAPI Bundling] Endpoint Management API\n" (cd x-pack/solutions/security/plugins/security_solution && yarn openapi:bundle:endpoint-management) diff --git a/.eslintrc.js b/.eslintrc.js index 6bf88444aaf70..93e3dabf3b861 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1343,8 +1343,8 @@ module.exports = { { // front end and common typescript and javascript files only files: [ - 'x-pack/plugins/lists/public/**/*.{js,mjs,ts,tsx}', - 'x-pack/plugins/lists/common/**/*.{js,mjs,ts,tsx}', + 'x-pack/solutions/security/plugins/lists/public/**/*.{js,mjs,ts,tsx}', + 'x-pack/solutions/security/plugins/lists/common/**/*.{js,mjs,ts,tsx}', ], rules: { 'import/no-nodejs-modules': 'error', @@ -1360,14 +1360,20 @@ module.exports = { }, { // typescript for /public and /common - files: ['x-pack/plugins/lists/public/*.{ts,tsx}', 'x-pack/plugins/lists/common/*.{ts,tsx}'], + files: [ + 'x-pack/solutions/security/plugins/lists/public/*.{ts,tsx}', + 'x-pack/solutions/security/plugins/lists/common/*.{ts,tsx}', + ], rules: { '@typescript-eslint/no-for-in-array': 'error', }, }, { // typescript for /public and /common - files: ['x-pack/plugins/lists/public/*.{ts,tsx}', 'x-pack/plugins/lists/common/*.{ts,tsx}'], + files: [ + 'x-pack/solutions/security/plugins/lists/public/*.{ts,tsx}', + 'x-pack/solutions/security/plugins/lists/common/*.{ts,tsx}', + ], plugins: ['react'], env: { jest: true, @@ -1425,7 +1431,7 @@ module.exports = { }, }, { - files: ['x-pack/plugins/lists/public/**/!(*.test).{js,mjs,ts,tsx}'], + files: ['x-pack/solutions/security/plugins/lists/public/**/!(*.test).{js,mjs,ts,tsx}'], plugins: ['react-perf'], rules: { 'react-perf/jsx-no-new-object-as-prop': 'error', @@ -1436,7 +1442,7 @@ module.exports = { }, { // typescript and javascript for front and back - files: ['x-pack/plugins/lists/**/*.{js,mjs,ts,tsx}'], + files: ['x-pack/solutions/security/plugins/lists/**/*.{js,mjs,ts,tsx}'], plugins: ['eslint-plugin-node'], env: { jest: true, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 627579d513e9f..882ff38a38b00 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -454,24 +454,6 @@ packages/kbn-search-index-documents @elastic/search-kibana packages/kbn-search-response-warnings @elastic/kibana-data-discovery packages/kbn-search-types @elastic/kibana-data-discovery packages/kbn-security-hardening @elastic/kibana-security -packages/kbn-securitysolution-autocomplete @elastic/security-detection-engine -packages/kbn-securitysolution-endpoint-exceptions-common @elastic/security-detection-engine -packages/kbn-securitysolution-es-utils @elastic/security-detection-engine -packages/kbn-securitysolution-exception-list-components @elastic/security-detection-engine -packages/kbn-securitysolution-exceptions-common @elastic/security-detection-engine -packages/kbn-securitysolution-hook-utils @elastic/security-detection-engine -packages/kbn-securitysolution-io-ts-alerting-types @elastic/security-detection-engine -packages/kbn-securitysolution-io-ts-list-types @elastic/security-detection-engine -packages/kbn-securitysolution-io-ts-types @elastic/security-detection-engine -packages/kbn-securitysolution-io-ts-utils @elastic/security-detection-engine -packages/kbn-securitysolution-list-api @elastic/security-detection-engine -packages/kbn-securitysolution-list-constants @elastic/security-detection-engine -packages/kbn-securitysolution-list-hooks @elastic/security-detection-engine -packages/kbn-securitysolution-list-utils @elastic/security-detection-engine -packages/kbn-securitysolution-lists-common @elastic/security-detection-engine -packages/kbn-securitysolution-rules @elastic/security-detection-engine -packages/kbn-securitysolution-t-grid @elastic/security-detection-engine -packages/kbn-securitysolution-utils @elastic/security-detection-engine packages/kbn-server-http-tools @elastic/kibana-core packages/kbn-set-map @elastic/kibana-operations packages/kbn-shared-svg @elastic/obs-ux-infra_services-team @@ -615,6 +597,10 @@ src/platform/packages/shared/kbn-management/settings/types @elastic/kibana-manag src/platform/packages/shared/kbn-management/settings/utilities @elastic/kibana-management src/platform/packages/shared/kbn-osquery-io-ts-types @elastic/security-asset-management src/platform/packages/shared/kbn-securitysolution-ecs @elastic/security-threat-hunting-explore +src/platform/packages/shared/kbn-securitysolution-es-utils @elastic/security-detection-engine +src/platform/packages/shared/kbn-securitysolution-io-ts-types @elastic/security-detection-engine +src/platform/packages/shared/kbn-securitysolution-io-ts-utils @elastic/security-detection-engine +src/platform/packages/shared/kbn-securitysolution-rules @elastic/security-detection-engine src/platform/packages/shared/kbn-server-route-repository @elastic/obs-knowledge-team src/platform/packages/shared/kbn-server-route-repository-client @elastic/obs-knowledge-team src/platform/packages/shared/kbn-server-route-repository-utils @elastic/obs-knowledge-team @@ -909,7 +895,6 @@ x-pack/plugins/graph @elastic/kibana-visualizations x-pack/plugins/index_management @elastic/kibana-management x-pack/plugins/lens @elastic/kibana-visualizations x-pack/plugins/licensing @elastic/kibana-core -x-pack/plugins/lists @elastic/security-detection-engine x-pack/plugins/logstash @elastic/logstash x-pack/plugins/maps @elastic/kibana-presentation x-pack/plugins/monitoring @elastic/stack-monitoring @@ -986,6 +971,20 @@ x-pack/solutions/security/packages/features @elastic/security-threat-hunting-exp x-pack/solutions/security/packages/index-adapter @elastic/security-threat-hunting x-pack/solutions/security/packages/kbn-cloud-security-posture/graph @elastic/kibana-cloud-security-posture x-pack/solutions/security/packages/kbn-cloud-security-posture/public @elastic/kibana-cloud-security-posture +x-pack/solutions/security/packages/kbn-securitysolution-autocomplete @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-hook-utils @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-list-api @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-list-constants @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-list-hooks @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-list-utils @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-lists-common @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-t-grid @elastic/security-detection-engine +x-pack/solutions/security/packages/kbn-securitysolution-utils @elastic/security-detection-engine x-pack/solutions/security/packages/navigation @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/side_nav @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/storybook/config @elastic/security-threat-hunting-explore @@ -996,6 +995,7 @@ x-pack/solutions/security/plugins/cloud_security_posture @elastic/kibana-cloud-s x-pack/solutions/security/plugins/ecs_data_quality_dashboard @elastic/security-threat-hunting-explore x-pack/solutions/security/plugins/elastic_assistant @elastic/security-generative-ai x-pack/solutions/security/plugins/kubernetes_security @elastic/kibana-cloud-security-posture +x-pack/solutions/security/plugins/lists @elastic/security-detection-engine x-pack/solutions/security/plugins/security_solution @elastic/security-solution x-pack/solutions/security/plugins/security_solution_ess @elastic/security-solution x-pack/solutions/security/plugins/security_solution_serverless @elastic/security-solution @@ -3354,20 +3354,20 @@ x-pack/solutions/security/packages/kbn-cloud-security-posture/public @elastic/ki x-pack/solutions/security/packages/data-stream-adapter @elastic/security-threat-hunting x-pack/solutions/security/packages/expandable-flyout @elastic/security-threat-hunting-investigations x-pack/solutions/security/packages/index-adapter @elastic/security-threat-hunting -x-pack/solutions/security/packages/kbn-securitysolution-autocomplete @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-hook-utils @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-list-api @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-list-constants @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-list-hooks @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-list-utils @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-lists-common @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-t-grid @elastic/security-detection-engine -x-pack/solutions/security/packages/kbn-securitysolution-utils @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-list-api @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-list-constants @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-list-utils @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-lists-common @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-t-grid @elastic/security-detection-engine +x-pack/solutions/security/x-pack/solutions/security/packages/kbn-securitysolution-utils @elastic/security-detection-engine x-pack/solutions/security/packages/navigation @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/side_nav @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/upselling @elastic/security-threat-hunting-explore @@ -3377,7 +3377,7 @@ x-pack/solutions/security/plugins/cloud_security_posture @elastic/kibana-cloud-s x-pack/solutions/security/plugins/ecs_data_quality_dashboard @elastic/security-threat-hunting-explore x-pack/solutions/security/plugins/elastic_assistant @elastic/security-generative-ai x-pack/solutions/security/plugins/kubernetes_security @elastic/kibana-cloud-security-posture -x-pack/solutions/security/plugins/lists @elastic/security-detection-engine +x-pack/solutions/security/solutions/security/plugins/lists @elastic/security-detection-engine x-pack/solutions/security/solutions/security/plugins/security_solution @elastic/security-solution x-pack/solutions/security/solutions/security/plugins/security_solution_ess @elastic/security-solution x-pack/solutions/security/solutions/security/plugins/security_solution_serverless @elastic/security-solution diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 8ad946732714b..3077ac0f51674 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -78,8 +78,8 @@ paths-ignore: - x-pack/solutions/security/plugins/elastic_assistant/scripts - x-pack/plugins/event_log/scripts - x-pack/plugins/fleet/scripts - - x-pack/plugins/lists/scripts - - x-pack/plugins/lists/server/scripts + - x-pack/solutions/security/plugins/lists/scripts + - x-pack/solutions/security/plugins/lists/server/scripts - x-pack/plugins/observability_solution/*/scripts - x-pack/platform/plugins/shared/osquery/scripts - x-pack/plugins/rule_registry/scripts diff --git a/.i18nrc.json b/.i18nrc.json index 63cbc62d13650..0e167c2b08b54 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -6,7 +6,7 @@ "alertsUIShared": "packages/kbn-alerts-ui-shared/src", "alertingTypes": "packages/kbn-alerting-types", "apmOss": "src/plugins/apm_oss", - "autocomplete": "packages/kbn-securitysolution-autocomplete/src", + "autocomplete": "x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src", "avcBanner": "src/platform/packages/shared/kbn-avc-banner/src", "bfetch": "src/plugins/bfetch", "bfetchError": "packages/kbn-bfetch-error", @@ -25,12 +25,13 @@ "data": "src/plugins/data", "observabilityAlertDetails": "x-pack/solutions/observability/packages/alert_details", "dataViews": "src/plugins/data_views", - "defaultNavigation": [ - "packages/default-nav", - "src/platform/packages/private/default-nav" - ], + "defaultNavigation": ["packages/default-nav", "src/platform/packages/private/default-nav"], "devTools": "src/platform/plugins/shared/dev_tools", - "discover": ["src/plugins/discover", "packages/kbn-discover-utils", "packages/kbn-discover-contextual-components"], + "discover": [ + "src/plugins/discover", + "packages/kbn-discover-utils", + "packages/kbn-discover-contextual-components" + ], "savedSearch": "src/plugins/saved_search", "embeddableApi": "src/plugins/embeddable", "presentationPanel": "src/plugins/presentation_panel", @@ -87,8 +88,8 @@ "kibana-react": "src/plugins/kibana_react", "kibanaOverview": "src/plugins/kibana_overview", "lensFormulaDocs": "packages/kbn-lens-formula-docs", - "lists": "packages/kbn-securitysolution-list-utils/src", - "exceptionList-components": "packages/kbn-securitysolution-exception-list-components/src", + "lists": "x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src", + "exceptionList-components": "x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src", "management": [ "src/platform/plugins/shared/management", "src/platform/packages/private/kbn-management", @@ -120,11 +121,15 @@ "searchResponseWarnings": "packages/kbn-search-response-warnings", "searchTypes": "packages/kbn-search-types", "securitySolutionPackages": [ - "x-pack/solutions/security/packages" - ], - "sharedPlatformPackages": [ - "x-pack/platform/packages/shared/kbn-cloud-security-posture" + "x-pack/solutions/security/packages/data_table", + "x-pack/solutions/security/packages/ecs_data_quality_dashboard", + "x-pack/solutions/security/packages/features", + "x-pack/solutions/security/packages/kbn-cloud-security-posture", + "x-pack/solutions/security/packages/navigation", + "x-pack/solutions/security/packages/side_nav", + "x-pack/solutions/security/packages/upselling" ], + "sharedPlatformPackages": ["x-pack/platform/packages/shared/kbn-cloud-security-posture"], "serverlessPackages": "packages/serverless", "sse": ["src/platform/packages/shared/kbn-sse-utils"], "coloring": "packages/kbn-coloring/src", @@ -140,7 +145,7 @@ "uiActionsExamples": "examples/ui_action_examples", "usageCollection": "src/plugins/usage_collection", "userProfileComponents": "packages/kbn-user-profile-components", - "utils": "packages/kbn-securitysolution-utils/src", + "utils": "x-pack/solutions/security/packages/kbn-securitysolution-utils/src", "visDefaultEditor": "src/plugins/vis_default_editor", "visTypeGauge": "src/plugins/vis_types/gauge", "visTypeHeatmap": "src/plugins/vis_types/heatmap", diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index f18bafe5221b3..9da7cdbdceee8 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -693,7 +693,7 @@ the infrastructure monitoring use-case within Kibana. |The licensing plugin retrieves license data from Elasticsearch at regular configurable intervals. -|{kib-repo}blob/{branch}/x-pack/plugins/lists/README.md[lists] +|{kib-repo}blob/{branch}/x-pack/solutions/security/plugins/lists/README.md[lists] |README.md for developers working on the backend lists on how to get started using the CURL scripts in the scripts folder. diff --git a/oas_docs/scripts/merge_ess_oas.js b/oas_docs/scripts/merge_ess_oas.js index 3d96ad5b5933f..df0b6e5a4ac04 100644 --- a/oas_docs/scripts/merge_ess_oas.js +++ b/oas_docs/scripts/merge_ess_oas.js @@ -27,9 +27,9 @@ const { REPO_ROOT } = require('@kbn/repo-info'); // Security solution `${REPO_ROOT}/x-pack/solutions/security/plugins/security_solution/docs/openapi/ess/*.schema.yaml`, - `${REPO_ROOT}/packages/kbn-securitysolution-lists-common/docs/openapi/ess/*.schema.yaml`, - `${REPO_ROOT}/packages/kbn-securitysolution-exceptions-common/docs/openapi/ess/*.schema.yaml`, - `${REPO_ROOT}/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/ess/*.schema.yaml`, + `${REPO_ROOT}/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/docs/openapi/ess/*.schema.yaml`, + `${REPO_ROOT}/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/docs/openapi/ess/*.schema.yaml`, + `${REPO_ROOT}/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/ess/*.schema.yaml`, `${REPO_ROOT}/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/ess/*.schema.yaml`, `${REPO_ROOT}/x-pack/platform/plugins/shared/osquery/docs/openapi/ess/*.schema.yaml`, ], diff --git a/oas_docs/scripts/merge_serverless_oas.js b/oas_docs/scripts/merge_serverless_oas.js index 2f92195502db1..343487d8fc4f8 100644 --- a/oas_docs/scripts/merge_serverless_oas.js +++ b/oas_docs/scripts/merge_serverless_oas.js @@ -25,9 +25,9 @@ const { REPO_ROOT } = require('@kbn/repo-info'); // Security solution `${REPO_ROOT}/x-pack/solutions/security/plugins/security_solution/docs/openapi/serverless/*.schema.yaml`, - `${REPO_ROOT}/packages/kbn-securitysolution-lists-common/docs/openapi/serverless/*.schema.yaml`, - `${REPO_ROOT}/packages/kbn-securitysolution-exceptions-common/docs/openapi/serverless/*.schema.yaml`, - `${REPO_ROOT}/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/serverless/*.schema.yaml`, + `${REPO_ROOT}/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/docs/openapi/serverless/*.schema.yaml`, + `${REPO_ROOT}/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/docs/openapi/serverless/*.schema.yaml`, + `${REPO_ROOT}/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/serverless/*.schema.yaml`, `${REPO_ROOT}/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/serverless/*.schema.yaml`, `${REPO_ROOT}/x-pack/platform/plugins/shared/osquery/docs/openapi/serverless/*.schema.yaml`, ], diff --git a/package.json b/package.json index ee007b076af4a..d4f8f9a4c6891 100644 --- a/package.json +++ b/package.json @@ -619,7 +619,7 @@ "@kbn/license-management-plugin": "link:x-pack/platform/plugins/shared/license_management", "@kbn/licensing-plugin": "link:x-pack/plugins/licensing", "@kbn/links-plugin": "link:src/plugins/links", - "@kbn/lists-plugin": "link:x-pack/plugins/lists", + "@kbn/lists-plugin": "link:x-pack/solutions/security/plugins/lists", "@kbn/llm-tasks-plugin": "link:x-pack/platform/plugins/shared/ai_infra/llm_tasks", "@kbn/locator-examples-plugin": "link:examples/locator_examples", "@kbn/locator-explorer-plugin": "link:examples/locator_explorer", @@ -839,26 +839,26 @@ "@kbn/security-solution-upselling": "link:x-pack/solutions/security/packages/upselling", "@kbn/security-test-endpoints-plugin": "link:x-pack/test/security_functional/plugins/test_endpoints", "@kbn/security-ui-components": "link:x-pack/packages/security/ui_components", - "@kbn/securitysolution-autocomplete": "link:packages/kbn-securitysolution-autocomplete", + "@kbn/securitysolution-autocomplete": "link:x-pack/solutions/security/packages/kbn-securitysolution-autocomplete", "@kbn/securitysolution-data-table": "link:x-pack/solutions/security/packages/data_table", "@kbn/securitysolution-ecs": "link:src/platform/packages/shared/kbn-securitysolution-ecs", - "@kbn/securitysolution-endpoint-exceptions-common": "link:packages/kbn-securitysolution-endpoint-exceptions-common", - "@kbn/securitysolution-es-utils": "link:packages/kbn-securitysolution-es-utils", - "@kbn/securitysolution-exception-list-components": "link:packages/kbn-securitysolution-exception-list-components", - "@kbn/securitysolution-exceptions-common": "link:packages/kbn-securitysolution-exceptions-common", - "@kbn/securitysolution-hook-utils": "link:packages/kbn-securitysolution-hook-utils", - "@kbn/securitysolution-io-ts-alerting-types": "link:packages/kbn-securitysolution-io-ts-alerting-types", - "@kbn/securitysolution-io-ts-list-types": "link:packages/kbn-securitysolution-io-ts-list-types", - "@kbn/securitysolution-io-ts-types": "link:packages/kbn-securitysolution-io-ts-types", - "@kbn/securitysolution-io-ts-utils": "link:packages/kbn-securitysolution-io-ts-utils", - "@kbn/securitysolution-list-api": "link:packages/kbn-securitysolution-list-api", - "@kbn/securitysolution-list-constants": "link:packages/kbn-securitysolution-list-constants", - "@kbn/securitysolution-list-hooks": "link:packages/kbn-securitysolution-list-hooks", - "@kbn/securitysolution-list-utils": "link:packages/kbn-securitysolution-list-utils", - "@kbn/securitysolution-lists-common": "link:packages/kbn-securitysolution-lists-common", - "@kbn/securitysolution-rules": "link:packages/kbn-securitysolution-rules", - "@kbn/securitysolution-t-grid": "link:packages/kbn-securitysolution-t-grid", - "@kbn/securitysolution-utils": "link:packages/kbn-securitysolution-utils", + "@kbn/securitysolution-endpoint-exceptions-common": "link:x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common", + "@kbn/securitysolution-es-utils": "link:src/platform/packages/shared/kbn-securitysolution-es-utils", + "@kbn/securitysolution-exception-list-components": "link:x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components", + "@kbn/securitysolution-exceptions-common": "link:x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common", + "@kbn/securitysolution-hook-utils": "link:x-pack/solutions/security/packages/kbn-securitysolution-hook-utils", + "@kbn/securitysolution-io-ts-alerting-types": "link:x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types", + "@kbn/securitysolution-io-ts-list-types": "link:x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types", + "@kbn/securitysolution-io-ts-types": "link:src/platform/packages/shared/kbn-securitysolution-io-ts-types", + "@kbn/securitysolution-io-ts-utils": "link:src/platform/packages/shared/kbn-securitysolution-io-ts-utils", + "@kbn/securitysolution-list-api": "link:x-pack/solutions/security/packages/kbn-securitysolution-list-api", + "@kbn/securitysolution-list-constants": "link:x-pack/solutions/security/packages/kbn-securitysolution-list-constants", + "@kbn/securitysolution-list-hooks": "link:x-pack/solutions/security/packages/kbn-securitysolution-list-hooks", + "@kbn/securitysolution-list-utils": "link:x-pack/solutions/security/packages/kbn-securitysolution-list-utils", + "@kbn/securitysolution-lists-common": "link:x-pack/solutions/security/packages/kbn-securitysolution-lists-common", + "@kbn/securitysolution-rules": "link:src/platform/packages/shared/kbn-securitysolution-rules", + "@kbn/securitysolution-t-grid": "link:x-pack/solutions/security/packages/kbn-securitysolution-t-grid", + "@kbn/securitysolution-utils": "link:x-pack/solutions/security/packages/kbn-securitysolution-utils", "@kbn/server-http-tools": "link:packages/kbn-server-http-tools", "@kbn/server-route-repository": "link:src/platform/packages/shared/kbn-server-route-repository", "@kbn/server-route-repository-client": "link:src/platform/packages/shared/kbn-server-route-repository-client", diff --git a/packages/kbn-babel-preset/styled_components_files.js b/packages/kbn-babel-preset/styled_components_files.js index 2a74c5b60f181..60dbb2b1053de 100644 --- a/packages/kbn-babel-preset/styled_components_files.js +++ b/packages/kbn-babel-preset/styled_components_files.js @@ -16,12 +16,13 @@ module.exports = { /packages[\/\\]kbn-ui-shared-deps-(npm|src)[\/\\]/, /src[\/\\]plugins[\/\\](kibana_react)[\/\\]/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\](exploratory_view|investigate|investigate_app|observability|observability_ai_assistant_app|observability_ai_assistant_management|observability_solution|serverless_observability|streams|streams_app|synthetics|uptime|ux)[\/\\]/, - /x-pack[\/\\]plugins[\/\\](observability_solution\/apm|beats_management|fleet|lists|observability_solution\/observability|observability_solution\/observability_shared|observability_solution\/exploratory_view|security_solution|timelines|observability_solution\/synthetics|observability_solution\/ux|observability_solution\/uptime)[\/\\]/, + /x-pack[\/\\]plugins[\/\\](observability_solution\/apm|beats_management|fleet|observability_solution\/observability|observability_solution\/observability_shared|observability_solution\/exploratory_view|security_solution|timelines|observability_solution\/synthetics|observability_solution\/ux|observability_solution\/uptime)[\/\\]/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\](observability_solution\/apm|beats_management|fleet|observability_solution\/infra|lists|observability_solution\/observability|observability_solution\/observability_shared|observability_solution\/exploratory_view|security_solution|timelines|observability_solution\/synthetics|observability_solution\/ux|observability_solution\/uptime)[\/\\]/, /x-pack[\/\\]test[\/\\]plugin_functional[\/\\]plugins[\/\\]resolver_test[\/\\]/, /x-pack[\/\\]packages[\/\\]elastic_assistant[\/\\]/, /x-pack[\/\\]solutions[\/\\]security[\/\\]packages[\/\\]ecs_data_quality_dashboard[\/\\]/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]/, /x-pack[\/\\]platform[\/\\]packages[\/\\]shared[\/\\]kbn-elastic-assistant[\/\\]/, + /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]lists/, ], }; diff --git a/packages/kbn-securitysolution-autocomplete/index.ts b/packages/kbn-securitysolution-autocomplete/index.ts deleted file mode 100644 index e47113719176f..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/check_empty_value'; -export * from './src/es_field_selector'; -export * from './src/field_value_exists'; -export * from './src/field_value_lists'; -export * from './src/field_value_match'; -export * from './src/field_value_match_any'; -export * from './src/field_value_wildcard'; -export * from './src/filter_field_to_list'; -export * from './src/get_generic_combo_box_props'; -export * from './src/get_operators'; -export * from './src/hooks'; -export * from './src/operator'; -export * from './src/param_is_valid'; -export * from './src/param_contains_space'; - -export { default as autoCompletei18n } from './src/translations'; diff --git a/packages/kbn-securitysolution-autocomplete/jest.config.js b/packages/kbn-securitysolution-autocomplete/jest.config.js deleted file mode 100644 index b7d1e59f77866..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-autocomplete'], -}; diff --git a/packages/kbn-securitysolution-autocomplete/package.json b/packages/kbn-securitysolution-autocomplete/package.json deleted file mode 100644 index f841706e57a7e..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/securitysolution-autocomplete", - "version": "1.0.0", - "description": "Security Solution auto complete", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-autocomplete/src/autocomplete/index.mock.ts b/packages/kbn-securitysolution-autocomplete/src/autocomplete/index.mock.ts deleted file mode 100644 index 71bfb7f4a67cd..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/autocomplete/index.mock.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -// Copied from "src/plugins/data/public/mocks.ts" but without any type information -// TODO: Remove this in favor of the data/public/mocks if/when they become available, https://github.com/elastic/kibana/issues/100715 -export const autocompleteStartMock = { - getQuerySuggestions: jest.fn(), - getValueSuggestions: jest.fn(), - hasQuerySuggestions: jest.fn(), -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.test.ts deleted file mode 100644 index d98feca80b75b..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { checkEmptyValue } from '.'; -import { getField } from '../fields/index.mock'; -import * as i18n from '../translations'; - -describe('check_empty_value', () => { - test('returns no errors if no field has been selected', () => { - const isValid = checkEmptyValue('', undefined, true, false); - - expect(isValid).toBeUndefined(); - }); - - test('returns error string if user has touched a required input and left empty', () => { - const isValid = checkEmptyValue(undefined, getField('@timestamp'), true, true); - - expect(isValid).toEqual(i18n.FIELD_REQUIRED_ERR); - }); - - test('returns no errors if required input is empty but user has not yet touched it', () => { - const isValid = checkEmptyValue(undefined, getField('@timestamp'), true, false); - - expect(isValid).toBeUndefined(); - }); - - test('returns no errors if user has touched an input that is not required and left empty', () => { - const isValid = checkEmptyValue(undefined, getField('@timestamp'), false, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns no errors if user has touched an input that is not required and left empty string', () => { - const isValid = checkEmptyValue('', getField('@timestamp'), false, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns null if input value is not empty string or undefined', () => { - const isValid = checkEmptyValue('hellooo', getField('@timestamp'), false, true); - - expect(isValid).toBeNull(); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.ts b/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.ts deleted file mode 100644 index 218b8fee94d1e..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewFieldBase } from '@kbn/es-query'; -import * as i18n from '../translations'; - -/** - * Determines if empty value is ok - */ -export const checkEmptyValue = ( - param: string | undefined, - field: DataViewFieldBase | undefined, - isRequired: boolean, - touched: boolean -): string | undefined | null => { - if (isRequired && touched && (param == null || param.trim() === '')) { - return i18n.FIELD_REQUIRED_ERR; - } - - if ( - field == null || - (isRequired && !touched) || - (!isRequired && (param == null || param === '')) - ) { - return undefined; - } - - return null; -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/disabled_types_with_tooltip_text.test.ts b/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/disabled_types_with_tooltip_text.test.ts deleted file mode 100644 index 980819d1cedf1..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/disabled_types_with_tooltip_text.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { disabledTypesWithTooltipText } from '../disabled_types_with_tooltip_text'; - -jest.mock('../../translations', () => ({ - BINARY_TYPE_NOT_SUPPORTED: 'Binary fields are currently unsupported', -})); -describe('disabledTypesWithTooltipText', () => { - it('should return Binary fields are currently unsupported for binary type', () => { - const type = 'binary'; - expect(disabledTypesWithTooltipText[type]).toEqual('Binary fields are currently unsupported'); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/index.test.tsx deleted file mode 100644 index 1b33b4b294644..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/index.test.tsx +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { fireEvent, render, waitFor, within } from '@testing-library/react'; -import '@testing-library/jest-dom'; - -import { EsFieldSelector } from '..'; -import { fields, getField } from '../../fields/index.mock'; - -describe('FieldComponent', () => { - it('should render the component enabled and displays the selected field correctly', () => { - const wrapper = render( - - ); - expect(wrapper.container).toMatchSnapshot(); - const comboBox = wrapper.getByTestId('fieldAutocompleteComboBox'); - const input = within(comboBox).getByRole('combobox'); - expect(input).toHaveAttribute('value', 'machine.os.raw'); - }); - it('should render the component disabled if isDisabled is true', () => { - const wrapper = render( - - ); - expect(wrapper.container).toMatchSnapshot(); - expect(wrapper.getByTestId('fieldAutocompleteComboBox').querySelector('input')).toBeDisabled(); - }); - it('should render the loading spinner if isLoading is true when clicked', () => { - const wrapper = render( - - ); - const fieldAutocompleteComboBox = wrapper.getByTestId('fieldAutocompleteComboBox'); - expect(wrapper.container).toMatchSnapshot(); - fireEvent.click(fieldAutocompleteComboBox); - expect(wrapper.getByRole('progressbar')).toBeInTheDocument(); - }); - it('should allow user to clear values if isClearable is true', () => { - const wrapper = render( - - ); - expect(wrapper.container).toMatchSnapshot(); - expect(wrapper.getByTestId('comboBoxClearButton')).toBeInTheDocument(); - }); - it('should change the selected value', async () => { - const wrapper = render( - - ); - const fieldAutocompleteComboBox = wrapper.getByTestId('comboBoxSearchInput'); - fireEvent.change(fieldAutocompleteComboBox, { target: { value: '_source' } }); - expect(fieldAutocompleteComboBox).toHaveValue('_source'); - }); - - it('it allows custom user input if "acceptsCustomOptions" is "true"', async () => { - const mockOnChange = jest.fn(); - const wrapper = render( - - ); - - const fieldAutocompleteComboBox = wrapper.getByTestId('comboBoxSearchInput'); - fireEvent.change(fieldAutocompleteComboBox, { target: { value: 'custom' } }); - await waitFor(() => - expect(wrapper.getByTestId('fieldAutocompleteComboBox')).toHaveTextContent('custom') - ); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/disabled_types_with_tooltip_text.ts b/packages/kbn-securitysolution-autocomplete/src/es_field_selector/disabled_types_with_tooltip_text.ts deleted file mode 100644 index 422a909bb9910..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/disabled_types_with_tooltip_text.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -interface DisabledTypesTextType { - [typeName: string]: string; -} -import * as i18n from '../translations'; - -export const disabledTypesWithTooltipText: DisabledTypesTextType = { - binary: i18n.BINARY_TYPE_NOT_SUPPORTED, -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/index.tsx b/packages/kbn-securitysolution-autocomplete/src/es_field_selector/index.tsx deleted file mode 100644 index 31efaa23b62df..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/index.tsx +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { EuiComboBox } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { FieldBaseProps } from './types'; -import { useEsField } from './use_es_field'; - -const AS_PLAIN_TEXT = { asPlainText: true }; - -interface EsFieldSelectorProps extends FieldBaseProps { - isClearable?: boolean; - isDisabled?: boolean; - isLoading?: boolean; - placeholder: string; - acceptsCustomOptions?: boolean; - showMappingConflicts?: boolean; - 'aria-label'?: string; -} - -export function EsFieldSelector({ - fieldInputWidth, - fieldTypeFilter = [], - indexPattern, - isClearable = false, - isDisabled = false, - isLoading = false, - isRequired = false, - onChange, - placeholder, - selectedField, - acceptsCustomOptions = false, - showMappingConflicts = false, - 'aria-label': ariaLabel, -}: EsFieldSelectorProps): JSX.Element { - const { - isInvalid, - comboOptions, - selectedComboOptions, - fieldWidth, - renderFields, - handleTouch, - handleValuesChange, - handleCreateCustomOption, - } = useEsField({ - indexPattern, - fieldTypeFilter, - isRequired, - selectedField, - fieldInputWidth, - showMappingConflicts, - onChange, - }); - - if (acceptsCustomOptions) { - return ( - - ); - } - - return ( - - ); -} diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/types.ts b/packages/kbn-securitysolution-autocomplete/src/es_field_selector/types.ts deleted file mode 100644 index b0f1ab56e8079..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/types.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; -import { FieldConflictsInfo } from '@kbn/securitysolution-list-utils'; -import { GetGenericComboBoxPropsReturn } from '../get_generic_combo_box_props'; - -export interface FieldBaseProps { - indexPattern: DataViewBase | undefined; - fieldTypeFilter?: string[]; - isRequired?: boolean; - selectedField?: DataViewFieldBase | undefined; - fieldInputWidth?: number; - showMappingConflicts?: boolean; - onChange: (a: DataViewFieldBase[]) => void; -} - -export interface ComboBoxFields { - availableFields: DataViewField[]; - selectedFields: DataViewField[]; -} - -export interface GetFieldComboBoxPropsReturn extends GetGenericComboBoxPropsReturn { - disabledLabelTooltipTexts: { [label: string]: string }; - mappingConflictsTooltipInfo: { [label: string]: FieldConflictsInfo[] }; -} - -export interface DataViewField extends DataViewFieldBase { - esTypes?: string[]; -} diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.test.tsx deleted file mode 100644 index 801f8e2864d55..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.test.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { mount } from 'enzyme'; - -import { AutocompleteFieldExistsComponent } from '.'; - -describe('AutocompleteFieldExistsComponent', () => { - test('it renders field disabled', () => { - const wrapper = mount(); - - expect( - wrapper - .find(`[data-test-subj="valuesAutocompleteComboBox existsComboxBox"] input`) - .prop('disabled') - ).toBeTruthy(); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.tsx deleted file mode 100644 index 592886905aaec..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; - -const NO_OPTIONS_FOR_EXIST: EuiComboBoxOptionOption[] = []; - -interface AutocompleteFieldExistsProps { - placeholder: string; - rowLabel?: string; - 'aria-label'?: string; -} - -export const AutocompleteFieldExistsComponent: React.FC = ({ - placeholder, - rowLabel, - 'aria-label': ariaLabel, -}): JSX.Element => ( - - - -); - -AutocompleteFieldExistsComponent.displayName = 'AutocompleteFieldExists'; diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx deleted file mode 100644 index b2d8dc0a70be9..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { mount } from 'enzyme'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; -import { waitFor } from '@testing-library/react'; -import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { getField } from '../fields/index.mock'; -import { AutocompleteFieldListsComponent } from '.'; -import { - getListResponseMock, - getFoundListsBySizeSchemaMock, - DATE_NOW, - IMMUTABLE, - VERSION, -} from '../list_schema/index.mock'; - -// TODO: Once these mocks are available, use them instead of hand mocking, https://github.com/elastic/kibana/issues/100715 -// const mockKibanaHttpService = coreMock.createStart().http; -// import { coreMock } from '../../../../../../../src/core/public/mocks'; -const mockKibanaHttpService = jest.fn(); -const mockShowValueListModal = jest.fn(); -const MockedShowValueListModal = (props: unknown) => { - mockShowValueListModal(props); - return <>; -}; -const mockStart = jest.fn(); -const mockKeywordList: ListSchema = { - ...getListResponseMock(), - id: 'keyword_list', - name: 'keyword list', - type: 'keyword', -}; -const mockResult = { ...getFoundListsBySizeSchemaMock() }; -mockResult.smallLists = [...mockResult.smallLists, mockKeywordList]; -mockResult.largeLists = []; -jest.mock('@kbn/securitysolution-list-hooks', () => { - const originalModule = jest.requireActual('@kbn/securitysolution-list-hooks'); - - return { - ...originalModule, - useFindListsBySize: () => ({ - error: undefined, - loading: false, - result: mockResult, - start: mockStart.mockReturnValue(mockResult), - }), - }; -}); - -describe('AutocompleteFieldListsComponent', () => { - test('it renders disabled if "isDisabled" is true', async () => { - const wrapper = mount( - - ); - - expect( - wrapper - .find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] input`) - .prop('disabled') - ).toBeTruthy(); - }); - - test('it renders loading if "isLoading" is true', async () => { - const wrapper = mount( - - ); - - wrapper - .find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] button`) - .at(0) - .simulate('click'); - expect( - wrapper - .find( - `EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteComboBox listsComboxBox-optionsList"]` - ) - .prop('isLoading') - ).toBeTruthy(); - }); - - test('it allows user to clear values if "isClearable" is true', async () => { - const wrapper = mount( - - ); - expect( - wrapper - .find('EuiComboBox[data-test-subj="valuesAutocompleteComboBox listsComboxBox"]') - .prop('options') - ).toEqual([{ label: 'some name', disabled: false }]); - }); - - test('it correctly displays lists that match the selected "keyword" field esType', () => { - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="comboBoxToggleListButton"] button').simulate('click'); - - expect( - wrapper - .find('EuiComboBox[data-test-subj="valuesAutocompleteComboBox listsComboxBox"]') - .prop('options') - ).toEqual([{ label: 'keyword list', disabled: false }]); - }); - - test('it correctly displays lists that match the selected "ip" field esType', () => { - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="comboBoxToggleListButton"] button').simulate('click'); - - expect( - wrapper - .find('EuiComboBox[data-test-subj="valuesAutocompleteComboBox listsComboxBox"]') - .prop('options') - ).toEqual([{ label: 'some name', disabled: false }]); - }); - - test('it correctly displays selected list', async () => { - const wrapper = mount( - - ); - - expect( - wrapper - .find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] input`) - .at(0) - .props().value - ).toEqual('some name'); - }); - - test('it invokes "onChange" when option selected', async () => { - const mockOnChange = jest.fn(); - const wrapper = mount( - - ); - - ( - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange([{ label: 'some name', disabled: false }]); - - await waitFor(() => { - expect(mockOnChange).toHaveBeenCalledWith({ - '@timestamp': DATE_NOW, - _version: undefined, - created_at: DATE_NOW, - created_by: 'some user', - description: 'some description', - deserializer: undefined, - id: 'some-list-id', - immutable: IMMUTABLE, - meta: {}, - name: 'some name', - serializer: undefined, - tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e', - type: 'ip', - updated_at: DATE_NOW, - updated_by: 'some user', - version: VERSION, - }); - }); - }); - - test('it render the value list modal', async () => { - mockShowValueListModal.mockReset(); - mount( - - ); - - expect(mockShowValueListModal).toHaveBeenCalledWith( - expect.objectContaining({ - children: 'Show value list', - listId: 'some-list-id', - shouldShowContentIfModalNotAvailable: false, - }) - ); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx deleted file mode 100644 index c332dde356f29..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { ElementType, useCallback, useEffect, useMemo, useState } from 'react'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow, EuiLink, EuiText } from '@elastic/eui'; -import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { useFindListsBySize } from '@kbn/securitysolution-list-hooks'; -import { DataViewFieldBase } from '@kbn/es-query'; -import { getDocLinks } from '@kbn/doc-links'; - -import { filterFieldToList } from '../filter_field_to_list'; -import { getGenericComboBoxProps } from '../get_generic_combo_box_props'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 -// import { HttpStart } from '@kbn/core/public'; -type HttpStart = any; - -import * as i18n from '../translations'; - -const SINGLE_SELECTION = { asPlainText: true }; - -interface AutocompleteFieldListsProps { - httpService: HttpStart; - isClearable: boolean; - isDisabled: boolean; - isLoading: boolean; - onChange: (arg: ListSchema) => void; - placeholder: string; - rowLabel?: string; - selectedField: DataViewFieldBase | undefined; - selectedValue: string | undefined; - allowLargeValueLists?: boolean; - 'aria-label'?: string; - showValueListModal: ElementType; -} - -export interface AutocompleteListsData { - smallLists: ListSchema[]; - largeLists: ListSchema[]; -} - -export const AutocompleteFieldListsComponent: React.FC = ({ - httpService, - isClearable = false, - isDisabled = false, - isLoading = false, - onChange, - placeholder, - rowLabel, - selectedField, - selectedValue, - allowLargeValueLists = false, - 'aria-label': ariaLabel, - showValueListModal, -}): JSX.Element => { - const [error, setError] = useState(undefined); - const [listData, setListData] = useState({ - smallLists: [], - largeLists: [], - }); - const { loading, result, start } = useFindListsBySize(); - const getLabel = useCallback(({ name }: ListSchema) => name, []); - - const optionsMemo = useMemo( - () => filterFieldToList(listData, selectedField), - [listData, selectedField] - ); - const selectedOptionsMemo = useMemo(() => { - if (selectedValue != null) { - const combinedLists = [...listData.smallLists, ...listData.largeLists]; - const list = combinedLists.filter(({ id }) => id === selectedValue); - return list ?? []; - } else { - return []; - } - }, [selectedValue, listData]); - const { comboOptions, labels, selectedComboOptions } = useMemo( - () => - getGenericComboBoxProps({ - getLabel, - options: [...optionsMemo.smallLists, ...optionsMemo.largeLists], - selectedOptions: selectedOptionsMemo, - disabledOptions: allowLargeValueLists ? undefined : optionsMemo.largeLists, // Disable large lists if the rule type doesn't allow it - }), - [optionsMemo, selectedOptionsMemo, getLabel, allowLargeValueLists] - ); - - const handleValuesChange = useCallback( - (newOptions: EuiComboBoxOptionOption[]) => { - const combinedLists = [...optionsMemo.smallLists, ...optionsMemo.largeLists]; - const [newValue] = newOptions.map(({ label }) => combinedLists[labels.indexOf(label)]); - onChange(newValue ?? ''); - }, - [labels, optionsMemo, onChange] - ); - - const setIsTouchedValue = useCallback((): void => { - setError(selectedValue == null ? i18n.FIELD_REQUIRED_ERR : undefined); - }, [selectedValue]); - - useEffect(() => { - if (result != null) { - setListData(result); - } - }, [result]); - - useEffect(() => { - if (selectedField != null && httpService != null) { - start({ - http: httpService, - pageIndex: 1, - pageSize: 500, - }); - } - }, [selectedField, start, httpService]); - - const isLoadingState = useMemo((): boolean => isLoading || loading, [isLoading, loading]); - const ShowValueListModal = showValueListModal; - - const helpText = useMemo(() => { - return ( - <> - {selectedValue && ( - - {i18n.SHOW_VALUE_LIST_MODAL} - - )} - {!allowLargeValueLists && ( - - {i18n.LISTS_TOOLTIP_INFO}{' '} - - {i18n.SEE_DOCUMENTATION} - - - )} - - ); - }, [allowLargeValueLists, selectedValue, ShowValueListModal]); - return ( - - - - ); -}; - -AutocompleteFieldListsComponent.displayName = 'AutocompleteFieldList'; diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx deleted file mode 100644 index e83d79b180e90..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx +++ /dev/null @@ -1,631 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; -import { - EuiComboBox, - EuiComboBoxOptionOption, - EuiFormHelpText, - EuiSuperSelect, -} from '@elastic/eui'; -import { act, waitFor } from '@testing-library/react'; -import { AutocompleteFieldMatchComponent } from '.'; -import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; -import { fields, getField } from '../fields/index.mock'; -import { autocompleteStartMock } from '../autocomplete/index.mock'; - -jest.mock('../hooks/use_field_value_autocomplete'); -jest.mock('../translations', () => ({ - FIELD_SPACE_WARNING: 'Warning: there is a space', -})); -describe('AutocompleteFieldMatchComponent', () => { - let wrapper: ReactWrapper; - - const getValueSuggestionsMock = jest - .fn() - .mockResolvedValue([false, true, ['value 3', 'value 4'], jest.fn()]); - - const findEuiComboBox = () => - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - onSearchChange: (a: string) => void; - onCreateOption: (a: string) => void; - }; - - beforeEach(() => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - true, - ['value 1', 'value 2'], - getValueSuggestionsMock, - ]); - }); - - afterEach(() => { - jest.clearAllMocks(); - wrapper.unmount(); - }); - - test('it renders row label if one passed in', () => { - wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="valuesAutocompleteMatchLabel"] label').at(0).text() - ).toEqual('Row Label'); - }); - - test('it renders disabled if "isDisabled" is true', () => { - wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="valuesAutocompleteMatch"] input').prop('disabled') - ).toBeTruthy(); - }); - - test('it renders loading if "isLoading" is true', () => { - wrapper = mount( - - ); - wrapper.find('[data-test-subj="valuesAutocompleteMatch"] button').at(0).simulate('click'); - expect( - wrapper - .find('EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteMatch-optionsList"]') - .prop('isLoading') - ).toBeTruthy(); - }); - - test('it allows user to clear values if "isClearable" is true', () => { - wrapper = mount( - - ); - - expect(wrapper.find(`[data-test-subj="comboBoxClearButton"]`)).toBeTruthy(); - }); - - test('it correctly displays selected value', () => { - wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="valuesAutocompleteMatch"] input').at(0).props().value - ).toEqual('127.0.0.1'); - }); - - test('it invokes "onChange" when new value created', () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - findEuiComboBox().onCreateOption('127.0.0.1'); - - expect(mockOnChange).toHaveBeenCalledWith('127.0.0.1'); - }); - - test('it invokes "onChange" when new value selected', () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - findEuiComboBox().onChange([{ label: 'value 1' }]); - - expect(mockOnChange).toHaveBeenCalledWith('value 1'); - }); - - test('it invokes "onChange" with empty value (i.e. clears selection) when new value searched', () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - act(() => { - findEuiComboBox().onSearchChange('value 12'); - }); - - expect(mockOnChange).toHaveBeenCalledWith(''); - }); - - test('should show the warning helper text if the new value contains spaces when change', async () => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - true, - [' value 1 ', 'value 2'], - getValueSuggestionsMock, - ]); - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - await waitFor(() => findEuiComboBox().onChange([{ label: ' value 1 ' }])); - wrapper.update(); - expect(mockOnChange).toHaveBeenCalledWith(' value 1 '); - - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - }); - - test('it refreshes autocomplete with search query when new value searched', () => { - wrapper = mount( - - ); - act(() => { - findEuiComboBox().onSearchChange('value 1'); - }); - - expect(useFieldValueAutocomplete).toHaveBeenCalledWith({ - autocompleteService: autocompleteStartMock, - fieldValue: '', - indexPattern: { - fields, - id: '1234', - title: 'logstash-*', - }, - operatorType: 'match', - query: 'value 1', - selectedField: getField('machine.os.raw'), - }); - }); - - test('it refreshes autocomplete with search query when input field is cleared', () => { - wrapper = mount( - - ); - - act(() => { - findEuiComboBox().onSearchChange('value 1'); - }); - act(() => { - findEuiComboBox().onSearchChange(''); - }); - - // 1st call is initial render, 2nd call sets the search query: - expect(useFieldValueAutocomplete).toHaveBeenNthCalledWith(2, { - autocompleteService: autocompleteStartMock, - fieldValue: 'windows', - indexPattern: { fields, id: '1234', title: 'logstash-*' }, - operatorType: 'match', - query: 'value 1', - selectedField: getField('machine.os.raw'), - }); - // last call is the refresh when input field is cleared - expect(useFieldValueAutocomplete).toHaveBeenLastCalledWith({ - autocompleteService: autocompleteStartMock, - fieldValue: 'windows', - indexPattern: { fields, id: '1234', title: 'logstash-*' }, - operatorType: 'match', - query: '', - selectedField: getField('machine.os.raw'), - }); - }); - - test('should show the warning helper text if the new value contains spaces when searching a new query', () => { - wrapper = mount( - - ); - act(() => { - findEuiComboBox().onSearchChange(' value 1'); - }); - - wrapper.update(); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); - }); - - test('should show the warning helper text if selectedValue contains spaces when editing', () => { - wrapper = mount( - - ); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); - }); - - test('should not show the warning helper text if selectedValue is falsy', () => { - wrapper = mount( - - ); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeFalsy(); - }); - - describe('boolean type', () => { - const valueSuggestionsMock = jest.fn().mockResolvedValue([false, false, [], jest.fn()]); - - beforeEach(() => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - false, - [], - valueSuggestionsMock, - ]); - }); - - test('it displays only two options - "true" or "false"', () => { - wrapper = mount( - - ); - expect( - wrapper.find('[data-test-subj="valuesAutocompleteMatchBoolean"]').exists() - ).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="valuesAutocompleteMatchBoolean"]').at(0).prop('options') - ).toEqual([ - { - inputDisplay: 'true', - value: 'true', - }, - { - inputDisplay: 'false', - value: 'false', - }, - ]); - }); - - test('it invokes "onChange" with "true" when selected', () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - ( - wrapper.find(EuiSuperSelect).props() as unknown as { - onChange: (a: string) => void; - } - ).onChange('true'); - - expect(mockOnChange).toHaveBeenCalledWith('true'); - }); - - test('it invokes "onChange" with "false" when selected', () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - ( - wrapper.find(EuiSuperSelect).props() as unknown as { - onChange: (a: string) => void; - } - ).onChange('false'); - - expect(mockOnChange).toHaveBeenCalledWith('false'); - }); - }); - - describe('number type', () => { - const valueSuggestionsMock = jest.fn().mockResolvedValue([false, false, [], jest.fn()]); - - beforeEach(() => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - false, - [], - valueSuggestionsMock, - ]); - }); - - test('it number input when field type is number', () => { - wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="valueAutocompleteFieldMatchNumber"]').exists() - ).toBeTruthy(); - }); - - test('it invokes "onChange" with numeric value when inputted', () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - wrapper - .find('[data-test-subj="valueAutocompleteFieldMatchNumber"] input') - .at(0) - .simulate('change', { target: { value: '8' } }); - - expect(mockOnChange).toHaveBeenCalledWith('8'); - }); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx deleted file mode 100644 index 5b627451db191..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx +++ /dev/null @@ -1,377 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { useCallback, useMemo, useState, useEffect } from 'react'; -import { - EuiSuperSelect, - EuiFormRow, - EuiFieldNumber, - EuiComboBoxOptionOption, - EuiComboBox, -} from '@elastic/eui'; -import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; - -import { uniq } from 'lodash'; - -import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 -// import { AutocompleteStart } from '../../../../../../../src/plugins/unified_search/public'; -type AutocompleteStart = any; - -import * as i18n from '../translations'; -import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; -import { - getGenericComboBoxProps, - GetGenericComboBoxPropsReturn, -} from '../get_generic_combo_box_props'; -import { paramIsValid } from '../param_is_valid'; -import { paramContainsSpace } from '../param_contains_space'; - -const BOOLEAN_OPTIONS = [ - { inputDisplay: 'true', value: 'true' }, - { inputDisplay: 'false', value: 'false' }, -]; - -const SINGLE_SELECTION = { asPlainText: true }; - -type Warning = string | React.ReactNode; - -interface AutocompleteFieldMatchProps { - placeholder: string; - selectedField: DataViewFieldBase | undefined; - selectedValue: string | undefined; - indexPattern: DataViewBase | undefined; - isLoading?: boolean; - isDisabled?: boolean; - isClearable?: boolean; - isRequired?: boolean; - fieldInputWidth?: number; - rowLabel?: string; - autocompleteService: AutocompleteStart; - onChange: (arg: string) => void; - onError?: (arg: boolean) => void; - onWarning?: (arg: boolean) => void; - warning?: Warning; - 'aria-label'?: string; -} - -export const AutocompleteFieldMatchComponent: React.FC = ({ - placeholder, - rowLabel, - selectedField, - selectedValue, - indexPattern, - isLoading = false, - isDisabled = false, - isClearable = false, - isRequired = false, - fieldInputWidth, - autocompleteService, - onChange, - onError, - onWarning, - warning, - 'aria-label': ariaLabel, -}): JSX.Element => { - const [searchQuery, setSearchQuery] = useState(''); - const [touched, setIsTouched] = useState(false); - const [error, setError] = useState(undefined); - const [showSpacesWarning, setShowSpacesWarning] = useState(false); - const [isLoadingSuggestions, isSuggestingValues, suggestions] = useFieldValueAutocomplete({ - autocompleteService, - fieldValue: selectedValue, - indexPattern, - operatorType: OperatorTypeEnum.MATCH, - query: searchQuery, - selectedField, - }); - const getLabel = useCallback((option: string): string => option, []); - - const optionsMemo = useMemo((): string[] => { - const valueAsStr = String(selectedValue); - return selectedValue != null && selectedValue.trim() !== '' - ? uniq([valueAsStr, ...suggestions]) - : suggestions; - }, [suggestions, selectedValue]); - - const selectedOptionsMemo = useMemo((): string[] => { - const valueAsStr = String(selectedValue); - return selectedValue ? [valueAsStr] : []; - }, [selectedValue]); - - const handleSpacesWarning = useCallback( - (param: string | undefined) => { - if (!param) return setShowSpacesWarning(false); - setShowSpacesWarning(!!paramContainsSpace(param)); - }, - [setShowSpacesWarning] - ); - - const handleError = useCallback( - (err: string | undefined): void => { - setError((existingErr): string | undefined => { - const oldErr = existingErr != null; - const newErr = err != null; - if (oldErr !== newErr && onError != null) { - onError(newErr); - } - - return err; - }); - }, - [setError, onError] - ); - - const handleWarning = useCallback( - (warn: Warning | undefined): void => { - if (onWarning) { - onWarning(warn !== undefined); - } - }, - [onWarning] - ); - - const { comboOptions, labels, selectedComboOptions } = useMemo( - (): GetGenericComboBoxPropsReturn => - getGenericComboBoxProps({ - getLabel, - options: optionsMemo, - selectedOptions: selectedOptionsMemo, - }), - [optionsMemo, selectedOptionsMemo, getLabel] - ); - - const handleValuesChange = useCallback( - (newOptions: EuiComboBoxOptionOption[]): void => { - const [newValue] = newOptions.map(({ label }) => optionsMemo[labels.indexOf(label)]); - - handleSpacesWarning(newValue); - handleError(undefined); - handleWarning(undefined); - onChange(newValue ?? ''); - }, - [handleError, handleWarning, handleSpacesWarning, labels, onChange, optionsMemo] - ); - - const handleSearchChange = useCallback( - (searchVal: string): void => { - if (searchVal !== '' && selectedField != null) { - const err = paramIsValid(searchVal, selectedField, isRequired, touched); - handleError(err); - handleWarning(warning); - - if (!err) handleSpacesWarning(searchVal); - } - - if (searchVal) { - // Clear selected option when user types to allow user to modify value without {backspace} - onChange(''); - } - - // Update search query unconditionally to show correct suggestions even when input is cleared - setSearchQuery(searchVal); - }, - [ - selectedField, - onChange, - isRequired, - touched, - handleError, - handleWarning, - warning, - handleSpacesWarning, - ] - ); - - const handleCreateOption = useCallback( - (option: string): boolean | undefined => { - const err = paramIsValid(option, selectedField, isRequired, touched); - handleError(err); - handleWarning(warning); - - if (err != null) { - // Explicitly reject the user's input - setShowSpacesWarning(false); - return false; - } - - handleSpacesWarning(option); - onChange(option); - return undefined; - }, - [ - isRequired, - onChange, - selectedField, - touched, - handleError, - handleSpacesWarning, - handleWarning, - warning, - ] - ); - - const handleNonComboBoxInputChange = useCallback( - (event: React.ChangeEvent): void => { - const newValue = event.target.value; - onChange(newValue); - }, - [onChange] - ); - - const handleBooleanInputChange = useCallback( - (newOption: string): void => { - onChange(newOption); - }, - [onChange] - ); - - const setIsTouchedValue = useCallback((): void => { - setIsTouched(true); - - const err = paramIsValid(selectedValue, selectedField, isRequired, true); - handleError(err); - handleWarning(warning); - }, [setIsTouched, handleError, selectedValue, selectedField, isRequired, warning, handleWarning]); - - const inputPlaceholder = useMemo((): string => { - if (isLoading || isLoadingSuggestions) { - return i18n.LOADING; - } else if (selectedField == null) { - return i18n.SELECT_FIELD_FIRST; - } else { - return placeholder; - } - }, [isLoading, selectedField, isLoadingSuggestions, placeholder]); - - const isLoadingState = useMemo( - (): boolean => isLoading || isLoadingSuggestions, - [isLoading, isLoadingSuggestions] - ); - - useEffect((): void => { - setError(undefined); - if (onError != null) onError(false); - - handleSpacesWarning(selectedValue); - // Looks like selectedField return new object every time when we for example add "and" entry - // that's why we need to check for name and type here - // Probably we should use some kind of memoization on parent components for entries - }, [selectedField?.name, selectedField?.type, selectedValue, handleSpacesWarning, onError]); - - const defaultInput = useMemo((): JSX.Element => { - return ( - - - - ); - }, [ - rowLabel, - error, - selectedField, - showSpacesWarning, - inputPlaceholder, - isDisabled, - isLoadingState, - isClearable, - comboOptions, - selectedComboOptions, - handleValuesChange, - handleSearchChange, - handleCreateOption, - setIsTouchedValue, - warning, - fieldInputWidth, - ariaLabel, - ]); - - if (!isSuggestingValues && selectedField != null) { - switch (selectedField.type) { - case 'number': - return ( - - 0 - ? parseFloat(selectedValue) - : selectedValue ?? '' - } - onChange={handleNonComboBoxInputChange} - data-test-subj="valueAutocompleteFieldMatchNumber" - style={fieldInputWidth ? { width: `${fieldInputWidth}px` } : {}} - aria-label={ariaLabel} - fullWidth - /> - - ); - case 'boolean': - return ( - - - - ); - default: - return defaultInput; - } - } else { - return defaultInput; - } -}; - -AutocompleteFieldMatchComponent.displayName = 'AutocompleteFieldMatch'; diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx deleted file mode 100644 index 0b73a57814aaf..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx +++ /dev/null @@ -1,400 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiFormHelpText } from '@elastic/eui'; -import { act, waitFor } from '@testing-library/react'; - -import { AutocompleteFieldMatchAnyComponent } from '.'; -import { getField, fields } from '../fields/index.mock'; -import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; -import { autocompleteStartMock } from '../autocomplete/index.mock'; - -jest.mock('../hooks/use_field_value_autocomplete', () => { - const actual = jest.requireActual('../hooks/use_field_value_autocomplete'); - return { - ...actual, - useFieldValueAutocomplete: jest.fn(), - }; -}); -jest.mock('../translations', () => ({ - FIELD_SPACE_WARNING: 'Warning: there is a space', -})); - -describe('AutocompleteFieldMatchAnyComponent', () => { - let wrapper: ReactWrapper; - const getValueSuggestionsMock = jest - .fn() - .mockResolvedValue([false, true, ['value 3', 'value 4'], jest.fn()]); - - beforeEach(() => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - true, - ['value 1', 'value 2'], - getValueSuggestionsMock, - ]); - }); - - afterEach(() => { - jest.clearAllMocks(); - wrapper.unmount(); - }); - - test('it renders disabled if "isDisabled" is true', () => { - wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="valuesAutocompleteMatchAny"] input`).prop('disabled') - ).toBeTruthy(); - }); - - test('it renders loading if "isLoading" is true', () => { - wrapper = mount( - - ); - wrapper.find(`[data-test-subj="valuesAutocompleteMatchAny"] button`).at(0).simulate('click'); - expect( - wrapper - .find(`EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteMatchAny-optionsList"]`) - .prop('isLoading') - ).toBeTruthy(); - }); - - test('it allows user to clear values if "isClearable" is true', () => { - wrapper = mount( - - ); - - expect(wrapper.find(`[data-test-subj="comboBoxClearButton"]`)).toBeTruthy(); - }); - - test('it correctly displays selected value', () => { - wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="valuesAutocompleteMatchAny"] EuiComboBoxPill`).at(0).text() - ).toEqual('127.0.0.1'); - }); - - test('it invokes "onChange" when new value created', async () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - ( - wrapper.find(EuiComboBox).props() as unknown as { - onCreateOption: (a: string) => void; - } - ).onCreateOption('127.0.0.1'); - - expect(mockOnChange).toHaveBeenCalledWith(['127.0.0.1']); - }); - - test('it invokes "onChange" when new value selected', async () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - ( - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange([{ label: 'value 1' }]); - - expect(mockOnChange).toHaveBeenCalledWith(['value 1']); - }); - - test('it refreshes autocomplete with search query when new value searched', () => { - wrapper = mount( - - ); - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onSearchChange: (a: string) => void; - } - ).onSearchChange('value 1'); - }); - expect(useFieldValueAutocomplete).toHaveBeenCalledWith({ - autocompleteService: autocompleteStartMock, - fieldValue: [], - indexPattern: { - fields, - id: '1234', - title: 'logstash-*', - }, - operatorType: 'match_any', - query: 'value 1', - selectedField: getField('machine.os.raw'), - }); - }); - test('should show the warning helper text if the new value contains spaces when change', async () => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - true, - [' value 1 ', 'value 2'], - getValueSuggestionsMock, - ]); - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - await waitFor(() => - ( - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange([{ label: ' value 1 ' }]) - ); - wrapper.update(); - expect(mockOnChange).toHaveBeenCalledWith([' value 1 ']); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - }); - test('should show the warning helper text if the new value contains spaces when searching a new query', () => { - wrapper = mount( - - ); - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onSearchChange: (a: string) => void; - } - ).onSearchChange(' value 1'); - }); - - wrapper.update(); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); - }); - test('should show the warning helper text if selectedValue contains spaces when editing', () => { - wrapper = mount( - - ); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); - }); - test('should not show the warning helper text if selectedValue is falsy', () => { - wrapper = mount( - - ); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeFalsy(); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx deleted file mode 100644 index 761712797c5e1..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; -import { uniq } from 'lodash'; -import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 -// import { AutocompleteStart } from '../../../../../../../src/plugins/unified_search/public'; -type AutocompleteStart = any; - -import * as i18n from '../translations'; -import { - getGenericComboBoxProps, - GetGenericComboBoxPropsReturn, -} from '../get_generic_combo_box_props'; -import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; -import { paramIsValid } from '../param_is_valid'; -import { paramContainsSpace } from '../param_contains_space'; - -interface AutocompleteFieldMatchAnyProps { - placeholder: string; - selectedField: DataViewFieldBase | undefined; - selectedValue: string[]; - indexPattern: DataViewBase | undefined; - isLoading: boolean; - isDisabled: boolean; - isClearable: boolean; - isRequired?: boolean; - rowLabel?: string; - autocompleteService: AutocompleteStart; - onChange: (arg: string[]) => void; - onError?: (arg: boolean) => void; - 'aria-label'?: string; -} - -export const AutocompleteFieldMatchAnyComponent: React.FC = ({ - placeholder, - rowLabel, - selectedField, - selectedValue, - indexPattern, - isLoading, - isDisabled = false, - isClearable = false, - isRequired = false, - onChange, - onError, - autocompleteService, - 'aria-label': ariaLabel, -}): JSX.Element => { - const [searchQuery, setSearchQuery] = useState(''); - const [touched, setIsTouched] = useState(false); - const [error, setError] = useState(undefined); - const [showSpacesWarning, setShowSpacesWarning] = useState(false); - const [isLoadingSuggestions, isSuggestingValues, suggestions] = useFieldValueAutocomplete({ - autocompleteService, - fieldValue: selectedValue, - indexPattern, - operatorType: OperatorTypeEnum.MATCH_ANY, - query: searchQuery, - selectedField, - }); - const getLabel = useCallback((option: string): string => option, []); - const optionsMemo = useMemo( - (): string[] => (selectedValue ? uniq([...selectedValue, ...suggestions]) : suggestions), - [suggestions, selectedValue] - ); - const { comboOptions, labels, selectedComboOptions } = useMemo( - (): GetGenericComboBoxPropsReturn => - getGenericComboBoxProps({ - getLabel, - options: optionsMemo, - selectedOptions: selectedValue, - }), - [optionsMemo, selectedValue, getLabel] - ); - const handleSpacesWarning = useCallback( - (params: string[]) => - setShowSpacesWarning(!!params.find((param: string) => paramContainsSpace(param))), - [setShowSpacesWarning] - ); - const handleError = useCallback( - (err: string | undefined): void => { - setError((existingErr): string | undefined => { - const oldErr = existingErr != null; - const newErr = err != null; - if (oldErr !== newErr && onError != null) { - onError(newErr); - } - - return err; - }); - }, - [setError, onError] - ); - - const handleValuesChange = useCallback( - (newOptions: EuiComboBoxOptionOption[]): void => { - const newValues: string[] = newOptions.map(({ label }) => optionsMemo[labels.indexOf(label)]); - handleError(undefined); - handleSpacesWarning(newValues); - onChange(newValues); - }, - [handleError, handleSpacesWarning, labels, onChange, optionsMemo] - ); - - const handleSearchChange = useCallback( - (searchVal: string) => { - if (searchVal === '') { - handleError(undefined); - } - - if (searchVal !== '' && selectedField != null) { - const err = paramIsValid(searchVal, selectedField, isRequired, touched); - handleError(err); - - if (!err) handleSpacesWarning([searchVal]); - - setSearchQuery(searchVal); - } - }, - [handleError, handleSpacesWarning, isRequired, selectedField, touched] - ); - - const handleCreateOption = useCallback( - (option: string): boolean => { - const err = paramIsValid(option, selectedField, isRequired, touched); - handleError(err); - - if (err != null) { - // Explicitly reject the user's input - setShowSpacesWarning(false); - return false; - } - - onChange([...(selectedValue || []), option]); - handleSpacesWarning([option]); - return true; - }, - [handleError, handleSpacesWarning, isRequired, onChange, selectedField, selectedValue, touched] - ); - - const setIsTouchedValue = useCallback((): void => { - handleError(selectedComboOptions.length === 0 ? i18n.FIELD_REQUIRED_ERR : undefined); - setIsTouched(true); - }, [setIsTouched, handleError, selectedComboOptions]); - - const inputPlaceholder = useMemo( - (): string => (isLoading || isLoadingSuggestions ? i18n.LOADING : placeholder), - [isLoading, isLoadingSuggestions, placeholder] - ); - - const isLoadingState = useMemo( - (): boolean => isLoading || isLoadingSuggestions, - [isLoading, isLoadingSuggestions] - ); - useEffect((): void => { - handleSpacesWarning(selectedValue); - }, [selectedField, selectedValue, handleSpacesWarning]); - - const defaultInput = useMemo((): JSX.Element => { - return ( - - - - ); - }, [ - rowLabel, - error, - selectedField, - showSpacesWarning, - inputPlaceholder, - isLoadingState, - isClearable, - isDisabled, - comboOptions, - selectedComboOptions, - handleValuesChange, - handleSearchChange, - handleCreateOption, - setIsTouchedValue, - ariaLabel, - ]); - - if (!isSuggestingValues && selectedField != null) { - switch (selectedField.type) { - case 'number': - return ( - - - - ); - default: - return defaultInput; - } - } - - return defaultInput; -}; - -AutocompleteFieldMatchAnyComponent.displayName = 'AutocompleteFieldMatchAny'; diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.test.tsx deleted file mode 100644 index 2840e428a69e2..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.test.tsx +++ /dev/null @@ -1,516 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiFormHelpText } from '@elastic/eui'; -import { act, waitFor } from '@testing-library/react'; -import { AutocompleteFieldWildcardComponent } from '.'; -import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; -import { fields, getField } from '../fields/index.mock'; -import { autocompleteStartMock } from '../autocomplete/index.mock'; -import { WILDCARD_WARNING, FILEPATH_WARNING } from '@kbn/securitysolution-utils'; - -jest.mock('../hooks/use_field_value_autocomplete'); -jest.mock('../translations', () => ({ - FIELD_SPACE_WARNING: 'Warning: there is a space', -})); -describe('AutocompleteFieldWildcardComponent', () => { - let wrapper: ReactWrapper; - - const getValueSuggestionsMock = jest - .fn() - .mockResolvedValue([false, true, ['value 3', 'value 4'], jest.fn()]); - - beforeEach(() => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - true, - ['value 1', 'value 2'], - getValueSuggestionsMock, - ]); - }); - - afterEach(() => { - jest.clearAllMocks(); - wrapper.unmount(); - }); - - test('it renders row label if one passed in', () => { - wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="valuesAutocompleteWildcardLabel"] label').at(0).text() - ).toEqual('Row Label'); - }); - - test('it renders disabled if "isDisabled" is true', () => { - wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="valuesAutocompleteWildcard"] input').prop('disabled') - ).toBeTruthy(); - }); - - test('it renders loading if "isLoading" is true', () => { - wrapper = mount( - - ); - wrapper.find('[data-test-subj="valuesAutocompleteWildcard"] button').at(0).simulate('click'); - expect( - wrapper - .find('EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteWildcard-optionsList"]') - .prop('isLoading') - ).toBeTruthy(); - }); - - test('it allows user to clear values if "isClearable" is true', () => { - wrapper = mount( - - ); - - expect(wrapper.find(`[data-test-subj="comboBoxClearButton"]`)).toBeTruthy(); - }); - - test('it correctly displays selected value', () => { - wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="valuesAutocompleteWildcard"] input').at(0).props().value - ).toEqual('/opt/*/app.dmg'); - }); - - test('it invokes "onChange" when new value created', async () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - ( - wrapper.find(EuiComboBox).props() as unknown as { - onCreateOption: (a: string) => void; - } - ).onCreateOption('/opt/*/app.dmg'); - - expect(mockOnChange).toHaveBeenCalledWith('/opt/*/app.dmg'); - }); - - test('it invokes "onChange" when new value selected', async () => { - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - ( - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange([{ label: 'value 1' }]); - - expect(mockOnChange).toHaveBeenCalledWith('value 1'); - }); - - test('it refreshes autocomplete with search query when new value searched', () => { - wrapper = mount( - - ); - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onSearchChange: (a: string) => void; - } - ).onSearchChange('A:\\Some Folder\\inc*.exe'); - }); - - expect(useFieldValueAutocomplete).toHaveBeenCalledWith({ - autocompleteService: autocompleteStartMock, - fieldValue: '', - indexPattern: { - fields, - id: '1234', - title: 'logs-endpoint.events.*', - }, - operatorType: 'wildcard', - query: 'A:\\Some Folder\\inc*.exe', - selectedField: getField('file.path.text'), - }); - }); - - test('it does not invoke "onWarning" when no warning exists', () => { - const mockOnWarning = jest.fn(); - wrapper = mount( - - ); - - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onBlur: () => void; - } - ).onBlur(); - }); - - expect(mockOnWarning).not.toHaveBeenCalledWith(true); - }); - - test('it invokes "onWarning" when warning exists', () => { - const mockOnWarning = jest.fn(); - wrapper = mount( - - ); - - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onBlur: () => void; - } - ).onBlur(); - }); - - expect(mockOnWarning).toHaveBeenCalledWith(true); - expect( - wrapper - .find('[data-test-subj="valuesAutocompleteWildcardLabel"] div.euiFormHelpText') - .at(0) - .text() - ).toEqual(FILEPATH_WARNING); - }); - - test('it invokes "onWarning" when warning exists and is wildcard warning', () => { - const mockOnWarning = jest.fn(); - wrapper = mount( - - ); - - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onBlur: () => void; - } - ).onBlur(); - }); - - expect(mockOnWarning).toHaveBeenCalledWith(true); - const helpText = wrapper - .find('[data-test-subj="valuesAutocompleteWildcardLabel"] div.euiFormHelpText') - .at(0); - expect(helpText.text()).toEqual(WILDCARD_WARNING); - expect(helpText.find('.euiToolTipAnchor')).toBeTruthy(); - }); - test('should show the warning helper text if the new value contains spaces when change', async () => { - (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ - false, - true, - [' value 1 ', 'value 2'], - getValueSuggestionsMock, - ]); - const mockOnChange = jest.fn(); - wrapper = mount( - - ); - - await waitFor(() => - ( - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange([{ label: ' value 1 ' }]) - ); - wrapper.update(); - expect(mockOnChange).toHaveBeenCalledWith(' value 1 '); - - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - }); - test('should show the warning helper text if the new value contains spaces when searching a new query', () => { - wrapper = mount( - - ); - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onSearchChange: (a: string) => void; - } - ).onSearchChange(' value 1'); - }); - - wrapper.update(); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); - }); - test('should show the warning helper text if selectedValue contains spaces when editing', () => { - wrapper = mount( - - ); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeTruthy(); - expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); - }); - test('should not show the warning helper text if selectedValue is falsy', () => { - wrapper = mount( - - ); - const euiFormHelptext = wrapper.find(EuiFormHelpText); - expect(euiFormHelptext.length).toBeFalsy(); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.tsx deleted file mode 100644 index 5a55b3399a6af..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.tsx +++ /dev/null @@ -1,286 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { useCallback, useMemo, useState, useEffect, memo } from 'react'; -import { EuiFormRow, EuiComboBoxOptionOption, EuiComboBox } from '@elastic/eui'; -import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; - -import { uniq } from 'lodash'; - -import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 -// import { AutocompleteStart } from '../../../../../../../src/plugins/unified_search/public'; -type AutocompleteStart = any; - -import * as i18n from '../translations'; -import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; -import { - getGenericComboBoxProps, - GetGenericComboBoxPropsReturn, -} from '../get_generic_combo_box_props'; -import { paramIsValid } from '../param_is_valid'; -import { paramContainsSpace } from '../param_contains_space'; - -const SINGLE_SELECTION = { asPlainText: true }; - -type Warning = string | React.ReactNode; -interface AutocompleteFieldWildcardProps { - placeholder: string; - selectedField: DataViewFieldBase | undefined; - selectedValue: string | undefined; - indexPattern: DataViewBase | undefined; - isLoading: boolean; - isDisabled?: boolean; - isClearable?: boolean; - isRequired?: boolean; - fieldInputWidth?: number; - rowLabel?: string; - autocompleteService: AutocompleteStart; - onChange: (arg: string) => void; - onError: (arg: boolean) => void; - onWarning: (arg: boolean) => void; - warning?: Warning; - 'aria-label'?: string; -} - -export const AutocompleteFieldWildcardComponent: React.FC = memo( - ({ - autocompleteService, - placeholder, - rowLabel, - selectedField, - selectedValue, - indexPattern, - isLoading, - isDisabled = false, - isClearable = false, - isRequired = false, - fieldInputWidth, - onChange, - onError, - onWarning, - warning, - 'aria-label': ariaLabel, - }): JSX.Element => { - const [searchQuery, setSearchQuery] = useState(''); - const [touched, setIsTouched] = useState(false); - const [error, setError] = useState(undefined); - const [showSpacesWarning, setShowSpacesWarning] = useState(false); - const [isLoadingSuggestions, , suggestions] = useFieldValueAutocomplete({ - autocompleteService, - fieldValue: selectedValue, - indexPattern, - operatorType: OperatorTypeEnum.WILDCARD, - query: searchQuery, - selectedField, - }); - const getLabel = useCallback((option: string): string => option, []); - const optionsMemo = useMemo((): string[] => { - const valueAsStr = String(selectedValue); - return selectedValue != null && selectedValue.trim() !== '' - ? uniq([valueAsStr, ...suggestions]) - : suggestions; - }, [suggestions, selectedValue]); - const selectedOptionsMemo = useMemo((): string[] => { - const valueAsStr = String(selectedValue); - return selectedValue ? [valueAsStr] : []; - }, [selectedValue]); - - const handleSpacesWarning = useCallback( - (param: string | undefined) => { - if (!param) return setShowSpacesWarning(false); - setShowSpacesWarning(!!paramContainsSpace(param)); - }, - [setShowSpacesWarning] - ); - const handleError = useCallback( - (err: string | undefined): void => { - setError((existingErr): string | undefined => { - const oldErr = existingErr != null; - const newErr = err != null; - if (oldErr !== newErr && onError != null) { - onError(newErr); - } - - return err; - }); - }, - [setError, onError] - ); - - const handleWarning = useCallback( - (warn: Warning | undefined): void => { - onWarning(warn !== undefined); - }, - [onWarning] - ); - - const { comboOptions, labels, selectedComboOptions } = useMemo( - (): GetGenericComboBoxPropsReturn => - getGenericComboBoxProps({ - getLabel, - options: optionsMemo, - selectedOptions: selectedOptionsMemo, - }), - [optionsMemo, selectedOptionsMemo, getLabel] - ); - - const handleValuesChange = useCallback( - (newOptions: EuiComboBoxOptionOption[]): void => { - const [newValue] = newOptions.map(({ label }) => optionsMemo[labels.indexOf(label)]); - handleError(undefined); - handleSpacesWarning(newValue); - setShowSpacesWarning(false); - - onChange(newValue ?? ''); - }, - [handleError, handleSpacesWarning, labels, onChange, optionsMemo] - ); - - const handleSearchChange = useCallback( - (searchVal: string): void => { - if (searchVal.trim() !== '' && selectedField != null) { - const err = paramIsValid(searchVal, selectedField, isRequired, touched); - handleError(err); - handleWarning(warning); - if (!err) handleSpacesWarning(searchVal); - - setSearchQuery(searchVal); - } - }, - [handleError, handleSpacesWarning, isRequired, selectedField, touched, warning, handleWarning] - ); - - const handleCreateOption = useCallback( - (option: string): boolean | undefined => { - const err = paramIsValid(option, selectedField, isRequired, touched); - handleError(err); - handleWarning(warning); - - if (err != null) { - // Explicitly reject the user's input - setShowSpacesWarning(false); - return false; - } - - handleSpacesWarning(option); - onChange(option); - return undefined; - }, - [ - isRequired, - handleSpacesWarning, - onChange, - selectedField, - touched, - handleError, - handleWarning, - warning, - ] - ); - - const setIsTouchedValue = useCallback((): void => { - setIsTouched(true); - - const err = paramIsValid(selectedValue, selectedField, isRequired, true); - handleError(err); - handleWarning(warning); - }, [ - setIsTouched, - handleError, - selectedValue, - selectedField, - isRequired, - handleWarning, - warning, - ]); - - const inputPlaceholder = useMemo((): string => { - if (isLoading || isLoadingSuggestions) { - return i18n.LOADING; - } else if (selectedField == null) { - return i18n.SELECT_FIELD_FIRST; - } else { - return placeholder; - } - }, [isLoading, selectedField, isLoadingSuggestions, placeholder]); - - const isLoadingState = useMemo( - (): boolean => isLoading || isLoadingSuggestions, - [isLoading, isLoadingSuggestions] - ); - - useEffect((): void => { - setError(undefined); - if (onError != null) { - onError(false); - } - handleSpacesWarning(selectedValue); - - onWarning(false); - }, [selectedField, selectedValue, onError, onWarning, handleSpacesWarning]); - - const defaultInput = useMemo((): JSX.Element => { - return ( - - - - ); - }, [ - rowLabel, - error, - warning, - showSpacesWarning, - selectedField, - inputPlaceholder, - isDisabled, - isLoadingState, - isClearable, - comboOptions, - selectedComboOptions, - handleValuesChange, - handleSearchChange, - handleCreateOption, - setIsTouchedValue, - fieldInputWidth, - ariaLabel, - ]); - - return defaultInput; - } -); - -AutocompleteFieldWildcardComponent.displayName = 'AutocompleteFieldWildcard'; diff --git a/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts b/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts deleted file mode 100644 index dcb719ccdb56c..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts +++ /dev/null @@ -1,323 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewFieldBase } from '@kbn/es-query'; - -// Copied from "src/plugins/data/common/index_patterns/fields/fields.mocks.ts" but with the types changed to "DataViewFieldBase" since that type is compatible. -// TODO: This should move out once those mocks are directly useable or in their own package, https://github.com/elastic/kibana/issues/100715 - -export const fields: DataViewFieldBase[] = [ - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'ssl', - type: 'boolean', - esTypes: ['boolean'], - count: 20, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: '@timestamp', - type: 'date', - esTypes: ['date'], - count: 30, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'time', - type: 'date', - esTypes: ['date'], - count: 30, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: '@tags', - type: 'string', - esTypes: ['keyword'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'utc_time', - type: 'date', - esTypes: ['date'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'phpmemory', - type: 'number', - esTypes: ['integer'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'ip', - type: 'ip', - esTypes: ['ip'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'request_body', - type: 'attachment', - esTypes: ['attachment'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'point', - type: 'geo_point', - esTypes: ['geo_point'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'area', - type: 'geo_shape', - esTypes: ['geo_shape'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'hashed', - type: 'murmur3', - esTypes: ['murmur3'], - count: 0, - scripted: false, - searchable: true, - aggregatable: false, - readFromDocValues: false, - }, - { - name: 'geo.coordinates', - type: 'geo_point', - esTypes: ['geo_point'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'extension', - type: 'string', - esTypes: ['keyword'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'machine.os', - type: 'string', - esTypes: ['text'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: 'machine.os.raw', - type: 'string', - esTypes: ['keyword'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - subType: { multi: { parent: 'machine.os' } }, - }, - { - name: 'geo.src', - type: 'string', - esTypes: ['keyword'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: '_id', - type: 'string', - esTypes: ['_id'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: '_type', - type: 'string', - esTypes: ['_type'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: '_source', - type: '_source', - esTypes: ['_source'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: 'non-filterable', - type: 'string', - esTypes: ['text'], - count: 0, - scripted: false, - searchable: false, - aggregatable: true, - readFromDocValues: false, - }, - { - name: 'non-sortable', - type: 'string', - esTypes: ['text'], - count: 0, - scripted: false, - searchable: false, - aggregatable: false, - readFromDocValues: false, - }, - { - name: 'custom_user_field', - type: 'conflict', - esTypes: ['long', 'text'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'script string', - type: 'string', - count: 0, - scripted: true, - script: "'i am a string'", - lang: 'expression', - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: 'script number', - type: 'number', - count: 0, - scripted: true, - script: '1234', - lang: 'expression', - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: 'script date', - type: 'date', - count: 0, - scripted: true, - script: '1234', - lang: 'painless', - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: 'script murmur3', - type: 'murmur3', - count: 0, - scripted: true, - script: '1234', - lang: 'expression', - searchable: true, - aggregatable: true, - readFromDocValues: false, - }, - { - name: 'nestedField.child', - type: 'string', - esTypes: ['text'], - count: 0, - scripted: false, - searchable: true, - aggregatable: false, - readFromDocValues: false, - subType: { nested: { path: 'nestedField' } }, - }, - { - name: 'nestedField.nestedChild.doublyNestedChild', - type: 'string', - esTypes: ['text'], - count: 0, - scripted: false, - searchable: true, - aggregatable: false, - readFromDocValues: false, - subType: { nested: { path: 'nestedField.nestedChild' } }, - }, - { - name: 'file.path.text', - type: 'string', - esTypes: ['text'], - searchable: true, - aggregatable: false, - subType: { multi: { parent: 'file.path' } }, - }, -] as unknown as DataViewFieldBase[]; - -export const getField = (name: string) => fields.find((field) => field.name === name); diff --git a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts deleted file mode 100644 index be0710bfd1bab..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { filterFieldToList } from '.'; - -import { getListResponseMock } from '../list_schema/index.mock'; -import { DataViewFieldBase } from '@kbn/es-query'; -import { AutocompleteListsData } from '../field_value_lists'; - -const emptyListData: AutocompleteListsData = { smallLists: [], largeLists: [] }; - -describe('#filterFieldToList', () => { - test('it returns empty list data object if given a undefined for field', () => { - const filter = filterFieldToList(emptyListData, undefined); - expect(filter).toEqual(emptyListData); - }); - - test('it returns empty list data object if filed does not contain esTypes', () => { - const field: DataViewFieldBase = { - name: 'some-name', - type: 'some-type', - }; - const filter = filterFieldToList(emptyListData, field); - expect(filter).toEqual(emptyListData); - }); - - test('it returns filtered lists of ip_range -> ip', () => { - const field: DataViewFieldBase & { esTypes: string[] } = { - esTypes: ['ip'], - name: 'some-name', - type: 'ip', - }; - const listData: AutocompleteListsData = { - smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], - largeLists: [], - }; - const filter = filterFieldToList(listData, field); - const expected = listData; - expect(filter).toEqual(expected); - }); - - test('it returns filtered lists of ip -> ip', () => { - const field: DataViewFieldBase & { esTypes: string[] } = { - esTypes: ['ip'], - name: 'some-name', - type: 'ip', - }; - const listData: AutocompleteListsData = { - smallLists: [{ ...getListResponseMock(), type: 'ip' }], - largeLists: [], - }; - const filter = filterFieldToList(listData, field); - const expected = listData; - expect(filter).toEqual(expected); - }); - - test('it returns filtered lists of keyword -> keyword', () => { - const field: DataViewFieldBase & { esTypes: string[] } = { - esTypes: ['keyword'], - name: 'some-name', - type: 'keyword', - }; - const listData: AutocompleteListsData = { - smallLists: [{ ...getListResponseMock(), type: 'keyword' }], - largeLists: [], - }; - const filter = filterFieldToList(listData, field); - const expected = listData; - expect(filter).toEqual(expected); - }); - - test('it returns filtered lists of text -> text', () => { - const field: DataViewFieldBase & { esTypes: string[] } = { - esTypes: ['text'], - name: 'some-name', - type: 'text', - }; - const listData: AutocompleteListsData = { - smallLists: [{ ...getListResponseMock(), type: 'text' }], - largeLists: [], - }; - const filter = filterFieldToList(listData, field); - const expected = listData; - expect(filter).toEqual(expected); - }); - - test('it returns small and large filtered lists of ip_range -> ip', () => { - const field: DataViewFieldBase & { esTypes: string[] } = { - esTypes: ['ip'], - name: 'some-name', - type: 'ip', - }; - const listData: AutocompleteListsData = { - smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], - largeLists: [{ ...getListResponseMock(), type: 'ip_range' }], - }; - const filter = filterFieldToList(listData, field); - const expected = listData; - expect(filter).toEqual(expected); - }); - - test('it returns 1 filtered lists of ip_range -> ip if the 2nd is not compatible type', () => { - const field: DataViewFieldBase & { esTypes: string[] } = { - esTypes: ['ip'], - name: 'some-name', - type: 'ip', - }; - const listData: AutocompleteListsData = { - smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], - largeLists: [{ ...getListResponseMock(), type: 'text' }], - }; - const filter = filterFieldToList(listData, field); - const expected: AutocompleteListsData = { - smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], - largeLists: [], - }; - expect(filter).toEqual(expected); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts b/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts deleted file mode 100644 index 86d429cc9ef80..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewFieldBase } from '@kbn/es-query'; -import { typeMatch } from '../type_match'; -import { AutocompleteListsData } from '../field_value_lists'; - -/** - * Given an array of lists and optionally a field this will return all - * the lists that match against the field based on the types from the field - * - * NOTE: That we support one additional property from "FieldSpec" located here: - * src/plugins/data/common/index_patterns/fields/types.ts - * This type property is esTypes. If it exists and is on there we will read off the esTypes. - * @param lists The lists to match against the field - * @param field The field to check against the list to see if they are compatible - */ -export const filterFieldToList = ( - lists: AutocompleteListsData, - field?: DataViewFieldBase & { esTypes?: string[] } -): AutocompleteListsData => { - if (field != null) { - const { esTypes = [] } = field; - return { - smallLists: lists.smallLists.filter(({ type }) => - esTypes.some((esType: string) => typeMatch(type, esType)) - ), - largeLists: lists.largeLists.filter(({ type }) => - esTypes.some((esType: string) => typeMatch(type, esType)) - ), - }; - } else { - return { smallLists: [], largeLists: [] }; - } -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.test.tsx deleted file mode 100644 index 82ca7f60de24b..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.test.tsx +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { getGenericComboBoxProps } from '.'; - -describe('get_generic_combo_box_props', () => { - test('it returns empty arrays if "options" is empty array', () => { - const result = getGenericComboBoxProps({ - options: [], - selectedOptions: ['option1'], - getLabel: (t: string) => t, - }); - - expect(result).toEqual({ comboOptions: [], labels: [], selectedComboOptions: [] }); - }); - - test('it returns formatted props if "options" array is not empty', () => { - const result = getGenericComboBoxProps({ - options: ['option1', 'option2', 'option3'], - selectedOptions: [], - getLabel: (t: string) => t, - }); - - expect(result).toEqual({ - comboOptions: [ - { - label: 'option1', - }, - { - label: 'option2', - }, - { - label: 'option3', - }, - ], - labels: ['option1', 'option2', 'option3'], - selectedComboOptions: [], - }); - }); - - test('it does not return "selectedOptions" items that do not appear in "options"', () => { - const result = getGenericComboBoxProps({ - options: ['option1', 'option2', 'option3'], - selectedOptions: ['option4'], - getLabel: (t: string) => t, - }); - - expect(result).toEqual({ - comboOptions: [ - { - label: 'option1', - }, - { - label: 'option2', - }, - { - label: 'option3', - }, - ], - labels: ['option1', 'option2', 'option3'], - selectedComboOptions: [], - }); - }); - - test('it returns "selectedOptions" items that do appear in "options"', () => { - const result = getGenericComboBoxProps({ - options: ['option1', 'option2', 'option3'], - selectedOptions: ['option2'], - getLabel: (t: string) => t, - }); - - expect(result).toEqual({ - comboOptions: [ - { - label: 'option1', - }, - { - label: 'option2', - }, - { - label: 'option3', - }, - ], - labels: ['option1', 'option2', 'option3'], - selectedComboOptions: [ - { - label: 'option2', - }, - ], - }); - }); - - test('it returns "disabledOptions" items that do appear in "options" as disabled', () => { - const result = getGenericComboBoxProps({ - options: ['option1', 'option2', 'option3'], - selectedOptions: [], - disabledOptions: ['option2'], - getLabel: (t: string) => t, - }); - - expect(result).toEqual({ - comboOptions: [ - { - label: 'option1', - disabled: false, - }, - { - label: 'option2', - disabled: true, - }, - { - label: 'option3', - disabled: false, - }, - ], - labels: ['option1', 'option2', 'option3'], - selectedComboOptions: [], - }); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.ts b/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.ts deleted file mode 100644 index 2f2a6697c4226..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EuiComboBoxOptionOption } from '@elastic/eui'; - -export interface GetGenericComboBoxPropsReturn { - comboOptions: EuiComboBoxOptionOption[]; - labels: string[]; - selectedComboOptions: EuiComboBoxOptionOption[]; -} - -/** - * Determines the options, selected values and option labels for EUI combo box - * @param options options user can select from - * @param selectedOptions user selection if any - * @param getLabel helper function to know which property to use for labels - */ -export const getGenericComboBoxProps = ({ - getLabel, - options, - selectedOptions, - disabledOptions, -}: { - getLabel: (value: T) => string; - options: T[]; - selectedOptions: T[]; - disabledOptions?: T[]; -}): GetGenericComboBoxPropsReturn => { - const newLabels = options.map(getLabel); - const disabledLabels = disabledOptions?.map(getLabel); - const newComboOptions: EuiComboBoxOptionOption[] = newLabels.map((label) => ({ - label, - disabled: disabledLabels && disabledLabels.length !== 0 && disabledLabels.includes(label), - })); - const newSelectedComboOptions = selectedOptions - .map(getLabel) - .filter((option) => { - return newLabels.indexOf(option) !== -1; - }) - .map((option) => { - return newComboOptions[newLabels.indexOf(option)]; - }); - - return { - comboOptions: newComboOptions, - labels: newLabels, - selectedComboOptions: newSelectedComboOptions, - }; -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts deleted file mode 100644 index 711e7ea87a8e0..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - doesNotExistOperator, - EVENT_FILTERS_OPERATORS, - ALL_OPERATORS, - existsOperator, - isNotOperator, - isOperator, -} from '@kbn/securitysolution-list-utils'; -import { getOperators } from '.'; -import { getField } from '../fields/index.mock'; - -describe('#getOperators', () => { - test('it returns "isOperator" if passed in field is "undefined"', () => { - const operator = getOperators(undefined); - - expect(operator).toEqual([isOperator]); - }); - - test('it returns expected operators when field type is "boolean"', () => { - const operator = getOperators(getField('ssl')); - - expect(operator).toEqual([isOperator, isNotOperator, existsOperator, doesNotExistOperator]); - }); - - test('it returns "isOperator" when field type is "nested"', () => { - const operator = getOperators({ - name: 'nestedField', - scripted: false, - subType: { nested: { path: 'nestedField' } }, - type: 'nested', - }); - - expect(operator).toEqual([isOperator]); - }); - - test('it includes a "matches" operator when field is "file.path.text"', () => { - const operator = getOperators({ - name: 'file.path.text', - type: 'simple', - }); - - expect(operator).toEqual(EVENT_FILTERS_OPERATORS); - }); - - test('it returns all operator types when field type is not null, boolean, or nested', () => { - const operator = getOperators(getField('machine.os.raw')); - - expect(operator).toEqual(ALL_OPERATORS); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts b/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts deleted file mode 100644 index dbb36fd479df6..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewFieldBase } from '@kbn/es-query'; - -import { - ALL_OPERATORS, - EVENT_FILTERS_OPERATORS, - OperatorOption, - doesNotExistOperator, - existsOperator, - isNotOperator, - isOperator, -} from '@kbn/securitysolution-list-utils'; - -/** - * Returns the appropriate operators given a field type - * - * @param field DataViewFieldBase selected field - * - */ -export const getOperators = (field: DataViewFieldBase | undefined): OperatorOption[] => { - if (field == null) { - return [isOperator]; - } else if (field.type === 'boolean') { - return [isOperator, isNotOperator, existsOperator, doesNotExistOperator]; - } else if (field.type === 'nested') { - return [isOperator]; - } else if (field.name === 'file.path.text') { - return EVENT_FILTERS_OPERATORS; - } else { - return ALL_OPERATORS; - } -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/index.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/index.ts deleted file mode 100644 index 5aa216af4c67e..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './use_field_value_autocomplete'; diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts deleted file mode 100644 index 836744f3ede28..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts +++ /dev/null @@ -1,300 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { waitFor, renderHook } from '@testing-library/react'; -import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; - -import { UseFieldValueAutocompleteReturn, useFieldValueAutocomplete } from '.'; -import { getField } from '../../fields/index.mock'; -import { autocompleteStartMock } from '../../autocomplete/index.mock'; -import { DataViewFieldBase } from '@kbn/es-query'; - -// Copied from "src/plugins/data/common/index_patterns/index_pattern.stub.ts" -// TODO: Remove this in favor of the above if/when it is ported, https://github.com/elastic/kibana/issues/100715 -export const stubIndexPatternWithFields = { - id: '1234', - title: 'logstash-*', - fields: [ - { - name: 'response', - type: 'number', - esTypes: ['integer'], - aggregatable: true, - filterable: true, - searchable: true, - }, - ], -}; - -describe('use_field_value_autocomplete', () => { - const onErrorMock = jest.fn(); - const getValueSuggestionsMock = jest.fn().mockResolvedValue(['value 1', 'value 2']); - - afterEach(() => { - onErrorMock.mockClear(); - getValueSuggestionsMock.mockClear(); - }); - - test('initializes hook', async () => { - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: getValueSuggestionsMock, - }, - fieldValue: '', - indexPattern: undefined, - operatorType: OperatorTypeEnum.MATCH, - query: '', - selectedField: undefined, - }) - ); - await waitFor(() => expect(result.current).toEqual([false, true, [], result.current[3]])); - }); - - test('does not call autocomplete service if "operatorType" is "exists"', async () => { - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: getValueSuggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.EXISTS, - query: '', - selectedField: getField('machine.os'), - }) - ); - - await waitFor(() => { - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - - expect(result.current).toEqual(expectedResult); - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - }); - }); - - test('does not call autocomplete service if "selectedField" is undefined', async () => { - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: getValueSuggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.EXISTS, - query: '', - selectedField: undefined, - }) - ); - - await waitFor(() => { - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - - expect(result.current).toEqual(expectedResult); - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - }); - }); - - test('does not call autocomplete service if "indexPattern" is undefined', async () => { - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: getValueSuggestionsMock, - }, - fieldValue: '', - indexPattern: undefined, - operatorType: OperatorTypeEnum.EXISTS, - query: '', - selectedField: getField('machine.os'), - }) - ); - - await waitFor(() => { - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - - expect(result.current).toEqual(expectedResult); - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - }); - }); - - test('it uses full path name for nested fields to fetch suggestions', async () => { - const suggestionsMock = jest.fn().mockResolvedValue([]); - - const selectedField: DataViewFieldBase | undefined = getField('nestedField.child'); - if (selectedField == null) { - throw new TypeError('selectedField for this test should always be defined'); - } - - const { signal } = new AbortController(); - renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: suggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.MATCH, - query: '', - selectedField: { ...selectedField, name: 'child' }, - }) - ); - - await waitFor(() => - expect(suggestionsMock).toHaveBeenCalledWith({ - field: { ...getField('nestedField.child'), name: 'nestedField.child' }, - indexPattern: { - fields: [ - { - aggregatable: true, - esTypes: ['integer'], - filterable: true, - name: 'response', - searchable: true, - type: 'number', - }, - ], - id: '1234', - title: 'logstash-*', - }, - query: '', - signal, - useTimeRange: false, - }) - ); - }); - - test('returns "isSuggestingValues" of false if field type is boolean', async () => { - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: getValueSuggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.MATCH, - query: '', - selectedField: getField('ssl'), - }) - ); - - await waitFor(() => { - const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; - - expect(result.current).toEqual(expectedResult); - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - }); - }); - - test('returns "isSuggestingValues" of false to note that autocomplete service is not in use if no autocomplete suggestions available', async () => { - const suggestionsMock = jest.fn().mockResolvedValue([]); - - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: suggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.MATCH, - query: '', - selectedField: getField('bytes'), - }) - ); - - await waitFor(() => { - const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; - - expect(suggestionsMock).toHaveBeenCalled(); - expect(result.current).toEqual(expectedResult); - }); - }); - - test('returns suggestions', async () => { - const { signal } = new AbortController(); - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: getValueSuggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.MATCH, - query: '', - selectedField: getField('@tags'), - }) - ); - - await waitFor(() => { - const expectedResult: UseFieldValueAutocompleteReturn = [ - false, - true, - ['value 1', 'value 2'], - result.current[3], - ]; - - expect(getValueSuggestionsMock).toHaveBeenCalledWith({ - field: getField('@tags'), - indexPattern: stubIndexPatternWithFields, - query: '', - signal, - useTimeRange: false, - }); - expect(result.current).toEqual(expectedResult); - }); - }); - - test('returns new suggestions on subsequent calls', async () => { - const { result } = renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: getValueSuggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.MATCH, - query: '', - selectedField: getField('@tags'), - }) - ); - - await waitFor(() => expect(result.current[3]).not.toBeNull()); - - // Added check for typescripts sake, if null, - // would not reach below logic as test would stop above - if (result.current[3] != null) { - result.current[3]({ - fieldSelected: getField('@tags'), - patterns: stubIndexPatternWithFields, - searchQuery: '', - value: 'hello', - }); - } - - await waitFor(() => { - const expectedResult: UseFieldValueAutocompleteReturn = [ - false, - true, - ['value 1', 'value 2'], - result.current[3], - ]; - - expect(getValueSuggestionsMock).toHaveBeenCalledTimes(2); - expect(result.current).toEqual(expectedResult); - }); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts deleted file mode 100644 index 9fff2abfd5be5..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useEffect, useRef, useState } from 'react'; -import { debounce } from 'lodash'; -import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { DataViewBase, DataViewFieldBase, getDataViewFieldSubtypeNested } from '@kbn/es-query'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 -// import { AutocompleteStart } from '../../../../../../../../src/plugins/unified_search/public'; -type AutocompleteStart = any; - -interface FuncArgs { - fieldSelected: DataViewFieldBase | undefined; - patterns: DataViewBase | undefined; - searchQuery: string; - value: string | string[] | undefined; -} - -type Func = (args: FuncArgs) => void; - -export type UseFieldValueAutocompleteReturn = [boolean, boolean, string[], Func | null]; - -export interface UseFieldValueAutocompleteProps { - autocompleteService: AutocompleteStart; - fieldValue: string | string[] | undefined; - indexPattern: DataViewBase | undefined; - operatorType: OperatorTypeEnum; - query: string; - selectedField: DataViewFieldBase | undefined; -} -/** - * Hook for using the field value autocomplete service - */ -export const useFieldValueAutocomplete = ({ - selectedField, - operatorType, - fieldValue, - query, - indexPattern, - autocompleteService, -}: UseFieldValueAutocompleteProps): UseFieldValueAutocompleteReturn => { - const [isLoading, setIsLoading] = useState(false); - const [isSuggestingValues, setIsSuggestingValues] = useState(true); - const [suggestions, setSuggestions] = useState([]); - const updateSuggestions = useRef(null); - - useEffect(() => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - - const fetchSuggestions = debounce( - async ({ fieldSelected, patterns, searchQuery }: FuncArgs) => { - try { - if (isSubscribed) { - if (fieldSelected == null || patterns == null) { - return; - } - - if (fieldSelected.type === 'boolean') { - setIsSuggestingValues(false); - return; - } - - setIsLoading(true); - const subTypeNested = getDataViewFieldSubtypeNested(fieldSelected); - const field = subTypeNested - ? { - ...fieldSelected, - name: `${subTypeNested.nested.path}.${fieldSelected.name}`, - } - : fieldSelected; - - const newSuggestions = await autocompleteService.getValueSuggestions({ - field, - indexPattern: patterns, - query: searchQuery, - signal: abortCtrl.signal, - useTimeRange: false, - }); - - if (newSuggestions.length === 0) { - setIsSuggestingValues(false); - } - - setIsLoading(false); - setSuggestions([...newSuggestions]); - } - } catch (error) { - if (isSubscribed) { - setSuggestions([]); - setIsLoading(false); - } - } - }, - 500 - ); - - if (operatorType !== OperatorTypeEnum.EXISTS) { - fetchSuggestions({ - fieldSelected: selectedField, - patterns: indexPattern, - searchQuery: query, - value: fieldValue, - }); - } - - updateSuggestions.current = fetchSuggestions; - - return (): void => { - isSubscribed = false; - abortCtrl.abort(); - }; - }, [selectedField, operatorType, fieldValue, indexPattern, query, autocompleteService]); - - return [isLoading, isSuggestingValues, suggestions, updateSuggestions.current]; -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts b/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts deleted file mode 100644 index e2c2c9b0fe051..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - FoundListSchema, - ListSchema, - FoundListsBySizeSchema, -} from '@kbn/securitysolution-io-ts-list-types'; - -// TODO: Once this mock is available within packages, use it instead, https://github.com/elastic/kibana/issues/100715 -// import { getFoundListSchemaMock } from '../../../../../lists/common/schemas/response/found_list_schema.mock'; -export const getFoundListSchemaMock = (): FoundListSchema => ({ - cursor: '123', - data: [getListResponseMock()], - page: 1, - per_page: 1, - total: 1, -}); - -export const getFoundListsBySizeSchemaMock = (): FoundListsBySizeSchema => ({ - smallLists: [getListResponseMock()], - largeLists: [getListResponseMock()], -}); - -// TODO: Once these mocks are available from packages use it instead, https://github.com/elastic/kibana/issues/100715 -export const DATE_NOW = '2020-04-20T15:25:31.830Z'; -export const USER = 'some user'; -export const IMMUTABLE = false; -export const VERSION = 1; -export const DESCRIPTION = 'some description'; -export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; -export const LIST_ID = 'some-list-id'; -export const META = {}; -export const TYPE = 'ip'; -export const NAME = 'some name'; - -// TODO: Once this mock is available within packages, use it instead, https://github.com/elastic/kibana/issues/100715 -// import { getListResponseMock } from '../../../../../lists/common/schemas/response/list_schema.mock'; -export const getListResponseMock = (): ListSchema => ({ - '@timestamp': DATE_NOW, - _version: undefined, - created_at: DATE_NOW, - created_by: USER, - description: DESCRIPTION, - deserializer: undefined, - id: LIST_ID, - immutable: IMMUTABLE, - meta: META, - name: NAME, - serializer: undefined, - tie_breaker_id: TIE_BREAKER, - type: TYPE, - updated_at: DATE_NOW, - updated_by: USER, - version: VERSION, -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx deleted file mode 100644 index 4d2112d8f31d1..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { mount } from 'enzyme'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; -import { isNotOperator, isOperator } from '@kbn/securitysolution-list-utils'; - -import { OperatorComponent } from '.'; -import { getField } from '../fields/index.mock'; - -describe('operator', () => { - test('it renders disabled if "isDisabled" is true', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"] input`).prop('disabled') - ).toBeTruthy(); - }); - - test('it renders loading if "isLoading" is true', () => { - const wrapper = mount( - - ); - wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"] button`).at(0).simulate('click'); - expect( - wrapper - .find(`EuiComboBoxOptionsList[data-test-subj="operatorAutocompleteComboBox-optionsList"]`) - .prop('isLoading') - ).toBeTruthy(); - }); - - test('it allows user to clear values if "isClearable" is true', () => { - const wrapper = mount( - - ); - - expect(wrapper.find(`button[data-test-subj="comboBoxClearButton"]`).exists()).toBeTruthy(); - }); - - test('it displays "operatorOptions" if param is passed in with items', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') - ).toEqual([{ label: 'is not' }]); - }); - - test('it does not display "operatorOptions" if param is passed in with no items', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') - ).toEqual([ - { - label: 'is', - }, - { - label: 'is not', - }, - { - label: 'is one of', - }, - { - label: 'is not one of', - }, - { - label: 'exists', - }, - { - label: 'does not exist', - }, - { - label: 'is in list', - }, - { - label: 'is not in list', - }, - { - label: 'matches', - }, - { - label: 'does not match', - }, - ]); - }); - - test('it correctly displays selected operator', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="operatorAutocompleteComboBox"] input').at(0).props().value - ).toEqual('is'); - }); - - test('it only displays subset of operators if field type is nested', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') - ).toEqual([{ label: 'is' }]); - }); - - test('it only displays subset of operators if field type is boolean', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') - ).toEqual([ - { label: 'is' }, - { label: 'is not' }, - { label: 'exists' }, - { label: 'does not exist' }, - ]); - }); - - test('it only displays subset of operators if field name is "file.path.text"', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') - ).toEqual([ - { label: 'is' }, - { label: 'is not' }, - { label: 'is one of' }, - { label: 'is not one of' }, - { label: 'matches' }, - { label: 'does not match' }, - ]); - }); - - test('it invokes "onChange" when option selected', () => { - const mockOnChange = jest.fn(); - const wrapper = mount( - - ); - - ( - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange([{ label: 'is not' }]); - - expect(mockOnChange).toHaveBeenCalledWith([ - { message: 'is not', operator: 'excluded', type: 'match', value: 'is_not' }, - ]); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx b/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx deleted file mode 100644 index c3d91c16eae91..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { useCallback, useMemo } from 'react'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; -import { OperatorOption } from '@kbn/securitysolution-list-utils'; -import { DataViewFieldBase } from '@kbn/es-query'; - -import { getOperators } from '../get_operators'; -import { - getGenericComboBoxProps, - GetGenericComboBoxPropsReturn, -} from '../get_generic_combo_box_props'; - -const AS_PLAIN_TEXT = { asPlainText: true }; - -interface OperatorState { - isClearable: boolean; - isDisabled: boolean; - isLoading: boolean; - onChange: (arg: OperatorOption[]) => void; - operator: OperatorOption; - operatorInputWidth?: number; - operatorOptions?: OperatorOption[]; - placeholder: string; - selectedField: DataViewFieldBase | undefined; - 'aria-label'?: string; -} - -export const OperatorComponent: React.FC = ({ - isClearable = false, - isDisabled = false, - isLoading = false, - onChange, - operator, - operatorOptions, - operatorInputWidth = 150, - placeholder, - selectedField, - 'aria-label': ariaLabel, -}): JSX.Element => { - const getLabel = useCallback(({ message }: OperatorOption): string => message, []); - const optionsMemo = useMemo( - (): OperatorOption[] => - operatorOptions != null && operatorOptions.length > 0 - ? operatorOptions - : getOperators(selectedField), - [operatorOptions, selectedField] - ); - const selectedOptionsMemo = useMemo( - (): OperatorOption[] => (operator ? [operator] : []), - [operator] - ); - const { comboOptions, labels, selectedComboOptions } = useMemo( - (): GetGenericComboBoxPropsReturn => - getGenericComboBoxProps({ - getLabel, - options: optionsMemo, - selectedOptions: selectedOptionsMemo, - }), - [optionsMemo, selectedOptionsMemo, getLabel] - ); - - const handleValuesChange = useCallback( - (newOptions: EuiComboBoxOptionOption[]): void => { - const newValues: OperatorOption[] = newOptions.map( - ({ label }) => optionsMemo[labels.indexOf(label)] - ); - onChange(newValues); - }, - [labels, onChange, optionsMemo] - ); - - const inputWidth = useMemo(() => { - return { width: `${operatorInputWidth}px` }; - }, [operatorInputWidth]); - - return ( - - ); -}; - -OperatorComponent.displayName = 'Operator'; diff --git a/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.test.ts deleted file mode 100644 index aef6fc4acffa2..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { paramContainsSpace } from '.'; - -describe('param_contains_space', () => { - test('should return true if leading spaces were found', () => { - expect(paramContainsSpace(' test')).toBeTruthy(); - }); - test('should return true if trailing spaces were found', () => { - expect(paramContainsSpace('test ')).toBeTruthy(); - }); - test('should return true if both trailing and leading spaces were found', () => { - expect(paramContainsSpace(' test ')).toBeTruthy(); - }); - test('should return true if tabs was found', () => { - expect(paramContainsSpace('\ttest')).toBeTruthy(); - }); - test('should return false if no spaces were found', () => { - expect(paramContainsSpace('test test')).toBeFalsy(); - }); - test('should return false if param is falsy', () => { - expect(paramContainsSpace('')).toBeFalsy(); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.ts b/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.ts deleted file mode 100644 index 996167f20536f..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export const paramContainsSpace = (param: string) => param && param.trim().length !== param.length; diff --git a/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.test.ts deleted file mode 100644 index c530bca356cbf..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { paramIsValid } from '.'; -import { getField } from '../fields/index.mock'; -import * as i18n from '../translations'; -import moment from 'moment'; - -describe('params_is_valid', () => { - beforeEach(() => { - // Disable momentJS deprecation warning and it looks like it is not typed either so - // we have to disable the type as well and cannot extend it easily. - ( - moment as unknown as { - suppressDeprecationWarnings: boolean; - } - ).suppressDeprecationWarnings = true; - }); - - afterEach(() => { - // Re-enable momentJS deprecation warning and it looks like it is not typed either so - // we have to disable the type as well and cannot extend it easily. - ( - moment as unknown as { - suppressDeprecationWarnings: boolean; - } - ).suppressDeprecationWarnings = false; - }); - - test('returns no errors if no field has been selected', () => { - const isValid = paramIsValid('', undefined, true, false); - - expect(isValid).toBeUndefined(); - }); - - test('returns error string if user has touched a required input and left empty', () => { - const isValid = paramIsValid(undefined, getField('@timestamp'), true, true); - - expect(isValid).toEqual(i18n.FIELD_REQUIRED_ERR); - }); - - test('returns no errors if required input is empty but user has not yet touched it', () => { - const isValid = paramIsValid(undefined, getField('@timestamp'), true, false); - - expect(isValid).toBeUndefined(); - }); - - test('returns no errors if user has touched an input that is not required and left empty', () => { - const isValid = paramIsValid(undefined, getField('@timestamp'), false, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns no errors if user has touched an input that is not required and left empty string', () => { - const isValid = paramIsValid('', getField('@timestamp'), false, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns no errors if field is of type date and value is valid', () => { - const isValid = paramIsValid('1994-11-05T08:15:30-05:00', getField('@timestamp'), false, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns errors if filed is of type date and value is not valid', () => { - const isValid = paramIsValid('1593478826', getField('@timestamp'), false, true); - - expect(isValid).toEqual(i18n.DATE_ERR); - }); - - test('returns no errors if field is of type number and value is an integer', () => { - const isValid = paramIsValid('4', getField('bytes'), true, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns no errors if field is of type number and value is a float', () => { - const isValid = paramIsValid('4.3', getField('bytes'), true, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns no errors if field is of type number and value is a long', () => { - const isValid = paramIsValid('-9223372036854775808', getField('bytes'), true, true); - - expect(isValid).toBeUndefined(); - }); - - test('returns errors if field is of type number and value is "hello"', () => { - const isValid = paramIsValid('hello', getField('bytes'), true, true); - - expect(isValid).toEqual(i18n.NUMBER_ERR); - }); - - test('returns errors if field is of type number and value is "123abc"', () => { - const isValid = paramIsValid('123abc', getField('bytes'), true, true); - - expect(isValid).toEqual(i18n.NUMBER_ERR); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts b/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts deleted file mode 100644 index 5abde0b36c4c7..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import dateMath from '@kbn/datemath'; -import { DataViewFieldBase } from '@kbn/es-query'; -import { checkEmptyValue } from '../check_empty_value'; - -import * as i18n from '../translations'; - -/** - * Very basic validation for values - * @param param the value being checked - * @param field the selected field - * @param isRequired whether or not an empty value is allowed - * @param touched has field been touched by user - * @returns undefined if valid, string with error message if invalid - */ -export const paramIsValid = ( - param: string | undefined, - field: DataViewFieldBase | undefined, - isRequired: boolean, - touched: boolean -): string | undefined => { - if (field == null) { - return undefined; - } - - const emptyValueError = checkEmptyValue(param, field, isRequired, touched); - if (emptyValueError !== null) { - return emptyValueError; - } - - switch (field.type) { - case 'date': - const moment = dateMath.parse(param ?? ''); - const isDate = Boolean(moment && moment.isValid()); - return isDate ? undefined : i18n.DATE_ERR; - case 'number': - const isNum = param != null && param.trim() !== '' && !isNaN(+param); - return isNum ? undefined : i18n.NUMBER_ERR; - default: - return undefined; - } -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/translations/index.ts b/packages/kbn-securitysolution-autocomplete/src/translations/index.ts deleted file mode 100644 index 01671880d2dcb..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/translations/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { i18n } from '@kbn/i18n'; - -export const LOADING = i18n.translate('autocomplete.loadingDescription', { - defaultMessage: 'Loading...', -}); - -export const SELECT_FIELD_FIRST = i18n.translate('autocomplete.selectField', { - defaultMessage: 'Please select a field first...', -}); - -export const FIELD_REQUIRED_ERR = i18n.translate('autocomplete.fieldRequiredError', { - defaultMessage: 'Value cannot be empty', -}); - -export const NUMBER_ERR = i18n.translate('autocomplete.invalidNumberError', { - defaultMessage: 'Not a valid number', -}); - -export const DATE_ERR = i18n.translate('autocomplete.invalidDateError', { - defaultMessage: 'Not a valid date', -}); - -export const BINARY_TYPE_NOT_SUPPORTED = i18n.translate('autocomplete.invalidBinaryType', { - defaultMessage: 'Binary fields are currently unsupported', -}); -export const FIELD_SPACE_WARNING = i18n.translate('autocomplete.fieldSpaceWarning', { - defaultMessage: "Warning: Spaces at the start or end of this value aren't being displayed.", -}); - -export const LISTS_TOOLTIP_INFO = i18n.translate('autocomplete.listsTooltipWarning', { - defaultMessage: "Lists that aren't able to be processed by this rule type will be disabled.", -}); - -export const SEE_DOCUMENTATION = i18n.translate('autocomplete.seeDocumentation', { - defaultMessage: 'See Documentation', -}); - -export const FIELD_CONFLICT_INDICES_WARNING_TITLE = i18n.translate( - 'autocomplete.conflictIndicesWarning.title', - { - defaultMessage: 'Mapping Conflict', - } -); - -export const FIELD_CONFLICT_INDICES_WARNING_DESCRIPTION = i18n.translate( - 'autocomplete.conflictIndicesWarning.description', - { - defaultMessage: - 'This field is defined as different types across the following indices or is unmapped. This can cause unexpected query results.', - } -); - -export const CONFLICT_MULTIPLE_INDEX_DESCRIPTION = (name: string, count: number): string => - i18n.translate('autocomplete.conflictIndicesWarning.index.description', { - defaultMessage: '{name} ({count} indices)', - values: { count, name }, - }); - -export const SHOW_VALUE_LIST_MODAL = i18n.translate('autocomplete.showValueListModal', { - defaultMessage: 'Show value list', -}); - -// eslint-disable-next-line import/no-default-export -export default { - LOADING, - SELECT_FIELD_FIRST, - FIELD_REQUIRED_ERR, - NUMBER_ERR, - DATE_ERR, - FIELD_SPACE_WARNING, - BINARY_TYPE_NOT_SUPPORTED, -}; diff --git a/packages/kbn-securitysolution-autocomplete/src/type_match/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/type_match/index.test.ts deleted file mode 100644 index 15c7c3f580da6..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/type_match/index.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { typeMatch } from '.'; - -describe('type_match', () => { - test('ip -> ip is true', () => { - expect(typeMatch('ip', 'ip')).toEqual(true); - }); - - test('keyword -> keyword is true', () => { - expect(typeMatch('keyword', 'keyword')).toEqual(true); - }); - - test('text -> text is true', () => { - expect(typeMatch('text', 'text')).toEqual(true); - }); - - test('ip_range -> ip is true', () => { - expect(typeMatch('ip_range', 'ip')).toEqual(true); - }); - - test('date_range -> date is true', () => { - expect(typeMatch('date_range', 'date')).toEqual(true); - }); - - test('double_range -> double is true', () => { - expect(typeMatch('double_range', 'double')).toEqual(true); - }); - - test('float_range -> float is true', () => { - expect(typeMatch('float_range', 'float')).toEqual(true); - }); - - test('integer_range -> integer is true', () => { - expect(typeMatch('integer_range', 'integer')).toEqual(true); - }); - - test('long_range -> long is true', () => { - expect(typeMatch('long_range', 'long')).toEqual(true); - }); - - test('ip -> date is false', () => { - expect(typeMatch('ip', 'date')).toEqual(false); - }); - - test('long -> float is false', () => { - expect(typeMatch('long', 'float')).toEqual(false); - }); - - test('integer -> long is false', () => { - expect(typeMatch('integer', 'long')).toEqual(false); - }); -}); diff --git a/packages/kbn-securitysolution-autocomplete/src/type_match/index.ts b/packages/kbn-securitysolution-autocomplete/src/type_match/index.ts deleted file mode 100644 index 4d5899a376a08..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/src/type_match/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { Type } from '@kbn/securitysolution-io-ts-list-types'; - -/** - * Given an input list type and a string based ES type this will match - * if they're exact or if they are compatible with a range - * @param type The type to match against the esType - * @param esType The ES type to match with - */ -export const typeMatch = (type: Type, esType: string): boolean => { - return ( - type === esType || - (type === 'ip_range' && esType === 'ip') || - (type === 'date_range' && esType === 'date') || - (type === 'double_range' && esType === 'double') || - (type === 'float_range' && esType === 'float') || - (type === 'integer_range' && esType === 'integer') || - (type === 'long_range' && esType === 'long') - ); -}; diff --git a/packages/kbn-securitysolution-autocomplete/tsconfig.json b/packages/kbn-securitysolution-autocomplete/tsconfig.json deleted file mode 100644 index f7df7da6f06ad..0000000000000 --- a/packages/kbn-securitysolution-autocomplete/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": ["jest", "node"] - }, - "include": [ - "**/*.ts", - "**/*.tsx", - ], - "kbn_references": [ - "@kbn/datemath", - "@kbn/es-query", - "@kbn/i18n", - "@kbn/securitysolution-io-ts-list-types", - "@kbn/securitysolution-list-hooks", - "@kbn/securitysolution-list-utils", - "@kbn/doc-links", - "@kbn/securitysolution-utils", - ], - "exclude": [ - "target/**/*", - ], -} diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.gen.ts b/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.gen.ts deleted file mode 100644 index 42a3b67106c02..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.gen.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Create endpoint list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { EndpointList } from '../model/endpoint_list_common.gen'; - -export type CreateEndpointListResponse = z.infer; -export const CreateEndpointListResponse = EndpointList; diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.schema.yaml b/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.schema.yaml deleted file mode 100644 index b2ca0f563617d..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.schema.yaml +++ /dev/null @@ -1,45 +0,0 @@ -openapi: 3.0.0 -info: - title: Create endpoint list API endpoint - version: '2023-10-31' -paths: - /api/endpoint_list: - post: - x-labels: [serverless, ess] - x-codegen-enabled: true - operationId: CreateEndpointList - summary: Create an endpoint exception list - description: Create an endpoint exception list, which groups endpoint exception list items. If an endpoint exception list already exists, an empty response is returned. - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointList' - 400: - description: Invalid input data - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Insufficient privileges - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 500: - description: Internal server error - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.schema.yaml b/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.schema.yaml deleted file mode 100644 index 69db506169187..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.schema.yaml +++ /dev/null @@ -1,64 +0,0 @@ -openapi: 3.0.0 -info: - title: Delete endpoint list item API endpoint - version: '2023-10-31' -paths: - /api/endpoint_list/items: - delete: - x-labels: [serverless, ess] - x-codegen-enabled: true - operationId: DeleteEndpointListItem - summary: Delete an endpoint exception list item - description: Delete an endpoint exception list item using the `id` or `item_id` field. - parameters: - - name: id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' - - name: item_id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointListItem' - 400: - description: Invalid input data - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Insufficient privileges - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Endpoint list item not found - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.schema.yaml b/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.schema.yaml deleted file mode 100644 index 6dc2fcaa7e87a..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.schema.yaml +++ /dev/null @@ -1,113 +0,0 @@ -openapi: 3.0.0 -info: - title: Find endpoint list items API endpoint - version: '2023-10-31' -paths: - /api/endpoint_list/items/_find: - get: - x-labels: [serverless, ess] - x-codegen-enabled: true - operationId: FindEndpointListItems - summary: Get endpoint exception list items - description: Get a list of all endpoint exception list items. - parameters: - - name: filter - in: query - required: false - description: | - Filters the returned results according to the value of the specified field, - using the `:` syntax. - schema: - $ref: '#/components/schemas/FindEndpointListItemsFilter' - - name: page - in: query - required: false - description: The page number to return - schema: - type: integer - minimum: 0 - - name: per_page - in: query - required: false - description: The number of exception list items to return per page - schema: - type: integer - minimum: 0 - - name: sort_field - in: query - required: false - description: Determines which field is used to sort the results - schema: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - - name: sort_order - in: query - required: false - description: Determines the sort order, which can be `desc` or `asc` - schema: - type: string - enum: [desc, asc] - responses: - 200: - description: Successful response - content: - application/json: - schema: - type: object - properties: - data: - type: array - items: - $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointListItem' - page: - type: integer - minimum: 0 - per_page: - type: integer - minimum: 0 - total: - type: integer - minimum: 0 - pit: - type: string - required: - - data - - page - - per_page - - total - 400: - description: Invalid input data - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Insufficient privileges - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Endpoint list not found - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - -components: - schemas: - FindEndpointListItemsFilter: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/index.ts b/packages/kbn-securitysolution-endpoint-exceptions-common/api/index.ts deleted file mode 100644 index c71b02c448db8..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './create_endpoint_list/create_endpoint_list.gen'; -export * from './create_endpoint_list_item/create_endpoint_list_item.gen'; -export * from './read_endpoint_list_item/read_endpoint_list_item.gen'; -export * from './update_endpoint_list_item/update_endpoint_list_item.gen'; -export * from './delete_endpoint_list_item/delete_endpoint_list_item.gen'; -export * from './find_endpoint_list_item/find_endpoint_list_item.gen'; diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.gen.ts b/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.gen.ts deleted file mode 100644 index 6c8093246b1a6..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.gen.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Common Exception List Attributes - * version: not applicable - */ - -import { z } from '@kbn/zod'; - -import { - ExceptionList, - ExceptionListItem, -} from '@kbn/securitysolution-exceptions-common/api/model/exception_list_common.gen'; - -export type EndpointList = z.infer; -export const EndpointList = z.union([ExceptionList, z.object({}).strict()]); - -export type EndpointListItem = z.infer; -export const EndpointListItem = ExceptionListItem; diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.schema.yaml b/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.schema.yaml deleted file mode 100644 index 8a4e0b291c76f..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.schema.yaml +++ /dev/null @@ -1,66 +0,0 @@ -openapi: 3.0.0 -info: - title: Read endpoint list item API endpoint - version: '2023-10-31' -paths: - /api/endpoint_list/items: - get: - x-labels: [serverless, ess] - x-codegen-enabled: true - operationId: ReadEndpointListItem - summary: Get an endpoint exception list item - description: Get the details of an endpoint exception list item using the `id` or `item_id` field. - parameters: - - name: id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' - - name: item_id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' - responses: - 200: - description: Successful response - content: - application/json: - schema: - type: array - items: - $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointListItem' - 400: - description: Invalid input data - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Insufficient privileges - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Endpoint list item not found - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/package.json b/packages/kbn-securitysolution-endpoint-exceptions-common/package.json deleted file mode 100644 index 78470be1d4e4f..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "description": "OpenAPI Endpoint Exceptions Common", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "name": "@kbn/securitysolution-endpoint-exceptions-common", - "private": true, - "version": "1.0.0", - "scripts": { - "openapi:generate": "node scripts/openapi_generate", - "openapi:bundle": "node scripts/openapi_bundle" - } -} diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js b/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js deleted file mode 100644 index e5a02965593c3..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -require('../../../src/setup_node_env'); -const { join, resolve } = require('path'); -const { bundle } = require('@kbn/openapi-bundler'); - -const ROOT = resolve(__dirname, '..'); - -(async () => { - await bundle({ - sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), - outputFilePath: join( - ROOT, - 'docs/openapi/serverless/security_solution_endpoint_exceptions_api_{version}.bundled.schema.yaml' - ), - options: { - includeLabels: ['serverless'], - prototypeDocument: { - info: { - title: 'Security Endpoint Exceptions API (Elastic Cloud Serverless)', - description: 'Endpoint Exceptions API allow you to manage Endpoint lists.', - }, - tags: [ - { - name: 'Security Endpoint Exceptions API', - 'x-displayName': 'Security endpoint exceptions', - description: - "Endpoint Exceptions API allows you to manage detection rule endpoint exceptions to prevent a rule from generating an alert from incoming events even when the rule's other criteria are met.", - }, - ], - }, - }, - }); - - await bundle({ - sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), - outputFilePath: join( - ROOT, - 'docs/openapi/ess/security_solution_endpoint_exceptions_api_{version}.bundled.schema.yaml' - ), - options: { - includeLabels: ['ess'], - prototypeDocument: { - info: { - title: 'Security Endpoint Exceptions API (Elastic Cloud and self-hosted)', - description: 'Endpoint Exceptions API allow you to manage Endpoint lists.', - }, - tags: [ - { - name: 'Security Endpoint Exceptions API', - 'x-displayName': 'Security endpoint exceptions', - description: - "Endpoint Exceptions API allows you to manage detection rule endpoint exceptions to prevent a rule from generating an alert from incoming events even when the rule's other criteria are met.", - }, - ], - }, - }, - }); -})(); diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_generate.js b/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_generate.js deleted file mode 100644 index bca85786a518f..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_generate.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -require('../../../src/setup_node_env'); -const { join, resolve } = require('path'); -const { generate } = require('@kbn/openapi-generator'); -const { REPO_ROOT } = require('@kbn/repo-info'); - -const ROOT = resolve(__dirname, '..'); - -(async () => { - await generate({ - title: 'OpenAPI Endpoint Exceptions API Schemas', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'zod_operation_schema', - }); - - await generate({ - title: 'Endpoint Exceptions API client for tests', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'api_client_supertest', - skipLinting: true, - bundle: { - outFile: join( - REPO_ROOT, - 'x-pack/test/api_integration/services/security_solution_endpoint_exceptions_api.gen.ts' - ), - }, - }); -})(); diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/tsconfig.json b/packages/kbn-securitysolution-endpoint-exceptions-common/tsconfig.json deleted file mode 100644 index 7e3c3fd7396dc..0000000000000 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "outDir": "target/types", - "types": ["jest", "node"] - }, - "exclude": ["target/**/*"], - "extends": "../../tsconfig.base.json", - "include": ["**/*.ts"], - "kbn_references": [ - "@kbn/securitysolution-exceptions-common", - "@kbn/openapi-common", - "@kbn/zod", - ] -} diff --git a/packages/kbn-securitysolution-es-utils/jest.config.js b/packages/kbn-securitysolution-es-utils/jest.config.js deleted file mode 100644 index 5d52b2d390b57..0000000000000 --- a/packages/kbn-securitysolution-es-utils/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-es-utils'], -}; diff --git a/packages/kbn-securitysolution-es-utils/tsconfig.json b/packages/kbn-securitysolution-es-utils/tsconfig.json deleted file mode 100644 index e584d504cc9c0..0000000000000 --- a/packages/kbn-securitysolution-es-utils/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "target/**/*", - ], - "kbn_references": [ - "@kbn/zod-helpers", - "@kbn/zod", - ] -} diff --git a/packages/kbn-securitysolution-exception-list-components/index.ts b/packages/kbn-securitysolution-exception-list-components/index.ts deleted file mode 100644 index 0e11a4694384d..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/search_bar'; -export * from './src/empty_viewer_state'; -export * from './src/pagination/pagination'; -// export * from './src/exceptions_utility/exceptions_utility'; -export * from './src/exception_items'; -export * from './src/exception_item_card'; -export * from './src/value_with_space_warning'; -export * from './src/types'; -export * from './src/list_header'; -export * from './src/header_menu'; -export * from './src/generate_linked_rules_menu_item'; -export * from './src/wildcard_with_wrong_operator_callout'; -export * from './src/partial_code_signature_callout'; diff --git a/packages/kbn-securitysolution-exception-list-components/jest.config.js b/packages/kbn-securitysolution-exception-list-components/jest.config.js deleted file mode 100644 index e9d4ad8ad8487..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/jest.config.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-exception-list-components'], - coverageReporters: ['text', 'html'], - collectCoverageFrom: [ - '/packages/kbn-securitysolution-exception-list-components/**/*.{ts,tsx}', - '!/packages/kbn-securitysolution-exception-list-components/**/*.test', - '!/packages/kbn-securitysolution-exception-list-components/**/types/*', - '!/packages/kbn-securitysolution-exception-list-components/**/*.type', - '!/packages/kbn-securitysolution-exception-list-components/**/*.styles', - '!/packages/kbn-securitysolution-exception-list-components/**/mocks/*', - '!/packages/kbn-securitysolution-exception-list-components/**/*.config', - '!/packages/kbn-securitysolution-exception-list-components/**/translations', - '!/packages/kbn-securitysolution-exception-list-components/**/types/*', - ], - setupFilesAfterEnv: [ - '/packages/kbn-securitysolution-exception-list-components/setup_test.ts', - ], -}; diff --git a/packages/kbn-securitysolution-exception-list-components/package.json b/packages/kbn-securitysolution-exception-list-components/package.json deleted file mode 100644 index 0b99a01c071e8..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/securitysolution-exception-list-components", - "private": true, - "version": "1.0.0", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-exception-list-components/setup_test.ts b/packages/kbn-securitysolution-exception-list-components/setup_test.ts deleted file mode 100644 index 5ebc6d3dac1ca..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/setup_test.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import '@testing-library/jest-dom'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/custom.d.ts b/packages/kbn-securitysolution-exception-list-components/src/custom.d.ts deleted file mode 100644 index aa99593b9e877..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/custom.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -declare module '*.svg' { - const content: string; - // eslint-disable-next-line import/no-default-export - export default content; -} diff --git a/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/index.tsx deleted file mode 100644 index e9996e814c34a..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/index.tsx +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { useMemo } from 'react'; -import type { FC } from 'react'; -import { css } from '@emotion/react'; -import { - EuiSkeletonText, - EuiImage, - EuiEmptyPrompt, - EuiButton, - useEuiTheme, - EuiPanel, -} from '@elastic/eui'; -import type { ExpressionColor } from '@elastic/eui/src/components/expression/expression'; -import type { EuiFacetGroupLayout } from '@elastic/eui/src/components/facet/facet_group'; -import { euiThemeVars } from '@kbn/ui-theme'; -import { ListTypeText, ViewerStatus } from '../types'; -import * as i18n from '../translations'; -import illustration from '../assets/images/illustration_product_no_results_magnifying_glass.svg'; - -interface EmptyViewerStateProps { - title?: string; - body?: string; - buttonText?: string; - listType?: ListTypeText; - isReadOnly: boolean; - viewerStatus: ViewerStatus; - onEmptyButtonStateClick?: () => void | null; -} - -const panelCss = css` - margin: ${euiThemeVars.euiSizeL} 0; - padding: ${euiThemeVars.euiSizeL} 0; -`; -const EmptyViewerStateComponent: FC = ({ - title, - body, - buttonText, - listType, - isReadOnly, - viewerStatus, - onEmptyButtonStateClick, -}) => { - const { euiTheme } = useEuiTheme(); - - const euiEmptyPromptProps = useMemo(() => { - switch (viewerStatus) { - case ViewerStatus.ERROR: { - return { - color: 'danger' as ExpressionColor, - iconType: 'error', - title: ( -

{title || i18n.EMPTY_VIEWER_STATE_ERROR_TITLE}

- ), - body:

{body || i18n.EMPTY_VIEWER_STATE_ERROR_BODY}

, - 'data-test-subj': 'errorViewerState', - }; - } - case ViewerStatus.EMPTY: - return { - color: 'subdued' as ExpressionColor, - iconType: 'plusInCircle', - iconColor: euiTheme.colors.darkestShade, - title: ( -

{title || i18n.EMPTY_VIEWER_STATE_EMPTY_TITLE}

- ), - body:

{body || i18n.EMPTY_VIEWER_STATE_EMPTY_BODY}

, - 'data-test-subj': 'emptyViewerState', - actions: [ - - {buttonText || i18n.EMPTY_VIEWER_STATE_EMPTY_VIEWER_BUTTON(listType || 'rule')} - , - ], - }; - case ViewerStatus.EMPTY_SEARCH: - return { - color: 'plain' as ExpressionColor, - layout: 'horizontal' as EuiFacetGroupLayout, - hasBorder: true, - hasShadow: false, - icon: , - title: ( -

- {title || i18n.EMPTY_VIEWER_STATE_EMPTY_SEARCH_TITLE} -

- ), - body: ( -

- {body || i18n.EMPTY_VIEWER_STATE_EMPTY_SEARCH_BODY} -

- ), - 'data-test-subj': 'emptySearchViewerState', - }; - } - }, [ - viewerStatus, - euiTheme.colors.darkestShade, - title, - body, - onEmptyButtonStateClick, - isReadOnly, - buttonText, - listType, - ]); - - return ( - - - - - - ); -}; - -export const EmptyViewerState = React.memo(EmptyViewerStateComponent); - -EmptyViewerState.displayName = 'EmptyViewerState'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/index.tsx deleted file mode 100644 index d2e5ac0577af3..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { memo } from 'react'; -import type { EuiCommentProps } from '@elastic/eui'; -import { EuiAccordion, EuiCommentList, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; -import * as i18n from '../translations'; - -const accordionCss = css` - color: ${euiThemeVars.euiColorPrimary}; -`; - -export interface ExceptionItemCardCommentsProps { - comments: EuiCommentProps[]; - dataTestSubj?: string; -} - -export const ExceptionItemCardComments = memo( - ({ comments, dataTestSubj }) => { - if (!comments.length) return null; - return ( - - - {i18n.exceptionItemCardCommentsAccordion(comments.length)} - - } - arrowDisplay="none" - data-test-subj="exceptionItemCardComments" - > - - - - - - ); - } -); - -ExceptionItemCardComments.displayName = 'ExceptionItemCardComments'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.styles.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.styles.tsx deleted file mode 100644 index 8a089df54f2f6..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.styles.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { cx } from '@emotion/css'; -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; - -// TODO check font Roboto Mono -export const nestedGroupSpaceCss = css` - margin-left: ${euiThemeVars.euiSizeXL}; - margin-bottom: ${euiThemeVars.euiSizeXS}; - padding-top: ${euiThemeVars.euiSizeXS}; -`; - -export const borderCss = cx( - 'eui-xScroll', - ` - border: 1px; - border-color: #d3dae6; - border-style: solid; -` -); - -export const valueContainerCss = css` - display: flex; - align-items: center; - margin-left: ${euiThemeVars.euiSizeS}; -`; -export const expressionContainerCss = css` - display: flex; - align-items: center; -`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/index.tsx deleted file mode 100644 index b765439116ced..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/index.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { ElementType, FC, memo } from 'react'; -import { EuiExpression, EuiToken, EuiFlexGroup } from '@elastic/eui'; -import { ListOperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { - nestedGroupSpaceCss, - valueContainerCss, - expressionContainerCss, -} from '../conditions.styles'; -import type { Entry } from '../types'; -import * as i18n from '../../translations'; -import { getValue, getValueExpression } from './entry_content.helper'; - -interface EntryContentProps { - entry: Entry; - index: number; - isNestedEntry?: boolean; - dataTestSubj?: string; - showValueListModal: ElementType; -} - -export const EntryContent: FC = memo( - ({ entry, index, isNestedEntry = false, dataTestSubj, showValueListModal }) => { - const { field, type } = entry; - const value = getValue(entry); - const operator = 'operator' in entry ? entry.operator : ''; - - const entryKey = `${field}${type}${value}${index}`; - return ( -
-
- {isNestedEntry ? ( - - - -
- - {getValueExpression( - type as ListOperatorTypeEnum, - operator, - value, - showValueListModal - )} -
-
- ) : ( - <> - - - {getValueExpression( - type as ListOperatorTypeEnum, - operator, - value, - showValueListModal - )} - - )} -
-
- ); - } -); -EntryContent.displayName = 'EntryContent'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/index.tsx deleted file mode 100644 index f472402adddc4..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { memo } from 'react'; -import { EuiPanel } from '@elastic/eui'; - -import { borderCss } from './conditions.styles'; -import { EntryContent } from './entry_content'; -import { OsCondition } from './os_conditions'; -import type { CriteriaConditionsProps, Entry } from './types'; - -export const ExceptionItemCardConditions = memo( - ({ os, entries, dataTestSubj, showValueListModal }) => { - return ( - - {os?.length ? : null} - {entries.map((entry: Entry, index: number) => { - const nestedEntries = 'entries' in entry ? entry.entries : []; - return ( -
- - {nestedEntries?.length - ? nestedEntries.map((nestedEntry: Entry, nestedIndex: number) => ( - - )) - : null} -
- ); - })} -
- ); - } -); -ExceptionItemCardConditions.displayName = 'ExceptionItemCardConditions'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/index.tsx deleted file mode 100644 index 0d8285924c314..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { memo, useMemo } from 'react'; -import { EuiExpression } from '@elastic/eui'; - -import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { OS_LABELS } from '../conditions.config'; -import * as i18n from '../../translations'; - -export interface OsConditionsProps { - dataTestSubj?: string; - os: ExceptionListItemSchema['os_types']; -} - -export const OsCondition = memo(({ os, dataTestSubj }) => { - const osLabel = useMemo(() => { - return os.map((osValue) => OS_LABELS[osValue] ?? osValue).join(', '); - }, [os]); - return osLabel ? ( -
- - - - -
- ) : null; -}); -OsCondition.displayName = 'OsCondition'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/types.ts b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/types.ts deleted file mode 100644 index 0400ca6548d9f..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/types.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { - EntryExists, - EntryList, - EntryMatch, - EntryMatchAny, - EntryMatchWildcard, - EntryNested, - ExceptionListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { ElementType } from 'react'; - -export type Entry = - | EntryExists - | EntryList - | EntryMatch - | EntryMatchAny - | EntryMatchWildcard - | EntryNested; - -export type Entries = ExceptionListItemSchema['entries']; -export interface CriteriaConditionsProps { - entries: Entries; - dataTestSubj: string; - os?: ExceptionListItemSchema['os_types']; - showValueListModal: ElementType; -} diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/index.tsx deleted file mode 100644 index 72b02cc79a791..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/index.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { memo } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; -import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { HeaderMenu } from '../../header_menu'; - -export interface ExceptionItemCardHeaderProps { - item: ExceptionListItemSchema; - actions: Array<{ key: string; icon: string; label: string | boolean; onClick: () => void }>; - disableActions?: boolean; - dataTestSubj: string; -} - -export const ExceptionItemCardHeader = memo( - ({ item, actions, disableActions = false, dataTestSubj }) => { - return ( - - - -

{item.name}

-
-
- - - -
- ); - } -); - -ExceptionItemCardHeader.displayName = 'ExceptionItemCardHeader'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/index.ts b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/index.ts deleted file mode 100644 index 26af377092336..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './conditions'; -export * from './header'; -export * from './meta'; -export * from './comments'; -export * from './exception_item_card'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/details_info.test.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/details_info.test.tsx deleted file mode 100644 index cbb48e172322e..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/details_info.test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { render } from '@testing-library/react'; -import { MetaInfoDetails } from '.'; - -describe('MetaInfoDetails', () => { - it('should render lastUpdate as string', () => { - const wrapper = render( - - ); - expect(wrapper.container).toMatchSnapshot(); - expect(wrapper.getByTestId('MetaInfoDetailslastUpdate')).toHaveTextContent('last update'); - }); - it('should render lastUpdate as JSX Element', () => { - const wrapper = render( - Last update value

} - lastUpdateValue="value" - /> - ); - expect(wrapper.container).toMatchSnapshot(); - expect(wrapper.getByTestId('MetaInfoDetailslastUpdate')).toHaveTextContent('Last update value'); - }); -}); diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/index.tsx deleted file mode 100644 index cc9eaa813aa9b..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/index.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { memo } from 'react'; -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; -import * as i18n from '../../translations'; - -interface MetaInfoDetailsProps { - label: string; - lastUpdate: JSX.Element | string; - lastUpdateValue?: string; - dataTestSubj?: string; -} - -const euiBadgeFontFamily = css` - font-family: ${euiThemeVars.euiFontFamily}; -`; -export const MetaInfoDetails = memo( - ({ label, lastUpdate, lastUpdateValue, dataTestSubj }) => { - return ( - - - - {label} - - - - - {lastUpdate} - - - {lastUpdateValue != null && ( - <> - - - {i18n.EXCEPTION_ITEM_CARD_META_BY} - - - - - - - {lastUpdateValue} - - - - - - )} - - ); - } -); - -MetaInfoDetails.displayName = 'MetaInfoDetails'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx deleted file mode 100644 index d9c0f84b02d0f..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { memo, useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; -import * as i18n from '../translations'; -import type { Rule } from '../../types'; -import { MetaInfoDetails } from './details_info'; -import { HeaderMenu } from '../../header_menu'; -import { generateLinkedRulesMenuItems } from '../../generate_linked_rules_menu_item'; - -const itemCss = css` - border-right: 1px solid #d3dae6; - padding: ${euiThemeVars.euiSizeS} ${euiThemeVars.euiSizeM} ${euiThemeVars.euiSizeS} 0; -`; - -export interface ExceptionItemCardMetaInfoProps { - item: ExceptionListItemSchema; - rules: Rule[]; - dataTestSubj: string; - formattedDateComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common - securityLinkAnchorComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common -} - -export const ExceptionItemCardMetaInfo = memo( - ({ item, rules, dataTestSubj, securityLinkAnchorComponent, formattedDateComponent }) => { - const FormattedDateComponent = formattedDateComponent; - - const referencedLinks = useMemo( - () => - generateLinkedRulesMenuItems({ - dataTestSubj, - linkedRules: rules, - securityLinkAnchorComponent, - }), - [dataTestSubj, rules, securityLinkAnchorComponent] - ); - - const isExpired = useMemo( - () => (item.expire_time ? new Date(item.expire_time) <= new Date() : false), - [item] - ); - - return ( - - {FormattedDateComponent !== null && ( - <> - - - } - lastUpdateValue={item.created_by} - dataTestSubj={`${dataTestSubj || ''}CreatedBy`} - /> - - - - - } - lastUpdateValue={item.updated_by} - dataTestSubj={`${dataTestSubj || ''}UpdatedBy`} - /> - - {item.expire_time != null && ( - <> - - - } - dataTestSubj={`${dataTestSubj || ''}ExpireTime`} - /> - - - )} - - )} - - - - - ); - } -); -ExceptionItemCardMetaInfo.displayName = 'ExceptionItemCardMetaInfo'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/translations.ts b/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/translations.ts deleted file mode 100644 index 78a0dac775cf3..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/translations.ts +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { i18n } from '@kbn/i18n'; - -export const exceptionItemCardEditButton = (listType: string) => - i18n.translate('exceptionList-components.exceptions.exceptionItem.card.editItemButton', { - values: { listType }, - defaultMessage: 'Edit {listType} exception', - }); - -export const exceptionItemCardDeleteButton = (listType: string) => - i18n.translate('exceptionList-components.exceptions.exceptionItem.card.deleteItemButton', { - values: { listType }, - defaultMessage: 'Delete {listType} exception', - }); - -export const EXCEPTION_ITEM_CARD_CREATED_LABEL = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.createdLabel', - { - defaultMessage: 'Created', - } -); - -export const EXCEPTION_ITEM_CARD_UPDATED_LABEL = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.updatedLabel', - { - defaultMessage: 'Updated', - } -); - -export const EXCEPTION_ITEM_CARD_EXPIRES_LABEL = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.expiresLabel', - { - defaultMessage: 'Expires at', - } -); - -export const EXCEPTION_ITEM_CARD_EXPIRED_LABEL = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.expiredLabel', - { - defaultMessage: 'Expired at', - } -); - -export const EXCEPTION_ITEM_CARD_META_BY = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.metaDetailsBy', - { - defaultMessage: 'by', - } -); - -export const exceptionItemCardCommentsAccordion = (comments: number) => - i18n.translate('exceptionList-components.exceptions.exceptionItem.card.showCommentsLabel', { - values: { comments }, - defaultMessage: 'Show {comments, plural, =1 {comment} other {comments}} ({comments})', - }); - -export const CONDITION_OPERATOR_TYPE_MATCH = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchOperator', - { - defaultMessage: 'IS', - } -); - -export const CONDITION_OPERATOR_TYPE_NOT_MATCH = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchOperator.not', - { - defaultMessage: 'IS NOT', - } -); - -export const CONDITION_OPERATOR_TYPE_WILDCARD_MATCHES = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.wildcardMatchesOperator', - { - defaultMessage: 'MATCHES', - } -); - -export const CONDITION_OPERATOR_TYPE_WILDCARD_DOES_NOT_MATCH = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.wildcardDoesNotMatchOperator', - { - defaultMessage: 'DOES NOT MATCH', - } -); - -export const CONDITION_OPERATOR_TYPE_NESTED = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.nestedOperator', - { - defaultMessage: 'has', - } -); - -export const CONDITION_OPERATOR_TYPE_MATCH_ANY = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchAnyOperator', - { - defaultMessage: 'is one of', - } -); - -export const CONDITION_OPERATOR_TYPE_NOT_MATCH_ANY = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchAnyOperator.not', - { - defaultMessage: 'is not one of', - } -); - -export const CONDITION_OPERATOR_TYPE_EXISTS = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.existsOperator', - { - defaultMessage: 'exists', - } -); - -export const CONDITION_OPERATOR_TYPE_DOES_NOT_EXIST = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.existsOperator.not', - { - defaultMessage: 'does not exist', - } -); - -export const CONDITION_OPERATOR_TYPE_LIST = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.listOperator', - { - defaultMessage: 'included in', - } -); - -export const CONDITION_OPERATOR_TYPE_NOT_IN_LIST = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.listOperator.not', - { - defaultMessage: 'is not included in', - } -); - -export const CONDITION_AND = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.and', - { - defaultMessage: 'AND', - } -); - -export const CONDITION_OS = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.os', - { - defaultMessage: 'OS', - } -); - -export const OS_WINDOWS = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.windows', - { - defaultMessage: 'Windows', - } -); - -export const OS_LINUX = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.linux', - { - defaultMessage: 'Linux', - } -); - -export const OS_MAC = i18n.translate( - 'exceptionList-components.exceptions.exceptionItem.card.conditions.macos', - { - defaultMessage: 'Mac', - } -); - -export const AFFECTED_RULES = (numRules: number) => - i18n.translate('exceptionList-components.exceptions.card.exceptionItem.affectedRules', { - values: { numRules }, - defaultMessage: 'Affects {numRules} {numRules, plural, =1 {rule} other {rules}}', - }); diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_items/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/exception_items/index.tsx deleted file mode 100644 index edad9aecdb0d0..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_items/index.tsx +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { ElementType } from 'react'; -import { css } from '@emotion/react'; -import type { FC } from 'react'; -import { EuiCommentProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - -import type { - CommentsArray, - ExceptionListItemSchema, - ExceptionListTypeEnum, -} from '@kbn/securitysolution-io-ts-list-types'; - -import { euiThemeVars } from '@kbn/ui-theme'; -import { EmptyViewerState, ExceptionItemCard, Pagination, PaginationProps } from '../..'; - -import type { - RuleReferences, - ExceptionListItemIdentifiers, - ViewerStatus, - GetExceptionItemProps, -} from '../types'; - -const exceptionItemCss = css` - margin: ${euiThemeVars.euiSize} 0; - &div:first-child { - margin: ${euiThemeVars.euiSizeXS} 0 ${euiThemeVars.euiSize}; - } -`; - -interface ExceptionItemsProps { - lastUpdated: string | number | null; - viewerStatus: ViewerStatus; - isReadOnly: boolean; - emptyViewerTitle?: string; - emptyViewerBody?: string; - emptyViewerButtonText?: string; - exceptions: ExceptionListItemSchema[]; - listType: ExceptionListTypeEnum; - ruleReferences: RuleReferences; - pagination: PaginationProps['pagination']; - editActionLabel?: string; - deleteActionLabel?: string; - dataTestSubj?: string; - securityLinkAnchorComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common - formattedDateComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common - exceptionsUtilityComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common - getFormattedComments: (comments: CommentsArray) => EuiCommentProps[]; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common - onCreateExceptionListItem?: () => void; - onDeleteException: (arg: ExceptionListItemIdentifiers) => void; - onEditExceptionItem: (item: ExceptionListItemSchema) => void; - onPaginationChange: (arg: GetExceptionItemProps) => void; - showValueListModal: ElementType; -} - -const ExceptionItemsComponent: FC = ({ - lastUpdated, - viewerStatus, - isReadOnly, - exceptions, - listType, - ruleReferences, - emptyViewerTitle, - emptyViewerBody, - emptyViewerButtonText, - pagination, - dataTestSubj, - editActionLabel, - deleteActionLabel, - securityLinkAnchorComponent, - exceptionsUtilityComponent, - formattedDateComponent, - getFormattedComments, - onPaginationChange, - onDeleteException, - onEditExceptionItem, - onCreateExceptionListItem, - showValueListModal, -}) => { - const ExceptionsUtility = exceptionsUtilityComponent; - if (!exceptions.length || viewerStatus) - return ( - - ); - const ShowValueListModal = showValueListModal; - return ( - <> - - - - - {exceptions.map((exception) => ( - - - - ))} - - - - - - ); -}; - -ExceptionItemsComponent.displayName = 'ExceptionItemsComponent'; - -export const ExceptionItems = React.memo(ExceptionItemsComponent); - -ExceptionItems.displayName = 'ExceptionsItems'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx deleted file mode 100644 index d68ac8f114a09..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { ElementType, ReactElement } from 'react'; -import { EuiContextMenuItem, EuiFlexGroup, EuiFlexItem, EuiIcon, IconType } from '@elastic/eui'; -import { Rule } from '../types'; -import { itemContentCss, containerCss } from './menu_link.styles'; - -interface MenuItemLinkedRulesProps { - leftIcon?: IconType; - dataTestSubj?: string; - linkedRules: Rule[]; - securityLinkAnchorComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common -} - -export const generateLinkedRulesMenuItems = ({ - dataTestSubj, - linkedRules, - securityLinkAnchorComponent, - leftIcon = '', -}: MenuItemLinkedRulesProps): ReactElement[] | null => { - if (!linkedRules.length || securityLinkAnchorComponent === null) return null; - - const SecurityLinkAnchor = securityLinkAnchorComponent; - return linkedRules.map((rule) => { - return ( - 1 ? containerCss : ''} - data-test-subj={`${dataTestSubj || ''}ActionItem${rule.id}`} - key={rule.id} - > - - {leftIcon ? ( - - - - ) : null} - - - - - - ); - }); -}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/menu_link.styles.ts b/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/menu_link.styles.ts deleted file mode 100644 index 42f470ce39dd5..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/menu_link.styles.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; - -export const containerCss = css` - border-bottom: 1px solid ${euiThemeVars.euiColorLightShade}; -`; - -export const itemContentCss = css` - color: ${euiThemeVars.euiColorPrimary}; - flex-basis: content; -`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx deleted file mode 100644 index 2f39959c33fe4..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { FC, ReactElement, useMemo, useState } from 'react'; -import { - EuiButtonEmpty, - EuiButtonEmptyProps, - EuiButtonIcon, - EuiContextMenuItem, - EuiContextMenuPanel, - EuiFlexGroup, - EuiPopover, - PanelPaddingSize, - PopoverAnchorPosition, -} from '@elastic/eui'; - -import { css } from '@emotion/react'; - -export interface Action { - key: string; - icon: string; - label: string | boolean; - disabled?: boolean; - onClick: (e: React.MouseEvent) => void; -} - -interface HeaderMenuComponentProps { - disableActions: boolean; - actions: Action[] | ReactElement[] | null; - text?: string; - iconType?: EuiButtonEmptyProps['iconType']; - iconSide?: EuiButtonEmptyProps['iconSide']; - dataTestSubj?: string; - emptyButton?: boolean; - useCustomActions?: boolean; - anchorPosition?: PopoverAnchorPosition; - panelPaddingSize?: PanelPaddingSize; -} - -const popoverHeightStyle = css` - max-height: 300px; - height: 100%; - overflow-x: hidden; - overflow-y: auto; -`; -const HeaderMenuComponent: FC = ({ - text, - dataTestSubj, - actions, - disableActions, - emptyButton, - useCustomActions, - iconType, - iconSide = 'left', - anchorPosition = 'downCenter', - panelPaddingSize = 's', -}) => { - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - - const onAffectedRulesClick = () => setIsPopoverOpen((isOpen) => !isOpen); - const onClosePopover = () => setIsPopoverOpen(false); - - const itemActions = useMemo(() => { - if (useCustomActions || actions === null) return actions; - return (actions as Action[]).map((action) => ( - { - onClosePopover(); - if (typeof action.onClick === 'function') action.onClick(e); - }} - > - {action.label} - - )); - }, [actions, dataTestSubj, useCustomActions]); - - return ( - - - {text} - - ) : ( - - {text} - - ) - } - onClick={(e) => e.stopPropagation()} - panelPaddingSize={panelPaddingSize} - isOpen={isPopoverOpen} - closePopover={onClosePopover} - anchorPosition={anchorPosition} - data-test-subj={`${dataTestSubj || ''}Items`} - > - {!itemActions ? null : ( - - )} - - - ); -}; -HeaderMenuComponent.displayName = 'HeaderMenuComponent'; - -export const HeaderMenu = React.memo(HeaderMenuComponent); - -HeaderMenu.displayName = 'HeaderMenu'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/index.tsx deleted file mode 100644 index 82aec99bebb3a..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/index.tsx +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { FC } from 'react'; -import { - EuiButton, - EuiButtonEmpty, - EuiFieldText, - EuiForm, - EuiFormRow, - EuiModal, - EuiModalBody, - EuiModalFooter, - EuiModalHeader, - EuiModalHeaderTitle, - EuiTextArea, - EuiProgress, -} from '@elastic/eui'; -import * as i18n from '../../translations'; -import { ListDetails } from '../../types'; -import { useEditModal } from './use_edit_modal'; - -interface EditModalProps { - listDetails: ListDetails; - onSave: (newListDetails: ListDetails) => void; - onCancel: () => void; -} - -const EditModalComponent: FC = ({ listDetails, onSave, onCancel }) => { - const { error, modalFormId, newListDetails, showProgress, onBlur, onSubmit, onChange } = - useEditModal({ - listDetails, - onSave, - }); - return ( - - {showProgress && ( - - )} - - - {i18n.EXCEPTION_LIST_HEADER_EDIT_MODAL_TITLE(listDetails.name)} - - - - - - - - - - - - - - - - - - {i18n.EXCEPTION_LIST_HEADER_EDIT_MODAL_CANCEL_BUTTON} - - - - {i18n.EXCEPTION_LIST_HEADER_EDIT_MODAL_SAVE_BUTTON} - - - - ); -}; -EditModalComponent.displayName = 'EditModalComponent'; - -export const EditModal = React.memo(EditModalComponent); - -EditModal.displayName = 'EditModal'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/list_header/index.tsx deleted file mode 100644 index 849dd4ef1ba85..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/index.tsx +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import type { FC } from 'react'; -import { EuiIcon, EuiPageHeader, EuiText } from '@elastic/eui'; -import * as i18n from '../translations'; -import { textCss, descriptionContainerCss, backTextCss } from './list_header.styles'; -import { MenuItems } from './menu_items'; -import { TextWithEdit } from '../text_with_edit'; -import { EditModal } from './edit_modal'; -import { ListDetails, Rule } from '../types'; -import { useExceptionListHeader } from './use_list_header'; -import { textWithEditContainerCss } from '../text_with_edit/text_with_edit.styles'; - -interface ExceptionListHeaderComponentProps { - name: string; - description?: string; - listId: string; - isReadonly: boolean; - linkedRules: Rule[]; - dataTestSubj?: string; - backOptions: BackOptions; - canUserEditList?: boolean; - securityLinkAnchorComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common - onEditListDetails: (listDetails: ListDetails) => void; - onDeleteList: () => void; - onManageRules: () => void; - onExportList: () => void; - onDuplicateList: () => void; -} - -export interface BackOptions { - pageId: string; - path: string; - dataTestSubj?: string; - onNavigate: (path: string) => void; -} -const ExceptionListHeaderComponent: FC = ({ - name, - description, - listId, - linkedRules, - isReadonly, - dataTestSubj, - securityLinkAnchorComponent, - backOptions, - canUserEditList = true, - onEditListDetails, - onDeleteList, - onManageRules, - onExportList, - onDuplicateList, -}) => { - const { isModalVisible, listDetails, onEdit, onSave, onCancel } = useExceptionListHeader({ - name, - description, - onEditListDetails, - }); - return ( -
- - } - responsive - data-test-subj={`${dataTestSubj || ''}PageHeader`} - description={ -
- -
- {i18n.EXCEPTION_LIST_HEADER_LIST_ID}: - {listId} -
-
- } - rightSideItems={[ - , - ]} - breadcrumbs={[ - { - text: ( -
- - {i18n.EXCEPTION_LIST_HEADER_BREADCRUMB} -
- ), - color: 'primary', - 'aria-current': false, - href: backOptions.path, - onClick: (e) => { - e.preventDefault(); - backOptions.onNavigate(backOptions.path); - }, - }, - ]} - /> - {isModalVisible && ( - - )} -
- ); -}; - -ExceptionListHeaderComponent.displayName = 'ExceptionListHeaderComponent'; - -export const ExceptionListHeader = React.memo(ExceptionListHeaderComponent); - -ExceptionListHeader.displayName = 'ExceptionListHeader'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.styles.ts b/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.styles.ts deleted file mode 100644 index c3cba9f9dcdbe..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.styles.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; - -export const headerMenuCss = css` - border-right: 1px solid #d3dae6; - padding: ${euiThemeVars.euiSizeXS} ${euiThemeVars.euiSizeL} ${euiThemeVars.euiSizeXS} 0; -`; - -export const noLinkedRulesCss = css` - width: max-content; -`; - -export const textCss = css` - font-size: ${euiThemeVars.euiFontSize}; - color: ${euiThemeVars.euiTextSubduedColor}; - margin-left: ${euiThemeVars.euiSizeXS}; -`; -export const descriptionContainerCss = css` - margin-top: -${euiThemeVars.euiSizeL}; - margin-bottom: -${euiThemeVars.euiSizeL}; -`; - -export const backTextCss = css` - font-size: ${euiThemeVars.euiFontSizeXS}; -`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/index.tsx deleted file mode 100644 index f0aecf21b6c73..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/index.tsx +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui'; -import React, { FC, useMemo } from 'react'; -import { HeaderMenu } from '../../header_menu'; -import { headerMenuCss, noLinkedRulesCss } from '../list_header.styles'; -import * as i18n from '../../translations'; -import { Rule } from '../../types'; -import { generateLinkedRulesMenuItems } from '../../generate_linked_rules_menu_item'; -interface MenuItemsProps { - isReadonly: boolean; - dataTestSubj?: string; - linkedRules: Rule[]; - canUserEditList?: boolean; - securityLinkAnchorComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common - onDeleteList: () => void; - onManageRules: () => void; - onExportList: () => void; - onDuplicateList: () => void; -} - -const MenuItemsComponent: FC = ({ - dataTestSubj, - linkedRules, - securityLinkAnchorComponent, - isReadonly, - canUserEditList = true, - onDeleteList, - onManageRules, - onExportList, - onDuplicateList, -}) => { - const referencedLinks = useMemo( - () => - generateLinkedRulesMenuItems({ - leftIcon: 'check', - dataTestSubj, - linkedRules, - securityLinkAnchorComponent, - }), - [dataTestSubj, linkedRules, securityLinkAnchorComponent] - ); - return ( - - - {linkedRules.length ? ( - - ) : ( - - {i18n.EXCEPTION_LIST_HEADER_LINKED_RULES(linkedRules.length)} - - )} - - - {canUserEditList && ( - - { - if (typeof onManageRules === 'function') onManageRules(); - }} - > - {i18n.EXCEPTION_LIST_HEADER_LINK_RULES_BUTTON} - - - )} - - { - if (typeof onExportList === 'function') onExportList(); - }, - }, - { - key: '2', - icon: 'copy', - label: i18n.EXCEPTION_LIST_HEADER_DUPLICATE_ACTION, - onClick: () => { - if (typeof onDuplicateList === 'function') onDuplicateList(); - }, - disabled: !canUserEditList, - }, - { - key: '3', - icon: 'trash', - label: i18n.EXCEPTION_LIST_HEADER_DELETE_ACTION, - onClick: () => { - if (typeof onDeleteList === 'function') onDeleteList(); - }, - disabled: !canUserEditList, - }, - ]} - disableActions={isReadonly} - anchorPosition="downCenter" - /> - - - ); -}; - -MenuItemsComponent.displayName = 'MenuItemsComponent'; - -export const MenuItems = React.memo(MenuItemsComponent); - -MenuItems.displayName = 'MenuItems'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.ts b/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.ts deleted file mode 100644 index 676dd08a53be1..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useState } from 'react'; -import { ListDetails } from '../types'; - -interface UseExceptionListHeaderProps { - name: string; - description?: string; - onEditListDetails: (listDetails: ListDetails) => void; -} -export const useExceptionListHeader = ({ - name, - description, - onEditListDetails, -}: UseExceptionListHeaderProps) => { - const [isModalVisible, setIsModalVisible] = useState(false); - const [listDetails, setListDetails] = useState({ name, description }); - const onEdit = () => { - setIsModalVisible(true); - }; - const onSave = (newListDetails: ListDetails) => { - setListDetails(newListDetails); - if (typeof onEditListDetails === 'function') onEditListDetails(newListDetails); - setTimeout(() => { - setIsModalVisible(false); - }, 200); - }; - const onCancel = () => { - setIsModalVisible(false); - }; - - return { - isModalVisible, - listDetails, - onEdit, - onSave, - onCancel, - }; -}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/mocks/comments.mock.tsx b/packages/kbn-securitysolution-exception-list-components/src/mocks/comments.mock.tsx deleted file mode 100644 index 4c9b813463ca3..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/mocks/comments.mock.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import type { Comment, CommentsArray } from '@kbn/securitysolution-io-ts-list-types'; - -export const getCommentsMock = (): Comment => ({ - comment: 'some old comment', - created_at: '2020-04-20T15:25:31.830Z', - created_by: 'some user', - id: 'uuid_here', -}); - -export const getCommentsArrayMock = (): CommentsArray => [getCommentsMock(), getCommentsMock()]; - -export const mockGetFormattedComments = () => - getCommentsArrayMock().map((comment) => ({ - username: comment.created_by, - children:

{comment.comment}

, - })); diff --git a/packages/kbn-securitysolution-exception-list-components/src/mocks/entry.mock.ts b/packages/kbn-securitysolution-exception-list-components/src/mocks/entry.mock.ts deleted file mode 100644 index a39fe947caa2e..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/mocks/entry.mock.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { Entry } from '../exception_item_card/conditions/types'; - -export const includedListTypeEntry: Entry = { - field: '', - operator: 'included', - type: 'list', - list: { id: 'list_id', type: 'boolean' }, -}; - -export const includedMatchTypeEntry: Entry = { - field: '', - operator: 'included', - type: 'match', - value: 'matches value', -}; - -export const includedExistsTypeEntry: Entry = { - field: '', - operator: 'included', - type: 'exists', -}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/mocks/exception_list_item_schema.mock.ts b/packages/kbn-securitysolution-exception-list-components/src/mocks/exception_list_item_schema.mock.ts deleted file mode 100644 index f9c24d46228c5..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/mocks/exception_list_item_schema.mock.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export const getExceptionListItemSchemaMock = ( - overrides?: Partial -): ExceptionListItemSchema => ({ - _version: undefined, - comments: [], - created_at: '2020-04-20T15:25:31.830Z', - created_by: 'some user', - description: 'some description', - entries: [ - { - entries: [ - { field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }, - ], - field: 'some.parentField', - type: 'nested', - }, - { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, - ], - expire_time: undefined, - id: '1', - item_id: 'endpoint_list_item', - list_id: 'endpoint_list_id', - meta: {}, - name: 'some name', - namespace_type: 'single', - os_types: [], - tags: ['user added string for a tag', 'malware'], - tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e', - type: 'simple', - updated_at: '2020-04-20T15:25:31.830Z', - updated_by: 'some user', - ...(overrides || {}), -}); diff --git a/packages/kbn-securitysolution-exception-list-components/src/mocks/header.mock.ts b/packages/kbn-securitysolution-exception-list-components/src/mocks/header.mock.ts deleted file mode 100644 index 06aa00b5ff724..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/mocks/header.mock.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export const handleEdit = jest.fn(); -export const handleDelete = jest.fn(); -export const actions = [ - { - key: 'edit', - icon: 'pencil', - label: 'Edit detection exception', - onClick: handleEdit, - }, - { - key: 'delete', - icon: 'trash', - label: 'Delete detection exception', - onClick: handleDelete, - }, -]; -export const actionsWithDisabledDelete = [ - { - key: 'edit', - icon: 'pencil', - label: 'Edit detection exception', - onClick: handleEdit, - }, - { - key: 'delete', - icon: 'trash', - disabled: true, - label: 'Delete detection exception', - onClick: handleDelete, - }, -]; diff --git a/packages/kbn-securitysolution-exception-list-components/src/mocks/rule_references.mock.ts b/packages/kbn-securitysolution-exception-list-components/src/mocks/rule_references.mock.ts deleted file mode 100644 index 3592d5f03cc4c..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/mocks/rule_references.mock.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { Rule, RuleReference } from '../types'; - -export const rules: Rule[] = [ - { - exceptions_list: [ - { - id: '123', - list_id: 'i_exist', - namespace_type: 'single', - type: 'detection', - }, - { - id: '456', - list_id: 'i_exist_2', - namespace_type: 'single', - type: 'detection', - }, - ], - id: '1a2b3c', - name: 'Simple Rule Query', - rule_id: 'rule-2', - }, -]; - -export const ruleReference: RuleReference = { - name: 'endpoint list', - id: 'endpoint_list', - referenced_rules: rules, - listId: 'endpoint_list_id', -}; - -export const ruleReferences = { - endpoint_list_id: ruleReference, -}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/mocks/security_link_component.mock.tsx b/packages/kbn-securitysolution-exception-list-components/src/mocks/security_link_component.mock.tsx deleted file mode 100644 index 1ad7d2921c5a0..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/mocks/security_link_component.mock.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { ReactElement } from 'react'; -import { generateLinkedRulesMenuItems } from '../generate_linked_rules_menu_item'; -import { rules } from './rule_references.mock'; -export const securityLinkAnchorComponentMock = ({ - referenceName, - referenceId, -}: { - referenceName: string; - referenceId: string; -}) => ( - -); - -export const getSecurityLinkAction = (dataTestSubj: string) => - generateLinkedRulesMenuItems({ - dataTestSubj, - linkedRules: [ - ...rules, - { - exceptions_list: [], - id: '2a2b3c', - name: 'Simple Rule Query 2', - rule_id: 'rule-2', - }, - ], - securityLinkAnchorComponent: securityLinkAnchorComponentMock, - }) as ReactElement[]; diff --git a/packages/kbn-securitysolution-exception-list-components/src/mocks/value_list_modal.mock.tsx b/packages/kbn-securitysolution-exception-list-components/src/mocks/value_list_modal.mock.tsx deleted file mode 100644 index 930439b577fff..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/mocks/value_list_modal.mock.tsx +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; - -export const mockShowValueListModal = jest.fn(); -export const MockedShowValueListModal = (props: { children: React.ReactNode }) => { - mockShowValueListModal(props); - return <>{props.children}; -}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.tsx b/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.tsx deleted file mode 100644 index 38be3b8474ad7..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import type { FC } from 'react'; -import { EuiTablePagination } from '@elastic/eui'; - -import type { PaginationProps } from '../types'; -import { usePagination } from './use_pagination'; - -const PaginationComponent: FC = ({ - dataTestSubj, - ariaLabel, - pagination, - onPaginationChange, -}) => { - const { - pageIndex, - pageCount, - pageSize, - pageSizeOptions, - - handleItemsPerPageChange, - handlePageIndexChange, - } = usePagination({ pagination, onPaginationChange }); - - return ( - - ); -}; - -PaginationComponent.displayName = 'PaginationComponent'; - -export const Pagination = React.memo(PaginationComponent); - -Pagination.displayName = 'Pagination'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx deleted file mode 100644 index 72836fc78fb55..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { i18n } from '@kbn/i18n'; - -import { EuiCallOut } from '@elastic/eui'; - -export const PartialCodeSignatureCallout = () => { - return ( - - - - ); -}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx deleted file mode 100644 index 0670a2553a696..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { useCallback } from 'react'; -import type { FC } from 'react'; - -import type { EuiSearchBarProps, IconType, SearchFilterConfig } from '@elastic/eui'; -import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiSearchBar } from '@elastic/eui'; -import type { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import type { GetExceptionItemProps } from '../types'; - -const ITEMS_SCHEMA = { - strict: true, - fields: { - created_by: { - type: 'string', - }, - description: { - type: 'string', - }, - id: { - type: 'string', - }, - item_id: { - type: 'string', - }, - list_id: { - type: 'string', - }, - name: { - type: 'string', - }, - os_types: { - type: 'string', - }, - tags: { - type: 'string', - }, - }, -}; -interface SearchBarProps { - addExceptionButtonText?: string; - placeholdertext?: string; - canAddException?: boolean; // TODO what is the default value - - // TODO: REFACTOR: not to send the listType and handle it in the Parent - // Exception list type used to determine what type of item is - // being created when "onAddExceptionClick" is invoked - listType: ExceptionListTypeEnum; - isSearching?: boolean; - dataTestSubj?: string; - filters?: SearchFilterConfig[]; // TODO about filters - isButtonFilled?: boolean; - buttonIconType?: IconType; - onSearch: (arg: GetExceptionItemProps) => void; - onAddExceptionClick: (type: ExceptionListTypeEnum) => void; -} -const SearchBarComponent: FC = ({ - addExceptionButtonText, - placeholdertext, - canAddException, - listType, - isSearching, - dataTestSubj, - filters = [], - isButtonFilled = true, - buttonIconType, - onSearch, - onAddExceptionClick, -}) => { - const handleOnSearch = useCallback>( - ({ queryText }): void => { - onSearch({ search: queryText }); - }, - [onSearch] - ); - - const handleAddException = useCallback(() => { - // TODO: ASK YARA why we need to send the listType - onAddExceptionClick(listType); - }, [onAddExceptionClick, listType]); - - return ( - - - - - {!canAddException && ( - - - {addExceptionButtonText} - - - )} - - ); -}; - -SearchBarComponent.displayName = 'SearchBarComponent'; - -export const SearchBar = React.memo(SearchBarComponent); - -SearchBar.displayName = 'SearchBar'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/index.tsx deleted file mode 100644 index aa5625cfe671c..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React, { FC } from 'react'; -import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { Interpolation, Theme } from '@emotion/react'; -import { textWithEditContainerCss, editIconCss } from './text_with_edit.styles'; -interface TextWithEditProps { - isReadonly: boolean; - dataTestSubj?: string; - text: string; - textCss?: Interpolation; - onEdit?: () => void; -} - -const TextWithEditComponent: FC = ({ - isReadonly, - dataTestSubj, - text, - onEdit, - textCss, -}) => { - return ( - - - - {text} - - - - {isReadonly ? null : ( - (typeof onEdit === 'function' ? onEdit() : null)} - /> - )} - - - ); -}; -TextWithEditComponent.displayName = 'TextWithEditComponent'; - -export const TextWithEdit = React.memo(TextWithEditComponent); - -TextWithEdit.displayName = 'TextWithEdit'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.styles.ts b/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.styles.ts deleted file mode 100644 index e293ea0730410..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.styles.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; - -export const textWithEditContainerCss = css` - display: flex; - width: fit-content; - align-items: baseline; - padding-bottom: ${euiThemeVars.euiSizeS}; - h1 { - margin-bottom: 0; - } -`; -export const editIconCss = css` - button { - margin-left: -${euiThemeVars.euiSizeM}; - } -`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/translations.ts b/packages/kbn-securitysolution-exception-list-components/src/translations.ts deleted file mode 100644 index dff688d156da8..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/translations.ts +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { i18n } from '@kbn/i18n'; - -export const EMPTY_VIEWER_STATE_EMPTY_TITLE = i18n.translate( - 'exceptionList-components.empty.viewer.state.empty.title', - { - defaultMessage: 'Add exceptions to this list', - } -); - -export const EMPTY_VIEWER_STATE_EMPTY_BODY = i18n.translate( - 'exceptionList-components.empty.viewer.state.empty.body', - { - defaultMessage: 'There is no exception in your list. Create your first exception.', - } -); -export const EMPTY_VIEWER_STATE_EMPTY_SEARCH_TITLE = i18n.translate( - 'exceptionList-components.empty.viewer.state.empty_search.search.title', - { - defaultMessage: 'No results match your search criteria', - } -); - -export const EMPTY_VIEWER_STATE_EMPTY_SEARCH_BODY = i18n.translate( - 'exceptionList-components.empty.viewer.state.empty_search.body', - { - defaultMessage: 'Try modifying your search', - } -); - -export const EMPTY_VIEWER_STATE_EMPTY_VIEWER_BUTTON = (exceptionType: string) => - i18n.translate('exceptionList-components.empty.viewer.state.empty.viewer_button', { - values: { exceptionType }, - defaultMessage: 'Create {exceptionType} exception', - }); - -export const EMPTY_VIEWER_STATE_ERROR_TITLE = i18n.translate( - 'exceptionList-components.empty.viewer.state.error_title', - { - defaultMessage: 'Unable to load exception items', - } -); - -export const EMPTY_VIEWER_STATE_ERROR_BODY = i18n.translate( - 'exceptionList-components.empty.viewer.state.error_body', - { - defaultMessage: - 'There was an error loading the exception items. Contact your administrator for help.', - } -); -export const EXCEPTION_LIST_HEADER_EXPORT_ACTION = i18n.translate( - 'exceptionList-components.exception_list_header_export_action', - { - defaultMessage: 'Export exception list', - } -); -export const EXCEPTION_LIST_HEADER_DELETE_ACTION = i18n.translate( - 'exceptionList-components.exception_list_header_delete_action', - { - defaultMessage: 'Delete exception list', - } -); -export const EXCEPTION_LIST_HEADER_DUPLICATE_ACTION = i18n.translate( - 'exceptionList-components.exception_list_header_duplicate_action', - { - defaultMessage: 'Duplicate exception list', - } -); -export const EXCEPTION_LIST_HEADER_LINK_RULES_BUTTON = i18n.translate( - 'exceptionList-components.exception_list_header_link_rules_button', - { - defaultMessage: 'Link rules', - } -); - -export const EXCEPTION_LIST_HEADER_LINKED_RULES = (noOfRules: number) => - i18n.translate('exceptionList-components.exception_list_header_linked_rules', { - values: { noOfRules }, - defaultMessage: 'Linked to {noOfRules} rules', - }); - -export const EXCEPTION_LIST_HEADER_BREADCRUMB = i18n.translate( - 'exceptionList-components.exception_list_header_breadcrumb', - { - defaultMessage: 'Shared Exception Lists', - } -); - -export const EXCEPTION_LIST_HEADER_LIST_ID = i18n.translate( - 'exceptionList-components.exception_list_header_list_id', - { - defaultMessage: 'List ID', - } -); - -export const EXCEPTION_LIST_HEADER_NAME = i18n.translate( - 'exceptionList-components.exception_list_header_name', - { - defaultMessage: 'Add a name', - } -); - -export const EXCEPTION_LIST_HEADER_DESCRIPTION = i18n.translate( - 'exceptionList-components.exception_list_header_description', - { - defaultMessage: 'Add a description', - } -); - -export const EXCEPTION_LIST_HEADER_EDIT_MODAL_TITLE = (listName: string) => - i18n.translate('exceptionList-components.exception_list_header_edit_modal_name', { - defaultMessage: 'Edit {listName}', - values: { listName }, - }); - -export const EXCEPTION_LIST_HEADER_EDIT_MODAL_SAVE_BUTTON = i18n.translate( - 'exceptionList-components.exception_list_header_edit_modal_save_button', - { - defaultMessage: 'Save', - } -); - -export const EXCEPTION_LIST_HEADER_EDIT_MODAL_CANCEL_BUTTON = i18n.translate( - 'exceptionList-components.exception_list_header_edit_modal_cancel_button', - { - defaultMessage: 'Cancel', - } -); -export const EXCEPTION_LIST_HEADER_NAME_TEXTBOX = i18n.translate( - 'exceptionList-components.exception_list_header_Name_textbox', - { - defaultMessage: 'Name', - } -); - -export const EXCEPTION_LIST_HEADER_DESCRIPTION_TEXTBOX = i18n.translate( - 'exceptionList-components.exception_list_header_description_textbox', - { - defaultMessage: 'Description (optional)', - } -); - -export const LIST_NAME_REQUIRED_ERROR = i18n.translate( - 'exceptionList-components.exception_list_header_description_textboxexceptionList-components.exception_list_header_name_required_eror', - { - defaultMessage: 'List name cannot be empty', - } -); diff --git a/packages/kbn-securitysolution-exception-list-components/src/types/index.ts b/packages/kbn-securitysolution-exception-list-components/src/types/index.ts deleted file mode 100644 index 57a0ee3901ba4..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/types/index.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ListArray } from '@kbn/securitysolution-io-ts-list-types'; - -import type { Pagination } from '@elastic/eui'; -import type { NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; - -export interface GetExceptionItemProps { - pagination?: PaginationProps['pagination']; - search?: string; - filters?: string; -} - -export interface PaginationProps { - dataTestSubj?: string; - ariaLabel?: string; - pagination: Pagination & { pageSize: number }; - onPaginationChange: (arg: GetExceptionItemProps) => void; -} - -export enum ViewerStatus { - ERROR = 'error', - EMPTY = 'empty', - EMPTY_SEARCH = 'empty_search', - LOADING = 'loading', - SEARCHING = 'searching', - DELETING = 'deleting', -} - -export interface ExceptionListSummaryProps { - pagination: Pagination; - // Corresponds to last time exception items were fetched - lastUpdated: string | number | null; -} - -export type ViewerFlyoutName = 'addException' | 'editException' | null; - -export interface RuleReferences { - [key: string]: RuleReference; -} - -export interface ExceptionListItemIdentifiers { - id: string; - name: string; - namespaceType: NamespaceType; -} - -export enum ListTypeText { - ENDPOINT = 'endpoint', - DETECTION = 'empty', - RULE_DEFAULT = 'empty_search', -} -export interface Rule { - name: string; - id: string; - rule_id: string; - exceptions_list?: ListArray; -} - -export interface RuleReference { - name: string; - id: string; - referenced_rules: Rule[]; - listId?: string; -} - -export interface ListDetails { - name: string; - description?: string; -} diff --git a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/index.ts b/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/index.ts deleted file mode 100644 index 5a0843be833f7..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export { ValueWithSpaceWarning } from './value_with_space_warning'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.ts b/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.ts deleted file mode 100644 index d5a6392815a78..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { paramContainsSpace, autoCompletei18n } from '@kbn/securitysolution-autocomplete'; - -interface UseValueWithSpaceWarningResult { - showSpaceWarningIcon: boolean; - warningText: string; -} -interface UseValueWithSpaceWarningProps { - value: string | string[]; - tooltipIconText?: string; -} - -export const useValueWithSpaceWarning = ({ - value, - tooltipIconText, -}: UseValueWithSpaceWarningProps): UseValueWithSpaceWarningResult => { - const showSpaceWarningIcon = Array.isArray(value) - ? value.find(paramContainsSpace) - : paramContainsSpace(value); - - return { - showSpaceWarningIcon: !!showSpaceWarningIcon, - warningText: tooltipIconText || autoCompletei18n.FIELD_SPACE_WARNING, - }; -}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/wildcard_with_wrong_operator_callout/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/wildcard_with_wrong_operator_callout/index.tsx deleted file mode 100644 index d68782b4c17f8..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/src/wildcard_with_wrong_operator_callout/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { i18n } from '@kbn/i18n'; - -import { EuiCallOut } from '@elastic/eui'; - -export const WildCardWithWrongOperatorCallout = () => { - return ( - -

- - {i18n.translate( - 'exceptionList-components.wildcardWithWrongOperatorCallout.changeTheOperator', - { defaultMessage: 'Change the operator' } - )} - - ), - matches: ( - - {i18n.translate( - 'exceptionList-components.wildcardWithWrongOperatorCallout.matches', - { defaultMessage: 'matches' } - )} - - ), - }} - /> -

-
- ); -}; diff --git a/packages/kbn-securitysolution-exception-list-components/tsconfig.json b/packages/kbn-securitysolution-exception-list-components/tsconfig.json deleted file mode 100644 index b3df3a2aa208b..0000000000000 --- a/packages/kbn-securitysolution-exception-list-components/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node", - "react", - "@emotion/react/types/css-prop" - ] - }, - "include": [ - "**/*.ts", - "**/*.tsx", - "**/*.d.ts" - ], - "kbn_references": [ - "@kbn/securitysolution-io-ts-list-types", - "@kbn/securitysolution-autocomplete", - "@kbn/ui-theme", - "@kbn/i18n", - "@kbn/i18n-react", - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.gen.ts b/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.gen.ts deleted file mode 100644 index aedd1f5fc5cc6..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.gen.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Create shared exception list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { - ExceptionListName, - ExceptionListDescription, - ExceptionList, -} from '../model/exception_list_common.gen'; - -export type CreateSharedExceptionListRequestBody = z.infer< - typeof CreateSharedExceptionListRequestBody ->; -export const CreateSharedExceptionListRequestBody = z.object({ - name: ExceptionListName, - description: ExceptionListDescription, -}); -export type CreateSharedExceptionListRequestBodyInput = z.input< - typeof CreateSharedExceptionListRequestBody ->; - -export type CreateSharedExceptionListResponse = z.infer; -export const CreateSharedExceptionListResponse = ExceptionList; diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.schema.yaml deleted file mode 100644 index c4cee089e5836..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.schema.yaml +++ /dev/null @@ -1,68 +0,0 @@ -openapi: 3.0.0 -info: - title: Create shared exception list API endpoint - version: '2023-10-31' -paths: - /api/exceptions/shared: - post: - x-labels: [serverless, ess] - operationId: CreateSharedExceptionList - x-codegen-enabled: true - summary: Create a shared exception list - description: | - An exception list groups exception items and can be associated with detection rules. A shared exception list can apply to multiple detection rules. - > info - > All exception items added to the same list are evaluated using `OR` logic. That is, if any of the items in a list evaluate to `true`, the exception prevents the rule from generating an alert. Likewise, `OR` logic is used for evaluating exceptions when more than one exception list is assigned to a rule. To use the `AND` operator, you can define multiple clauses (`entries`) in a single exception item. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - name: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListName' - description: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListDescription' - required: - - name - - description - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 409: - description: Exception list already exists response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.schema.yaml deleted file mode 100644 index 92afc3232efee..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.schema.yaml +++ /dev/null @@ -1,70 +0,0 @@ -openapi: 3.0.0 -info: - title: Delete exception list API endpoint - version: '2023-10-31' -paths: - /api/exception_lists: - delete: - x-labels: [serverless, ess] - operationId: DeleteExceptionList - x-codegen-enabled: true - summary: Delete an exception list - description: Delete an exception list using the `id` or `list_id` field. - parameters: - - name: id - in: query - required: false - description: Either `id` or `list_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' - - name: list_id - in: query - required: false - description: Either `id` or `list_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' - - name: namespace_type - in: query - required: false - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' - default: single - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Exception list not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.schema.yaml deleted file mode 100644 index 9f57afcd5ab1c..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.schema.yaml +++ /dev/null @@ -1,70 +0,0 @@ -openapi: 3.0.0 -info: - title: Delete exception list item API endpoint - version: '2023-10-31' -paths: - /api/exception_lists/items: - delete: - x-labels: [serverless, ess] - operationId: DeleteExceptionListItem - x-codegen-enabled: true - summary: Delete an exception list item - description: Delete an exception list item using the `id` or `item_id` field. - parameters: - - name: id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' - - name: item_id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' - - name: namespace_type - in: query - required: false - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' - default: single - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItem' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Exception list item not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.schema.yaml deleted file mode 100644 index 758171327ee4c..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.schema.yaml +++ /dev/null @@ -1,71 +0,0 @@ -openapi: 3.0.0 -info: - title: Duplicate exception list API endpoint - version: '2023-10-31' -paths: - /api/exception_lists/_duplicate: - post: - x-labels: [serverless, ess] - operationId: DuplicateExceptionList - x-codegen-enabled: true - summary: Duplicate an exception list - description: Duplicate an existing exception list. - parameters: - - name: list_id - in: query - required: true - description: Exception list's human identifier - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' - - name: namespace_type - in: query - required: true - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' - - name: include_expired_exceptions - in: query - required: true - description: Determines whether to include expired exceptions in the exported list - schema: - type: string - enum: ['true', 'false'] - default: 'true' - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 405: - description: Exception list to duplicate not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.gen.ts b/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.gen.ts deleted file mode 100644 index 9645b8ac793cb..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.gen.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Export exception list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { - ExceptionListId, - ExceptionListHumanId, - ExceptionNamespaceType, -} from '../model/exception_list_common.gen'; - -export type ExportExceptionListRequestQuery = z.infer; -export const ExportExceptionListRequestQuery = z.object({ - /** - * Exception list's identifier - */ - id: ExceptionListId, - /** - * Exception list's human identifier - */ - list_id: ExceptionListHumanId, - namespace_type: ExceptionNamespaceType, - /** - * Determines whether to include expired exceptions in the exported list - */ - include_expired_exceptions: z.enum(['true', 'false']).default('true'), -}); -export type ExportExceptionListRequestQueryInput = z.input; diff --git a/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.schema.yaml deleted file mode 100644 index 3232f46c238c8..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.schema.yaml +++ /dev/null @@ -1,79 +0,0 @@ -openapi: 3.0.0 -info: - title: Export exception list API endpoint - version: '2023-10-31' -paths: - /api/exception_lists/_export: - post: - x-labels: [serverless, ess] - operationId: ExportExceptionList - x-codegen-enabled: true - summary: Export an exception list - description: Export an exception list and its associated items to an NDJSON file. - parameters: - - name: id - in: query - required: true - description: Exception list's identifier - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' - - name: list_id - in: query - required: true - description: Exception list's human identifier - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' - - name: namespace_type - in: query - required: true - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' - - name: include_expired_exceptions - in: query - required: true - description: Determines whether to include expired exceptions in the exported list - schema: - type: string - enum: ['true', 'false'] - default: 'true' - responses: - 200: - description: Successful response - content: - application/ndjson: - schema: - type: string - format: binary - description: A `.ndjson` file containing specified exception list and its items - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Exception list not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/index.ts b/packages/kbn-securitysolution-exceptions-common/api/index.ts deleted file mode 100644 index fd6722b67ace3..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './model/exception_list_common.gen'; -export * from './model/exception_list_item_entry.gen'; -export * from './create_exception_list_item/create_exception_list_item.gen'; -export * from './create_rule_exceptions/create_rule_exceptions.gen'; -export * from './create_shared_exceptions_list/create_shared_exceptions_list.gen'; -export * from './create_exception_list/create_exception_list.gen'; -export * from './delete_exception_list_item/delete_exception_list_item.gen'; -export * from './delete_exception_list/delete_exception_list.gen'; -export * from './duplicate_exception_list/duplicate_exception_list.gen'; -export * from './export_exception_list/export_exception_list.gen'; -export * from './find_exception_list_items/find_exception_list_items.gen'; -export * from './find_exception_lists/find_exception_lists.gen'; -export * from './import_exceptions/import_exceptions.gen'; -export * from './read_exception_list_item/read_exception_list_item.gen'; -export * from './read_exception_list/read_exception_list.gen'; -export * from './read_exception_list_summary/read_exception_list_summary.gen'; -export * from './update_exception_list_item/update_exception_list_item.gen'; -export * from './update_exception_list/update_exception_list.gen'; diff --git a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.schema.yaml deleted file mode 100644 index 883a62e5bbec5..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.schema.yaml +++ /dev/null @@ -1,147 +0,0 @@ -openapi: 3.0.0 -info: - title: Common Exception List Item Entry Attributes - version: 'not applicable' -paths: {} -components: - x-codegen-enabled: true - schemas: - ExceptionListItemEntryOperator: - type: string - enum: [excluded, included] - - ExceptionListItemEntryMatch: - type: object - properties: - type: - type: string - enum: [match] - field: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - value: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - operator: - $ref: '#/components/schemas/ExceptionListItemEntryOperator' - required: - - type - - field - - value - - operator - - ExceptionListItemEntryMatchAny: - type: object - properties: - type: - type: string - enum: [match_any] - field: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - value: - type: array - items: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - minItems: 1 - operator: - $ref: '#/components/schemas/ExceptionListItemEntryOperator' - required: - - type - - field - - value - - operator - - ExceptionListItemEntryList: - type: object - properties: - type: - type: string - enum: [list] - field: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - list: - type: object - properties: - id: - $ref: '../../../kbn-securitysolution-lists-common/api/model/list_common.schema.yaml#/components/schemas/ListId' - type: - $ref: '../../../kbn-securitysolution-lists-common/api/model/list_common.schema.yaml#/components/schemas/ListType' - required: [id, type] - operator: - $ref: '#/components/schemas/ExceptionListItemEntryOperator' - required: - - type - - field - - list - - operator - - ExceptionListItemEntryExists: - type: object - properties: - type: - type: string - enum: [exists] - field: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - operator: - $ref: '#/components/schemas/ExceptionListItemEntryOperator' - required: - - type - - field - - operator - - ExceptionListItemEntryNestedEntryItem: - oneOf: - - $ref: '#/components/schemas/ExceptionListItemEntryMatch' - - $ref: '#/components/schemas/ExceptionListItemEntryMatchAny' - - $ref: '#/components/schemas/ExceptionListItemEntryExists' - - ExceptionListItemEntryNested: - type: object - properties: - type: - type: string - enum: [nested] - field: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - entries: - type: array - items: - $ref: '#/components/schemas/ExceptionListItemEntryNestedEntryItem' - minItems: 1 - required: - - type - - field - - entries - - ExceptionListItemEntryMatchWildcard: - type: object - properties: - type: - type: string - enum: [wildcard] - field: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - value: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - operator: - $ref: '#/components/schemas/ExceptionListItemEntryOperator' - required: - - type - - field - - value - - operator - - ExceptionListItemEntry: - discriminator: - propertyName: type - anyOf: - - $ref: '#/components/schemas/ExceptionListItemEntryMatch' - - $ref: '#/components/schemas/ExceptionListItemEntryMatchAny' - - $ref: '#/components/schemas/ExceptionListItemEntryList' - - $ref: '#/components/schemas/ExceptionListItemEntryExists' - - $ref: '#/components/schemas/ExceptionListItemEntryNested' - - $ref: '#/components/schemas/ExceptionListItemEntryMatchWildcard' - - ExceptionListItemEntryArray: - type: array - items: - $ref: '#/components/schemas/ExceptionListItemEntry' diff --git a/packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts b/packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts deleted file mode 100644 index 4827baab85e90..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts +++ /dev/null @@ -1,427 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Exceptions API client for quickstart - * version: Bundle (no version) - */ - -import type { KbnClient } from '@kbn/test'; -import { ToolingLog } from '@kbn/tooling-log'; -import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import { replaceParams } from '@kbn/openapi-common/shared'; -import { catchAxiosErrorFormatAndThrow } from '@kbn/securitysolution-utils'; - -import type { - CreateExceptionListItemRequestBodyInput, - CreateExceptionListItemResponse, -} from './create_exception_list_item/create_exception_list_item.gen'; -import type { - CreateExceptionListRequestBodyInput, - CreateExceptionListResponse, -} from './create_exception_list/create_exception_list.gen'; -import type { - CreateRuleExceptionListItemsRequestParamsInput, - CreateRuleExceptionListItemsRequestBodyInput, - CreateRuleExceptionListItemsResponse, -} from './create_rule_exceptions/create_rule_exceptions.gen'; -import type { - CreateSharedExceptionListRequestBodyInput, - CreateSharedExceptionListResponse, -} from './create_shared_exceptions_list/create_shared_exceptions_list.gen'; -import type { - DeleteExceptionListItemRequestQueryInput, - DeleteExceptionListItemResponse, -} from './delete_exception_list_item/delete_exception_list_item.gen'; -import type { - DeleteExceptionListRequestQueryInput, - DeleteExceptionListResponse, -} from './delete_exception_list/delete_exception_list.gen'; -import type { - DuplicateExceptionListRequestQueryInput, - DuplicateExceptionListResponse, -} from './duplicate_exception_list/duplicate_exception_list.gen'; -import type { ExportExceptionListRequestQueryInput } from './export_exception_list/export_exception_list.gen'; -import type { - FindExceptionListItemsRequestQueryInput, - FindExceptionListItemsResponse, -} from './find_exception_list_items/find_exception_list_items.gen'; -import type { - FindExceptionListsRequestQueryInput, - FindExceptionListsResponse, -} from './find_exception_lists/find_exception_lists.gen'; -import type { - ImportExceptionListRequestQueryInput, - ImportExceptionListResponse, -} from './import_exceptions/import_exceptions.gen'; -import type { - ReadExceptionListItemRequestQueryInput, - ReadExceptionListItemResponse, -} from './read_exception_list_item/read_exception_list_item.gen'; -import type { - ReadExceptionListSummaryRequestQueryInput, - ReadExceptionListSummaryResponse, -} from './read_exception_list_summary/read_exception_list_summary.gen'; -import type { - ReadExceptionListRequestQueryInput, - ReadExceptionListResponse, -} from './read_exception_list/read_exception_list.gen'; -import type { - UpdateExceptionListItemRequestBodyInput, - UpdateExceptionListItemResponse, -} from './update_exception_list_item/update_exception_list_item.gen'; -import type { - UpdateExceptionListRequestBodyInput, - UpdateExceptionListResponse, -} from './update_exception_list/update_exception_list.gen'; - -export interface ClientOptions { - kbnClient: KbnClient; - log: ToolingLog; -} - -export class Client { - readonly kbnClient: KbnClient; - readonly log: ToolingLog; - - constructor(options: ClientOptions) { - this.kbnClient = options.kbnClient; - this.log = options.log; - } - /** - * An exception list groups exception items and can be associated with detection rules. You can assign detection rules with multiple exception lists. -> info -> All exception items added to the same list are evaluated using `OR` logic. That is, if any of the items in a list evaluate to `true`, the exception prevents the rule from generating an alert. Likewise, `OR` logic is used for evaluating exceptions when more than one exception list is assigned to a rule. To use the `AND` operator, you can define multiple clauses (`entries`) in a single exception item. - - */ - async createExceptionList(props: CreateExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API CreateExceptionList`); - return this.kbnClient - .request({ - path: '/api/exception_lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Create an exception item and associate it with the specified exception list. -> info -> Before creating exception items, you must create an exception list. - - */ - async createExceptionListItem(props: CreateExceptionListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API CreateExceptionListItem`); - return this.kbnClient - .request({ - path: '/api/exception_lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Create exception items that apply to a single detection rule. - */ - async createRuleExceptionListItems(props: CreateRuleExceptionListItemsProps) { - this.log.info(`${new Date().toISOString()} Calling API CreateRuleExceptionListItems`); - return this.kbnClient - .request({ - path: replaceParams('/api/detection_engine/rules/{id}/exceptions', props.params), - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * An exception list groups exception items and can be associated with detection rules. A shared exception list can apply to multiple detection rules. -> info -> All exception items added to the same list are evaluated using `OR` logic. That is, if any of the items in a list evaluate to `true`, the exception prevents the rule from generating an alert. Likewise, `OR` logic is used for evaluating exceptions when more than one exception list is assigned to a rule. To use the `AND` operator, you can define multiple clauses (`entries`) in a single exception item. - - */ - async createSharedExceptionList(props: CreateSharedExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API CreateSharedExceptionList`); - return this.kbnClient - .request({ - path: '/api/exceptions/shared', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Delete an exception list using the `id` or `list_id` field. - */ - async deleteExceptionList(props: DeleteExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API DeleteExceptionList`); - return this.kbnClient - .request({ - path: '/api/exception_lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'DELETE', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Delete an exception list item using the `id` or `item_id` field. - */ - async deleteExceptionListItem(props: DeleteExceptionListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API DeleteExceptionListItem`); - return this.kbnClient - .request({ - path: '/api/exception_lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'DELETE', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Duplicate an existing exception list. - */ - async duplicateExceptionList(props: DuplicateExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API DuplicateExceptionList`); - return this.kbnClient - .request({ - path: '/api/exception_lists/_duplicate', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Export an exception list and its associated items to an NDJSON file. - */ - async exportExceptionList(props: ExportExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API ExportExceptionList`); - return this.kbnClient - .request({ - path: '/api/exception_lists/_export', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get a list of all exception list items in the specified list. - */ - async findExceptionListItems(props: FindExceptionListItemsProps) { - this.log.info(`${new Date().toISOString()} Calling API FindExceptionListItems`); - return this.kbnClient - .request({ - path: '/api/exception_lists/items/_find', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get a list of all exception lists. - */ - async findExceptionLists(props: FindExceptionListsProps) { - this.log.info(`${new Date().toISOString()} Calling API FindExceptionLists`); - return this.kbnClient - .request({ - path: '/api/exception_lists/_find', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Import an exception list and its associated items from an NDJSON file. - */ - async importExceptionList(props: ImportExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API ImportExceptionList`); - return this.kbnClient - .request({ - path: '/api/exception_lists/_import', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.attachment, - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get the details of an exception list using the `id` or `list_id` field. - */ - async readExceptionList(props: ReadExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API ReadExceptionList`); - return this.kbnClient - .request({ - path: '/api/exception_lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get the details of an exception list item using the `id` or `item_id` field. - */ - async readExceptionListItem(props: ReadExceptionListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API ReadExceptionListItem`); - return this.kbnClient - .request({ - path: '/api/exception_lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get a summary of the specified exception list. - */ - async readExceptionListSummary(props: ReadExceptionListSummaryProps) { - this.log.info(`${new Date().toISOString()} Calling API ReadExceptionListSummary`); - return this.kbnClient - .request({ - path: '/api/exception_lists/summary', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Update an exception list using the `id` or `list_id` field. - */ - async updateExceptionList(props: UpdateExceptionListProps) { - this.log.info(`${new Date().toISOString()} Calling API UpdateExceptionList`); - return this.kbnClient - .request({ - path: '/api/exception_lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'PUT', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Update an exception list item using the `id` or `item_id` field. - */ - async updateExceptionListItem(props: UpdateExceptionListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API UpdateExceptionListItem`); - return this.kbnClient - .request({ - path: '/api/exception_lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'PUT', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } -} - -export interface CreateExceptionListProps { - body: CreateExceptionListRequestBodyInput; -} -export interface CreateExceptionListItemProps { - body: CreateExceptionListItemRequestBodyInput; -} -export interface CreateRuleExceptionListItemsProps { - params: CreateRuleExceptionListItemsRequestParamsInput; - body: CreateRuleExceptionListItemsRequestBodyInput; -} -export interface CreateSharedExceptionListProps { - body: CreateSharedExceptionListRequestBodyInput; -} -export interface DeleteExceptionListProps { - query: DeleteExceptionListRequestQueryInput; -} -export interface DeleteExceptionListItemProps { - query: DeleteExceptionListItemRequestQueryInput; -} -export interface DuplicateExceptionListProps { - query: DuplicateExceptionListRequestQueryInput; -} -export interface ExportExceptionListProps { - query: ExportExceptionListRequestQueryInput; -} -export interface FindExceptionListItemsProps { - query: FindExceptionListItemsRequestQueryInput; -} -export interface FindExceptionListsProps { - query: FindExceptionListsRequestQueryInput; -} -export interface ImportExceptionListProps { - query: ImportExceptionListRequestQueryInput; - attachment: FormData; -} -export interface ReadExceptionListProps { - query: ReadExceptionListRequestQueryInput; -} -export interface ReadExceptionListItemProps { - query: ReadExceptionListItemRequestQueryInput; -} -export interface ReadExceptionListSummaryProps { - query: ReadExceptionListSummaryRequestQueryInput; -} -export interface UpdateExceptionListProps { - body: UpdateExceptionListRequestBodyInput; -} -export interface UpdateExceptionListItemProps { - body: UpdateExceptionListItemRequestBodyInput; -} diff --git a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.gen.ts b/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.gen.ts deleted file mode 100644 index 67a832b01195c..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.gen.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Read exception list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { - ExceptionListId, - ExceptionListHumanId, - ExceptionNamespaceType, - ExceptionList, -} from '../model/exception_list_common.gen'; - -export type ReadExceptionListRequestQuery = z.infer; -export const ReadExceptionListRequestQuery = z.object({ - /** - * Either `id` or `list_id` must be specified - */ - id: ExceptionListId.optional(), - /** - * Either `id` or `list_id` must be specified - */ - list_id: ExceptionListHumanId.optional(), - namespace_type: ExceptionNamespaceType.optional().default('single'), -}); -export type ReadExceptionListRequestQueryInput = z.input; - -export type ReadExceptionListResponse = z.infer; -export const ReadExceptionListResponse = ExceptionList; diff --git a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.schema.yaml deleted file mode 100644 index 0bf082c1713bd..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.schema.yaml +++ /dev/null @@ -1,70 +0,0 @@ -openapi: 3.0.0 -info: - title: Read exception list API endpoint - version: '2023-10-31' -paths: - /api/exception_lists: - get: - x-labels: [serverless, ess] - operationId: ReadExceptionList - x-codegen-enabled: true - summary: Get exception list details - description: Get the details of an exception list using the `id` or `list_id` field. - parameters: - - name: id - in: query - required: false - description: Either `id` or `list_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' - - name: list_id - in: query - required: false - description: Either `id` or `list_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' - - name: namespace_type - in: query - required: false - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' - default: single - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Exception list item not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.schema.yaml deleted file mode 100644 index c271016a87eb5..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.schema.yaml +++ /dev/null @@ -1,70 +0,0 @@ -openapi: 3.0.0 -info: - title: Read exception list item API endpoint - version: '2023-10-31' -paths: - /api/exception_lists/items: - get: - x-labels: [serverless, ess] - operationId: ReadExceptionListItem - x-codegen-enabled: true - summary: Get an exception list item - description: Get the details of an exception list item using the `id` or `item_id` field. - parameters: - - name: id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' - - name: item_id - in: query - required: false - description: Either `id` or `item_id` must be specified - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' - - name: namespace_type - in: query - required: false - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' - default: single - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItem' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Exception list item not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.schema.yaml b/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.schema.yaml deleted file mode 100644 index b0627111e877f..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.schema.yaml +++ /dev/null @@ -1,89 +0,0 @@ -openapi: 3.0.0 -info: - title: Read exception list summary API endpoint - version: '2023-10-31' -paths: - /api/exception_lists/summary: - get: - x-labels: [serverless, ess] - operationId: ReadExceptionListSummary - x-codegen-enabled: true - summary: Get an exception list summary - description: Get a summary of the specified exception list. - parameters: - - name: id - in: query - required: false - description: Exception list's identifier generated upon creation - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' - - name: list_id - in: query - required: false - description: Exception list's human readable identifier - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' - - name: namespace_type - in: query - required: false - schema: - $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' - default: single - - name: filter - in: query - required: false - description: Search filter clause - schema: - type: string - responses: - 200: - description: Successful response - content: - application/json: - schema: - type: object - properties: - windows: - type: integer - minimum: 0 - linux: - type: integer - minimum: 0 - macos: - type: integer - minimum: 0 - total: - type: integer - minimum: 0 - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: Exception list not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/package.json b/packages/kbn-securitysolution-exceptions-common/package.json deleted file mode 100644 index 5148c4d5eedf5..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "description": "Security Solution Exceptions common package", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "name": "@kbn/securitysolution-exceptions-common", - "private": true, - "version": "1.0.0", - "scripts": { - "openapi:generate": "node scripts/openapi_generate", - "openapi:bundle": "node scripts/openapi_bundle" - } -} diff --git a/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js b/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js deleted file mode 100644 index 70299e56eac2e..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -require('../../../src/setup_node_env'); -const { join, resolve } = require('path'); -const { bundle } = require('@kbn/openapi-bundler'); - -const ROOT = resolve(__dirname, '..'); - -(async () => { - await bundle({ - sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), - outputFilePath: join( - ROOT, - 'docs/openapi/serverless/security_solution_exceptions_api_{version}.bundled.schema.yaml' - ), - options: { - includeLabels: ['serverless'], - prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/exceptions_serverless.info.yaml'), - }, - }); - - await bundle({ - sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), - outputFilePath: join( - ROOT, - 'docs/openapi/ess/security_solution_exceptions_api_{version}.bundled.schema.yaml' - ), - options: { - includeLabels: ['ess'], - prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/exceptions_ess.info.yaml'), - }, - }); -})(); diff --git a/packages/kbn-securitysolution-exceptions-common/scripts/openapi_generate.js b/packages/kbn-securitysolution-exceptions-common/scripts/openapi_generate.js deleted file mode 100644 index 13b260476f3a3..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/scripts/openapi_generate.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -require('../../../src/setup_node_env'); -const { join, resolve } = require('path'); -const { generate } = require('@kbn/openapi-generator'); -const { REPO_ROOT } = require('@kbn/repo-info'); - -const ROOT = resolve(__dirname, '..'); - -(async () => { - await generate({ - title: 'OpenAPI Exceptions API Schemas', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'zod_operation_schema', - }); - - await generate({ - title: 'Exceptions API client for tests', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'api_client_supertest', - skipLinting: true, - bundle: { - outFile: join( - REPO_ROOT, - 'x-pack/test/api_integration/services/security_solution_exceptions_api.gen.ts' - ), - }, - }); - - await generate({ - title: 'Exceptions API client for quickstart', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'api_client_quickstart', - skipLinting: true, - bundle: { - outFile: join( - REPO_ROOT, - 'packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts' - ), - }, - }); -})(); diff --git a/packages/kbn-securitysolution-exceptions-common/tsconfig.json b/packages/kbn-securitysolution-exceptions-common/tsconfig.json deleted file mode 100644 index a58753f53a4fb..0000000000000 --- a/packages/kbn-securitysolution-exceptions-common/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "outDir": "target/types", - "types": ["jest", "node"] - }, - "exclude": ["target/**/*"], - "extends": "../../tsconfig.base.json", - "include": ["**/*.ts"], - "kbn_references": [ - "@kbn/openapi-common", - "@kbn/zod-helpers", - "@kbn/securitysolution-lists-common", - "@kbn/test", - "@kbn/tooling-log", - "@kbn/core-http-common", - "@kbn/securitysolution-utils", - "@kbn/zod", - ] -} diff --git a/packages/kbn-securitysolution-hook-utils/index.ts b/packages/kbn-securitysolution-hook-utils/index.ts deleted file mode 100644 index be336bddcf9b5..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/types'; -export * from './src/use_async'; -export * from './src/use_is_mounted'; -export * from './src/use_observable'; -export * from './src/with_optional_signal'; diff --git a/packages/kbn-securitysolution-hook-utils/jest.config.js b/packages/kbn-securitysolution-hook-utils/jest.config.js deleted file mode 100644 index badea193370b6..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-hook-utils'], -}; diff --git a/packages/kbn-securitysolution-hook-utils/package.json b/packages/kbn-securitysolution-hook-utils/package.json deleted file mode 100644 index 71a83ce3ebb4b..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/securitysolution-hook-utils", - "version": "1.0.0", - "description": "Security Solution utilities for React hooks", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-hook-utils/src/types.ts b/packages/kbn-securitysolution-hook-utils/src/types.ts deleted file mode 100644 index 6642afac7381e..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/types.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/** - * Represents the state of an asynchronous task, along with an initiator - * function to kick off the work. - */ -export interface Task { - loading: boolean; - error: unknown | undefined; - result: Result | undefined; - start: (...args: Args) => void; -} diff --git a/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts deleted file mode 100644 index 99417c1fe3292..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { waitFor, renderHook, act } from '@testing-library/react'; - -import { useAsync } from '.'; - -interface TestArgs { - n: number; - s: string; -} - -type TestReturn = Promise; - -describe('useAsync', () => { - /** - * Timeout for both jest tests and for the waitFor. - * jest tests default to 5 seconds and waitFor defaults to 1 second. - * 20_0000 = 20,000 milliseconds = 20 seconds - */ - const timeout = 20_000; - - let fn: jest.Mock; - let args: TestArgs; - - beforeEach(() => { - args = { n: 1, s: 's' }; - fn = jest.fn().mockResolvedValue(false); - }); - - it('does not invoke fn if start was not called', () => { - renderHook(() => useAsync(fn)); - expect(fn).not.toHaveBeenCalled(); - }); - - it( - 'invokes the function when start is called', - async () => { - const { result } = renderHook(() => useAsync(fn)); - - act(() => { - result.current.start(args); - }); - await waitFor(() => expect(fn).toHaveBeenCalled(), { timeout }); - }, - timeout - ); - - it('invokes the function with start args', async () => { - const { result } = renderHook(() => useAsync(fn)); - const expectedArgs = { ...args }; - - act(() => { - result.current.start(args); - }); - await waitFor(() => expect(fn).toHaveBeenCalledWith(expectedArgs), { timeout }); - }); - - it( - 'populates result with the resolved value of the fn', - async () => { - const { result } = renderHook(() => useAsync(fn)); - fn.mockResolvedValue({ resolved: 'value' }); - - act(() => { - result.current.start(args); - }); - await waitFor( - () => { - expect(result.current.result).toEqual({ resolved: 'value' }); - expect(result.current.error).toBeUndefined(); - }, - { timeout } - ); - }, - timeout - ); - - it( - 'populates error if function rejects', - async () => { - fn.mockRejectedValue(new Error('whoops')); - const { result } = renderHook(() => useAsync(fn)); - - act(() => { - result.current.start(args); - }); - - await waitFor( - () => { - expect(result.current.result).toBeUndefined(); - expect(result.current.error).toEqual(new Error('whoops')); - }, - { timeout } - ); - }, - timeout - ); - - it( - 'populates the loading state while the function is pending', - async () => { - let resolve: () => void; - fn.mockImplementation(() => new Promise((_resolve) => (resolve = _resolve))); - - const { result } = renderHook(() => useAsync(fn)); - - act(() => { - result.current.start(args); - }); - - expect(result.current.loading).toBe(true); - - act(() => resolve()); - await waitFor(() => expect(result.current.loading).toBe(false), { timeout }); - }, - timeout - ); - - it( - 'multiple start calls reset state', - async () => { - let resolve: (result: string) => void; - fn.mockImplementation(() => new Promise((_resolve) => (resolve = _resolve))); - - const { result } = renderHook(() => useAsync(fn)); - - act(() => { - result.current.start(args); - }); - - expect(result.current.loading).toBe(true); - - act(() => resolve('result')); - await waitFor( - () => { - expect(result.current.loading).toBe(false); - expect(result.current.result).toBe('result'); - }, - { timeout } - ); - - act(() => { - result.current.start(args); - }); - - expect(result.current.loading).toBe(true); - expect(result.current.result).toBe(undefined); - act(() => resolve('result')); - await waitFor( - () => { - expect(result.current.loading).toBe(false); - expect(result.current.result).toBe('result'); - }, - { timeout } - ); - }, - timeout - ); -}); diff --git a/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts b/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts deleted file mode 100644 index 2c695b26acdd6..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useCallback, useState } from 'react'; - -import { Task } from '../types'; -import { useIsMounted } from '../use_is_mounted'; - -/** - * - * This hook wraps a promise-returning thunk (task) in order to conditionally - * initiate the work, and automatically provide state corresponding to the - * task's status. - * - * In order to function properly and not rerender unnecessarily, ensure that - * your task is a stable function reference. - * - * @param fn a function returning a promise. - * - * @returns An {@link Task} containing the task's current state along with a - * start callback - */ -export const useAsync = ( - fn: (...args: Args) => Promise -): Task => { - const isMounted = useIsMounted(); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(); - const [result, setResult] = useState(); - - const start = useCallback( - (...args: Args) => { - setLoading(true); - setResult(undefined); - setError(undefined); - fn(...args) - .then((r) => isMounted() && setResult(r)) - .catch((e) => isMounted() && setError(e)) - .finally(() => isMounted() && setLoading(false)); - }, - [fn, isMounted] - ); - - return { - error, - loading, - result, - start, - }; -}; diff --git a/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts deleted file mode 100644 index a8013a65441c9..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { renderHook } from '@testing-library/react'; - -import { useIsMounted } from '.'; - -describe('useIsMounted', () => { - it('evaluates to true when mounted', () => { - const { result } = renderHook(() => useIsMounted()); - - expect(result.current()).toEqual(true); - }); - - it('evaluates to false when unmounted', () => { - const { result, unmount } = renderHook(() => useIsMounted()); - - unmount(); - expect(result.current()).toEqual(false); - }); -}); diff --git a/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts b/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts deleted file mode 100644 index b563840d2f73a..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useCallback, useEffect, useRef } from 'react'; - -type GetIsMounted = () => boolean; - -/** - * - * @returns A {@link GetIsMounted} getter function returning whether the component is currently mounted - */ -export const useIsMounted = (): GetIsMounted => { - const isMounted = useRef(false); - const getIsMounted: GetIsMounted = useCallback(() => isMounted.current, []); - const handleCleanup = useCallback(() => { - isMounted.current = false; - }, []); - - useEffect(() => { - isMounted.current = true; - return handleCleanup; - }, [handleCleanup]); - - return getIsMounted; -}; diff --git a/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts deleted file mode 100644 index 8d90bffeb3ee2..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { renderHook, act } from '@testing-library/react'; -import { Subject, throwError } from 'rxjs'; - -import { useObservable } from '.'; - -interface TestArgs { - n: number; - s: string; -} - -type TestReturn = Subject; - -describe('useObservable', () => { - let fn: jest.Mock; - let subject: TestReturn; - let args: TestArgs; - - beforeEach(() => { - args = { n: 1, s: 's' }; - subject = new Subject(); - fn = jest.fn().mockReturnValue(subject); - }); - - it('does not invoke fn if start was not called', () => { - renderHook(() => useObservable(fn)); - expect(fn).not.toHaveBeenCalled(); - }); - - it('invokes the function when start is called', () => { - const { result } = renderHook(() => useObservable(fn)); - - act(() => { - result.current.start(args); - }); - - expect(fn).toHaveBeenCalled(); - }); - - it('invokes the function with start args', () => { - const { result } = renderHook(() => useObservable(fn)); - const expectedArgs = { ...args }; - - act(() => { - result.current.start(args); - }); - - expect(fn).toHaveBeenCalledWith(expectedArgs); - }); - - it('populates result with the next value of the fn', () => { - const { result } = renderHook(() => useObservable(fn)); - - act(() => { - result.current.start(args); - }); - act(() => subject.next('value')); - - expect(result.current.result).toEqual('value'); - expect(result.current.error).toBeUndefined(); - }); - - it('populates error if observable throws an error', () => { - const error = new Error('whoops'); - const errorFn = () => throwError(error); - - const { result } = renderHook(() => useObservable(errorFn)); - - act(() => { - result.current.start(); - }); - - expect(result.current.result).toBeUndefined(); - expect(result.current.error).toEqual(error); - }); - - it('populates the loading state while no value has resolved', () => { - const { result } = renderHook(() => useObservable(fn)); - - act(() => { - result.current.start(args); - }); - - expect(result.current.loading).toBe(true); - - act(() => subject.next('a value')); - - expect(result.current.loading).toBe(false); - }); - - it('updates result with each resolved value', () => { - const { result } = renderHook(() => useObservable(fn)); - - act(() => { - result.current.start(args); - }); - - act(() => subject.next('a value')); - expect(result.current.result).toEqual('a value'); - - act(() => subject.next('a subsequent value')); - expect(result.current.result).toEqual('a subsequent value'); - }); - - it('does not update result with values if start has not been called', () => { - const { result } = renderHook(() => useObservable(fn)); - - act(() => subject.next('a value')); - expect(result.current.result).toBeUndefined(); - - act(() => subject.next('a subsequent value')); - expect(result.current.result).toBeUndefined(); - }); - - it('unsubscribes on unmount', () => { - const { result, unmount } = renderHook(() => useObservable(fn)); - - act(() => { - result.current.start(args); - }); - expect(subject.observers).toHaveLength(1); - - unmount(); - expect(subject.observers).toHaveLength(0); - }); - - it('multiple start calls reset state', () => { - const { result } = renderHook(() => useObservable(fn)); - - act(() => { - result.current.start(args); - }); - - expect(result.current.loading).toBe(true); - - act(() => subject.next('one value')); - - expect(result.current.loading).toBe(false); - expect(result.current.result).toBe('one value'); - - act(() => { - result.current.start(args); - }); - - expect(result.current.loading).toBe(true); - expect(result.current.result).toBe(undefined); - - act(() => subject.next('another value')); - - expect(result.current.loading).toBe(false); - expect(result.current.result).toBe('another value'); - }); -}); diff --git a/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts b/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts deleted file mode 100644 index 0b7f9ab93e022..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useCallback, useEffect, useRef, useReducer, Reducer } from 'react'; -import { Observable, Subscription } from 'rxjs'; - -import { useIsMounted } from '../use_is_mounted'; -import { Task } from '../types'; - -interface State { - loading: boolean; - error?: unknown; - result?: T; -} - -export type Action = - | { type: 'setResult'; result: T } - | { type: 'setError'; error: unknown } - | { type: 'load' }; - -function reducer(state: State, action: Action) { - switch (action.type) { - case 'setResult': - return { ...state, result: action.result, loading: false }; - case 'setError': - return { ...state, error: action.error, loading: false }; - case 'load': - return { loading: true, result: undefined, error: undefined }; - } -} - -/** - * - * @param fn function returning an observable - * - * @returns An {@link Async} containing the underlying task's state along with a start callback - */ -export const useObservable = ( - fn: (...args: Args) => Observable -): Task => { - const isMounted = useIsMounted(); - const subRef = useRef(); - const [state, dispatch] = useReducer, Action>>(reducer, { - loading: false, - error: undefined, - result: undefined, - }); - - const start = useCallback( - (...args: Args) => { - if (subRef.current) { - subRef.current.unsubscribe(); - } - dispatch({ type: 'load' }); - - subRef.current = fn(...args).subscribe( - (r) => { - if (isMounted()) { - dispatch({ type: 'setResult', result: r }); - } - }, - (e) => { - if (isMounted()) { - dispatch({ type: 'setError', error: e }); - } - } - ); - }, - [fn, isMounted] - ); - - useEffect( - () => () => { - if (subRef.current) { - subRef.current.unsubscribe(); - } - }, - [] - ); - - return { - result: state.result, - error: state.error, - loading: state.loading, - start, - }; -}; diff --git a/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts deleted file mode 100644 index fa77482d24bed..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { withOptionalSignal } from '.'; - -type TestFn = ({ number, signal }: { number: number; signal: AbortSignal }) => boolean; - -describe('withOptionalSignal', () => { - it('does not require a signal on the returned function', () => { - const fn = jest.fn().mockReturnValue('hello') as TestFn; - - const wrappedFn = withOptionalSignal(fn); - - expect(wrappedFn({ number: 1 })).toEqual('hello'); - }); - - it('will pass a given signal to the wrapped function', () => { - const fn = jest.fn().mockReturnValue('hello') as TestFn; - const { signal } = new AbortController(); - - const wrappedFn = withOptionalSignal(fn); - - wrappedFn({ number: 1, signal }); - expect(fn).toHaveBeenCalledWith({ number: 1, signal }); - }); -}); diff --git a/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts b/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts deleted file mode 100644 index eb7cffeb7e003..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -interface SignalArgs { - signal: AbortSignal; -} - -export type OptionalSignalArgs = Omit & Partial; - -/** - * - * @param fn an async function receiving an AbortSignal argument - * - * @returns An async function where the AbortSignal argument is optional - */ -export const withOptionalSignal = - (fn: (args: Args) => Result) => - (args: OptionalSignalArgs): Result => { - const signal = args.signal != null ? args.signal : new AbortController().signal; - return fn({ ...args, signal } as Args); - }; diff --git a/packages/kbn-securitysolution-hook-utils/tsconfig.json b/packages/kbn-securitysolution-hook-utils/tsconfig.json deleted file mode 100644 index 9b5c5373afe0e..0000000000000 --- a/packages/kbn-securitysolution-hook-utils/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": ["jest", "node"] - }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/index.ts deleted file mode 100644 index 6baaf0a704036..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/actions'; -export * from './src/default_actions_array'; -export * from './src/default_export_file_name'; -export * from './src/default_from_string'; -export * from './src/default_interval_string'; -export * from './src/default_language_string'; -export * from './src/default_max_signals_number'; -export * from './src/default_page'; -export * from './src/default_per_page'; -export * from './src/default_risk_score_mapping_array'; -export * from './src/default_severity_mapping_array'; -export * from './src/default_threat_array'; -export * from './src/default_to_string'; -export * from './src/default_uuid'; -export * from './src/frequency'; -export * from './src/language'; -export * from './src/machine_learning_job_id'; -export * from './src/max_signals'; -export * from './src/normalized_ml_job_id'; -export * from './src/references_default_array'; -export * from './src/risk_score'; -export * from './src/risk_score_mapping'; -export * from './src/rule_schedule'; -export * from './src/saved_object_attributes'; -export * from './src/severity'; -export * from './src/severity_mapping'; -export * from './src/threat'; -export * from './src/threat_mapping'; -export * from './src/threat_subtechnique'; -export * from './src/threat_tactic'; -export * from './src/threat_technique'; -export * from './src/throttle'; -export * from './src/type'; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/jest.config.js b/packages/kbn-securitysolution-io-ts-alerting-types/jest.config.js deleted file mode 100644 index b4c7014f91544..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-io-ts-alerting-types'], -}; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/package.json b/packages/kbn-securitysolution-io-ts-alerting-types/package.json deleted file mode 100644 index ab19f69d20b3f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/securitysolution-io-ts-alerting-types", - "version": "1.0.0", - "description": "io ts utilities and types to be shared with plugins from the security solution project", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts deleted file mode 100644 index ad1dde3da7450..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -import * as t from 'io-ts'; -import { saved_object_attributes } from '../saved_object_attributes'; -import { RuleActionFrequency } from '../frequency'; - -export type RuleActionGroup = t.TypeOf; -export const RuleActionGroup = t.string; - -export type RuleActionId = t.TypeOf; -export const RuleActionId = t.string; - -export type RuleActionTypeId = t.TypeOf; -export const RuleActionTypeId = t.string; - -export type RuleActionUuid = t.TypeOf; -export const RuleActionUuid = NonEmptyString; - -/** - * Params is an "object", since it is a type of RuleActionParams which is action templates. - * @see x-pack/plugins/alerting/common/rule.ts - */ -export type RuleActionParams = t.TypeOf; -export const RuleActionParams = saved_object_attributes; - -export const RuleActionAlertsFilter = t.partial({ - query: t.union([ - t.undefined, - t.intersection([ - t.strict({ - kql: t.string, - filters: t.array( - t.intersection([ - t.type({ - meta: t.partial({ - alias: t.union([t.string, t.null]), - disabled: t.boolean, - negate: t.boolean, - controlledBy: t.string, - group: t.string, - index: t.string, - isMultiIndex: t.boolean, - type: t.string, - key: t.string, - params: t.any, - value: t.string, - }), - }), - t.partial({ - $state: t.type({ store: t.any }), - query: t.record(t.string, t.any), - }), - ]) - ), - }), - t.partial({ dsl: t.string }), - ]), - ]), - timeframe: t.union([ - t.undefined, - t.strict({ - timezone: t.string, - days: t.array( - t.union([ - t.literal(1), - t.literal(2), - t.literal(3), - t.literal(4), - t.literal(5), - t.literal(6), - t.literal(7), - ]) - ), - hours: t.strict({ - start: t.string, - end: t.string, - }), - }), - ]), -}); - -export type RuleAction = t.TypeOf; -export const RuleAction = t.exact( - t.intersection([ - t.type({ - group: RuleActionGroup, - id: RuleActionId, - action_type_id: RuleActionTypeId, - params: RuleActionParams, - }), - t.partial({ - uuid: RuleActionUuid, - alerts_filter: RuleActionAlertsFilter, - frequency: RuleActionFrequency, - }), - ]) -); - -export type RuleActionArray = t.TypeOf; -export const RuleActionArray = t.array(RuleAction); - -export type RuleActionCamel = t.TypeOf; -export const RuleActionCamel = t.exact( - t.intersection([ - t.type({ - group: RuleActionGroup, - id: RuleActionId, - actionTypeId: RuleActionTypeId, - params: RuleActionParams, - }), - t.partial({ - uuid: RuleActionUuid, - alertsFilter: RuleActionAlertsFilter, - frequency: RuleActionFrequency, - }), - ]) -); - -export type RuleActionArrayCamel = t.TypeOf; -export const RuleActionArrayCamel = t.array(RuleActionCamel); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.mock.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.mock.ts deleted file mode 100644 index bb398e0df8460..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.mock.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export const ENTRY_VALUE = 'some host name'; -export const FIELD = 'host.name'; -export const MATCH = 'match'; -export const MATCH_ANY = 'match_any'; -export const OPERATOR = 'included'; -export const NESTED = 'nested'; -export const NESTED_FIELD = 'parent.field'; -export const LIST_ID = 'some-list-id'; -export const LIST = 'list'; -export const TYPE = 'ip'; -export const EXISTS = 'exists'; -export const WILDCARD = 'wildcard'; -export const USER = 'some user'; -export const DATE_NOW = '2020-04-20T15:25:31.830Z'; - -// Exception List specific -export const ID = 'uuid_here'; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.ts deleted file mode 100644 index 0c930e5f4a808..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/** - * TODO: Create a kbn-alerting-constants and add this to it. - * @deprecated Use a DEFAULT_MAX_SIGNALS from a kbn-alerting-constants package. - */ -export const DEFAULT_MAX_SIGNALS = 100; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_actions_array/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_actions_array/index.ts deleted file mode 100644 index 17c3f9301c6d7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_actions_array/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { RuleActionArray } from '../actions'; - -export const DefaultActionsArray = new t.Type< - RuleActionArray, - RuleActionArray | undefined, - unknown ->( - 'DefaultActionsArray', - RuleActionArray.is, - (input, context): Either => - input == null ? t.success([]) : RuleActionArray.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.test.ts deleted file mode 100644 index b07ade238db28..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultExportFileName } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_export_file_name', () => { - test('it should validate a regular string', () => { - const payload = 'some string'; - const decoded = DefaultExportFileName.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate a number', () => { - const payload = 5; - const decoded = DefaultExportFileName.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultExportFileName"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of "export.ndjson"', () => { - const payload = null; - const decoded = DefaultExportFileName.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual('export.ndjson'); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.ts deleted file mode 100644 index dedbadfa6f522..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; - -/** - * Types the DefaultExportFileName as: - * - If null or undefined, then a default of "export.ndjson" will be used - */ -export const DefaultExportFileName = new t.Type( - 'DefaultExportFileName', - t.string.is, - (input, context): Either => - input == null ? t.success('export.ndjson') : t.string.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.test.ts deleted file mode 100644 index 2515b3f8b0152..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultFromString } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_from_string', () => { - test('it should validate a from string', () => { - const payload = 'now-20m'; - const decoded = DefaultFromString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate a number', () => { - const payload = 5; - const decoded = DefaultFromString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultFromString"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of "now-6m"', () => { - const payload = null; - const decoded = DefaultFromString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual('now-6m'); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.ts deleted file mode 100644 index ccf70aab8a7b9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { From } from '../from'; - -/** - * Types the DefaultFromString as: - * - If null or undefined, then a default of the string "now-6m" will be used - */ -export const DefaultFromString = new t.Type( - 'DefaultFromString', - t.string.is, - (input, context): Either => { - if (input == null) { - return t.success('now-6m'); - } - return From.validate(input, context); - }, - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.test.ts deleted file mode 100644 index 8944d57ba8999..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultIntervalString } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_interval_string', () => { - test('it should validate a interval string', () => { - const payload = '20m'; - const decoded = DefaultIntervalString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate a number', () => { - const payload = 5; - const decoded = DefaultIntervalString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultIntervalString"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of "5m"', () => { - const payload = null; - const decoded = DefaultIntervalString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual('5m'); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.ts deleted file mode 100644 index 3fc5d4f42ccbd..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; - -/** - * Types the DefaultIntervalString as: - * - If null or undefined, then a default of the string "5m" will be used - */ -export const DefaultIntervalString = new t.Type( - 'DefaultIntervalString', - t.string.is, - (input, context): Either => - input == null ? t.success('5m') : t.string.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.test.ts deleted file mode 100644 index 4a8d50c88eaa8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { Language } from '../language'; -import { DefaultLanguageString } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_language_string', () => { - test('it should validate a string', () => { - const payload: Language = 'lucene'; - const decoded = DefaultLanguageString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate a number', () => { - const payload = 5; - const decoded = DefaultLanguageString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultLanguageString"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of "kuery"', () => { - const payload = null; - const decoded = DefaultLanguageString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual('kuery'); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.ts deleted file mode 100644 index 02328d94b0114..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { language } from '../language'; - -/** - * Types the DefaultLanguageString as: - * - If null or undefined, then a default of the string "kuery" will be used - */ -export const DefaultLanguageString = new t.Type( - 'DefaultLanguageString', - t.string.is, - (input, context): Either => - input == null ? t.success('kuery') : language.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.test.ts deleted file mode 100644 index 66eb77400ac1d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultMaxSignalsNumber } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { DEFAULT_MAX_SIGNALS } from '../constants'; - -describe('default_from_string', () => { - test('it should validate a max signal number', () => { - const payload = 5; - const decoded = DefaultMaxSignalsNumber.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate a string', () => { - const payload = '5'; - const decoded = DefaultMaxSignalsNumber.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultMaxSignals"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate a zero', () => { - const payload = 0; - const decoded = DefaultMaxSignalsNumber.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "0" supplied to "DefaultMaxSignals"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate a negative number', () => { - const payload = -1; - const decoded = DefaultMaxSignalsNumber.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "-1" supplied to "DefaultMaxSignals"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of DEFAULT_MAX_SIGNALS', () => { - const payload = null; - const decoded = DefaultMaxSignalsNumber.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(DEFAULT_MAX_SIGNALS); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.ts deleted file mode 100644 index 8acbc2f223a14..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { max_signals } from '../max_signals'; -import { DEFAULT_MAX_SIGNALS } from '../constants'; - -/** - * Types the default max signal: - * - Natural Number (positive integer and not a float), - * - greater than 1 - * - If undefined then it will use DEFAULT_MAX_SIGNALS (100) as the default - */ -export const DefaultMaxSignalsNumber = new t.Type( - 'DefaultMaxSignals', - t.number.is, - (input, context): Either => { - return input == null ? t.success(DEFAULT_MAX_SIGNALS) : max_signals.validate(input, context); - }, - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.test.ts deleted file mode 100644 index 5af986fefe8dd..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultPage } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_page', () => { - test('it should validate a regular number greater than zero', () => { - const payload = 5; - const decoded = DefaultPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate a string of a number', () => { - const payload = '5'; - const decoded = DefaultPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(5); - }); - - test('it should not validate a junk string', () => { - const payload = 'invalid-string'; - const decoded = DefaultPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "NaN" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate an empty string', () => { - const payload = ''; - const decoded = DefaultPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "NaN" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate a zero', () => { - const payload = 0; - const decoded = DefaultPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "0" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate a negative number', () => { - const payload = -1; - const decoded = DefaultPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "-1" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of 20', () => { - const payload = null; - const decoded = DefaultPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(1); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.ts deleted file mode 100644 index 8486c516aebf7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; - -/** - * Types the DefaultPerPage as: - * - If a string this will convert the string to a number - * - If null or undefined, then a default of 1 will be used - * - If the number is 0 or less this will not validate as it has to be a positive number greater than zero - */ -export const DefaultPage = new t.Type( - 'DefaultPerPage', - t.number.is, - (input, context): Either => { - if (input == null) { - return t.success(1); - } else if (typeof input === 'string') { - return PositiveIntegerGreaterThanZero.validate(parseInt(input, 10), context); - } else { - return PositiveIntegerGreaterThanZero.validate(input, context); - } - }, - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.test.ts deleted file mode 100644 index 78fa2a9be8c82..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultPerPage } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_per_page', () => { - test('it should validate a regular number greater than zero', () => { - const payload = 5; - const decoded = DefaultPerPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate a string of a number', () => { - const payload = '5'; - const decoded = DefaultPerPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(5); - }); - - test('it should not validate a junk string', () => { - const payload = 'invalid-string'; - const decoded = DefaultPerPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "NaN" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate an empty string', () => { - const payload = ''; - const decoded = DefaultPerPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "NaN" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate a zero', () => { - const payload = 0; - const decoded = DefaultPerPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "0" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not validate a negative number', () => { - const payload = -1; - const decoded = DefaultPerPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "-1" supplied to "DefaultPerPage"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of 20', () => { - const payload = null; - const decoded = DefaultPerPage.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(20); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.ts deleted file mode 100644 index 4f272fc0517eb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; - -/** - * Types the DefaultPerPage as: - * - If a string this will convert the string to a number - * - If null or undefined, then a default of 20 will be used - * - If the number is 0 or less this will not validate as it has to be a positive number greater than zero - */ -export const DefaultPerPage = new t.Type( - 'DefaultPerPage', - t.number.is, - (input, context): Either => { - if (input == null) { - return t.success(20); - } else if (typeof input === 'string') { - return PositiveIntegerGreaterThanZero.validate(parseInt(input, 10), context); - } else { - return PositiveIntegerGreaterThanZero.validate(input, context); - } - }, - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_risk_score_mapping_array/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_risk_score_mapping_array/index.ts deleted file mode 100644 index 9eb6938bcfcbd..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_risk_score_mapping_array/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { RiskScoreMapping } from '../risk_score_mapping'; - -/** - * Types the DefaultStringArray as: - * - If null or undefined, then a default RiskScoreMapping array will be set - */ -export const DefaultRiskScoreMappingArray = new t.Type< - RiskScoreMapping, - RiskScoreMapping | undefined, - unknown ->( - 'DefaultRiskScoreMappingArray', - RiskScoreMapping.is, - (input, context): Either => - input == null ? t.success([]) : RiskScoreMapping.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_severity_mapping_array/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_severity_mapping_array/index.ts deleted file mode 100644 index ac72e3330f2a1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_severity_mapping_array/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { SeverityMapping } from '../severity_mapping'; - -/** - * Types the DefaultStringArray as: - * - If null or undefined, then a default SeverityMapping array will be set - */ -export const DefaultSeverityMappingArray = new t.Type< - SeverityMapping, - SeverityMapping | undefined, - unknown ->( - 'DefaultSeverityMappingArray', - SeverityMapping.is, - (input, context): Either => - input == null ? t.success([]) : SeverityMapping.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.test.ts deleted file mode 100644 index ebd1ca9384b13..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { Threats } from '../threat'; -import { DefaultThreatArray } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_threat_null', () => { - test('it should validate an empty array', () => { - const payload: Threats = []; - const decoded = DefaultThreatArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of threats', () => { - const payload: Threats = [ - { - framework: 'MITRE ATTACK', - technique: [{ reference: 'https://test.com', name: 'Audio Capture', id: 'T1123' }], - tactic: { reference: 'https://test.com', name: 'Collection', id: 'TA000999' }, - }, - ]; - const decoded = DefaultThreatArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate an array with a number', () => { - const payload = [ - { - framework: 'MITRE ATTACK', - technique: [{ reference: 'https://test.com', name: 'Audio Capture', id: 'T1123' }], - tactic: { reference: 'https://test.com', name: 'Collection', id: 'TA000999' }, - }, - 5, - ]; - const decoded = DefaultThreatArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultThreatArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default empty array if not provided a value', () => { - const payload = null; - const decoded = DefaultThreatArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.ts deleted file mode 100644 index bb38b6382230c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { threats, Threats } from '../threat'; - -/** - * Types the DefaultThreatArray as: - * - If null or undefined, then an empty array will be set - */ -export const DefaultThreatArray = new t.Type( - 'DefaultThreatArray', - threats.is, - (input, context): Either => - input == null ? t.success([]) : threats.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.test.ts deleted file mode 100644 index e8bcdcc664cfe..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultToString } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_to_string', () => { - test('it should validate a to string', () => { - const payload = 'now-5m'; - const decoded = DefaultToString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate a number', () => { - const payload = 5; - const decoded = DefaultToString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultToString"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of "now"', () => { - const payload = null; - const decoded = DefaultToString.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual('now'); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.ts deleted file mode 100644 index 4074cc3bbbe9e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; - -/** - * Types the DefaultToString as: - * - If null or undefined, then a default of the string "now" will be used - */ -export const DefaultToString = new t.Type( - 'DefaultToString', - t.string.is, - (input, context): Either => - input == null ? t.success('now') : t.string.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.ts deleted file mode 100644 index 4144b4e6824ce..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { v4 as uuidv4 } from 'uuid'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -/** - * Types the DefaultUuid as: - * - If null or undefined, then a default string uuidv4() will be - * created otherwise it will be checked just against an empty string - */ -export const DefaultUuid = new t.Type( - 'DefaultUuid', - t.string.is, - (input, context): Either => - input == null ? t.success(uuidv4()) : NonEmptyString.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/frequency/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/frequency/index.ts deleted file mode 100644 index 0247bfb155f32..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/frequency/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RuleActionThrottle } from '../throttle'; - -/** - * Action summary indicates whether we will send a summary notification about all the generate alerts or notification per individual alert - */ -export type RuleActionSummary = t.TypeOf; -export const RuleActionSummary = t.boolean; - -/** - * The condition for throttling the notification: `onActionGroupChange`, `onActiveAlert`, or `onThrottleInterval` - */ -export type RuleActionNotifyWhen = t.TypeOf; -export const RuleActionNotifyWhen = t.union([ - t.literal('onActionGroupChange'), - t.literal('onActiveAlert'), - t.literal('onThrottleInterval'), -]); - -/** - * The action frequency defines when the action runs (for example, only on rule execution or at specific time intervals). - */ -export type RuleActionFrequency = t.TypeOf; -export const RuleActionFrequency = t.type({ - summary: RuleActionSummary, - notifyWhen: RuleActionNotifyWhen, - throttle: t.union([RuleActionThrottle, t.null]), -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/from/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/from/index.ts deleted file mode 100644 index 390649416273d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/from/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { Either } from 'fp-ts/lib/Either'; -import * as t from 'io-ts'; -import { parseScheduleDates } from '@kbn/securitysolution-io-ts-utils'; - -const stringValidator = (input: unknown): input is string => typeof input === 'string'; - -export type From = t.TypeOf; -export const From = new t.Type( - 'From', - t.string.is, - (input, context): Either => { - if (stringValidator(input) && parseScheduleDates(input) == null) { - return t.failure(input, context, 'Failed to parse "from" on rule param'); - } - return t.string.validate(input, context); - }, - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/language/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/language/index.ts deleted file mode 100644 index 95017209b2c6d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/language/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const language = t.keyof({ eql: null, kuery: null, lucene: null, esql: null }); -export type Language = t.TypeOf; - -export const languageOrUndefined = t.union([language, t.undefined]); -export type LanguageOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/machine_learning_job_id/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/machine_learning_job_id/index.ts deleted file mode 100644 index 00dc70eb55751..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/machine_learning_job_id/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -import { machine_learning_job_id_normalized } from '../normalized_ml_job_id'; - -export const machine_learning_job_id = t.union([t.string, machine_learning_job_id_normalized]); -export type MachineLearningJobId = t.TypeOf; - -export const machineLearningJobIdOrUndefined = t.union([machine_learning_job_id, t.undefined]); -export type MachineLearningJobIdOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/max_signals/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/max_signals/index.ts deleted file mode 100644 index aa8bdf6f539af..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/max_signals/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; -import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; - -export const max_signals = PositiveIntegerGreaterThanZero; -export type MaxSignals = t.TypeOf; - -export const maxSignalsOrUndefined = t.union([max_signals, t.undefined]); -export type MaxSignalsOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/normalized_ml_job_id/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/normalized_ml_job_id/index.ts deleted file mode 100644 index 2d89147c4fa11..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/normalized_ml_job_id/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -import { NonEmptyArray } from '@kbn/securitysolution-io-ts-types'; - -export const machine_learning_job_id_normalized = NonEmptyArray(t.string); -export type MachineLearningJobIdNormalized = t.TypeOf; - -export const machineLearningJobIdNormalizedOrUndefined = t.union([ - machine_learning_job_id_normalized, - t.undefined, -]); -export type MachineLearningJobIdNormalizedOrUndefined = t.TypeOf< - typeof machineLearningJobIdNormalizedOrUndefined ->; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.test.ts deleted file mode 100644 index 7b6146a320d6b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { ReferencesDefaultArray } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_string_array', () => { - test('it should validate an empty array', () => { - const payload: string[] = []; - const decoded = ReferencesDefaultArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of strings', () => { - const payload = ['value 1', 'value 2']; - const decoded = ReferencesDefaultArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate an array with a number', () => { - const payload = ['value 1', 5]; - const decoded = ReferencesDefaultArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "referencesWithDefaultArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default array entry', () => { - const payload = null; - const decoded = ReferencesDefaultArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.ts deleted file mode 100644 index fcf22ad918c9b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; - -/** - * Types the ReferencesDefaultArray as: - * - If null or undefined, then a default array will be set - */ -export const ReferencesDefaultArray = new t.Type( - 'referencesWithDefaultArray', - t.array(t.string).is, - (input, context): Either => - input == null ? t.success([]) : t.array(t.string).validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.test.ts deleted file mode 100644 index 85d83d0ec77d7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { RiskScore } from '.'; - -describe('risk_score', () => { - test('it should validate a positive number', () => { - const payload = 1; - const decoded = RiskScore.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate a zero', () => { - const payload = 0; - const decoded = RiskScore.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate a negative number', () => { - const payload = -1; - const decoded = RiskScore.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "-1" supplied to "RiskScore"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a string', () => { - const payload = 'some string'; - const decoded = RiskScore.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "RiskScore"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a risk score greater than 100', () => { - const payload = 101; - const decoded = RiskScore.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "101" supplied to "RiskScore"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.ts deleted file mode 100644 index ecc48e9a699de..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; - -/** - * Types the risk score as: - * - Natural Number (positive integer and not a float), - * - Between the values [0 and 100] inclusive. - */ -export type RiskScore = t.TypeOf; -export const RiskScore = new t.Type( - 'RiskScore', - t.number.is, - (input, context): Either => { - return typeof input === 'number' && Number.isSafeInteger(input) && input >= 0 && input <= 100 - ? t.success(input) - : t.failure(input, context); - }, - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score_mapping/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score_mapping/index.ts deleted file mode 100644 index 59f7c7ab69fbe..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score_mapping/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { operator } from '@kbn/securitysolution-io-ts-types'; -import { RiskScore } from '../risk_score'; - -export type RiskScoreMappingItem = t.TypeOf; -export const RiskScoreMappingItem = t.exact( - t.type({ - field: t.string, - value: t.string, - operator, - risk_score: t.union([RiskScore, t.undefined]), - }) -); - -export type RiskScoreMapping = t.TypeOf; -export const RiskScoreMapping = t.array(RiskScoreMappingItem); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/rule_schedule/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/rule_schedule/index.ts deleted file mode 100644 index 4d0113f330ae9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/rule_schedule/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { From } from '../from'; - -export type RuleInterval = t.TypeOf; -export const RuleInterval = t.string; // we need a more specific schema - -export type RuleIntervalFrom = t.TypeOf; -export const RuleIntervalFrom = From; - -/** - * TODO: Create a regular expression type or custom date math part type here - */ -export type RuleIntervalTo = t.TypeOf; -export const RuleIntervalTo = t.string; // we need a more specific schema diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/saved_object_attributes/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/saved_object_attributes/index.ts deleted file mode 100644 index 2a7af4e665183..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/saved_object_attributes/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -/** - * TODO: This type are originally from "src/core/types/saved_objects.ts", once that is package friendly remove - * this copied type. - * - * Don't use this type, it's simply a helper type for {@link SavedObjectAttribute} - * - * @public - */ -export type SavedObjectAttributeSingle = - | string - | number - | boolean - | null - | undefined - | SavedObjectAttributes; - -/** - * TODO: This type are originally from "src/core/types/saved_objects.ts", once that is package friendly remove - * this copied type. - * - * Type definition for a Saved Object attribute value - * - * @public - */ -export type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; - -/** - * TODO: This type are originally from "src/core/types/saved_objects.ts", once that is package friendly remove - * this copied type. - * - * The data for a Saved Object is stored as an object in the `attributes` - * property. - * - * @public - */ -export interface SavedObjectAttributes { - [key: string]: SavedObjectAttribute; -} - -export const saved_object_attribute_single: t.Type = t.recursion( - 'saved_object_attribute_single', - () => t.union([t.string, t.number, t.boolean, t.null, t.undefined, saved_object_attributes]) -); -export const saved_object_attribute: t.Type = t.recursion( - 'saved_object_attribute', - () => t.union([saved_object_attribute_single, t.array(saved_object_attribute_single)]) -); -export const saved_object_attributes: t.Type = t.recursion( - 'saved_object_attributes', - () => t.record(t.string, saved_object_attribute) -); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/severity/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/severity/index.ts deleted file mode 100644 index fef1082129df8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/severity/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export type Severity = t.TypeOf; -export const Severity = t.keyof({ low: null, medium: null, high: null, critical: null }); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/severity_mapping/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/severity_mapping/index.ts deleted file mode 100644 index afd7889658a35..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/severity_mapping/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { operator } from '@kbn/securitysolution-io-ts-types'; -import { Severity } from '../severity'; - -export type SeverityMappingItem = t.TypeOf; -export const SeverityMappingItem = t.exact( - t.type({ - field: t.string, - operator, - value: t.string, - severity: Severity, - }) -); - -export type SeverityMapping = t.TypeOf; -export const SeverityMapping = t.array(SeverityMappingItem); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/threat/index.ts deleted file mode 100644 index e60f9ccafcc13..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; -import { threat_tactic } from '../threat_tactic'; -import { threat_techniques } from '../threat_technique'; - -export const threat_framework = t.string; - -export const threat = t.intersection([ - t.exact( - t.type({ - framework: threat_framework, - tactic: threat_tactic, - }) - ), - t.exact( - t.partial({ - technique: threat_techniques, - }) - ), -]); - -export type Threat = t.TypeOf; - -export const threats = t.array(threat); -export type Threats = t.TypeOf; - -export const threatsOrUndefined = t.union([threats, t.undefined]); -export type ThreatsOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.test.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.test.ts deleted file mode 100644 index 3d3e1ab9a22bf..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.test.ts +++ /dev/null @@ -1,237 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { - concurrent_searches, - items_per_search, - ThreatMapping, - threatMappingEntries, - ThreatMappingEntries, - threat_mapping, -} from '.'; -import { foldLeftRight, getPaths, exactCheck } from '@kbn/securitysolution-io-ts-utils'; - -describe('threat_mapping', () => { - describe('threatMappingEntries', () => { - test('it should validate an entry', () => { - const payload: ThreatMappingEntries = [ - { - field: 'field.one', - type: 'mapping', - value: 'field.one', - }, - ]; - const decoded = threatMappingEntries.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation with an extra entry item', () => { - const payload: Array = [ - { - field: 'field.one', - type: 'mapping', - value: 'field.one', - extra: 'blah', - }, - ]; - const decoded = threatMappingEntries.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extra"']); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation with a non string', () => { - const payload = [ - { - field: 5, - type: 'mapping', - value: 'field.one', - }, - ] as unknown as ThreatMappingEntries[]; - const decoded = threatMappingEntries.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "5" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation with a wrong type', () => { - const payload = [ - { - field: 'field.one', - type: 'invalid', - value: 'field.one', - }, - ] as unknown as ThreatMappingEntries[]; - const decoded = threatMappingEntries.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "invalid" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('threat_mapping', () => { - test('it should validate a threat mapping', () => { - const payload: ThreatMapping = [ - { - entries: [ - { - field: 'field.one', - type: 'mapping', - value: 'field.one', - }, - ], - }, - ]; - const decoded = threat_mapping.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - }); - - test('it should fail validate with an extra key', () => { - const payload: Array = [ - { - entries: [ - { - field: 'field.one', - type: 'mapping', - value: 'field.one', - }, - ], - extra: 'invalid', - }, - ]; - - const decoded = threat_mapping.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extra"']); - expect(message.schema).toEqual({}); - }); - - test('it should fail validate with an extra inner entry', () => { - const payload: Array }> = [ - { - entries: [ - { - field: 'field.one', - type: 'mapping', - value: 'field.one', - extra: 'blah', - }, - ], - }, - ]; - - const decoded = threat_mapping.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extra"']); - expect(message.schema).toEqual({}); - }); - - test('it should fail validate with an extra inner entry with the wrong data type', () => { - const payload = [ - { - entries: [ - { - field: 5, - type: 'mapping', - value: 'field.one', - }, - ], - }, - ] as unknown as ThreatMapping; - - const decoded = threat_mapping.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "entries,field"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validate with empty array', () => { - const payload: string[] = []; - - const decoded = threat_mapping.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "[]" supplied to "NonEmptyArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when concurrent_searches is < 0', () => { - const payload = -1; - const decoded = concurrent_searches.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "-1" supplied to "PositiveIntegerGreaterThanZero"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when concurrent_searches is 0', () => { - const payload = 0; - const decoded = concurrent_searches.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "0" supplied to "PositiveIntegerGreaterThanZero"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when items_per_search is 0', () => { - const payload = 0; - const decoded = items_per_search.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "0" supplied to "PositiveIntegerGreaterThanZero"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when items_per_search is < 0', () => { - const payload = -1; - const decoded = items_per_search.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "-1" supplied to "PositiveIntegerGreaterThanZero"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.ts deleted file mode 100644 index 0cc8c950f7549..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; -import { - NonEmptyArray, - NonEmptyString, - PositiveIntegerGreaterThanZero, -} from '@kbn/securitysolution-io-ts-types'; -import { language } from '../language'; - -export const threat_query = t.string; -export type ThreatQuery = t.TypeOf; -export const threatQueryOrUndefined = t.union([threat_query, t.undefined]); -export type ThreatQueryOrUndefined = t.TypeOf; - -export const threat_indicator_path = t.string; -export type ThreatIndicatorPath = t.TypeOf; -export const threatIndicatorPathOrUndefined = t.union([threat_indicator_path, t.undefined]); -export type ThreatIndicatorPathOrUndefined = t.TypeOf; - -export const threat_filters = t.array(t.unknown); // Filters are not easily type-able yet -export type ThreatFilters = t.TypeOf; -export const threatFiltersOrUndefined = t.union([threat_filters, t.undefined]); -export type ThreatFiltersOrUndefined = t.TypeOf; - -export const threatMapEntry = t.exact( - t.type({ - field: NonEmptyString, - type: t.keyof({ mapping: null }), - value: NonEmptyString, - }) -); - -export type ThreatMapEntry = t.TypeOf; - -export const threatMappingEntries = t.array(threatMapEntry); -export type ThreatMappingEntries = t.TypeOf; - -export const threatMap = t.exact( - t.type({ - entries: threatMappingEntries, - }) -); -export type ThreatMap = t.TypeOf; - -export const threat_mapping = NonEmptyArray(threatMap, 'NonEmptyArray'); -export type ThreatMapping = t.TypeOf; - -export const threatMappingOrUndefined = t.union([threat_mapping, t.undefined]); -export type ThreatMappingOrUndefined = t.TypeOf; - -export const threat_index = t.array(t.string); -export type ThreatIndex = t.TypeOf; -export const threatIndexOrUndefined = t.union([threat_index, t.undefined]); -export type ThreatIndexOrUndefined = t.TypeOf; - -export const threat_language = t.union([language, t.undefined]); -export type ThreatLanguage = t.TypeOf; -export const threatLanguageOrUndefined = t.union([threat_language, t.undefined]); -export type ThreatLanguageOrUndefined = t.TypeOf; - -export const concurrent_searches = PositiveIntegerGreaterThanZero; -export type ConcurrentSearches = t.TypeOf; -export const concurrentSearchesOrUndefined = t.union([concurrent_searches, t.undefined]); -export type ConcurrentSearchesOrUndefined = t.TypeOf; - -export const items_per_search = PositiveIntegerGreaterThanZero; -export type ItemsPerSearch = t.TypeOf; -export const itemsPerSearchOrUndefined = t.union([items_per_search, t.undefined]); -export type ItemsPerSearchOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_subtechnique/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_subtechnique/index.ts deleted file mode 100644 index 963bf76bf5f87..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_subtechnique/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const threat_subtechnique_id = t.string; -export const threat_subtechnique_name = t.string; -export const threat_subtechnique_reference = t.string; - -export const threat_subtechnique = t.type({ - id: threat_subtechnique_id, - name: threat_subtechnique_name, - reference: threat_subtechnique_reference, -}); - -export const threat_subtechniques = t.array(threat_subtechnique); - -export type ThreatSubtechnique = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_tactic/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_tactic/index.ts deleted file mode 100644 index a142788876e7d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_tactic/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const threat_tactic_id = t.string; -export const threat_tactic_name = t.string; -export const threat_tactic_reference = t.string; - -export const threat_tactic = t.type({ - id: threat_tactic_id, - name: threat_tactic_name, - reference: threat_tactic_reference, -}); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_technique/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_technique/index.ts deleted file mode 100644 index 2953ea86b3b3d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_technique/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; -import { threat_subtechniques } from '../threat_subtechnique'; - -export const threat_technique_id = t.string; -export const threat_technique_name = t.string; -export const threat_technique_reference = t.string; - -export const threat_technique = t.intersection([ - t.exact( - t.type({ - id: threat_technique_id, - name: threat_technique_name, - reference: threat_technique_reference, - }) - ), - t.exact( - t.partial({ - subtechnique: threat_subtechniques, - }) - ), -]); -export const threat_techniques = t.array(threat_technique); - -export type ThreatTechnique = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/throttle/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/throttle/index.ts deleted file mode 100644 index f1d6bdca8fed9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/throttle/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { TimeDuration } from '@kbn/securitysolution-io-ts-types'; - -export type RuleActionThrottle = t.TypeOf; -export const RuleActionThrottle = t.union([ - t.literal('no_actions'), - t.literal('rule'), - TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }), -]); diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/type/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/type/index.ts deleted file mode 100644 index 68c7a2f30a2bb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/type/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const type = t.keyof({ - eql: null, - machine_learning: null, - query: null, - saved_query: null, - threshold: null, - threat_match: null, - new_terms: null, - esql: null, -}); -export type Type = t.TypeOf; - -export const typeOrUndefined = t.union([type, t.undefined]); -export type TypeOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/tsconfig.json b/packages/kbn-securitysolution-io-ts-alerting-types/tsconfig.json deleted file mode 100644 index f9fb0b0fcebb2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-alerting-types/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/securitysolution-io-ts-types", - "@kbn/securitysolution-io-ts-utils" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-io-ts-list-types/index.ts b/packages/kbn-securitysolution-io-ts-list-types/index.ts deleted file mode 100644 index 6d6b4e241b6d1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/common'; -export * from './src/request'; -export * from './src/response'; -export * from './src/typescript_types'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/jest.config.js b/packages/kbn-securitysolution-io-ts-list-types/jest.config.js deleted file mode 100644 index adcf48629dd7d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-io-ts-list-types'], -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/package.json b/packages/kbn-securitysolution-io-ts-list-types/package.json deleted file mode 100644 index 50c88fb22054f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/securitysolution-io-ts-list-types", - "version": "1.0.0", - "description": "io ts utilities and types to be shared with plugins from the security solution project", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.mock.ts deleted file mode 100644 index d824f23fe74b8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.mock.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { Comment, CommentsArray } from '.'; -import { DATE_NOW, ID, USER } from '../../constants/index.mock'; - -export const getCommentsMock = (): Comment => ({ - comment: 'some old comment', - created_at: DATE_NOW, - created_by: USER, - id: ID, -}); - -export const getCommentsArrayMock = (): CommentsArray => [getCommentsMock(), getCommentsMock()]; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.test.ts deleted file mode 100644 index deca11f809cbe..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.test.ts +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getCommentsArrayMock, getCommentsMock } from './index.mock'; -import { - Comment, - comment, - CommentsArray, - commentsArray, - CommentsArrayOrUndefined, - commentsArrayOrUndefined, -} from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { DATE_NOW } from '../../constants/index.mock'; - -describe('Comment', () => { - describe('comment', () => { - test('it fails validation when "id" is undefined', () => { - const payload = { ...getCommentsMock(), id: undefined }; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it passes validation with a typical comment', () => { - const payload = getCommentsMock(); - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation with "updated_at" and "updated_by" fields included', () => { - const payload = getCommentsMock(); - payload.updated_at = DATE_NOW; - payload.updated_by = 'someone'; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when undefined', () => { - const payload = undefined; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when "comment" is an empty string', () => { - const payload: Omit & { comment: string } = { - ...getCommentsMock(), - comment: '', - }; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "comment"']); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when "comment" is not a string', () => { - const payload: Omit & { comment: string[] } = { - ...getCommentsMock(), - comment: ['some value'], - }; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "["some value"]" supplied to "comment"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when "created_at" is not a string', () => { - const payload: Omit & { created_at: number } = { - ...getCommentsMock(), - created_at: 1, - }; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "created_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when "created_by" is not a string', () => { - const payload: Omit & { created_by: number } = { - ...getCommentsMock(), - created_by: 1, - }; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "created_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when "updated_at" is not a string', () => { - const payload: Omit & { updated_at: number } = { - ...getCommentsMock(), - updated_at: 1, - }; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "updated_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when "updated_by" is not a string', () => { - const payload: Omit & { updated_by: number } = { - ...getCommentsMock(), - updated_by: 1, - }; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "updated_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: Comment & { - extraKey?: string; - } = getCommentsMock(); - payload.extraKey = 'some value'; - const decoded = comment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getCommentsMock()); - }); - }); - - describe('commentsArray', () => { - test('it passes validation an array of Comment', () => { - const payload = getCommentsArrayMock(); - const decoded = commentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation when a Comment includes "updated_at" and "updated_by"', () => { - const commentsPayload = getCommentsMock(); - commentsPayload.updated_at = DATE_NOW; - commentsPayload.updated_by = 'someone'; - const payload = [{ ...commentsPayload }, ...getCommentsArrayMock()]; - const decoded = commentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when undefined', () => { - const payload = undefined; - const decoded = commentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when array includes non Comment types', () => { - const payload = [1] as unknown as CommentsArray; - const decoded = commentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('commentsArrayOrUndefined', () => { - test('it passes validation an array of Comment', () => { - const payload = getCommentsArrayMock(); - const decoded = commentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation when undefined', () => { - const payload = undefined; - const decoded = commentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when array includes non Comment types', () => { - const payload = [1] as unknown as CommentsArrayOrUndefined; - const decoded = commentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.ts deleted file mode 100644 index 3aac99e6c48e2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { created_at } from '../created_at'; -import { created_by } from '../created_by'; -import { id } from '../id'; -import { updated_at } from '../updated_at'; -import { updated_by } from '../updated_by'; - -export const comment = t.intersection([ - t.exact( - t.type({ - comment: NonEmptyString, - created_at, - created_by, - id, - }) - ), - t.exact( - t.partial({ - updated_at, - updated_by, - }) - ), -]); - -export const commentsArray = t.array(comment); -export type CommentsArray = t.TypeOf; -export type Comment = t.TypeOf; -export const commentsArrayOrUndefined = t.union([commentsArray, t.undefined]); -export type CommentsArrayOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.mock.ts deleted file mode 100644 index bad427de97471..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.mock.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { CreateComment, CreateCommentsArray } from '.'; - -export const getCreateCommentsMock = (): CreateComment => ({ - comment: 'some comments', -}); - -export const getCreateCommentsArrayMock = (): CreateCommentsArray => [getCreateCommentsMock()]; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.test.ts deleted file mode 100644 index c537e9e28091c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.test.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getCreateCommentsArrayMock, getCreateCommentsMock } from './index.mock'; -import { - CreateComment, - createComment, - CreateCommentsArray, - createCommentsArray, - CreateCommentsArrayOrUndefined, - createCommentsArrayOrUndefined, -} from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('CreateComment', () => { - describe('createComment', () => { - test('it passes validation with a default comment', () => { - const payload = getCreateCommentsMock(); - const decoded = createComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when undefined', () => { - const payload = undefined; - const decoded = createComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "{| comment: NonEmptyString |}"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when "comment" is not a string', () => { - const payload: Omit & { comment: string[] } = { - ...getCreateCommentsMock(), - comment: ['some value'], - }; - const decoded = createComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "["some value"]" supplied to "comment"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: CreateComment & { - extraKey?: string; - } = getCreateCommentsMock(); - payload.extraKey = 'some value'; - const decoded = createComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getCreateCommentsMock()); - }); - }); - - describe('createCommentsArray', () => { - test('it passes validation an array of comments', () => { - const payload = getCreateCommentsArrayMock(); - const decoded = createCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when undefined', () => { - const payload = undefined; - const decoded = createCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "Array<{| comment: NonEmptyString |}>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when array includes non comments types', () => { - const payload = [1] as unknown as CreateCommentsArray; - const decoded = createCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<{| comment: NonEmptyString |}>"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('createCommentsArrayOrUndefined', () => { - test('it passes validation an array of comments', () => { - const payload = getCreateCommentsArrayMock(); - const decoded = createCommentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation when undefined', () => { - const payload = undefined; - const decoded = createCommentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when array includes non comments types', () => { - const payload = [1] as unknown as CreateCommentsArrayOrUndefined; - const decoded = createCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<{| comment: NonEmptyString |}>"', - ]); - expect(message.schema).toEqual({}); - }); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.ts deleted file mode 100644 index f4082df289ac2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -export const createComment = t.exact( - t.type({ - comment: NonEmptyString, - }) -); - -export type CreateComment = t.TypeOf; -export const createCommentsArray = t.array(createComment); -export type CreateCommentsArray = t.TypeOf; -export type CreateComments = t.TypeOf; -export const createCommentsArrayOrUndefined = t.union([createCommentsArray, t.undefined]); -export type CreateCommentsArrayOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/created_at/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/created_at/index.ts deleted file mode 100644 index 697a5034cbf05..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/created_at/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const created_at = t.string; // TODO: Make this into an ISO Date string check diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/created_by/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/created_by/index.ts deleted file mode 100644 index e6f3e2f90edb4..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/created_by/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const created_by = t.string; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/cursor/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/cursor/index.ts deleted file mode 100644 index 4844ffe7e3640..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/cursor/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const cursor = t.string; -export type Cursor = t.TypeOf; -export const cursorOrUndefined = t.union([cursor, t.undefined]); -export type CursorOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.test.ts deleted file mode 100644 index d0c7e3cc0447a..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { CommentsArray } from '../comment'; -import { DefaultCommentsArray } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getCommentsArrayMock } from '../comment/index.mock'; - -describe('default_comments_array', () => { - test('it should pass validation when supplied an empty array', () => { - const payload: CommentsArray = []; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should pass validation when supplied an array of comments', () => { - const payload: CommentsArray = getCommentsArrayMock(); - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an array of numbers', () => { - const payload = [1]; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an array of strings', () => { - const payload = ['some string']; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default array entry', () => { - const payload = null; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.ts deleted file mode 100644 index 6a89b00633513..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { comment, CommentsArray } from '../comment'; - -/** - * Types the DefaultCommentsArray as: - * - If null or undefined, then a default array of type entry will be set - */ -export const DefaultCommentsArray = new t.Type( - 'DefaultCommentsArray', - t.array(comment).is, - (input): Either => - input == null ? t.success([]) : t.array(comment).decode(input), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.test.ts deleted file mode 100644 index ce909c0314b3b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { CommentsArray } from '../comment'; -import { DefaultCommentsArray } from '../default_comments_array'; -import { getCommentsArrayMock } from '../comment/index.mock'; - -describe('default_comments_array', () => { - test('it should pass validation when supplied an empty array', () => { - const payload: CommentsArray = []; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should pass validation when supplied an array of comments', () => { - const payload: CommentsArray = getCommentsArrayMock(); - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an array of numbers', () => { - const payload = [1]; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an array of strings', () => { - const payload = ['some string']; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default array entry', () => { - const payload = null; - const decoded = DefaultCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.ts deleted file mode 100644 index 0ed345891719b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { createComment, CreateCommentsArray } from '../create_comment'; - -/** - * Types the DefaultCreateComments as: - * - If null or undefined, then a default array of type entry will be set - */ -export const DefaultCreateCommentsArray = new t.Type< - CreateCommentsArray, - CreateCommentsArray, - unknown ->( - 'DefaultCreateComments', - t.array(createComment).is, - (input): Either => - input == null ? t.success([]) : t.array(createComment).decode(input), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts deleted file mode 100644 index 9b6f8df6850cb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { ImportCommentsArray } from '../import_comment'; -import { DefaultImportCommentsArray } from '.'; -import { getCommentsArrayMock } from '../comment/index.mock'; -import { getCreateCommentsArrayMock } from '../create_comment/index.mock'; - -describe('default_import_comments_array', () => { - test('it should pass validation when supplied an empty array', () => { - const payload: ImportCommentsArray = []; - const decoded = DefaultImportCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should pass validation when supplied an array of comments', () => { - const payload: ImportCommentsArray = getCommentsArrayMock(); - const decoded = DefaultImportCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should pass validation when supplied an array of new comments', () => { - const payload: ImportCommentsArray = getCreateCommentsArrayMock(); - const decoded = DefaultImportCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should pass validation when supplied an array of new and existing comments', () => { - const payload: ImportCommentsArray = [ - ...getCommentsArrayMock(), - ...getCreateCommentsArrayMock(), - ]; - const decoded = DefaultImportCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an array of numbers', () => { - const payload = [1]; - const decoded = DefaultImportCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "DefaultImportComments"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an array of strings', () => { - const payload = ['some string']; - const decoded = DefaultImportCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "DefaultImportComments"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default array entry', () => { - const payload = null; - const decoded = DefaultImportCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts deleted file mode 100644 index dc8d18e7e11e6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { importComment, ImportCommentsArray } from '../import_comment'; - -/** - * Types the DefaultImportCommentsArray as: - * - If null or undefined, then a default array of type ImportCommentsArray will be set - */ -export const DefaultImportCommentsArray = new t.Type< - ImportCommentsArray, - ImportCommentsArray, - unknown ->( - 'DefaultImportComments', - t.array(importComment).is, - (input, context): Either => - input == null ? t.success([]) : t.array(importComment).validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.test.ts deleted file mode 100644 index 69cdd841c0a5e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultNamespace } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_namespace', () => { - test('it should validate "single"', () => { - const payload = 'single'; - const decoded = DefaultNamespace.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate "agnostic"', () => { - const payload = 'agnostic'; - const decoded = DefaultNamespace.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it defaults to "single" if "undefined"', () => { - const payload = undefined; - const decoded = DefaultNamespace.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual('single'); - }); - - test('it defaults to "single" if "null"', () => { - const payload = null; - const decoded = DefaultNamespace.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual('single'); - }); - - test('it should FAIL validation if not "single" or "agnostic"', () => { - const payload = 'something else'; - const decoded = DefaultNamespace.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - `Invalid value "something else" supplied to "DefaultNamespace"`, - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.ts deleted file mode 100644 index 33f53c55b1986..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; - -export const namespaceType = t.keyof({ agnostic: null, single: null }); -export type NamespaceType = t.TypeOf; - -/** - * Types the DefaultNamespace as: - * - If null or undefined, then a default string/enumeration of "single" will be used. - */ -export const DefaultNamespace = new t.Type( - 'DefaultNamespace', - namespaceType.is, - (input, context): Either => - input == null ? t.success('single') : namespaceType.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.test.ts deleted file mode 100644 index 359674e57041e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultNamespaceArray, DefaultNamespaceArrayType } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_namespace_array', () => { - test('it should validate "null" single item as an array with a "single" value', () => { - const payload: DefaultNamespaceArrayType = null; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(['single']); - }); - - test('it should FAIL validation of numeric value', () => { - const payload = 5; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "5" supplied to "DefaultNamespaceArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should validate "undefined" item as an array with a "single" value', () => { - const payload: DefaultNamespaceArrayType = undefined; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(['single']); - }); - - test('it should validate "single" as an array of a "single" value', () => { - const payload: DefaultNamespaceArrayType = 'single'; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([payload]); - }); - - test('it should validate "agnostic" as an array of a "agnostic" value', () => { - const payload: DefaultNamespaceArrayType = 'agnostic'; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([payload]); - }); - - test('it should validate "single,agnostic" as an array of 2 values of ["single", "agnostic"] values', () => { - const payload: DefaultNamespaceArrayType = 'agnostic,single'; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(['agnostic', 'single']); - }); - - test('it should validate 3 elements of "single,agnostic,single" as an array of 3 values of ["single", "agnostic", "single"] values', () => { - const payload: DefaultNamespaceArrayType = 'single,agnostic,single'; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(['single', 'agnostic', 'single']); - }); - - test('it should validate 3 elements of "single,agnostic, single" as an array of 3 values of ["single", "agnostic", "single"] values when there are spaces', () => { - const payload: DefaultNamespaceArrayType = ' single, agnostic, single '; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(['single', 'agnostic', 'single']); - }); - - test('it should FAIL validation when given 3 elements of "single,agnostic,junk" since the 3rd value is junk', () => { - const payload: DefaultNamespaceArrayType = 'single,agnostic,junk'; - const decoded = DefaultNamespaceArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "junk" supplied to "DefaultNamespaceArray"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.ts deleted file mode 100644 index 9692b8a2783d8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { namespaceType } from '../default_namespace'; - -export const namespaceTypeArray = t.array(namespaceType); -export type NamespaceTypeArray = t.TypeOf; - -/** - * Types the DefaultNamespaceArray as: - * - If null or undefined, then a default string array of "single" will be used. - * - If it contains a string, then it is split along the commas and puts them into an array and validates it - */ -export const DefaultNamespaceArray = new t.Type< - NamespaceTypeArray, - string | undefined | null, - unknown ->( - 'DefaultNamespaceArray', - namespaceTypeArray.is, - (input, context): Either => { - if (input == null) { - return t.success(['single']); - } else if (typeof input === 'string') { - const commaSeparatedValues = input - .trim() - .split(',') - .map((value) => value.trim()); - return namespaceTypeArray.validate(commaSeparatedValues, context); - } - return t.failure(input, context); - }, - String -); - -export type DefaultNamespaceArrayType = t.OutputOf; -export type DefaultNamespaceArrayTypeDecoded = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts deleted file mode 100644 index aaffae53cecab..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { UpdateCommentsArray } from '../update_comment'; -import { DefaultUpdateCommentsArray } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getUpdateCommentsArrayMock } from '../update_comment/index.mock'; - -describe('default_update_comments_array', () => { - test('it should pass validation when supplied an empty array', () => { - const payload: UpdateCommentsArray = []; - const decoded = DefaultUpdateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should pass validation when supplied an array of comments', () => { - const payload: UpdateCommentsArray = getUpdateCommentsArrayMock(); - const decoded = DefaultUpdateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an array of numbers', () => { - const payload = [1]; - const decoded = DefaultUpdateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "DefaultUpdateComments"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an array of strings', () => { - const payload = ['some string']; - const decoded = DefaultUpdateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "DefaultUpdateComments"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should return a default array entry', () => { - const payload = null; - const decoded = DefaultUpdateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts deleted file mode 100644 index 47c0e562133df..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { updateCommentsArray, UpdateCommentsArray } from '../update_comment'; - -/** - * Types the DefaultUpdateComments as: - * - If null or undefined, then a default array of type UpdateCommentsArray will be set - */ -export const DefaultUpdateCommentsArray = new t.Type< - UpdateCommentsArray, - UpdateCommentsArray, - unknown ->( - 'DefaultUpdateComments', - updateCommentsArray.is, - (input, context): Either => - input == null ? t.success([]) : updateCommentsArray.validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/description/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/description/index.ts deleted file mode 100644 index 75fd7ac92ffcf..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/description/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const description = t.string; -export type Description = t.TypeOf; -export const descriptionOrUndefined = t.union([description, t.undefined]); -export type DescriptionOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/deserializer/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/deserializer/index.ts deleted file mode 100644 index c5489a946897e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/deserializer/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const deserializer = t.string; -export type Deserializer = t.TypeOf; -export const deserializerOrUndefined = t.union([deserializer, t.undefined]); -export type DeserializerOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.mock.ts deleted file mode 100644 index bc091b1e33c35..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.mock.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EndpointEntriesArray } from '.'; -import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; -import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { getEndpointEntryNestedMock } from '../entry_nested/index.mock'; -import { getEndpointEntryMatchWildcardMock } from '../entry_match_wildcard/index.mock'; - -export const getEndpointEntriesArrayMock = (): EndpointEntriesArray => [ - getEndpointEntryMatchMock(), - getEndpointEntryMatchAnyMock(), - getEndpointEntryNestedMock(), - getEndpointEntryMatchWildcardMock(), -]; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.test.ts deleted file mode 100644 index 574bf4276461b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; -import { - endpointEntriesArray, - nonEmptyEndpointEntriesArray, - NonEmptyEndpointEntriesArray, -} from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { getEndpointEntryNestedMock } from '../entry_nested/index.mock'; -import { getEndpointEntriesArrayMock } from './index.mock'; -import { getEntryListMock } from '../../entries_list/index.mock'; -import { getEntryExistsMock } from '../../entries_exist/index.mock'; -import { getEndpointEntryMatchWildcardMock } from '../entry_match_wildcard/index.mock'; - -describe('Endpoint', () => { - describe('entriesArray', () => { - test('it should validate an array with match entry', () => { - const payload = [getEndpointEntryMatchMock()]; - const decoded = endpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with match_any entry', () => { - const payload = [getEndpointEntryMatchAnyMock()]; - const decoded = endpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate an empty array', () => { - const payload: NonEmptyEndpointEntriesArray = []; - const decoded = nonEmptyEndpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "[]" supplied to "NonEmptyEndpointEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('type guard for nonEmptyEndpointNestedEntries should allow array of endpoint entries', () => { - const payload: NonEmptyEndpointEntriesArray = [getEndpointEntryMatchAnyMock()]; - const guarded = nonEmptyEndpointEntriesArray.is(payload); - expect(guarded).toBeTruthy(); - }); - - test('type guard for nonEmptyEndpointNestedEntries should disallow empty arrays', () => { - const payload: NonEmptyEndpointEntriesArray = []; - const guarded = nonEmptyEndpointEntriesArray.is(payload); - expect(guarded).toBeFalsy(); - }); - - test('it should NOT validate an array with exists entry', () => { - const payload = [getEntryExistsMock()]; - const decoded = endpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "exists" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate an array with list entry', () => { - const payload = [getEntryListMock()]; - const decoded = endpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "list" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should validate an array with nested entry', () => { - const payload = [getEndpointEntryNestedMock()]; - const decoded = endpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with wildcard entry', () => { - const payload = [getEndpointEntryMatchWildcardMock()]; - const decoded = endpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with all types of entries', () => { - const payload = getEndpointEntriesArrayMock(); - const decoded = endpointEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.ts deleted file mode 100644 index 992237161d06c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { endpointEntryMatch } from '../entry_match'; -import { endpointEntryMatchAny } from '../entry_match_any'; -import { endpointEntryNested } from '../entry_nested'; -import { endpointEntryMatchWildcard } from '../entry_match_wildcard'; - -export const endpointEntriesArray = t.array( - t.union([ - endpointEntryMatch, - endpointEntryMatchAny, - endpointEntryMatchWildcard, - endpointEntryNested, - ]) -); -export type EndpointEntriesArray = t.TypeOf; - -/** - * Types the nonEmptyEndpointEntriesArray as: - * - An array of entries of length 1 or greater - * - */ -export const nonEmptyEndpointEntriesArray = new t.Type< - EndpointEntriesArray, - EndpointEntriesArray, - unknown ->( - 'NonEmptyEndpointEntriesArray', - (u: unknown): u is EndpointEntriesArray => endpointEntriesArray.is(u) && u.length > 0, - (input, context): Either => { - if (Array.isArray(input) && input.length === 0) { - return t.failure(input, context); - } else { - return endpointEntriesArray.validate(input, context); - } - }, - t.identity -); - -export type NonEmptyEndpointEntriesArray = t.OutputOf; -export type NonEmptyEndpointEntriesArrayDecoded = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.mock.ts deleted file mode 100644 index 76305cf70c585..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EndpointEntryMatch } from '.'; -import { ENTRY_VALUE, FIELD, MATCH, OPERATOR } from '../../../constants/index.mock'; - -export const getEndpointEntryMatchMock = (): EndpointEntryMatch => ({ - field: FIELD, - operator: OPERATOR, - type: MATCH, - value: ENTRY_VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.test.ts deleted file mode 100644 index 5c20b697b3bf5..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEndpointEntryMatchMock } from './index.mock'; -import { EndpointEntryMatch, endpointEntryMatch } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEntryMatchMock } from '../../entry_match/index.mock'; - -describe('endpointEntryMatch', () => { - test('it should validate an entry', () => { - const payload = getEndpointEntryMatchMock(); - const decoded = endpointEntryMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate when "operator" is "excluded"', () => { - // Use the generic entry mock so we can test operator: excluded - const payload = getEntryMatchMock(); - payload.operator = 'excluded'; - const decoded = endpointEntryMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "excluded" supplied to "operator"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "field" is empty string', () => { - const payload: Omit & { field: string } = { - ...getEndpointEntryMatchMock(), - field: '', - }; - const decoded = endpointEntryMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is not string', () => { - const payload: Omit & { value: string[] } = { - ...getEndpointEntryMatchMock(), - value: ['some value'], - }; - const decoded = endpointEntryMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "["some value"]" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is empty string', () => { - const payload: Omit & { value: string } = { - ...getEndpointEntryMatchMock(), - value: '', - }; - const decoded = endpointEntryMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "type" is not "match"', () => { - const payload: Omit & { type: string } = { - ...getEndpointEntryMatchMock(), - type: 'match_any', - }; - const decoded = endpointEntryMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "match_any" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EndpointEntryMatch & { - extraKey?: string; - } = getEndpointEntryMatchMock(); - payload.extraKey = 'some value'; - const decoded = endpointEntryMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryMatchMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.ts deleted file mode 100644 index 5ae0258ebfb79..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString, operatorIncluded } from '@kbn/securitysolution-io-ts-types'; - -export const endpointEntryMatch = t.exact( - t.type({ - field: NonEmptyString, - operator: operatorIncluded, - type: t.keyof({ match: null }), - value: NonEmptyString, - }) -); -export type EndpointEntryMatch = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.mock.ts deleted file mode 100644 index b3bfffd4daf97..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ENTRY_VALUE, FIELD, MATCH_ANY, OPERATOR } from '../../../constants/index.mock'; -import { EndpointEntryMatchAny } from '.'; - -export const getEndpointEntryMatchAnyMock = (): EndpointEntryMatchAny => ({ - field: FIELD, - operator: OPERATOR, - type: MATCH_ANY, - value: [ENTRY_VALUE], -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.test.ts deleted file mode 100644 index e121eed769ea9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEndpointEntryMatchAnyMock } from './index.mock'; -import { EndpointEntryMatchAny, endpointEntryMatchAny } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEntryMatchAnyMock } from '../../entry_match_any/index.mock'; - -describe('endpointEntryMatchAny', () => { - test('it should validate an entry', () => { - const payload = getEndpointEntryMatchAnyMock(); - const decoded = endpointEntryMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate when operator is "excluded"', () => { - // Use the generic entry mock so we can test operator: excluded - const payload = getEntryMatchAnyMock(); - payload.operator = 'excluded'; - const decoded = endpointEntryMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "excluded" supplied to "operator"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when field is empty string', () => { - const payload: Omit & { field: string } = { - ...getEndpointEntryMatchAnyMock(), - field: '', - }; - const decoded = endpointEntryMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when value is empty array', () => { - const payload: Omit & { value: string[] } = { - ...getEndpointEntryMatchAnyMock(), - value: [], - }; - const decoded = endpointEntryMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "[]" supplied to "value"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when value is not string array', () => { - const payload: Omit & { value: string } = { - ...getEndpointEntryMatchAnyMock(), - value: 'some string', - }; - const decoded = endpointEntryMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "type" is not "match_any"', () => { - const payload: Omit & { type: string } = { - ...getEndpointEntryMatchAnyMock(), - type: 'match', - }; - const decoded = endpointEntryMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EndpointEntryMatchAny & { - extraKey?: string; - } = getEndpointEntryMatchAnyMock(); - payload.extraKey = 'some extra key'; - const decoded = endpointEntryMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryMatchAnyMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.ts deleted file mode 100644 index d639f4481d4d3..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { - NonEmptyString, - nonEmptyOrNullableStringArray, - operatorIncluded, -} from '@kbn/securitysolution-io-ts-types'; - -export const endpointEntryMatchAny = t.exact( - t.type({ - field: NonEmptyString, - operator: operatorIncluded, - type: t.keyof({ match_any: null }), - value: nonEmptyOrNullableStringArray, - }) -); -export type EndpointEntryMatchAny = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.mock.ts deleted file mode 100644 index f1b5c7e7421af..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ENTRY_VALUE, FIELD, OPERATOR, WILDCARD } from '../../../constants/index.mock'; -import { EndpointEntryMatchWildcard } from '.'; - -export const getEndpointEntryMatchWildcardMock = (): EndpointEntryMatchWildcard => ({ - field: FIELD, - operator: OPERATOR, - type: WILDCARD, - value: ENTRY_VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.test.ts deleted file mode 100644 index 025994afcd9ef..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.test.ts +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEndpointEntryMatchWildcardMock } from './index.mock'; -import { EndpointEntryMatchWildcard, endpointEntryMatchWildcard } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEntryMatchWildcardMock } from '../../entry_match_wildcard/index.mock'; - -describe('endpointEntryMatchWildcard', () => { - test('it should validate an entry', () => { - const payload = getEndpointEntryMatchWildcardMock(); - const decoded = endpointEntryMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when "operator" is "excluded"', () => { - const payload = getEntryMatchWildcardMock(); - payload.operator = 'excluded'; - const decoded = endpointEntryMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when "field" is empty string', () => { - const payload: Omit & { field: string } = { - ...getEndpointEntryMatchWildcardMock(), - field: '', - }; - const decoded = endpointEntryMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is not string', () => { - const payload: Omit & { value: string[] } = { - ...getEndpointEntryMatchWildcardMock(), - value: ['some value'], - }; - const decoded = endpointEntryMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "["some value"]" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is empty string', () => { - const payload: Omit & { value: string } = { - ...getEndpointEntryMatchWildcardMock(), - value: '', - }; - const decoded = endpointEntryMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "type" is not "wildcard"', () => { - const payload: Omit & { type: string } = { - ...getEndpointEntryMatchWildcardMock(), - type: 'match', - }; - const decoded = endpointEntryMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EndpointEntryMatchWildcard & { - extraKey?: string; - } = getEndpointEntryMatchWildcardMock(); - payload.extraKey = 'some value'; - const decoded = endpointEntryMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryMatchWildcardMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.ts deleted file mode 100644 index b42f6245ea28d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { - NonEmptyString, - operatorExcluded, - operatorIncluded, -} from '@kbn/securitysolution-io-ts-types'; - -export const endpointEntryMatchWildcard = t.exact( - t.type({ - field: NonEmptyString, - operator: t.union([operatorIncluded, operatorExcluded]), - type: t.keyof({ wildcard: null }), - value: NonEmptyString, - }) -); -export type EndpointEntryMatchWildcard = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.mock.ts deleted file mode 100644 index 44c5f8db5f6e7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.mock.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EndpointEntryNested } from '.'; -import { FIELD, NESTED } from '../../../constants/index.mock'; -import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; -import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; - -export const getEndpointEntryNestedMock = (): EndpointEntryNested => ({ - entries: [getEndpointEntryMatchMock(), getEndpointEntryMatchAnyMock()], - field: FIELD, - type: NESTED, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.test.ts deleted file mode 100644 index c062deb88af81..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { EndpointEntryNested, endpointEntryNested } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEndpointEntryNestedMock } from './index.mock'; -import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { - nonEmptyEndpointNestedEntriesArray, - NonEmptyEndpointNestedEntriesArray, -} from '../non_empty_nested_entries_array'; -import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; -import { getEntryExistsMock } from '../../entries_exist/index.mock'; - -describe('endpointEntryNested', () => { - test('it should validate a nested entry', () => { - const payload = getEndpointEntryNestedMock(); - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when "type" is not "nested"', () => { - const payload: Omit & { type: 'match' } = { - ...getEndpointEntryNestedMock(), - type: 'match', - }; - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "field" is empty string', () => { - const payload: Omit & { - field: string; - } = { ...getEndpointEntryNestedMock(), field: '' }; - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "field" is not a string', () => { - const payload: Omit & { - field: number; - } = { ...getEndpointEntryNestedMock(), field: 1 }; - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "entries" is not an array', () => { - const payload: Omit & { - entries: string; - } = { ...getEndpointEntryNestedMock(), entries: 'im a string' }; - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "im a string" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should validate when "entries" contains an entry item that is type "match"', () => { - const payload = { ...getEndpointEntryNestedMock(), entries: [getEndpointEntryMatchAnyMock()] }; - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual({ - entries: [ - { - field: 'host.name', - operator: 'included', - type: 'match_any', - value: ['some host name'], - }, - ], - field: 'host.name', - type: 'nested', - }); - }); - - test('it should NOT validate when "entries" contains an entry item that is type "exists"', () => { - const payload = { ...getEndpointEntryNestedMock(), entries: [getEntryExistsMock()] }; - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "exists" supplied to "entries,type"', - 'Invalid value "undefined" supplied to "entries,value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EndpointEntryNested & { - extraKey?: string; - } = getEndpointEntryNestedMock(); - payload.extraKey = 'some extra key'; - const decoded = endpointEntryNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEndpointEntryNestedMock()); - }); - - test('type guard for nonEmptyEndpointNestedEntries should allow array of endpoint entries', () => { - const payload: NonEmptyEndpointNestedEntriesArray = [ - getEndpointEntryMatchMock(), - getEndpointEntryMatchAnyMock(), - ]; - const guarded = nonEmptyEndpointNestedEntriesArray.is(payload); - expect(guarded).toBeTruthy(); - }); - - test('type guard for nonEmptyEndpointNestedEntries should disallow empty arrays', () => { - const payload: NonEmptyEndpointNestedEntriesArray = []; - const guarded = nonEmptyEndpointNestedEntriesArray.is(payload); - expect(guarded).toBeFalsy(); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.ts deleted file mode 100644 index 6625c1dfeaf59..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { nonEmptyEndpointNestedEntriesArray } from '../non_empty_nested_entries_array'; - -export const endpointEntryNested = t.exact( - t.type({ - entries: nonEmptyEndpointNestedEntriesArray, - field: NonEmptyString, - type: t.keyof({ nested: null }), - }) -); -export type EndpointEntryNested = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/index.ts deleted file mode 100644 index fb42cc8ee4686..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './entries'; -export * from './non_empty_nested_entries_array'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/non_empty_nested_entries_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/non_empty_nested_entries_array/index.ts deleted file mode 100644 index 9bcfccae97b31..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/non_empty_nested_entries_array/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { endpointEntryMatch } from '../entry_match'; -import { endpointEntryMatchAny } from '../entry_match_any'; - -export const endpointNestedEntriesArray = t.array( - t.union([endpointEntryMatch, endpointEntryMatchAny]) -); -export type EndpointNestedEntriesArray = t.TypeOf; - -/** - * Types the nonEmptyNestedEntriesArray as: - * - An array of entries of length 1 or greater - * - */ -export const nonEmptyEndpointNestedEntriesArray = new t.Type< - EndpointNestedEntriesArray, - EndpointNestedEntriesArray, - unknown ->( - 'NonEmptyEndpointNestedEntriesArray', - (u: unknown): u is EndpointNestedEntriesArray => endpointNestedEntriesArray.is(u) && u.length > 0, - (input, context): Either => { - if (Array.isArray(input) && input.length === 0) { - return t.failure(input, context); - } else { - return endpointNestedEntriesArray.validate(input, context); - } - }, - t.identity -); - -export type NonEmptyEndpointNestedEntriesArray = t.OutputOf< - typeof nonEmptyEndpointNestedEntriesArray ->; -export type NonEmptyEndpointNestedEntriesArrayDecoded = t.TypeOf< - typeof nonEmptyEndpointNestedEntriesArray ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.mock.ts deleted file mode 100644 index 5b8c802c94a38..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.mock.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EntriesArray } from '.'; -import { getEntryExistsMock } from '../entries_exist/index.mock'; -import { getEntryListMock } from '../entries_list/index.mock'; -import { getEntryMatchMock } from '../entry_match/index.mock'; -import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { getEntryNestedMock } from '../entry_nested/index.mock'; - -export const getListAndNonListEntriesArrayMock = (): EntriesArray => [ - getEntryMatchMock(), - getEntryMatchAnyMock(), - getEntryListMock(), - getEntryExistsMock(), - getEntryNestedMock(), -]; - -export const getListEntriesArrayMock = (): EntriesArray => [getEntryListMock(), getEntryListMock()]; - -export const getEntriesArrayMock = (): EntriesArray => [ - getEntryMatchMock(), - getEntryMatchAnyMock(), - getEntryExistsMock(), - getEntryNestedMock(), -]; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.test.ts deleted file mode 100644 index 73553be78b9a1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.test.ts +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEntryMatchMock } from '../entry_match/index.mock'; -import { entriesArray, entriesArrayOrUndefined, entry } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { getEntryExistsMock } from '../entries_exist/index.mock'; -import { getEntryListMock } from '../entries_list/index.mock'; -import { getEntryNestedMock } from '../entry_nested/index.mock'; -import { getEntriesArrayMock } from './index.mock'; - -describe('Entries', () => { - describe('entry', () => { - test('it should validate a match entry', () => { - const payload = getEntryMatchMock(); - const decoded = entry.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate a match_any entry', () => { - const payload = getEntryMatchAnyMock(); - const decoded = entry.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate a exists entry', () => { - const payload = getEntryExistsMock(); - const decoded = entry.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate a list entry', () => { - const payload = getEntryListMock(); - const decoded = entry.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation of nested entry', () => { - const payload = getEntryNestedMock(); - const decoded = entry.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', - 'Invalid value "undefined" supplied to "list"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('entriesArray', () => { - test('it should validate an array with match entry', () => { - const payload = [getEntryMatchMock()]; - const decoded = entriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with match_any entry', () => { - const payload = [getEntryMatchAnyMock()]; - const decoded = entriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with exists entry', () => { - const payload = [getEntryExistsMock()]; - const decoded = entriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with list entry', () => { - const payload = [getEntryListMock()]; - const decoded = entriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with nested entry', () => { - const payload = [getEntryNestedMock()]; - const decoded = entriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with all types of entries', () => { - const payload = [...getEntriesArrayMock()]; - const decoded = entriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - }); - - describe('entriesArrayOrUndefined', () => { - test('it should validate undefined', () => { - const payload = undefined; - const decoded = entriesArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array with nested entry', () => { - const payload = [getEntryNestedMock()]; - const decoded = entriesArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.ts deleted file mode 100644 index f2dbbd91dfceb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { entriesExists } from '../entries_exist'; -import { entriesList } from '../entries_list'; -import { entriesMatch } from '../entry_match'; -import { entriesMatchAny } from '../entry_match_any'; -import { entriesMatchWildcard } from '../entry_match_wildcard'; -import { entriesNested } from '../entry_nested'; - -// NOTE: Type nested is not included here to denote it's non-recursive nature. -// So a nested entry is really just a collection of `Entry` types. -export const entry = t.union([ - entriesMatch, - entriesMatchAny, - entriesList, - entriesExists, - entriesMatchWildcard, -]); -export type Entry = t.TypeOf; - -export const entriesArray = t.array( - t.union([ - entriesMatch, - entriesMatchAny, - entriesList, - entriesExists, - entriesNested, - entriesMatchWildcard, - ]) -); -export type EntriesArray = t.TypeOf; - -export const entriesArrayOrUndefined = t.union([entriesArray, t.undefined]); -export type EntriesArrayOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.mock.ts deleted file mode 100644 index 3a588ec9cc7ba..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.mock.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EntryExists } from '.'; -import { EXISTS, FIELD, OPERATOR } from '../../constants/index.mock'; - -export const getEntryExistsMock = (): EntryExists => ({ - field: FIELD, - operator: OPERATOR, - type: EXISTS, -}); - -export const getEntryExistsExcludedMock = (): EntryExists => ({ - ...getEntryExistsMock(), - operator: 'excluded', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.test.ts deleted file mode 100644 index 8ebf60ebc19f1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEntryExistsMock } from './index.mock'; -import { entriesExists, EntryExists } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('entriesExists', () => { - test('it should validate an entry', () => { - const payload = getEntryExistsMock(); - const decoded = entriesExists.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when "operator" is "included"', () => { - const payload = getEntryExistsMock(); - const decoded = entriesExists.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when "operator" is "excluded"', () => { - const payload = getEntryExistsMock(); - payload.operator = 'excluded'; - const decoded = entriesExists.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when "field" is empty string', () => { - const payload: Omit & { field: string } = { - ...getEntryExistsMock(), - field: '', - }; - const decoded = entriesExists.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EntryExists & { - extraKey?: string; - } = getEntryExistsMock(); - payload.extraKey = 'some extra key'; - const decoded = entriesExists.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryExistsMock()); - }); - - test('it should FAIL validation when "type" is not "exists"', () => { - const payload: Omit & { type: string } = { - ...getEntryExistsMock(), - type: 'match', - }; - const decoded = entriesExists.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.ts deleted file mode 100644 index 460030dcc951b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { listOperator as operator } from '../list_operator'; - -export const entriesExists = t.exact( - t.type({ - field: NonEmptyString, - operator, - type: t.keyof({ exists: null }), - }) -); -export type EntryExists = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.mock.ts deleted file mode 100644 index 06e006ed661ba..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EntryList } from '.'; -import { FIELD, LIST, LIST_ID, OPERATOR, TYPE } from '../../constants/index.mock'; - -export const getEntryListMock = (): EntryList => ({ - field: FIELD, - list: { id: LIST_ID, type: TYPE }, - operator: OPERATOR, - type: LIST, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.test.ts deleted file mode 100644 index eb047a07f08dd..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEntryListMock } from './index.mock'; -import { entriesList, EntryList } from '.'; - -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('entriesList', () => { - test('it should validate an entry', () => { - const payload = getEntryListMock(); - const decoded = entriesList.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when operator is "included"', () => { - const payload = getEntryListMock(); - const decoded = entriesList.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when "operator" is "excluded"', () => { - const payload = getEntryListMock(); - payload.operator = 'excluded'; - const decoded = entriesList.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when "list" is not expected value', () => { - const payload: Omit & { list: string } = { - ...getEntryListMock(), - list: 'someListId', - }; - const decoded = entriesList.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "someListId" supplied to "list"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "list.id" is empty string', () => { - const payload: Omit & { list: { id: string; type: 'ip' } } = { - ...getEntryListMock(), - list: { id: '', type: 'ip' }, - }; - const decoded = entriesList.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "list,id"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "type" is not "lists"', () => { - const payload: Omit & { type: 'match_any' } = { - ...getEntryListMock(), - type: 'match_any', - }; - const decoded = entriesList.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "match_any" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EntryList & { - extraKey?: string; - } = getEntryListMock(); - payload.extraKey = 'some extra key'; - const decoded = entriesList.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryListMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.ts deleted file mode 100644 index f55a3f056218a..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -import { type } from '../type'; -import { listOperator as operator } from '../list_operator'; - -export const entriesList = t.exact( - t.type({ - field: NonEmptyString, - list: t.exact(t.type({ id: NonEmptyString, type })), - operator, - type: t.keyof({ list: null }), - }) -); -export type EntryList = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.mock.ts deleted file mode 100644 index 9e09661c29456..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.mock.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EntryMatch } from '.'; -import { ENTRY_VALUE, FIELD, MATCH, OPERATOR } from '../../constants/index.mock'; - -export const getEntryMatchMock = (): EntryMatch => ({ - field: FIELD, - operator: OPERATOR, - type: MATCH, - value: ENTRY_VALUE, -}); - -export const getEntryMatchExcludeMock = (): EntryMatch => ({ - ...getEntryMatchMock(), - operator: 'excluded', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.test.ts deleted file mode 100644 index f2f8dbb8998f3..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.test.ts +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEntryMatchMock } from './index.mock'; -import { entriesMatch, EntryMatch } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('entriesMatch', () => { - test('it should validate an entry', () => { - const payload = getEntryMatchMock(); - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when operator is "included"', () => { - const payload = getEntryMatchMock(); - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when "operator" is "excluded"', () => { - const payload = getEntryMatchMock(); - payload.operator = 'excluded'; - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when "field" is empty string', () => { - const payload: Omit & { field: string } = { - ...getEntryMatchMock(), - field: '', - }; - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is not string', () => { - const payload: Omit & { value: string[] } = { - ...getEntryMatchMock(), - value: ['some value'], - }; - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "["some value"]" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is empty string', () => { - const payload: Omit & { value: string } = { - ...getEntryMatchMock(), - value: '', - }; - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "type" is not "match"', () => { - const payload: Omit & { type: string } = { - ...getEntryMatchMock(), - type: 'match_any', - }; - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "match_any" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EntryMatch & { - extraKey?: string; - } = getEntryMatchMock(); - payload.extraKey = 'some value'; - const decoded = entriesMatch.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryMatchMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.ts deleted file mode 100644 index 17bf0ab5b89e6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { listOperator as operator } from '../list_operator'; - -export const entriesMatch = t.exact( - t.type({ - field: NonEmptyString, - operator, - type: t.keyof({ match: null }), - value: NonEmptyString, - }) -); -export type EntryMatch = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.mock.ts deleted file mode 100644 index 7a5c4c57fa32f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.mock.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EntryMatchAny } from '.'; -import { ENTRY_VALUE, FIELD, MATCH_ANY, OPERATOR } from '../../constants/index.mock'; - -export const getEntryMatchAnyMock = (): EntryMatchAny => ({ - field: FIELD, - operator: OPERATOR, - type: MATCH_ANY, - value: [ENTRY_VALUE], -}); - -export const getEntryMatchAnyExcludeMock = (): EntryMatchAny => ({ - ...getEntryMatchAnyMock(), - operator: 'excluded', - value: [ENTRY_VALUE, 'some other host name'], -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.test.ts deleted file mode 100644 index 3e4752f395088..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEntryMatchAnyMock } from './index.mock'; -import { entriesMatchAny, EntryMatchAny } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('entriesMatchAny', () => { - test('it should validate an entry', () => { - const payload = getEntryMatchAnyMock(); - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when operator is "included"', () => { - const payload = getEntryMatchAnyMock(); - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when operator is "excluded"', () => { - const payload = getEntryMatchAnyMock(); - payload.operator = 'excluded'; - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when field is empty string', () => { - const payload: Omit & { field: string } = { - ...getEntryMatchAnyMock(), - field: '', - }; - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when value is empty array', () => { - const payload: Omit & { value: string[] } = { - ...getEntryMatchAnyMock(), - value: [], - }; - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "[]" supplied to "value"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when value is not string array', () => { - const payload: Omit & { value: string } = { - ...getEntryMatchAnyMock(), - value: 'some string', - }; - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "type" is not "match_any"', () => { - const payload: Omit & { type: string } = { - ...getEntryMatchAnyMock(), - type: 'match', - }; - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EntryMatchAny & { - extraKey?: string; - } = getEntryMatchAnyMock(); - payload.extraKey = 'some extra key'; - const decoded = entriesMatchAny.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryMatchAnyMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.ts deleted file mode 100644 index be08fb370abdc..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NonEmptyString, nonEmptyOrNullableStringArray } from '@kbn/securitysolution-io-ts-types'; -import { listOperator as operator } from '../list_operator'; - -export const entriesMatchAny = t.exact( - t.type({ - field: NonEmptyString, - operator, - type: t.keyof({ match_any: null }), - value: nonEmptyOrNullableStringArray, - }) -); -export type EntryMatchAny = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.mock.ts deleted file mode 100644 index 6dc33289d22db..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.mock.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EntryMatchWildcard } from '.'; -import { ENTRY_VALUE, FIELD, OPERATOR, WILDCARD } from '../../constants/index.mock'; - -export const getEntryMatchWildcardMock = (): EntryMatchWildcard => ({ - field: FIELD, - operator: OPERATOR, - type: WILDCARD, - value: ENTRY_VALUE, -}); - -export const getEntryMatchWildcardExcludeMock = (): EntryMatchWildcard => ({ - ...getEntryMatchWildcardMock(), - operator: 'excluded', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.test.ts deleted file mode 100644 index a84996a6c1050..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEntryMatchWildcardMock } from './index.mock'; -import { entriesMatchWildcard, EntryMatchWildcard } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('entriesMatchWildcard', () => { - test('it should validate an entry', () => { - const payload = getEntryMatchWildcardMock(); - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when operator is "included"', () => { - const payload = getEntryMatchWildcardMock(); - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when "operator" is "excluded"', () => { - const payload = getEntryMatchWildcardMock(); - payload.operator = 'excluded'; - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when "field" is empty string', () => { - const payload: Omit & { field: string } = { - ...getEntryMatchWildcardMock(), - field: '', - }; - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is not string', () => { - const payload: Omit & { value: string[] } = { - ...getEntryMatchWildcardMock(), - value: ['some value'], - }; - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "["some value"]" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "value" is empty string', () => { - const payload: Omit & { value: string } = { - ...getEntryMatchWildcardMock(), - value: '', - }; - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "type" is not "wildcard"', () => { - const payload: Omit & { type: string } = { - ...getEntryMatchWildcardMock(), - type: 'match', - }; - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: EntryMatchWildcard & { - extraKey?: string; - } = getEntryMatchWildcardMock(); - payload.extraKey = 'some value'; - const decoded = entriesMatchWildcard.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryMatchWildcardMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.ts deleted file mode 100644 index 17afe342961c2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { listOperator as operator } from '../list_operator'; - -export const entriesMatchWildcard = t.exact( - t.type({ - field: NonEmptyString, - operator, - type: t.keyof({ wildcard: null }), - value: NonEmptyString, - }) -); -export type EntryMatchWildcard = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.mock.ts deleted file mode 100644 index 34d687502e245..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.mock.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EntryNested } from '.'; -import { NESTED, NESTED_FIELD } from '../../constants/index.mock'; -import { getEntryExistsMock } from '../entries_exist/index.mock'; -import { getEntryMatchExcludeMock, getEntryMatchMock } from '../entry_match/index.mock'; -import { getEntryMatchAnyExcludeMock, getEntryMatchAnyMock } from '../entry_match_any/index.mock'; - -export const getEntryNestedMock = (): EntryNested => ({ - entries: [getEntryMatchMock(), getEntryMatchAnyMock()], - field: NESTED_FIELD, - type: NESTED, -}); - -export const getEntryNestedExcludeMock = (): EntryNested => ({ - ...getEntryNestedMock(), - entries: [getEntryMatchExcludeMock(), getEntryMatchAnyExcludeMock()], -}); - -export const getEntryNestedMixedEntries = (): EntryNested => ({ - ...getEntryNestedMock(), - entries: [getEntryMatchMock(), getEntryMatchAnyExcludeMock(), getEntryExistsMock()], -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.test.ts deleted file mode 100644 index cfd43c4c09935..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEntryNestedMock } from './index.mock'; -import { entriesNested, EntryNested } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { getEntryExistsMock } from '../entries_exist/index.mock'; - -describe('entriesNested', () => { - test('it should validate a nested entry', () => { - const payload = getEntryNestedMock(); - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when "type" is not "nested"', () => { - const payload: Omit & { type: 'match' } = { - ...getEntryNestedMock(), - type: 'match', - }; - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "field" is empty string', () => { - const payload: Omit & { - field: string; - } = { ...getEntryNestedMock(), field: '' }; - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "field" is not a string', () => { - const payload: Omit & { - field: number; - } = { ...getEntryNestedMock(), field: 1 }; - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "field"']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when "entries" is not a an array', () => { - const payload: Omit & { - entries: string; - } = { ...getEntryNestedMock(), entries: 'im a string' }; - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "im a string" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should validate when "entries" contains an entry item that is type "match"', () => { - const payload = { ...getEntryNestedMock(), entries: [getEntryMatchAnyMock()] }; - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual({ - entries: [ - { - field: 'host.name', - operator: 'included', - type: 'match_any', - value: ['some host name'], - }, - ], - field: 'parent.field', - type: 'nested', - }); - }); - - test('it should validate when "entries" contains an entry item that is type "exists"', () => { - const payload = { ...getEntryNestedMock(), entries: [getEntryExistsMock()] }; - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual({ - entries: [ - { - field: 'host.name', - operator: 'included', - type: 'exists', - }, - ], - field: 'parent.field', - type: 'nested', - }); - }); - - test('it should strip out extra keys', () => { - const payload: EntryNested & { - extraKey?: string; - } = getEntryNestedMock(); - payload.extraKey = 'some extra key'; - const decoded = entriesNested.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getEntryNestedMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.ts deleted file mode 100644 index 8b19fee9fb5cf..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { nonEmptyNestedEntriesArray } from '../non_empty_nested_entries_array'; - -export const entriesNested = t.exact( - t.type({ - entries: nonEmptyNestedEntriesArray, - field: NonEmptyString, - type: t.keyof({ nested: null }), - }) -); -export type EntryNested = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.mock.ts deleted file mode 100644 index 15cdd79dc2e9b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.mock.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ExportExceptionDetails } from '.'; - -export interface ExportExceptionDetailsMock { - listCount?: number; - missingListsCount?: number; - missingLists?: Array>; - itemCount?: number; - missingItemCount?: number; - missingItems?: Array>; -} - -export const getExceptionExportDetailsMock = ( - details?: ExportExceptionDetailsMock -): ExportExceptionDetails => ({ - exported_exception_list_count: details?.listCount ?? 0, - exported_exception_list_item_count: details?.itemCount ?? 0, - missing_exception_list_item_count: details?.missingItemCount ?? 0, - missing_exception_list_items: details?.missingItems ?? [], - missing_exception_lists: details?.missingLists ?? [], - missing_exception_lists_count: details?.missingListsCount ?? 0, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.test.ts deleted file mode 100644 index c9b1a4767e573..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getExceptionExportDetailsMock } from './index.mock'; -import { exportExceptionDetailsSchema, ExportExceptionDetails } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('exportExceptionDetails', () => { - test('it should validate export meta', () => { - const payload = getExceptionExportDetailsMock(); - const decoded = exportExceptionDetailsSchema.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should strip out extra keys', () => { - const payload: ExportExceptionDetails & { - extraKey?: string; - } = getExceptionExportDetailsMock(); - payload.extraKey = 'some extra key'; - const decoded = exportExceptionDetailsSchema.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getExceptionExportDetailsMock()); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.ts deleted file mode 100644 index 9e4ff134d6e9f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -export const exportExceptionDetails = { - exported_exception_list_count: t.number, - exported_exception_list_item_count: t.number, - missing_exception_list_item_count: t.number, - missing_exception_list_items: t.array( - t.exact( - t.type({ - item_id: NonEmptyString, - }) - ) - ), - missing_exception_lists: t.array( - t.exact( - t.type({ - list_id: NonEmptyString, - }) - ) - ), - missing_exception_lists_count: t.number, -}; - -export const exportExceptionDetailsSchema = t.exact(t.type(exportExceptionDetails)); - -export type ExportExceptionDetails = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.test.ts deleted file mode 100644 index 2c6aae8a56937..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exceptionListType, ExceptionListTypeEnum } from '.'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('exceptionListType', () => { - test('it should validate for "detection"', () => { - const payload = 'detection'; - const decoded = exceptionListType.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate for "rule_default"', () => { - const payload = 'rule_default'; - const decoded = exceptionListType.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate for "endpoint"', () => { - const payload = 'endpoint'; - const decoded = exceptionListType.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should contain same amount of keys as enum', () => { - // Might seem like a weird test, but its meant to - // ensure that if exceptionListType is updated, you - // also update the ExceptionListTypeEnum, a workaround - // for io-ts not yet supporting enums - // https://github.com/gcanti/io-ts/issues/67 - const keys = Object.keys(exceptionListType.keys).sort().join(',').toLowerCase(); - const enumKeys = Object.keys(ExceptionListTypeEnum).sort().join(',').toLowerCase(); - - expect(keys).toEqual(enumKeys); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.ts deleted file mode 100644 index db7633705ac5b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const exceptionListType = t.keyof({ - detection: null, - rule_default: null, - endpoint: null, - endpoint_trusted_apps: null, - endpoint_events: null, - endpoint_host_isolation_exceptions: null, - endpoint_blocklists: null, -}); -export const exceptionListTypeOrUndefined = t.union([exceptionListType, t.undefined]); -export type ExceptionListType = t.TypeOf; -export type ExceptionListTypeOrUndefined = t.TypeOf; -export enum ExceptionListTypeEnum { - DETECTION = 'detection', // shared exception list type - RULE_DEFAULT = 'rule_default', // rule default, cannot be shared - ENDPOINT = 'endpoint', - ENDPOINT_TRUSTED_APPS = 'endpoint', - ENDPOINT_EVENTS = 'endpoint_events', - ENDPOINT_HOST_ISOLATION_EXCEPTIONS = 'endpoint_host_isolation_exceptions', - ENDPOINT_BLOCKLISTS = 'endpoint_blocklists', -} diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list_item_type/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list_item_type/index.ts deleted file mode 100644 index 5e124b9f923d9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list_item_type/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const exceptionListItemType = t.keyof({ simple: null }); -export const exceptionListItemTypeOrUndefined = t.union([exceptionListItemType, t.undefined]); -export type ExceptionListItemType = t.TypeOf; -export type ExceptionListItemTypeOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/expire_time/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/expire_time/index.ts deleted file mode 100644 index 4e8184d4e6ce9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/expire_time/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { IsoDateString } from '@kbn/securitysolution-io-ts-types'; - -export const expireTime = IsoDateString; -export const expireTimeOrUndefined = t.union([expireTime, t.undefined]); -export type ExpireTimeOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/file/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/file/index.ts deleted file mode 100644 index f569d42c41f17..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/file/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const file = t.object; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/filter/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/filter/index.ts deleted file mode 100644 index 70d526eaefbe5..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/filter/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const filter = t.string; -export type Filter = t.TypeOf; -export const filterOrUndefined = t.union([filter, t.undefined]); -export type FilterOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/id/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/id/index.ts deleted file mode 100644 index c9f35b36ee577..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/id/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -export const id = NonEmptyString; -export type Id = t.TypeOf; -export const idOrUndefined = t.union([id, t.undefined]); -export type IdOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/immutable/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/immutable/index.ts deleted file mode 100644 index 9bdb50647abd2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/immutable/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const immutable = t.boolean; -export type Immutable = t.TypeOf; -export const immutableOrUndefined = t.union([immutable, t.undefined]); -export type ImmutableOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts deleted file mode 100644 index 50121086c1411..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getCommentsArrayMock, getCommentsMock } from '../comment/index.mock'; -import { getCreateCommentsArrayMock } from '../create_comment/index.mock'; -import { - importComment, - ImportCommentsArray, - importCommentsArray, - ImportCommentsArrayOrUndefined, - importCommentsArrayOrUndefined, -} from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('ImportComment', () => { - describe('importComment', () => { - test('it passes validation with a typical comment', () => { - const payload = getCommentsMock(); - const decoded = importComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation with a new comment', () => { - const payload = { comment: 'new comment' }; - const decoded = importComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when undefined', () => { - const payload = undefined; - const decoded = importComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('importCommentsArray', () => { - test('it passes validation an array of Comment', () => { - const payload = getCommentsArrayMock(); - const decoded = importCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation an array of CreateComment', () => { - const payload = getCreateCommentsArrayMock(); - const decoded = importCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation an array of Comment and CreateComment', () => { - const payload = [...getCommentsArrayMock(), ...getCreateCommentsArrayMock()]; - const decoded = importCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when undefined', () => { - const payload = undefined; - const decoded = importCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it fails validation when array includes non ImportComment types', () => { - const payload = [1] as unknown as ImportCommentsArray; - const decoded = importCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('importCommentsArrayOrUndefined', () => { - test('it passes validation an array of ImportComment', () => { - const payload = [...getCommentsArrayMock(), ...getCreateCommentsArrayMock()]; - const decoded = importCommentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it passes validation when undefined', () => { - const payload = undefined; - const decoded = importCommentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it fails validation when array includes non ImportComment types', () => { - const payload = [1] as unknown as ImportCommentsArrayOrUndefined; - const decoded = importCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', - ]); - expect(message.schema).toEqual({}); - }); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts deleted file mode 100644 index 4511b28078bc6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { createComment } from '../create_comment'; -import { comment } from '../comment'; - -export const importComment = t.union([comment, createComment]); - -export type ImportComment = t.TypeOf; -export const importCommentsArray = t.array(importComment); -export type ImportCommentsArray = t.TypeOf; -export const importCommentsArrayOrUndefined = t.union([importCommentsArray, t.undefined]); -export type ImportCommentsArrayOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/include_expired_exceptions/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/include_expired_exceptions/index.ts deleted file mode 100644 index 7c40e74d81895..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/include_expired_exceptions/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const include_expired_exceptions = t.keyof({ true: null, false: null }); -export const includeExpiredExceptionsOrUndefined = t.union([ - include_expired_exceptions, - t.undefined, -]); -export type IncludeExpiredExceptionsOrUndefined = t.TypeOf< - typeof includeExpiredExceptionsOrUndefined ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts deleted file mode 100644 index b30ac02dab962..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './comment'; -export * from './create_comment'; -export * from './created_at'; -export * from './created_by'; -export * from './cursor'; -export * from './default_namespace'; -export * from './default_namespace_array'; -export * from './default_create_comments_array'; -export * from './default_import_comments_array'; -export * from './description'; -export * from './deserializer'; -export * from './endpoint'; -export * from './entries'; -export * from './entries_exist'; -export * from './entries_list'; -export * from './entry_match'; -export * from './entry_match_any'; -export * from './entry_match_wildcard'; -export * from './entry_nested'; -export * from './exception_export_details'; -export * from './exception_list'; -export * from './exception_list_item_type'; -export * from './expire_time'; -export * from './filter'; -export * from './id'; -export * from './immutable'; -export * from './import_comment'; -export * from './item_id'; -export * from './list_id'; -export * from './list_operator'; -export * from './list_type'; -export * from './lists'; -export * from './lists_default_array'; -export * from './max_size'; -export * from './meta'; -export * from './name'; -export * from './namespace_type'; -export * from './non_empty_entries_array'; -export * from './non_empty_nested_entries_array'; -export * from './os_type'; -export * from './page'; -export * from './per_page'; -export * from './pit'; -export * from './search'; -export * from './search_after'; -export * from './serializer'; -export * from './sort_field'; -export * from './sort_order'; -export * from './tags'; -export * from './tie_breaker_id'; -export * from './timestamp'; -export * from './total'; -export * from './type'; -export * from './underscore_version'; -export * from './update_comment'; -export * from './updated_at'; -export * from './updated_by'; -export * from './refresh'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/item/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/item/index.ts deleted file mode 100644 index d69ec53584001..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/item/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const item = t.string; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/item_id/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/item_id/index.ts deleted file mode 100644 index 0e4551ad5c8f6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/item_id/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -export const item_id = NonEmptyString; -export type ItemId = t.TypeOf; -export const itemIdOrUndefined = t.union([item_id, t.undefined]); -export type ItemIdOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_id/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/list_id/index.ts deleted file mode 100644 index 88e88aa8bc3c7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_id/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; - -export const list_id = NonEmptyString; -export type ListId = t.TypeOf; -export const list_idOrUndefined = t.union([list_id, t.undefined]); -export type ListIdOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.test.ts deleted file mode 100644 index 054af26b4a620..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { ListOperatorEnum as OperatorEnum, listOperator as operator } from '.'; - -describe('operator', () => { - test('it should validate for "included"', () => { - const payload = 'included'; - const decoded = operator.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate for "excluded"', () => { - const payload = 'excluded'; - const decoded = operator.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should contain same amount of keys as enum', () => { - // Might seem like a weird test, but its meant to - // ensure that if operator is updated, you - // also update the operatorEnum, a workaround - // for io-ts not yet supporting enums - // https://github.com/gcanti/io-ts/issues/67 - const keys = Object.keys(operator.keys).sort().join(',').toLowerCase(); - const enumKeys = Object.keys(OperatorEnum).sort().join(',').toLowerCase(); - - expect(keys).toEqual(enumKeys); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.ts deleted file mode 100644 index 574a64e0f0320..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const listOperator = t.keyof({ excluded: null, included: null }); -export type ListOperator = t.TypeOf; -export enum ListOperatorEnum { - INCLUDED = 'included', - EXCLUDED = 'excluded', -} - -export const listOperatorType = t.keyof({ - nested: null, - match: null, - match_any: null, - wildcard: null, - exists: null, - list: null, -}); -export type ListOperatorType = t.TypeOf; -export enum ListOperatorTypeEnum { - NESTED = 'nested', - MATCH = 'match', - MATCH_ANY = 'match_any', - WILDCARD = 'wildcard', - EXISTS = 'exists', - LIST = 'list', -} diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_type/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/list_type/index.ts deleted file mode 100644 index 716d9a6b24d7e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/list_type/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const list_type = t.keyof({ item: null, list: null }); -export type ListType = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.mock.ts deleted file mode 100644 index c8319867b5775..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.mock.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { List, ListArray } from '.'; -import { ENDPOINT_LIST_ID } from '@kbn/securitysolution-list-constants'; - -export const getListMock = (): List => ({ - id: 'some_uuid', - list_id: 'list_id_single', - namespace_type: 'single', - type: 'detection', -}); - -export const getEndpointListMock = (): List => ({ - id: ENDPOINT_LIST_ID, - list_id: ENDPOINT_LIST_ID, - namespace_type: 'agnostic', - type: 'endpoint', -}); - -export const getListArrayMock = (): ListArray => [getListMock(), getEndpointListMock()]; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.test.ts deleted file mode 100644 index 57c221f10384f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getEndpointListMock, getListArrayMock, getListMock } from './index.mock'; -import { List, list, ListArray, listArray, ListArrayOrUndefined, listArrayOrUndefined } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('Lists', () => { - describe('list', () => { - test('it should validate a list', () => { - const payload = getListMock(); - const decoded = list.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate a list with "namespace_type" of "agnostic"', () => { - const payload = getEndpointListMock(); - const decoded = list.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate a list without an "id"', () => { - const payload = getListMock(); - // @ts-expect-error - delete payload.id; - const decoded = list.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a list without "namespace_type"', () => { - const payload = getListMock(); - // @ts-expect-error - delete payload.namespace_type; - const decoded = list.decode(payload); - const message = pipe(decoded, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "namespace_type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra keys', () => { - const payload: List & { - extraKey?: string; - } = getListMock(); - payload.extraKey = 'some value'; - const decoded = list.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getListMock()); - }); - }); - - describe('listArray', () => { - test('it should validate an array of lists', () => { - const payload = getListArrayMock(); - const decoded = listArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate when unexpected type found in array', () => { - const payload = [1] as unknown as ListArray; - const decoded = listArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "rule_default" | "endpoint" | "endpoint_trusted_apps" | "endpoint_events" | "endpoint_host_isolation_exceptions" | "endpoint_blocklists", namespace_type: "agnostic" | "single" |}>"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('listArrayOrUndefined', () => { - test('it should validate an array of lists', () => { - const payload = getListArrayMock(); - const decoded = listArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate when undefined', () => { - const payload = undefined; - const decoded = listArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an item that is not of type "list" in array', () => { - const payload = [1] as unknown as ListArrayOrUndefined; - const decoded = listArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "rule_default" | "endpoint" | "endpoint_trusted_apps" | "endpoint_events" | "endpoint_host_isolation_exceptions" | "endpoint_blocklists", namespace_type: "agnostic" | "single" |}> | undefined)"', - 'Invalid value "[1]" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "rule_default" | "endpoint" | "endpoint_trusted_apps" | "endpoint_events" | "endpoint_host_isolation_exceptions" | "endpoint_blocklists", namespace_type: "agnostic" | "single" |}> | undefined)"', - ]); - expect(message.schema).toEqual({}); - }); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.ts deleted file mode 100644 index 564ce7833b0f0..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { exceptionListType } from '../exception_list'; -import { namespaceType } from '../default_namespace'; - -export const list = t.exact( - t.type({ - id: NonEmptyString, - list_id: NonEmptyString, - type: exceptionListType, - namespace_type: namespaceType, - }) -); - -export type List = t.TypeOf; -export const listArray = t.array(list); -export type ListArray = t.TypeOf; -export const listArrayOrUndefined = t.union([listArray, t.undefined]); -export type ListArrayOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.test.ts deleted file mode 100644 index fa4f22c4718e1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.test.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultListArray } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getListArrayMock } from '../lists/index.mock'; - -describe('lists_default_array', () => { - test('it should return a default array when null', () => { - const payload = null; - const decoded = DefaultListArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); - - test('it should return a default array when undefined', () => { - const payload = undefined; - const decoded = DefaultListArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); - - test('it should validate an empty array', () => { - const payload: string[] = []; - const decoded = DefaultListArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of lists', () => { - const payload = getListArrayMock(); - const decoded = DefaultListArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate an array of non accepted types', () => { - // Terrible casting for purpose of tests - const payload = [1] as unknown; - const decoded = DefaultListArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "DefaultListArray"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.ts deleted file mode 100644 index a014d769410ee..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { list, ListArray } from '../lists'; - -/** - * Types the DefaultListArray as: - * - If null or undefined, then a default array of type list will be set - */ -export const DefaultListArray = new t.Type( - 'DefaultListArray', - t.array(list).is, - (input, context): Either => - input == null ? t.success([]) : t.array(list).validate(input, context), - t.identity -); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.test.ts deleted file mode 100644 index 9ddf86818eaf7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exactCheck } from '@kbn/securitysolution-io-ts-utils'; -import { maxSizeOrUndefined } from '.'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; - -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('maxSizeOrUndefined', () => { - test('it will validate a correct max value', () => { - const payload = 123; - const decoded = maxSizeOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will fail to validate a 0', () => { - const payload = 0; - const decoded = maxSizeOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "0" supplied to "(PositiveIntegerGreaterThanZero | undefined)"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it will fail to validate a -1', () => { - const payload = -1; - const decoded = maxSizeOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "-1" supplied to "(PositiveIntegerGreaterThanZero | undefined)"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it will fail to validate a string', () => { - const payload = '123'; - const decoded = maxSizeOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "123" supplied to "(PositiveIntegerGreaterThanZero | undefined)"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.ts deleted file mode 100644 index 0c99edf692527..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; -import * as t from 'io-ts'; - -export const max_size = PositiveIntegerGreaterThanZero; -export type MaxSize = t.TypeOf; - -export const maxSizeOrUndefined = t.union([max_size, t.undefined]); -export type MaxSizeOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts deleted file mode 100644 index 07f329819fc12..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const meta = t.object; -export type Meta = t.TypeOf; -export const metaOrUndefined = t.union([meta, t.undefined]); -export type MetaOrUndefined = t.TypeOf; - -export const nullableMetaOrUndefined = t.union([metaOrUndefined, t.null]); -export type NullableMetaOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/name/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/name/index.ts deleted file mode 100644 index 5d4a13c06ceef..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/name/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const name = t.string; -export type Name = t.TypeOf; -export const nameOrUndefined = t.union([name, t.undefined]); -export type NameOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/namespace_type/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/namespace_type/index.ts deleted file mode 100644 index b8d052910b86a..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/namespace_type/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import { DefaultNamespace } from '../default_namespace'; - -export const namespace_type = DefaultNamespace; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.test.ts deleted file mode 100644 index 1128dd53871ee..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { EntriesArray } from '../entries'; -import { nonEmptyEntriesArray } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEntryMatchMock } from '../entry_match/index.mock'; -import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { getEntryExistsMock } from '../entries_exist/index.mock'; -import { - getEntriesArrayMock, - getListAndNonListEntriesArrayMock, - getListEntriesArrayMock, -} from '../entries/index.mock'; -import { getEntryNestedMock } from '../entry_nested/index.mock'; - -describe('non_empty_entries_array', () => { - test('it should FAIL validation when given an empty array', () => { - const payload: EntriesArray = []; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "[]" supplied to "NonEmptyEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when given "undefined"', () => { - const payload = undefined; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "NonEmptyEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when given "null"', () => { - const payload = null; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "null" supplied to "NonEmptyEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should validate an array of "match" entries', () => { - const payload: EntriesArray = [getEntryMatchMock(), getEntryMatchMock()]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of "match_any" entries', () => { - const payload: EntriesArray = [getEntryMatchAnyMock(), getEntryMatchAnyMock()]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of "exists" entries', () => { - const payload: EntriesArray = [getEntryExistsMock(), getEntryExistsMock()]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of "list" entries', () => { - const payload: EntriesArray = [...getListEntriesArrayMock()]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of "nested" entries', () => { - const payload: EntriesArray = [getEntryNestedMock(), getEntryNestedMock()]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of entries', () => { - const payload: EntriesArray = [...getEntriesArrayMock()]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when given an array of entries of value list and non-value list entries', () => { - const payload: EntriesArray = [...getListAndNonListEntriesArrayMock()]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Cannot have entry of type list and other']); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when given an array of non entries', () => { - const payload = [1]; - const decoded = nonEmptyEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "NonEmptyEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.ts deleted file mode 100644 index a5e06d5bb2c43..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { entriesArray, EntriesArray } from '../entries'; -import { entriesList } from '../entries_list'; - -/** - * Types the nonEmptyEntriesArray as: - * - An array of entries of length 1 or greater - * - */ -export const nonEmptyEntriesArray = new t.Type( - 'NonEmptyEntriesArray', - entriesArray.is, - (input, context): Either => { - if (Array.isArray(input) && input.length === 0) { - return t.failure(input, context); - } else { - if ( - Array.isArray(input) && - input.some((entry) => entriesList.is(entry)) && - input.some((entry) => !entriesList.is(entry)) - ) { - // fail when an exception item contains both a value list entry and a non-value list entry - return t.failure(input, context, 'Cannot have entry of type list and other'); - } - return entriesArray.validate(input, context); - } - }, - t.identity -); - -export type NonEmptyEntriesArray = t.OutputOf; -export type NonEmptyEntriesArrayDecoded = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.test.ts deleted file mode 100644 index afb62d1f87685..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { EntriesArray } from '../entries'; -import { nonEmptyNestedEntriesArray } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getEntryMatchMock } from '../entry_match/index.mock'; -import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; -import { getEntryExistsMock } from '../entries_exist/index.mock'; -import { getEntryNestedMock } from '../entry_nested/index.mock'; - -describe('non_empty_nested_entries_array', () => { - test('it should FAIL validation when given an empty array', () => { - const payload: EntriesArray = []; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "[]" supplied to "NonEmptyNestedEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when given "undefined"', () => { - const payload = undefined; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "NonEmptyNestedEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should FAIL validation when given "null"', () => { - const payload = null; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "null" supplied to "NonEmptyNestedEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should validate an array of "match" entries', () => { - const payload: EntriesArray = [getEntryMatchMock(), getEntryMatchMock()]; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of "match_any" entries', () => { - const payload: EntriesArray = [getEntryMatchAnyMock(), getEntryMatchAnyMock()]; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate an array of "exists" entries', () => { - const payload: EntriesArray = [getEntryExistsMock(), getEntryExistsMock()]; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when given an array of "nested" entries', () => { - const payload: EntriesArray = [getEntryNestedMock(), getEntryNestedMock()]; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should validate an array of entries', () => { - const payload: EntriesArray = [ - getEntryExistsMock(), - getEntryMatchAnyMock(), - getEntryMatchMock(), - ]; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should FAIL validation when given an array of non entries', () => { - const payload = [1]; - const decoded = nonEmptyNestedEntriesArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "NonEmptyNestedEntriesArray"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.ts deleted file mode 100644 index 73a00e75010f3..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { Either } from 'fp-ts/lib/Either'; -import { entriesMatch } from '../entry_match'; -import { entriesMatchAny } from '../entry_match_any'; -import { entriesExists } from '../entries_exist'; - -export const nestedEntryItem = t.union([entriesMatch, entriesMatchAny, entriesExists]); -export const nestedEntriesArray = t.array(nestedEntryItem); -export type NestedEntriesArray = t.TypeOf; - -/** - * Types the nonEmptyNestedEntriesArray as: - * - An array of entries of length 1 or greater - * - */ -export const nonEmptyNestedEntriesArray = new t.Type< - NestedEntriesArray, - NestedEntriesArray, - unknown ->( - 'NonEmptyNestedEntriesArray', - nestedEntriesArray.is, - (input, context): Either => { - if (Array.isArray(input) && input.length === 0) { - return t.failure(input, context); - } else { - return nestedEntriesArray.validate(input, context); - } - }, - t.identity -); - -export type NonEmptyNestedEntriesArray = t.OutputOf; -export type NonEmptyNestedEntriesArrayDecoded = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.test.ts deleted file mode 100644 index 566a2aa0973aa..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exactCheck } from '@kbn/securitysolution-io-ts-utils'; -import { osType, osTypeArrayOrUndefined } from '.'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; - -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('osType', () => { - test('it will validate a correct osType', () => { - const payload = 'windows'; - const decoded = osType.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will fail to validate an incorrect osType', () => { - const payload = 'foo'; - const decoded = osType.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "foo" supplied to ""linux" | "macos" | "windows""', - ]); - expect(message.schema).toEqual({}); - }); - - test('it will default to an empty array when osTypeArrayOrUndefined is used', () => { - const payload = undefined; - const decoded = osTypeArrayOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([]); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.ts deleted file mode 100644 index 1dfbb9687e214..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { DefaultArray } from '@kbn/securitysolution-io-ts-types'; - -export const osType = t.keyof({ - linux: null, - macos: null, - windows: null, -}); -export type OsType = t.TypeOf; - -export const osTypeArray = DefaultArray(osType); -export type OsTypeArray = t.TypeOf; - -export const osTypeArrayOrUndefined = t.union([osTypeArray, t.undefined]); -export type OsTypeArrayOrUndefined = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/page/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/page/index.ts deleted file mode 100644 index 58c5581cc6e26..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/page/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const page = t.number; // TODO: Change this out for PositiveNumber from siem -export type Page = t.TypeOf; - -export const pageOrUndefined = t.union([page, t.undefined]); -export type PageOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/per_page/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/per_page/index.ts deleted file mode 100644 index 9ab3d1dde38c9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/per_page/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const per_page = t.number; // TODO: Change this out for PositiveNumber from siem -export type PerPage = t.TypeOf; - -export const perPageOrUndefined = t.union([per_page, t.undefined]); -export type PerPageOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.test.ts deleted file mode 100644 index 36bc95ce17862..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exactCheck } from '@kbn/securitysolution-io-ts-utils'; -import { pitOrUndefined } from '.'; - -import * as t from 'io-ts'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; - -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('pitOrUndefined', () => { - test('it will validate a correct pit', () => { - const payload = { id: '123', keepAlive: '1m' }; - const decoded = pitOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will validate with the value of "undefined"', () => { - const obj = t.exact( - t.type({ - pit_id: pitOrUndefined, - }) - ); - const payload: t.TypeOf = { - pit_id: undefined, - }; - const decoded = obj.decode({ - pit_id: undefined, - }); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will validate a correct pit without having a "keepAlive"', () => { - const payload = { id: '123' }; - const decoded = pitOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will fail to validate an incorrect pit', () => { - const payload = 'foo'; - const decoded = pitOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "foo" supplied to "({| id: string, keepAlive: (string | undefined) |} | undefined)"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.ts deleted file mode 100644 index 3347f986113e2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const pitId = t.string; -export const pit = t.exact( - t.type({ - id: pitId, - keepAlive: t.union([t.string, t.undefined]), - }) -); -export const pitOrUndefined = t.union([pit, t.undefined]); - -export type Pit = t.TypeOf; -export type PitId = t.TypeOf; -export type PitOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/refresh/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/refresh/index.ts deleted file mode 100644 index faa301fd450ae..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/refresh/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const refresh = t.union([t.literal('true'), t.literal('false')]); -export const refreshWithWaitFor = t.union([ - t.literal('true'), - t.literal('false'), - t.literal('wait_for'), -]); -export type Refresh = t.TypeOf; -export type RefreshWithWaitFor = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/required_keep_undefined/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/required_keep_undefined/index.ts deleted file mode 100644 index 5e6b30cf720cb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/required_keep_undefined/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/** - * This makes any optional property the same as Required would but also has the - * added benefit of keeping your undefined. - * - * For example: - * type A = RequiredKeepUndefined<{ a?: undefined; b: number }>; - * - * will yield a type of: - * type A = { a: undefined; b: number; } - * @deprecated This has no replacement. We should stop using/relying on this and just remove it. - */ -export type RequiredKeepUndefined = { [K in keyof T]-?: [T[K]] } extends infer U - ? U extends Record - ? { [K in keyof U]: U[K][0] } - : never - : never; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts deleted file mode 100644 index 1224b277c8520..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exactCheck } from '@kbn/securitysolution-io-ts-utils'; -import { searchOrUndefined } from '.'; - -import * as t from 'io-ts'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; - -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('search', () => { - test('it will validate a correct search', () => { - const payload = 'name:foo'; - const decoded = searchOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will validate with the value of "undefined"', () => { - const obj = t.exact( - t.type({ - search: searchOrUndefined, - }) - ); - const payload: t.TypeOf = { - search: undefined, - }; - const decoded = obj.decode({ - pit_id: undefined, - }); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will fail to validate an incorrect search', () => { - const payload = ['foo']; - const decoded = searchOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "["foo"]" supplied to "(string | undefined)"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts deleted file mode 100644 index 85e360b842672..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const search = t.string; -export type Search = t.TypeOf; - -export const searchOrUndefined = t.union([search, t.undefined]); -export type SearchOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.test.ts deleted file mode 100644 index d06198272792a..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exactCheck } from '@kbn/securitysolution-io-ts-utils'; -import { searchAfterOrUndefined } from '.'; - -import * as t from 'io-ts'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; - -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('searchAfter', () => { - test('it will validate a correct search_after', () => { - const payload = ['test-1', 'test-2']; - const decoded = searchAfterOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will validate with the value of "undefined"', () => { - const obj = t.exact( - t.type({ - search_after: searchAfterOrUndefined, - }) - ); - const payload: t.TypeOf = { - search_after: undefined, - }; - const decoded = obj.decode({ - pit_id: undefined, - }); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will fail to validate an incorrect search_after', () => { - const payload = 'foo'; - const decoded = searchAfterOrUndefined.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "foo" supplied to "(Array | undefined)"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.ts deleted file mode 100644 index 5cef26cbb0c47..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const search_after = t.array(t.string); -export type SearchAfter = t.TypeOf; - -export const searchAfterOrUndefined = t.union([search_after, t.undefined]); -export type SearchAfterOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/serializer/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/serializer/index.ts deleted file mode 100644 index 7eb585c068e2d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/serializer/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const serializer = t.string; -export type Serializer = t.TypeOf; -export const serializerOrUndefined = t.union([serializer, t.undefined]); -export type SerializerOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_field/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_field/index.ts deleted file mode 100644 index e2c61659a94e4..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_field/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const sort_field = t.string; -export const sortFieldOrUndefined = t.union([sort_field, t.undefined]); -export type SortFieldOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_order/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_order/index.ts deleted file mode 100644 index fb075ff63fee4..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_order/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const sort_order = t.keyof({ asc: null, desc: null }); -export const sortOrderOrUndefined = t.union([sort_order, t.undefined]); -export type SortOrderOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/tags/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/tags/index.ts deleted file mode 100644 index ad99a1d0800fb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/tags/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { DefaultStringArray } from '@kbn/securitysolution-io-ts-types'; - -export const tags = DefaultStringArray; -export type Tags = t.TypeOf; -export const tagsOrUndefined = t.union([tags, t.undefined]); -export type TagsOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/tie_breaker_id/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/tie_breaker_id/index.ts deleted file mode 100644 index 0e393c7f154b8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/tie_breaker_id/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const tie_breaker_id = t.string; // TODO: Use UUID for this instead of a string for validation diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts deleted file mode 100644 index ba47dd545fbbb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { IsoDateString } from '@kbn/securitysolution-io-ts-types'; - -export const timestamp = IsoDateString; -export const timestampOrUndefined = t.union([IsoDateString, t.undefined]); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/total/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/total/index.ts deleted file mode 100644 index f3c84417cd419..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/total/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const total = t.number; // TODO: Change this out for PositiveNumber from siem -export const totalUndefined = t.union([total, t.undefined]); -export type TotalOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.test.ts deleted file mode 100644 index 60156cda9fe6d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { Type, type } from '.'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('type', () => { - test('it will work with a given expected type', () => { - const payload: Type = 'keyword'; - const decoded = type.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it will give an error if given a type that does not exist', () => { - const payload: Type | 'madeup' = 'madeup'; - const decoded = type.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "madeup" supplied to ""binary" | "boolean" | "byte" | "date" | "date_nanos" | "date_range" | "double" | "double_range" | "float" | "float_range" | "geo_point" | "geo_shape" | "half_float" | "integer" | "integer_range" | "ip" | "ip_range" | "keyword" | "long" | "long_range" | "shape" | "short" | "text""', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.ts deleted file mode 100644 index d617fd2cccdf3..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -/** - * Types of all the regular single value list items but not exception list - * or exception list types. Those types are in the list_types folder. - */ -export const type = t.keyof({ - binary: null, - boolean: null, - byte: null, - date: null, - date_nanos: null, - date_range: null, - double: null, - double_range: null, - float: null, - float_range: null, - geo_point: null, - geo_shape: null, - half_float: null, - integer: null, - integer_range: null, - ip: null, - ip_range: null, - keyword: null, - long: null, - long_range: null, - shape: null, - short: null, - text: null, -}); - -export const typeOrUndefined = t.union([type, t.undefined]); -export type Type = t.TypeOf; -export type TypeOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/underscore_version/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/underscore_version/index.ts deleted file mode 100644 index 2e4901990fb5f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/underscore_version/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const _version = t.string; -export const _versionOrUndefined = t.union([_version, t.undefined]); -export type _VersionOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.mock.ts deleted file mode 100644 index c84db08f8c93c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.mock.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { UpdateComment, UpdateCommentsArray } from '.'; -import { ID } from '../../constants/index.mock'; - -export const getUpdateCommentMock = (): UpdateComment => ({ - comment: 'some comment', - id: ID, -}); - -export const getUpdateCommentsArrayMock = (): UpdateCommentsArray => [ - getUpdateCommentMock(), - getUpdateCommentMock(), -]; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts deleted file mode 100644 index 88cdfbdd573e6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { getUpdateCommentMock, getUpdateCommentsArrayMock } from './index.mock'; -import { - UpdateComment, - updateComment, - UpdateCommentsArray, - updateCommentsArray, - UpdateCommentsArrayOrUndefined, - updateCommentsArrayOrUndefined, -} from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('UpdateComment', () => { - describe('updateComment', () => { - test('it should pass validation when supplied typical comment update', () => { - const payload = getUpdateCommentMock(); - const decoded = updateComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an undefined for "comment"', () => { - const payload = getUpdateCommentMock(); - // @ts-expect-error - delete payload.comment; - const decoded = updateComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "comment"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an empty string for "comment"', () => { - const payload = { ...getUpdateCommentMock(), comment: '' }; - const decoded = updateComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "comment"']); - expect(message.schema).toEqual({}); - }); - - test('it should pass validation when supplied an undefined for "id"', () => { - const payload = getUpdateCommentMock(); - delete payload.id; - const decoded = updateComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an empty string for "id"', () => { - const payload = { ...getUpdateCommentMock(), id: '' }; - const decoded = updateComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should strip out extra key passed in', () => { - const payload: UpdateComment & { - extraKey?: string; - } = { ...getUpdateCommentMock(), extraKey: 'some new value' }; - const decoded = updateComment.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getUpdateCommentMock()); - }); - }); - - describe('updateCommentsArray', () => { - test('it should pass validation when supplied an array of comments', () => { - const payload = getUpdateCommentsArrayMock(); - const decoded = updateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when undefined', () => { - const payload = undefined; - const decoded = updateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when array includes non comments types', () => { - const payload = [1] as unknown as UpdateCommentsArray; - const decoded = updateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('updateCommentsArrayOrUndefined', () => { - test('it should pass validation when supplied an array of comments', () => { - const payload = getUpdateCommentsArrayMock(); - const decoded = updateCommentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should pass validation when supplied when undefined', () => { - const payload = undefined; - const decoded = updateCommentsArrayOrUndefined.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when array includes non comments types', () => { - const payload = [1] as unknown as UpdateCommentsArrayOrUndefined; - const decoded = updateCommentsArray.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', - ]); - expect(message.schema).toEqual({}); - }); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts deleted file mode 100644 index 79a721c8dad54..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; -import { id } from '../id'; - -export const updateComment = t.intersection([ - t.exact( - t.type({ - comment: NonEmptyString, - }) - ), - t.exact( - t.partial({ - id, - }) - ), -]); - -export type UpdateComment = t.TypeOf; -export const updateCommentsArray = t.array(updateComment); -export type UpdateCommentsArray = t.TypeOf; -export const updateCommentsArrayOrUndefined = t.union([updateCommentsArray, t.undefined]); -export type UpdateCommentsArrayOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_at/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_at/index.ts deleted file mode 100644 index a6c0a803e6dbc..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_at/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const updated_at = t.string; // TODO: Make this into an ISO Date string check diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_by/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_by/index.ts deleted file mode 100644 index b99396254c914..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_by/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* eslint-disable @typescript-eslint/naming-convention */ - -import * as t from 'io-ts'; - -export const updated_by = t.string; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/value/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/value/index.ts deleted file mode 100644 index cad092aee4b79..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/value/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const value = t.string; -export const valueOrUndefined = t.union([value, t.undefined]); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/constants/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/constants/index.mock.ts deleted file mode 100644 index 4d09fc1efbeb3..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/constants/index.mock.ts +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EndpointEntriesArray } from '../common/endpoint/entries'; -import { EntriesArray, Entry } from '../common/entries'; -import { EntryMatch } from '../common/entry_match'; -import { EntryNested } from '../common/entry_nested'; -import { OsTypeArray } from '../common/os_type'; - -export const DATE_NOW = '2020-04-20T15:25:31.830Z'; -export const OLD_DATE_RELATIVE_TO_DATE_NOW = '2020-04-19T15:25:31.830Z'; -export const USER = 'some user'; -export const ELASTIC_USER = 'elastic'; -export const LIST_INDEX = '.lists'; -export const LIST_ITEM_INDEX = '.items'; -export const NAME = 'some name'; -export const DESCRIPTION = 'some description'; -export const LIST_ID = 'some-list-id'; -export const LIST_ITEM_ID = 'some-list-item-id'; -export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; -export const TIE_BREAKERS = [ - '21530991-4051-46ec-bc35-2afa09a1b0b5', - '3c662054-ae37-4aa9-9936-3e8e2ea26775', - '60e49a20-3a23-48b6-8bf9-ed5e3b70f7a0', - '38814080-a40f-4358-992a-3b875f9b7dec', - '29fa61be-aaaf-411c-a78a-7059e3f723f1', - '9c19c959-cb9d-4cd2-99e4-1ea2baf0ef0e', - 'd409308c-f94b-4b3a-8234-bbd7a80c9140', - '87824c99-cd83-45c4-8aa6-4ad95dfea62c', - '7b940c17-9355-479f-b882-f3e575718f79', - '5983ad0c-4ef4-4fa0-8308-80ab9ecc4f74', -]; -export const META = {}; -export const TYPE = 'ip'; -export const VALUE = '127.0.0.1'; -export const VALUE_2 = '255.255.255'; -export const NAMESPACE_TYPE = 'single'; -export const NESTED_FIELD = 'parent.field'; - -// Exception List specific -export const ID = 'uuid_here'; -export const ITEM_ID = 'some-list-item-id'; -export const DETECTION_TYPE = 'detection'; -export const ENDPOINT_TYPE = 'endpoint'; -export const FIELD = 'host.name'; -export const OPERATOR = 'included'; -export const OPERATOR_EXCLUDED = 'excluded'; -export const ENTRY_VALUE = 'some host name'; -export const MATCH = 'match'; -export const MATCH_ANY = 'match_any'; -export const WILDCARD = 'wildcard'; -export const MAX_IMPORT_PAYLOAD_BYTES = 9000000; -export const IMPORT_BUFFER_SIZE = 1000; -export const LIST = 'list'; -export const EXISTS = 'exists'; -export const NESTED = 'nested'; -export const ENTRIES: EntriesArray = [ - { - entries: [{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }], - field: 'some.parentField', - type: 'nested', - }, - { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, -]; -export const ENDPOINT_ENTRIES: EndpointEntriesArray = [ - { - entries: [{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }], - field: 'some.parentField', - type: 'nested', - }, - { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, -]; -// ENTRIES_WITH_IDS should only be used to mock out functionality of a collection of transforms -// that are UI specific and useful for UI concerns that are inserted between the -// API and the actual user interface. In some ways these might be viewed as -// technical debt or to compensate for the differences and preferences -// of how ReactJS might prefer data vs. how we want to model data. -export const ENTRIES_WITH_IDS: EntriesArray = [ - { - entries: [ - { - field: 'nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as EntryMatch & { id: string }, - ], - field: 'some.parentField', - id: '123', - type: 'nested', - } as EntryNested & { id: string }, - { - field: 'some.not.nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as Entry & { id: string }, -]; -export const ITEM_TYPE = 'simple'; -export const OS_TYPES: OsTypeArray = ['windows']; -export const TAGS = []; -export const COMMENTS = []; -export const FILTER = 'name:Nicolas Bourbaki'; -export const CURSOR = 'c29tZXN0cmluZ2ZvcnlvdQ=='; -export const _VERSION = 'WzI5NywxXQ=='; -export const VERSION = 1; -export const IMMUTABLE = false; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.mock.ts deleted file mode 100644 index db83807b0271d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.mock.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { CreateEndpointListItemSchema } from '.'; -import { - COMMENTS, - DESCRIPTION, - ENDPOINT_ENTRIES, - ITEM_TYPE, - META, - NAME, - OS_TYPES, - TAGS, -} from '../../constants/index.mock'; - -export const getCreateEndpointListItemSchemaMock = (): CreateEndpointListItemSchema => ({ - comments: COMMENTS, - description: DESCRIPTION, - entries: ENDPOINT_ENTRIES, - item_id: undefined, - meta: META, - name: NAME, - os_types: OS_TYPES, - tags: TAGS, - type: ITEM_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.test.ts deleted file mode 100644 index 9dc599a75ad5c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.test.ts +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { getCreateEndpointListItemSchemaMock } from './index.mock'; -import { CreateEndpointListItemSchema, createEndpointListItemSchema } from '.'; -import { getCreateCommentsArrayMock } from '../../common/create_comment/index.mock'; -import { getCommentsMock } from '../../common/comment/index.mock'; -import { CommentsArray } from '../../common/comment'; - -describe('create_endpoint_list_item_schema', () => { - test('it should pass validation when supplied a typical list item request not counting the auto generated uuid', () => { - const payload = getCreateEndpointListItemSchemaMock(); - const decoded = createEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateEndpointListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an undefined for "description"', () => { - const payload = getCreateEndpointListItemSchemaMock(); - // @ts-expect-error - delete payload.description; - const decoded = createEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an undefined for "name"', () => { - const payload = getCreateEndpointListItemSchemaMock(); - // @ts-expect-error - delete payload.name; - const decoded = createEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an undefined for "type"', () => { - const payload = getCreateEndpointListItemSchemaMock(); - // @ts-expect-error - delete payload.type; - const decoded = createEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied a "list_id" since it does not required one', () => { - const inputPayload: CreateEndpointListItemSchema & { list_id: string } = { - ...getCreateEndpointListItemSchemaMock(), - list_id: 'list-123', - }; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "list_id"']); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied a "namespace_type" since it does not required one', () => { - const inputPayload: CreateEndpointListItemSchema & { namespace_type: string } = { - ...getCreateEndpointListItemSchemaMock(), - namespace_type: 'single', - }; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "namespace_type"']); - expect(message.schema).toEqual({}); - }); - - test('it should pass validation when supplied an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => { - const payload = getCreateEndpointListItemSchemaMock(); - const outputPayload = getCreateEndpointListItemSchemaMock(); - delete payload.meta; - delete outputPayload.meta; - const decoded = createEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateEndpointListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should pass validation when supplied an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => { - const inputPayload = getCreateEndpointListItemSchemaMock(); - const outputPayload = getCreateEndpointListItemSchemaMock(); - delete inputPayload.comments; - outputPayload.comments = []; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateEndpointListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should pass validation when supplied "comments" array', () => { - const inputPayload = { - ...getCreateEndpointListItemSchemaMock(), - comments: getCreateCommentsArrayMock(), - }; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateEndpointListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(inputPayload); - }); - - test('it should fail validation when supplied "comments" with "created_at", "created_by", or "id" values', () => { - const inputPayload: Omit & { - comments?: CommentsArray; - } = { - ...getCreateEndpointListItemSchemaMock(), - comments: [getCommentsMock()], - }; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by,id"']); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an undefined for "entries"', () => { - const inputPayload = getCreateEndpointListItemSchemaMock(); - const outputPayload = getCreateEndpointListItemSchemaMock(); - // @ts-expect-error - delete inputPayload.entries; - outputPayload.entries = []; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateEndpointListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should pass validation when supplied an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => { - const inputPayload = getCreateEndpointListItemSchemaMock(); - const outputPayload = getCreateEndpointListItemSchemaMock(); - delete inputPayload.tags; - outputPayload.tags = []; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateEndpointListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should pass validation when supplied an undefined for "item_id" and auto generate a uuid', () => { - const inputPayload = getCreateEndpointListItemSchemaMock(); - delete inputPayload.item_id; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect((message.schema as CreateEndpointListItemSchema).item_id).toMatch( - /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i - ); - }); - - test('it should pass validation when supplied an undefined for "item_id" and generate a correct body not counting the uuid', () => { - const inputPayload = getCreateEndpointListItemSchemaMock(); - delete inputPayload.item_id; - const decoded = createEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateEndpointListItemSchema).item_id; - expect(message.schema).toEqual(inputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: CreateEndpointListItemSchema & { - extraKey: string; - } = { ...getCreateEndpointListItemSchemaMock(), extraKey: 'some new value' }; - const decoded = createEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.ts deleted file mode 100644 index f8e3965df733e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { DefaultUuid } from '@kbn/securitysolution-io-ts-types'; -import { nonEmptyEndpointEntriesArray } from '../../common/endpoint/entries'; -import { exceptionListItemType } from '../../common/exception_list_item_type'; -import { DefaultCreateCommentsArray } from '../../common/default_create_comments_array'; -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { CreateCommentsArray } from '../../common/create_comment'; -import { Tags } from '../../common/tags'; -import { ItemId } from '../../common/item_id'; -import { EntriesArray } from '../../common/entries'; -import { description } from '../../common/description'; -import { name } from '../../common/name'; -import { meta } from '../../common/meta'; -import { tags } from '../../common/tags'; - -export const createEndpointListItemSchema = t.intersection([ - t.exact( - t.type({ - description, - entries: nonEmptyEndpointEntriesArray, - name, - type: exceptionListItemType, - }) - ), - t.exact( - t.partial({ - comments: DefaultCreateCommentsArray, // defaults to empty array if not set during decode - item_id: DefaultUuid, // defaults to GUID (uuid v4) if not set during decode - meta, // defaults to undefined if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - }) - ), -]); - -export type CreateEndpointListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type CreateEndpointListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'tags' | 'item_id' | 'entries' | 'comments' | 'os_types' -> & { - comments: CreateCommentsArray; - tags: Tags; - item_id: ItemId; - entries: EntriesArray; - os_types: OsTypeArray; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.mock.ts deleted file mode 100644 index 23b3eb19171de..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.mock.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { CreateExceptionListItemSchema } from '.'; -import { - COMMENTS, - DESCRIPTION, - ENTRIES, - ITEM_ID, - ITEM_TYPE, - LIST_ID, - META, - NAME, - NAMESPACE_TYPE, - OS_TYPES, - TAGS, -} from '../../constants/index.mock'; - -export const getCreateExceptionListItemSchemaMock = (): CreateExceptionListItemSchema => ({ - comments: COMMENTS, - description: DESCRIPTION, - entries: ENTRIES, - item_id: undefined, - list_id: LIST_ID, - meta: META, - name: NAME, - namespace_type: NAMESPACE_TYPE, - os_types: OS_TYPES, - tags: TAGS, - type: ITEM_TYPE, -}); - -/** - * Useful for end to end testing - */ -export const getCreateExceptionListItemMinimalSchemaMock = (): CreateExceptionListItemSchema => ({ - description: DESCRIPTION, - entries: ENTRIES, - item_id: ITEM_ID, - list_id: LIST_ID, - name: NAME, - os_types: OS_TYPES, - type: ITEM_TYPE, -}); - -/** - * Useful for end to end testing - */ -export const getCreateExceptionListItemMinimalSchemaMockWithoutId = - (): CreateExceptionListItemSchema => ({ - description: DESCRIPTION, - entries: ENTRIES, - list_id: LIST_ID, - name: NAME, - os_types: OS_TYPES, - type: ITEM_TYPE, - }); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.test.ts deleted file mode 100644 index dc5dcb63cf1b7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.test.ts +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getCreateExceptionListItemSchemaMock } from './index.mock'; -import { CreateExceptionListItemSchema, createExceptionListItemSchema } from '.'; -import { getCreateCommentsArrayMock } from '../../common/create_comment/index.mock'; -import { getCommentsMock } from '../../common/comment/index.mock'; -import { CommentsArray } from '../../common/comment'; - -describe('create_exception_list_item_schema', () => { - test('it should pass validation when supplied a typical exception list item request not counting the auto generated uuid', () => { - const payload = getCreateExceptionListItemSchemaMock(); - const decoded = createExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should fail validation when supplied an undefined for "description"', () => { - const payload = getCreateExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.description; - const decoded = createExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an undefined for "name"', () => { - const payload = getCreateExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.name; - const decoded = createExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an undefined for "type"', () => { - const payload = getCreateExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.type; - const decoded = createExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an undefined for "list_id"', () => { - const inputPayload = getCreateExceptionListItemSchemaMock(); - // @ts-expect-error - delete inputPayload.list_id; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should pass validation when supplied an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => { - const payload = getCreateExceptionListItemSchemaMock(); - const outputPayload = getCreateExceptionListItemSchemaMock(); - delete payload.meta; - delete outputPayload.meta; - const decoded = createExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should pass validation when supplied an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => { - const inputPayload = getCreateExceptionListItemSchemaMock(); - const outputPayload = getCreateExceptionListItemSchemaMock(); - delete inputPayload.comments; - outputPayload.comments = []; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should pass validation when supplied "comments" array', () => { - const inputPayload = { - ...getCreateExceptionListItemSchemaMock(), - comments: getCreateCommentsArrayMock(), - }; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(inputPayload); - }); - - test('it should fail validation when supplied "comments" with "created_at" or "created_by" values', () => { - const inputPayload: Omit & { - comments?: CommentsArray; - } = { - ...getCreateExceptionListItemSchemaMock(), - comments: [getCommentsMock()], - }; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by,id"']); - expect(message.schema).toEqual({}); - }); - - test('it should fail validation when supplied an undefined for "entries"', () => { - const inputPayload = getCreateExceptionListItemSchemaMock(); - const outputPayload = getCreateExceptionListItemSchemaMock(); - // @ts-expect-error - delete inputPayload.entries; - outputPayload.entries = []; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should pass validation when supplied an undefined for "namespace_type" but return enum "single" and generate a correct body not counting the auto generated uuid', () => { - const inputPayload = getCreateExceptionListItemSchemaMock(); - const outputPayload = getCreateExceptionListItemSchemaMock(); - delete inputPayload.namespace_type; - outputPayload.namespace_type = 'single'; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should pass validation when supplied an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => { - const inputPayload = getCreateExceptionListItemSchemaMock(); - const outputPayload = getCreateExceptionListItemSchemaMock(); - delete inputPayload.tags; - outputPayload.tags = []; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should pass validation when supplied an undefined for "item_id" and auto generate a uuid', () => { - const inputPayload = getCreateExceptionListItemSchemaMock(); - delete inputPayload.item_id; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect((message.schema as CreateExceptionListItemSchema).item_id).toMatch( - /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i - ); - }); - - test('it should pass validation when supplied an undefined for "item_id" and generate a correct body not counting the uuid', () => { - const inputPayload = getCreateExceptionListItemSchemaMock(); - delete inputPayload.item_id; - const decoded = createExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListItemSchema).item_id; - expect(message.schema).toEqual(inputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: CreateExceptionListItemSchema & { - extraKey?: string; - } = getCreateExceptionListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = createExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.ts deleted file mode 100644 index 8445b2d03d677..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { DefaultUuid } from '@kbn/securitysolution-io-ts-types'; - -import { DefaultCreateCommentsArray } from '../../common/default_create_comments_array'; -import { CreateCommentsArray } from '../../common/create_comment'; -import { Tags } from '../../common/tags'; -import { ItemId } from '../../common/item_id'; -import { EntriesArray } from '../../common/entries'; -import { NamespaceType } from '../../common/default_namespace'; -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { description } from '../../common/description'; -import { list_id } from '../../common/list_id'; -import { name } from '../../common/name'; -import { exceptionListItemType } from '../../common/exception_list_item_type'; -import { meta } from '../../common/meta'; -import { namespace_type } from '../../common/namespace_type'; -import { tags } from '../../common/tags'; -import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; -import { ExpireTimeOrUndefined, expireTimeOrUndefined } from '../../common'; - -export const createExceptionListItemSchema = t.intersection([ - t.exact( - t.type({ - description, - entries: nonEmptyEntriesArray, - list_id, - name, - type: exceptionListItemType, - }) - ), - t.exact( - t.partial({ - comments: DefaultCreateCommentsArray, // defaults to empty array if not set during decode - expire_time: expireTimeOrUndefined, - item_id: DefaultUuid, // defaults to GUID (uuid v4) if not set during decode - meta, // defaults to undefined if not set during decode - namespace_type, // defaults to 'single' if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - }) - ), -]); - -export type CreateExceptionListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type CreateExceptionListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments' | 'expire_time' -> & { - comments: CreateCommentsArray; - expire_time: ExpireTimeOrUndefined; - tags: Tags; - item_id: ItemId; - entries: EntriesArray; - namespace_type: NamespaceType; - os_types: OsTypeArray; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.mock.ts deleted file mode 100644 index 798d36783d7ca..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - DESCRIPTION, - ENDPOINT_TYPE, - LIST_ID, - META, - NAME, - NAMESPACE_TYPE, - VERSION, -} from '../../constants/index.mock'; - -import { CreateExceptionListSchema } from '.'; - -export const getCreateExceptionListSchemaMock = (): CreateExceptionListSchema => ({ - description: DESCRIPTION, - list_id: undefined, - meta: META, - name: NAME, - namespace_type: NAMESPACE_TYPE, - os_types: [], - tags: [], - type: ENDPOINT_TYPE, - version: VERSION, -}); - -/** - * Useful for end to end testing - */ -export const getCreateExceptionListMinimalSchemaMock = (): CreateExceptionListSchema => ({ - description: DESCRIPTION, - list_id: LIST_ID, - name: NAME, - type: ENDPOINT_TYPE, -}); - -/** - * Useful for end to end testing - */ -export const getCreateExceptionListMinimalSchemaMockWithoutId = (): CreateExceptionListSchema => ({ - description: DESCRIPTION, - name: NAME, - type: ENDPOINT_TYPE, -}); - -/** - * Useful for end to end testing with detections - */ -export const getCreateExceptionListDetectionSchemaMock = (): CreateExceptionListSchema => ({ - description: DESCRIPTION, - list_id: LIST_ID, - name: NAME, - type: 'detection', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.test.ts deleted file mode 100644 index f6d164f8786bb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { CreateExceptionListSchema, createExceptionListSchema } from '.'; -import { getCreateExceptionListSchemaMock } from './index.mock'; - -describe('create_exception_list_schema', () => { - test('it should validate a typical exception lists request and generate a correct body not counting the uuid', () => { - const payload = getCreateExceptionListSchemaMock(); - const decoded = createExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListSchema).list_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "meta" and generate a correct body not counting the uuid', () => { - const payload = getCreateExceptionListSchemaMock(); - delete payload.meta; - const decoded = createExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListSchema).list_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "tags" but return an array and generate a correct body not counting the uuid', () => { - const inputPayload = getCreateExceptionListSchemaMock(); - const outputPayload = getCreateExceptionListSchemaMock(); - delete inputPayload.tags; - outputPayload.tags = []; - const decoded = createExceptionListSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListSchema).list_id; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "list_id" and auto generate a uuid', () => { - const inputPayload = getCreateExceptionListSchemaMock(); - delete inputPayload.list_id; - const decoded = createExceptionListSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect((message.schema as CreateExceptionListSchema).list_id).toMatch( - /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i - ); - }); - - test('it should accept an undefined for "list_id" and generate a correct body not counting the uuid', () => { - const inputPayload = getCreateExceptionListSchemaMock(); - delete inputPayload.list_id; - const decoded = createExceptionListSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as CreateExceptionListSchema).list_id; - expect(message.schema).toEqual(inputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: CreateExceptionListSchema & { - extraKey?: string; - } = getCreateExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = createExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.ts deleted file mode 100644 index 786e39a618641..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { - DefaultUuid, - DefaultVersionNumber, - DefaultVersionNumberDecoded, -} from '@kbn/securitysolution-io-ts-types'; - -import { exceptionListType } from '../../common/exception_list'; -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { Tags } from '../../common/tags'; -import { ListId } from '../../common/list_id'; -import { NamespaceType } from '../../common/default_namespace'; -import { name } from '../../common/name'; -import { description } from '../../common/description'; -import { namespace_type } from '../../common/namespace_type'; -import { tags } from '../../common/tags'; -import { meta } from '../../common/meta'; - -export const createExceptionListSchema = t.intersection([ - t.exact( - t.type({ - description, - name, - type: exceptionListType, - }) - ), - t.exact( - t.partial({ - list_id: DefaultUuid, // defaults to a GUID (UUID v4) string if not set during decode - meta, // defaults to undefined if not set during decode - namespace_type, // defaults to 'single' if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - version: DefaultVersionNumber, // defaults to numerical 1 if not set during decode - }) - ), -]); - -export type CreateExceptionListSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type CreateExceptionListSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'tags' | 'list_id' | 'namespace_type' | 'os_types' -> & { - tags: Tags; - list_id: ListId; - namespace_type: NamespaceType; - os_types: OsTypeArray; - version: DefaultVersionNumberDecoded; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.mock.ts deleted file mode 100644 index ed9a77fb859ae..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.mock.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ID, LIST_ITEM_ID, META, VALUE } from '../../constants/index.mock'; - -import { CreateListItemSchema } from '.'; - -export const getCreateListItemSchemaMock = (): CreateListItemSchema => ({ - id: LIST_ITEM_ID, - list_id: LIST_ID, - meta: META, - value: VALUE, -}); - -/** - * Useful for end to end testing - */ -export const getCreateMinimalListItemSchemaMock = (): CreateListItemSchema => ({ - id: LIST_ITEM_ID, - list_id: LIST_ID, - value: VALUE, -}); - -/** - * Useful for end to end testing - */ -export const getCreateMinimalListItemSchemaMockWithoutId = (): CreateListItemSchema => ({ - list_id: LIST_ID, - value: VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.test.ts deleted file mode 100644 index 3e991933b664c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getCreateListItemSchemaMock } from './index.mock'; -import { CreateListItemSchema, createListItemSchema } from '.'; - -describe('create_list_item_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getCreateListItemSchemaMock(); - const decoded = createListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for an id', () => { - const payload = getCreateListItemSchemaMock(); - delete payload.id; - const decoded = createListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for meta', () => { - const payload = getCreateListItemSchemaMock(); - delete payload.meta; - const decoded = createListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: CreateListItemSchema & { extraKey?: string } = getCreateListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = createListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.ts deleted file mode 100644 index f1b3c65865357..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { list_id } from '../../common/list_id'; -import { value } from '../../common/value'; -import { id } from '../../common/id'; -import { meta } from '../../common/meta'; -import { refreshWithWaitFor } from '../../common/refresh'; - -export const createListItemSchema = t.intersection([ - t.exact( - t.type({ - list_id, - value, - }) - ), - t.exact(t.partial({ id, meta, refresh: refreshWithWaitFor })), -]); - -export type CreateListItemSchema = t.OutputOf; -export type CreateListItemSchemaDecoded = RequiredKeepUndefined< - t.TypeOf ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.mock.ts deleted file mode 100644 index bbdd927a58e74..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.mock.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DESCRIPTION, LIST_ID, META, NAME, TYPE, VERSION } from '../../constants/index.mock'; - -import { CreateListSchema } from '.'; - -export const getCreateListSchemaMock = (): CreateListSchema => ({ - description: DESCRIPTION, - deserializer: undefined, - id: LIST_ID, - meta: META, - name: NAME, - serializer: undefined, - type: TYPE, - version: VERSION, -}); - -/** - * Useful for end to end tests and other mechanisms which want to fill in the values - */ -export const getCreateMinimalListSchemaMock = (): CreateListSchema => ({ - description: DESCRIPTION, - id: LIST_ID, - name: NAME, - type: TYPE, -}); - -/** - * Useful for end to end tests and other mechanisms which want to fill in the values - */ -export const getCreateMinimalListSchemaMockWithoutId = (): CreateListSchema => ({ - description: DESCRIPTION, - name: NAME, - type: TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.test.ts deleted file mode 100644 index 0eb9ecd02505f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { CreateListSchema, createListSchema } from '.'; -import { getCreateListSchemaMock } from './index.mock'; - -describe('create_list_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getCreateListSchemaMock(); - const decoded = createListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for an id', () => { - const payload = getCreateListSchemaMock(); - delete payload.id; - const decoded = createListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for meta', () => { - const payload = getCreateListSchemaMock(); - delete payload.meta; - const decoded = createListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for serializer', () => { - const payload = getCreateListSchemaMock(); - delete payload.serializer; - const decoded = createListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for deserializer', () => { - const payload = getCreateListSchemaMock(); - delete payload.deserializer; - const decoded = createListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: CreateListSchema & { extraKey?: string } = getCreateListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = createListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.ts deleted file mode 100644 index c6e210a999ea7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { - DefaultVersionNumber, - DefaultVersionNumberDecoded, -} from '@kbn/securitysolution-io-ts-types'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { name } from '../../common/name'; -import { description } from '../../common/description'; -import { type } from '../../common/type'; -import { deserializer } from '../../common/deserializer'; -import { id } from '../../common/id'; -import { meta } from '../../common/meta'; -import { serializer } from '../../common/serializer'; - -export const createListSchema = t.intersection([ - t.exact( - t.type({ - description, - name, - type, - }) - ), - t.exact( - t.partial({ - deserializer, // defaults to undefined if not set during decode - id, // defaults to undefined if not set during decode - meta, // defaults to undefined if not set during decode - serializer, // defaults to undefined if not set during decode - version: DefaultVersionNumber, // defaults to a numerical 1 if not set during decode - }) - ), -]); - -export type CreateListSchema = t.OutputOf; -export type CreateListSchemaDecoded = RequiredKeepUndefined< - Omit, 'version'> -> & { version: DefaultVersionNumberDecoded }; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.test.ts deleted file mode 100644 index 1eda590adb5de..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { CreateRuleExceptionListItemSchema, createRuleExceptionListItemSchema } from '.'; -import { CreateExceptionListItemSchema } from '../create_exception_list_item_schema'; - -const getCreateExceptionListItemSchemaMock = (): CreateExceptionListItemSchema => ({ - comments: [], - description: 'some description', - entries: [ - { - field: 'host.name', - operator: 'included', - type: 'match_any', - value: ['foo', 'bar'], - }, - ], - item_id: undefined, - list_id: 'some-list-id', - name: 'some name', - namespace_type: 'single', - os_types: [], - tags: [], - type: 'simple', -}); - -describe('createRuleExceptionListItemSchema', () => { - test('empty objects do not validate', () => { - const payload = {} as CreateRuleExceptionListItemSchema; - - const decoded = createRuleExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - 'Invalid value "undefined" supplied to "entries"', - 'Invalid value "undefined" supplied to "name"', - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('items without list_id validate', () => { - const payload: CreateRuleExceptionListItemSchema = { - description: 'Exception item for rule default exception list', - entries: [ - { - field: 'some.not.nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - name: 'Sample exception item', - type: 'simple', - }; - - const decoded = createRuleExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual( - expect.objectContaining({ - comments: [], - description: 'Exception item for rule default exception list', - entries: [ - { - field: 'some.not.nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - name: 'Sample exception item', - os_types: [], - tags: [], - type: 'simple', - }) - ); - }); - - test('items with list_id do not validate', () => { - const payload = - getCreateExceptionListItemSchemaMock() as unknown as CreateRuleExceptionListItemSchema; - - const decoded = createRuleExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some-list-id" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('made up parameters do not validate', () => { - const payload: Partial & { madeUp: string } = { - description: 'Exception item for rule default exception list', - entries: [ - { - field: 'some.not.nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - name: 'Sample exception item', - type: 'simple', - madeUp: 'invalid value', - }; - - const decoded = createRuleExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "madeUp"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.ts deleted file mode 100644 index 1e4a254f92b81..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { DefaultUuid } from '@kbn/securitysolution-io-ts-types'; - -import { - CreateCommentsArray, - DefaultCreateCommentsArray, - description, - EntriesArray, - exceptionListItemType, - ItemId, - meta, - NamespaceType, - namespaceType, - nonEmptyEntriesArray, - OsTypeArray, - osTypeArrayOrUndefined, - Tags, - tags, - name, - ExpireTimeOrUndefined, - expireTimeOrUndefined, -} from '../../common'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; - -export const createRuleExceptionListItemSchema = t.intersection([ - t.exact( - t.type({ - description, - entries: nonEmptyEntriesArray, - name, - type: exceptionListItemType, - }) - ), - t.exact( - t.partial({ - comments: DefaultCreateCommentsArray, // defaults to empty array if not set during decode - item_id: DefaultUuid, // defaults to GUID (uuid v4) if not set during decode - list_id: t.undefined, - meta, // defaults to undefined if not set during decode - namespace_type: namespaceType, // defaults to 'single' if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - expire_time: expireTimeOrUndefined, - }) - ), -]); - -export type CreateRuleExceptionListItemSchema = t.OutputOf< - typeof createRuleExceptionListItemSchema ->; - -// This type is used after a decode since some things are defaults after a decode. -export type CreateRuleExceptionListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments' | 'expire_time' -> & { - comments: CreateCommentsArray; - tags: Tags; - item_id: ItemId; - entries: EntriesArray; - namespace_type: NamespaceType; - os_types: OsTypeArray; - expire_time: ExpireTimeOrUndefined; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.mock.ts deleted file mode 100644 index 2f7963171197f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.mock.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID } from '../../constants/index.mock'; - -import { DeleteEndpointListItemSchema } from '.'; - -export const getDeleteEndpointListItemSchemaMock = (): DeleteEndpointListItemSchema => ({ - id: ID, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.test.ts deleted file mode 100644 index d702632713a59..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { DeleteEndpointListItemSchema, deleteEndpointListItemSchema } from '.'; -import { getDeleteEndpointListItemSchemaMock } from './index.mock'; - -describe('delete_endpoint_list_item_schema', () => { - test('it should validate a typical endpoint list item request', () => { - const payload = getDeleteEndpointListItemSchemaMock(); - const decoded = deleteEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept a value for "namespace_type" since it does not require one', () => { - const payload: DeleteEndpointListItemSchema & { - namespace_type: string; - } = { ...getDeleteEndpointListItemSchemaMock(), namespace_type: 'single' }; - // @ts-expect-error - delete payload.namespace_type; - const decoded = deleteEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getDeleteEndpointListItemSchemaMock()); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: DeleteEndpointListItemSchema & { - extraKey?: string; - } = { ...getDeleteEndpointListItemSchemaMock(), extraKey: 'some new value' }; - const decoded = deleteEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.ts deleted file mode 100644 index f968b1410a25d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { id } from '../../common/id'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { item_id } from '../../common/item_id'; - -export const deleteEndpointListItemSchema = t.exact( - t.partial({ - id, - item_id, - }) -); - -export type DeleteEndpointListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type DeleteEndpointListItemSchemaDecoded = RequiredKeepUndefined< - t.TypeOf ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.mock.ts deleted file mode 100644 index 723b5acb6620c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.mock.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { DeleteExceptionListItemSchema } from '.'; - -export const getDeleteExceptionListItemSchemaMock = (): DeleteExceptionListItemSchema => ({ - id: ID, - namespace_type: NAMESPACE_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.test.ts deleted file mode 100644 index 375fc20ba4da4..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { DeleteExceptionListItemSchema, deleteExceptionListItemSchema } from '.'; -import { getDeleteExceptionListItemSchemaMock } from './index.mock'; - -describe('delete_exception_list_item_schema', () => { - test('it should validate a typical exception list item request', () => { - const payload = getDeleteExceptionListItemSchemaMock(); - const decoded = deleteExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "namespace_type" but default to "single"', () => { - const payload = getDeleteExceptionListItemSchemaMock(); - delete payload.namespace_type; - const decoded = deleteExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getDeleteExceptionListItemSchemaMock()); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: DeleteExceptionListItemSchema & { - extraKey?: string; - } = getDeleteExceptionListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = deleteExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.ts deleted file mode 100644 index 4d961aa9e1a5b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NamespaceType } from '../../common/default_namespace'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { item_id } from '../../common/item_id'; -import { namespace_type } from '../../common/namespace_type'; - -export const deleteExceptionListItemSchema = t.exact( - t.partial({ - id, - item_id, - namespace_type, // defaults to 'single' if not set during decode - }) -); - -export type DeleteExceptionListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type DeleteExceptionListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'namespace_type' -> & { - namespace_type: NamespaceType; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.mock.ts deleted file mode 100644 index f41f5b288004b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { DeleteExceptionListSchema } from '.'; - -export const getDeleteExceptionListSchemaMock = (): DeleteExceptionListSchema => ({ - id: ID, - namespace_type: NAMESPACE_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.test.ts deleted file mode 100644 index 5507f855d783a..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { DeleteExceptionListSchema, deleteExceptionListSchema } from '.'; -import { getDeleteExceptionListSchemaMock } from './index.mock'; - -describe('delete_exception_list_schema', () => { - test('it should validate a typical exception list request', () => { - const payload = getDeleteExceptionListSchemaMock(); - const decoded = deleteExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "namespace_type" but default to "single"', () => { - const payload = getDeleteExceptionListSchemaMock(); - delete payload.namespace_type; - const decoded = deleteExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getDeleteExceptionListSchemaMock()); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: DeleteExceptionListSchema & { - extraKey?: string; - } = getDeleteExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = deleteExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.ts deleted file mode 100644 index 62855c9dc212d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NamespaceType } from '../../common/default_namespace'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { list_id } from '../../common/list_id'; -import { namespace_type } from '../../common/namespace_type'; - -export const deleteExceptionListSchema = t.exact( - t.partial({ - id, - list_id, - namespace_type, // defaults to 'single' if not set during decode - }) -); - -export type DeleteExceptionListSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type DeleteExceptionListSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'namespace_type' -> & { - namespace_type: NamespaceType; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.mock.ts deleted file mode 100644 index aaa03621d676f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, LIST_ID, VALUE } from '../../constants/index.mock'; - -import { DeleteListItemSchema } from '.'; - -export const getDeleteListItemSchemaMock = (): DeleteListItemSchema => ({ - id: ID, - list_id: LIST_ID, - value: VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.test.ts deleted file mode 100644 index d838fbab4f162..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { DeleteListItemSchema, deleteListItemSchema } from '.'; -import { getDeleteListItemSchemaMock } from './index.mock'; - -describe('delete_list_item_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getDeleteListItemSchemaMock(); - const decoded = deleteListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: DeleteListItemSchema & { - extraKey?: string; - } = { ...getDeleteListItemSchemaMock(), extraKey: 'some new value' }; - const decoded = deleteListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.ts deleted file mode 100644 index bbf0a09a15c81..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { list_id } from '../../common/list_id'; -import { valueOrUndefined } from '../../common/value'; -import { refresh } from '../../common/refresh'; - -export const deleteListItemSchema = t.intersection([ - t.exact( - t.type({ - value: valueOrUndefined, - }) - ), - t.exact(t.partial({ id, list_id, refresh })), -]); - -export type DeleteListItemSchema = t.OutputOf; -export type DeleteListItemSchemaDecoded = RequiredKeepUndefined< - t.TypeOf ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.mock.ts deleted file mode 100644 index 4514b70ad39fe..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ID } from '../../constants/index.mock'; - -import { DeleteListSchema } from '.'; - -export const getDeleteListSchemaMock = (): DeleteListSchema => ({ - deleteReferences: false, - id: LIST_ID, - ignoreReferences: true, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.test.ts deleted file mode 100644 index 5de3ec2c21097..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { DeleteListSchema, deleteListSchema } from '.'; -import { getDeleteListSchemaMock } from './index.mock'; - -describe('delete_list_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getDeleteListSchemaMock(); - const decoded = deleteListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for an id', () => { - const payload = getDeleteListSchemaMock(); - // @ts-expect-error - delete payload.id; - const decoded = deleteListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: DeleteListSchema & { extraKey?: string } = getDeleteListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = deleteListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.ts deleted file mode 100644 index 239a4d72113d7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { DefaultStringBooleanFalse } from '@kbn/securitysolution-io-ts-types'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; - -export const deleteListSchema = t.intersection([ - t.exact( - t.type({ - id, - }) - ), - t.exact( - t.partial({ - deleteReferences: DefaultStringBooleanFalse, - ignoreReferences: DefaultStringBooleanFalse, - }) - ), -]); - -export type DeleteListSchema = RequiredKeepUndefined>; -export type DeleteListSchemaEncoded = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.mock.ts deleted file mode 100644 index 121ab5f0b914e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { DuplicateExceptionListQuerySchema } from '.'; - -export const getDuplicateExceptionListQuerySchemaMock = (): DuplicateExceptionListQuerySchema => ({ - list_id: LIST_ID, - namespace_type: NAMESPACE_TYPE, - include_expired_exceptions: 'true', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.test.ts deleted file mode 100644 index 244adc07a81d8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { DuplicateExceptionListQuerySchema, duplicateExceptionListQuerySchema } from '.'; -import { getDuplicateExceptionListQuerySchemaMock } from './index.mock'; - -describe('duplicate_exceptionList_query_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getDuplicateExceptionListQuerySchemaMock(); - const decoded = duplicateExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should default namespace_type to "single" if an undefined given for namespacetype', () => { - const payload = getDuplicateExceptionListQuerySchemaMock(); - delete payload.namespace_type; - const decoded = duplicateExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(message.schema).toEqual({ - include_expired_exceptions: 'true', - list_id: 'some-list-id', - namespace_type: 'single', - }); - }); - - test('it should NOT accept an undefined for an list_id', () => { - const payload = getDuplicateExceptionListQuerySchemaMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = duplicateExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: DuplicateExceptionListQuerySchema & { - extraKey?: string; - } = getDuplicateExceptionListQuerySchemaMock(); - payload.extraKey = 'some new value'; - const decoded = duplicateExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.ts deleted file mode 100644 index b329e1244eb90..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { NamespaceType } from '../../common'; - -import { includeExpiredExceptionsOrUndefined } from '../../common/include_expired_exceptions'; -import { list_id } from '../../common/list_id'; -import { namespace_type } from '../../common/namespace_type'; - -export const duplicateExceptionListQuerySchema = t.exact( - t.type({ - list_id, - namespace_type, - include_expired_exceptions: includeExpiredExceptionsOrUndefined, - }) -); - -export type DuplicateExceptionListQuerySchema = t.OutputOf< - typeof duplicateExceptionListQuerySchema ->; - -// This type is used after a decode since some things are defaults after a decode. -export type DuplicateExceptionListQuerySchemaDecoded = Omit< - t.TypeOf, - 'namespace_type' -> & { - namespace_type: NamespaceType; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.mock.ts deleted file mode 100644 index 4f34a59407eae..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.mock.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { ExportExceptionListQuerySchema } from '.'; - -export const getExportExceptionListQuerySchemaMock = (): ExportExceptionListQuerySchema => ({ - id: ID, - list_id: LIST_ID, - namespace_type: NAMESPACE_TYPE, - include_expired_exceptions: 'true', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.test.ts deleted file mode 100644 index 00b41f6d70f99..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { ExportExceptionListQuerySchema, exportExceptionListQuerySchema } from '.'; -import { getExportExceptionListQuerySchemaMock } from './index.mock'; - -describe('export_exception_list_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getExportExceptionListQuerySchemaMock(); - const decoded = exportExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for an id', () => { - const payload = getExportExceptionListQuerySchemaMock(); - // @ts-expect-error - delete payload.id; - const decoded = exportExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should default namespace_type to "single" if an undefined given for namespacetype', () => { - const payload = getExportExceptionListQuerySchemaMock(); - delete payload.namespace_type; - const decoded = exportExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(message.schema).toEqual({ - id: 'uuid_here', - include_expired_exceptions: 'true', - list_id: 'some-list-id', - namespace_type: 'single', - }); - }); - - test('it should NOT accept an undefined for an list_id', () => { - const payload = getExportExceptionListQuerySchemaMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = exportExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ExportExceptionListQuerySchema & { - extraKey?: string; - } = getExportExceptionListQuerySchemaMock(); - payload.extraKey = 'some new value'; - const decoded = exportExceptionListQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.ts deleted file mode 100644 index 3943af148b159..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { id } from '../../common/id'; -import { includeExpiredExceptionsOrUndefined } from '../../common/include_expired_exceptions'; -import { list_id } from '../../common/list_id'; -import { namespace_type } from '../../common/namespace_type'; - -export const exportExceptionListQuerySchema = t.exact( - t.type({ - id, - list_id, - namespace_type, - include_expired_exceptions: includeExpiredExceptionsOrUndefined, - // TODO: Add file_name here with a default value - }) -); - -export type ExportExceptionListQuerySchema = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.mock.ts deleted file mode 100644 index 3c66cae1fb0ee..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.mock.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ID } from '../../constants/index.mock'; - -import { ExportListItemQuerySchema } from '.'; - -export const getExportListItemQuerySchemaMock = (): ExportListItemQuerySchema => ({ - list_id: LIST_ID, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.test.ts deleted file mode 100644 index 55713e33f1600..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { ExportListItemQuerySchema, exportListItemQuerySchema } from '.'; -import { getExportListItemQuerySchemaMock } from './index.mock'; - -describe('export_list_item_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getExportListItemQuerySchemaMock(); - const decoded = exportListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for an id', () => { - const payload = getExportListItemQuerySchemaMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = exportListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ExportListItemQuerySchema & { - extraKey?: string; - } = getExportListItemQuerySchemaMock(); - payload.extraKey = 'some new value'; - const decoded = exportListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.ts deleted file mode 100644 index 86c8318f1ad5c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { list_id } from '../../common/list_id'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; - -export const exportListItemQuerySchema = t.exact( - t.type({ - list_id, - // TODO: Add file_name here with a default value - }) -); - -export type ExportListItemQuerySchema = RequiredKeepUndefined< - t.TypeOf ->; -export type ExportListItemQuerySchemaEncoded = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.mock.ts deleted file mode 100644 index d24d31cca5d98..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.mock.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FILTER } from '../../constants/index.mock'; - -import { FindEndpointListItemSchema, FindEndpointListItemSchemaDecoded } from '.'; - -export const getFindEndpointListItemSchemaMock = (): FindEndpointListItemSchema => ({ - filter: FILTER, - page: '1', - per_page: '25', - sort_field: undefined, - sort_order: undefined, -}); - -export const getFindEndpointListItemSchemaDecodedMock = (): FindEndpointListItemSchemaDecoded => ({ - filter: FILTER, - page: 1, - per_page: 25, - sort_field: undefined, - sort_order: undefined, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.test.ts deleted file mode 100644 index 776cc2976868d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.test.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { - getFindEndpointListItemSchemaDecodedMock, - getFindEndpointListItemSchemaMock, -} from './index.mock'; -import { FindEndpointListItemSchema, findEndpointListItemSchema } from '.'; - -describe('find_endpoint_list_item_schema', () => { - test('it should validate a typical find item request', () => { - const payload = getFindEndpointListItemSchemaMock(); - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getFindEndpointListItemSchemaDecodedMock()); - }); - - test('it should validate and empty object since everything is optional and has defaults', () => { - const payload: FindEndpointListItemSchema = {}; - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate with page missing', () => { - const payload = getFindEndpointListItemSchemaMock(); - delete payload.page; - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindEndpointListItemSchemaDecodedMock(); - delete expected.page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with pre_page missing', () => { - const payload = getFindEndpointListItemSchemaMock(); - delete payload.per_page; - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindEndpointListItemSchemaDecodedMock(); - delete expected.per_page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with filter missing', () => { - const payload = getFindEndpointListItemSchemaMock(); - delete payload.filter; - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindEndpointListItemSchemaDecodedMock(); - delete expected.filter; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_field missing', () => { - const payload = getFindEndpointListItemSchemaMock(); - delete payload.sort_field; - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindEndpointListItemSchemaDecodedMock(); - delete expected.sort_field; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_order missing', () => { - const payload = getFindEndpointListItemSchemaMock(); - delete payload.sort_order; - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindEndpointListItemSchemaDecodedMock(); - delete expected.sort_order; - expect(message.schema).toEqual(expected); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: FindEndpointListItemSchema & { - extraKey: string; - } = { ...getFindEndpointListItemSchemaMock(), extraKey: 'some new value' }; - const decoded = findEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.ts deleted file mode 100644 index a76854d3b4bfc..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { filter } from '../../common/filter'; -import { sort_field } from '../../common/sort_field'; -import { sort_order } from '../../common/sort_order'; - -export const findEndpointListItemSchema = t.exact( - t.partial({ - filter, // defaults to undefined if not set during decode - page: StringToPositiveNumber, // defaults to undefined if not set during decode - per_page: StringToPositiveNumber, // defaults to undefined if not set during decode - sort_field, // defaults to undefined if not set during decode - sort_order, // defaults to undefined if not set during decode - }) -); - -export type FindEndpointListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type FindEndpointListItemSchemaDecoded = RequiredKeepUndefined< - t.TypeOf ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts deleted file mode 100644 index 02b89bdf4c730..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FILTER, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { FindExceptionListItemSchema, FindExceptionListItemSchemaDecoded } from '.'; - -export const getFindExceptionListItemSchemaMock = (): FindExceptionListItemSchema => ({ - filter: FILTER, - list_id: LIST_ID, - namespace_type: NAMESPACE_TYPE, - page: '1', - per_page: '25', - search: undefined, - sort_field: undefined, - sort_order: undefined, -}); - -export const getFindExceptionListItemSchemaMultipleMock = (): FindExceptionListItemSchema => ({ - filter: 'name:Sofia Kovalevskaya,name:Hypatia,name:Sophie Germain', - list_id: 'list-1,list-2,list-3', - namespace_type: 'single,single,agnostic', - page: '1', - per_page: '25', - search: undefined, - sort_field: undefined, - sort_order: undefined, -}); - -export const getFindExceptionListItemSchemaDecodedMock = - (): FindExceptionListItemSchemaDecoded => ({ - filter: [FILTER], - list_id: [LIST_ID], - namespace_type: [NAMESPACE_TYPE], - page: 1, - per_page: 25, - search: undefined, - sort_field: undefined, - sort_order: undefined, - }); - -export const getFindExceptionListItemSchemaDecodedMultipleMock = - (): FindExceptionListItemSchemaDecoded => ({ - filter: ['name:Sofia Kovalevskaya', 'name:Hypatia', 'name:Sophie Germain'], - list_id: ['list-1', 'list-2', 'list-3'], - namespace_type: ['single', 'single', 'agnostic'], - page: 1, - per_page: 25, - search: undefined, - sort_field: undefined, - sort_order: undefined, - }); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts deleted file mode 100644 index da9c98d48e62b..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { LIST_ID } from '../../constants/index.mock'; - -import { - getFindExceptionListItemSchemaDecodedMock, - getFindExceptionListItemSchemaDecodedMultipleMock, - getFindExceptionListItemSchemaMock, - getFindExceptionListItemSchemaMultipleMock, -} from './index.mock'; -import { - FindExceptionListItemSchema, - FindExceptionListItemSchemaDecoded, - findExceptionListItemSchema, -} from '.'; - -describe('find_list_item_schema', () => { - test('it should validate a typical find item request', () => { - const payload = getFindExceptionListItemSchemaMock(); - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getFindExceptionListItemSchemaDecodedMock()); - }); - - test('it should validate a typical find item request with multiple input strings turned into array elements', () => { - const payload = getFindExceptionListItemSchemaMultipleMock(); - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getFindExceptionListItemSchemaDecodedMultipleMock()); - }); - - test('it should validate just a list_id where it decodes into an array for list_id and adds a namespace_type of "single" as an array', () => { - const payload: FindExceptionListItemSchema = { list_id: LIST_ID }; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected: FindExceptionListItemSchemaDecoded = { - filter: [], - list_id: [LIST_ID], - namespace_type: ['single'], - page: undefined, - per_page: undefined, - search: undefined, - sort_field: undefined, - sort_order: undefined, - }; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with page missing', () => { - const payload = getFindExceptionListItemSchemaMock(); - delete payload.page; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListItemSchemaDecodedMock(); - delete expected.page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with per_page missing', () => { - const payload = getFindExceptionListItemSchemaMock(); - delete payload.per_page; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListItemSchemaDecodedMock(); - delete expected.per_page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with filter missing and add filter as an empty array', () => { - const payload = getFindExceptionListItemSchemaMock(); - delete payload.filter; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected: FindExceptionListItemSchemaDecoded = { - ...getFindExceptionListItemSchemaDecodedMock(), - filter: [], - }; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_field missing', () => { - const payload = getFindExceptionListItemSchemaMock(); - delete payload.sort_field; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListItemSchemaDecodedMock(); - delete expected.sort_field; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_order missing', () => { - const payload = getFindExceptionListItemSchemaMock(); - delete payload.sort_order; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListItemSchemaDecodedMock(); - delete expected.sort_order; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with search missing', () => { - const payload = getFindExceptionListItemSchemaMock(); - delete payload.search; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListItemSchemaDecodedMock(); - delete expected.search; - expect(message.schema).toEqual(expected); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: FindExceptionListItemSchema & { - extraKey: string; - } = { ...getFindExceptionListItemSchemaMock(), extraKey: 'some new value' }; - const decoded = findExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts deleted file mode 100644 index 88258538e0311..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { - EmptyStringArray, - EmptyStringArrayDecoded, - NonEmptyStringArray, - StringToPositiveNumber, -} from '@kbn/securitysolution-io-ts-types'; - -import { - DefaultNamespaceArray, - DefaultNamespaceArrayTypeDecoded, -} from '../../common/default_namespace_array'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { sort_field } from '../../common/sort_field'; -import { sort_order } from '../../common/sort_order'; -import { search } from '../../common/search'; - -export const findExceptionListItemSchema = t.intersection([ - t.exact( - t.type({ - list_id: NonEmptyStringArray, - }) - ), - t.exact( - t.partial({ - filter: EmptyStringArray, // defaults to an empty array [] if not set during decode - namespace_type: DefaultNamespaceArray, // defaults to ['single'] if not set during decode - page: StringToPositiveNumber, // defaults to undefined if not set during decode - per_page: StringToPositiveNumber, // defaults to undefined if not set during decode - search, - sort_field, // defaults to undefined if not set during decode - sort_order, // defaults to undefined if not set during decode - }) - ), -]); - -export type FindExceptionListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type FindExceptionListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'namespace_type' | 'filter' -> & { - filter: EmptyStringArrayDecoded; - namespace_type: DefaultNamespaceArrayTypeDecoded; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.mock.ts deleted file mode 100644 index 0b8c9e3db9bb1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FILTER, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { FindExceptionListSchema, FindExceptionListSchemaDecoded } from '.'; - -export const getFindExceptionListSchemaMock = (): FindExceptionListSchema => ({ - filter: FILTER, - namespace_type: NAMESPACE_TYPE, - page: '1', - per_page: '25', - sort_field: undefined, - sort_order: undefined, -}); - -export const getFindExceptionListSchemaDecodedMock = (): FindExceptionListSchemaDecoded => ({ - filter: FILTER, - namespace_type: [NAMESPACE_TYPE], - page: 1, - per_page: 25, - sort_field: undefined, - sort_order: undefined, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.test.ts deleted file mode 100644 index fd105d3d2f61e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { - getFindExceptionListSchemaDecodedMock, - getFindExceptionListSchemaMock, -} from './index.mock'; -import { - FindExceptionListSchema, - FindExceptionListSchemaDecoded, - findExceptionListSchema, -} from '.'; - -describe('find_exception_list_schema', () => { - test('it should validate a typical find item request', () => { - const payload = getFindExceptionListSchemaMock(); - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getFindExceptionListSchemaDecodedMock()); - }); - - test('it should validate and empty object since everything is optional and will respond only with namespace_type filled out to be "single"', () => { - const payload: FindExceptionListSchema = {}; - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected: FindExceptionListSchemaDecoded = { - filter: undefined, - namespace_type: ['single'], - page: undefined, - per_page: undefined, - sort_field: undefined, - sort_order: undefined, - }; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with page missing', () => { - const payload = getFindExceptionListSchemaMock(); - delete payload.page; - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListSchemaDecodedMock(); - delete expected.page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with pre_page missing', () => { - const payload = getFindExceptionListSchemaMock(); - delete payload.per_page; - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListSchemaDecodedMock(); - delete expected.per_page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with filter missing', () => { - const payload = getFindExceptionListSchemaMock(); - delete payload.filter; - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListSchemaDecodedMock(); - delete expected.filter; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_field missing', () => { - const payload = getFindExceptionListSchemaMock(); - delete payload.sort_field; - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListSchemaDecodedMock(); - delete expected.sort_field; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_order missing', () => { - const payload = getFindExceptionListSchemaMock(); - delete payload.sort_order; - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindExceptionListSchemaDecodedMock(); - delete expected.sort_order; - expect(message.schema).toEqual(expected); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: FindExceptionListSchema & { - extraKey: string; - } = { ...getFindExceptionListSchemaMock(), extraKey: 'some new value' }; - const decoded = findExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.ts deleted file mode 100644 index 1e22f752d0142..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; - -import { DefaultNamespaceArray, NamespaceTypeArray } from '../../common/default_namespace_array'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { filter } from '../../common/filter'; -import { sort_field } from '../../common/sort_field'; -import { sort_order } from '../../common/sort_order'; - -export const findExceptionListSchema = t.exact( - t.partial({ - filter, // defaults to undefined if not set during decode - namespace_type: DefaultNamespaceArray, // defaults to 'single' if not set during decode - page: StringToPositiveNumber, // defaults to undefined if not set during decode - per_page: StringToPositiveNumber, // defaults to undefined if not set during decode - sort_field, // defaults to undefined if not set during decode - sort_order, // defaults to undefined if not set during decode - }) -); - -export type FindExceptionListSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type FindExceptionListSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'namespace_type' -> & { - namespace_type: NamespaceTypeArray; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.mock.ts deleted file mode 100644 index 601406ce3e37e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.mock.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { CURSOR, FILTER, LIST_ID } from '../../constants/index.mock'; - -import { FindListItemSchema, FindListItemSchemaDecoded } from '.'; - -export const getFindListItemSchemaMock = (): FindListItemSchema => ({ - cursor: CURSOR, - filter: FILTER, - list_id: LIST_ID, - page: '1', - per_page: '25', - sort_field: undefined, - sort_order: undefined, -}); - -export const getFindListItemSchemaDecodedMock = (): FindListItemSchemaDecoded => ({ - cursor: CURSOR, - filter: FILTER, - list_id: LIST_ID, - page: 1, - per_page: 25, - sort_field: undefined, - sort_order: undefined, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.test.ts deleted file mode 100644 index b80629f8546b5..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { LIST_ID } from '../../constants/index.mock'; - -import { FindListItemSchema, FindListItemSchemaDecoded, findListItemSchema } from '.'; -import { getFindListItemSchemaDecodedMock, getFindListItemSchemaMock } from './index.mock'; - -describe('find_list_item_schema', () => { - test('it should validate a typical find item request', () => { - const payload = getFindListItemSchemaMock(); - const decoded = findListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getFindListItemSchemaDecodedMock()); - }); - - test('it should validate just a list_id where it decodes into an array for list_id and adds a namespace_type of "single"', () => { - const payload: FindListItemSchema = { list_id: LIST_ID }; - const decoded = findListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected: FindListItemSchemaDecoded = { - cursor: undefined, - filter: undefined, - list_id: LIST_ID, - page: undefined, - per_page: undefined, - sort_field: undefined, - sort_order: undefined, - }; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with page missing', () => { - const payload = getFindListItemSchemaMock(); - delete payload.page; - const decoded = findListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListItemSchemaDecodedMock(); - delete expected.page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with pre_page missing', () => { - const payload = getFindListItemSchemaMock(); - delete payload.per_page; - const decoded = findListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListItemSchemaDecodedMock(); - delete expected.per_page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_field missing', () => { - const payload = getFindListItemSchemaMock(); - delete payload.sort_field; - const decoded = findListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListItemSchemaDecodedMock(); - delete expected.sort_field; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_order missing', () => { - const payload = getFindListItemSchemaMock(); - delete payload.sort_order; - const decoded = findListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListItemSchemaDecodedMock(); - delete expected.sort_order; - expect(message.schema).toEqual(expected); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: FindListItemSchema & { - extraKey: string; - } = { ...getFindListItemSchemaMock(), extraKey: 'some new value' }; - const decoded = findListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.ts deleted file mode 100644 index 4509f6bc973bf..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; -import { filter } from '../../common/filter'; -import { cursor } from '../../common/cursor'; -import { sort_field } from '../../common/sort_field'; -import { sort_order } from '../../common/sort_order'; -import { list_id } from '../../common/list_id'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; - -export const findListItemSchema = t.intersection([ - t.exact(t.type({ list_id })), - t.exact( - t.partial({ - cursor, // defaults to undefined if not set during decode - filter, // defaults to undefined if not set during decode - page: StringToPositiveNumber, // defaults to undefined if not set during decode - per_page: StringToPositiveNumber, // defaults to undefined if not set during decode - sort_field, // defaults to undefined if not set during decode - sort_order, // defaults to undefined if not set during decode - }) - ), -]); - -export type FindListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type FindListItemSchemaDecoded = RequiredKeepUndefined>; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.mock.ts deleted file mode 100644 index 48c9671e4ac17..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.mock.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FILTER } from '../../constants/index.mock'; - -import { FindListSchema, FindListSchemaEncoded } from '.'; - -export const getFindListSchemaMock = (): FindListSchemaEncoded => ({ - filter: FILTER, - page: '1', - per_page: '25', - sort_field: undefined, - sort_order: undefined, -}); - -export const getFindListSchemaDecodedMock = (): FindListSchema => ({ - cursor: undefined, - filter: FILTER, - page: 1, - per_page: 25, - sort_field: undefined, - sort_order: undefined, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.test.ts deleted file mode 100644 index ba03ddcb85269..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getFindListSchemaDecodedMock, getFindListSchemaMock } from './index.mock'; -import { FindListSchemaEncoded, findListSchema } from '.'; - -describe('find_list_schema', () => { - test('it should validate a typical find item request', () => { - const payload = getFindListSchemaMock(); - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getFindListSchemaDecodedMock()); - }); - - test('it should validate and empty object since everything is optional and will respond with an empty object', () => { - const payload: FindListSchemaEncoded = {}; - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate with page missing', () => { - const payload = getFindListSchemaMock(); - delete payload.page; - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListSchemaDecodedMock(); - delete expected.page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with pre_page missing', () => { - const payload = getFindListSchemaMock(); - delete payload.per_page; - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListSchemaDecodedMock(); - delete expected.per_page; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with filter missing', () => { - const payload = getFindListSchemaMock(); - delete payload.filter; - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListSchemaDecodedMock(); - delete expected.filter; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_field missing', () => { - const payload = getFindListSchemaMock(); - delete payload.sort_field; - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListSchemaDecodedMock(); - delete expected.sort_field; - expect(message.schema).toEqual(expected); - }); - - test('it should validate with sort_order missing', () => { - const payload = getFindListSchemaMock(); - delete payload.sort_order; - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - const expected = getFindListSchemaDecodedMock(); - delete expected.sort_order; - expect(message.schema).toEqual(expected); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: FindListSchemaEncoded & { - extraKey: string; - } = { ...getFindListSchemaMock(), extraKey: 'some new value' }; - const decoded = findListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.ts deleted file mode 100644 index 8b33ffc6a9470..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; -import { cursor } from '../../common/cursor'; -import { filter } from '../../common/filter'; -import { sort_field } from '../../common/sort_field'; -import { sort_order } from '../../common/sort_order'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; - -export const findListSchema = t.exact( - t.partial({ - cursor, // defaults to undefined if not set during decode - filter, // defaults to undefined if not set during decode - page: StringToPositiveNumber, // defaults to undefined if not set during decode - per_page: StringToPositiveNumber, // defaults to undefined if not set during decode - sort_field, // defaults to undefined if not set during decode - sort_order, // defaults to undefined if not set during decode - }) -); - -export type FindListSchema = RequiredKeepUndefined>; -export type FindListSchemaEncoded = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/get_exception_filter_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/get_exception_filter_schema/index.ts deleted file mode 100644 index 58c93b697a850..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/get_exception_filter_schema/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { namespaceType } from '../../common/default_namespace'; -import { exceptionListItemSchema } from '../../response'; -import { createExceptionListItemSchema } from '../create_exception_list_item_schema'; - -const exceptionListId = t.type({ - exception_list_id: t.string, - namespace_type: namespaceType, -}); - -export const exceptionListIds = t.type({ - exception_list_ids: t.array(exceptionListId), - type: t.literal('exception_list_ids'), -}); - -export const exceptions = t.type({ - exceptions: t.array(t.union([exceptionListItemSchema, createExceptionListItemSchema])), - type: t.literal('exception_items'), -}); - -const optionalExceptionParams = t.exact( - t.partial({ alias: t.string, chunk_size: t.number, exclude_exceptions: t.boolean }) -); - -export const getExceptionFilterSchema = t.intersection([ - t.union([exceptions, exceptionListIds]), - optionalExceptionParams, -]); - -export type GetExceptionFilterSchema = t.TypeOf; -export type ExceptionListId = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.mock.ts deleted file mode 100644 index e66b805de4967..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.mock.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ENTRIES } from '../../constants/index.mock'; -import { ImportExceptionListItemSchema, ImportExceptionListItemSchemaDecoded } from '.'; - -export const getImportExceptionsListItemSchemaMock = ( - itemId = 'item_id_1', - listId = 'detection_list_id' -): ImportExceptionListItemSchema => ({ - description: 'some description', - entries: ENTRIES, - item_id: itemId, - list_id: listId, - name: 'Query with a rule id', - type: 'simple', -}); - -export const getImportExceptionsListItemSchemaDecodedMock = ( - itemId = 'item_id_1', - listId = 'detection_list_id' -): ImportExceptionListItemSchemaDecoded => ({ - ...getImportExceptionsListItemSchemaMock(itemId, listId), - comments: [], - meta: undefined, - namespace_type: 'single', - os_types: [], - tags: [], - expire_time: undefined, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts deleted file mode 100644 index 58b9bce4c4108..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { importExceptionListItemSchema, ImportExceptionListItemSchema } from '.'; -import { - getImportExceptionsListItemSchemaDecodedMock, - getImportExceptionsListItemSchemaMock, -} from './index.mock'; -import { getCommentsArrayMock } from '../../common/comment/index.mock'; - -describe('import_list_item_schema', () => { - test('it should validate a typical item request', () => { - const payload = getImportExceptionsListItemSchemaMock(); - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getImportExceptionsListItemSchemaDecodedMock()); - }); - - test('it should validate a typical item request with comments', () => { - const payload = { - ...getImportExceptionsListItemSchemaMock(), - comments: getCommentsArrayMock(), - }; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual({ - ...getImportExceptionsListItemSchemaDecodedMock(), - comments: [ - { - comment: 'some old comment', - created_at: '2020-04-20T15:25:31.830Z', - created_by: 'some user', - id: 'uuid_here', - }, - { - comment: 'some old comment', - created_at: '2020-04-20T15:25:31.830Z', - created_by: 'some user', - id: 'uuid_here', - }, - ], - }); - }); - - test('it should NOT accept an undefined for "item_id"', () => { - const payload: Partial> = - getImportExceptionsListItemSchemaMock(); - delete payload.item_id; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "item_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "list_id"', () => { - const payload: Partial> = - getImportExceptionsListItemSchemaMock(); - delete payload.list_id; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "description"', () => { - const payload: Partial> = - getImportExceptionsListItemSchemaMock(); - delete payload.description; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "name"', () => { - const payload: Partial> = - getImportExceptionsListItemSchemaMock(); - delete payload.name; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "type"', () => { - const payload: Partial> = - getImportExceptionsListItemSchemaMock(); - delete payload.type; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "entries"', () => { - const payload: Partial> = - getImportExceptionsListItemSchemaMock(); - delete payload.entries; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept any partial fields', () => { - const payload: ImportExceptionListItemSchema = { - ...getImportExceptionsListItemSchemaMock(), - id: '123', - namespace_type: 'single', - comments: [], - os_types: [], - tags: ['123'], - created_at: '2018-08-24T17:49:30.145142000', - created_by: 'elastic', - updated_at: '2018-08-24T17:49:30.145142000', - updated_by: 'elastic', - tie_breaker_id: '123', - _version: '3', - meta: undefined, - }; - - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ImportExceptionListItemSchema & { - extraKey?: string; - } = getImportExceptionsListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = importExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts deleted file mode 100644 index 9b0762005f3af..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { Tags } from '../../common/tags'; -import { NamespaceType } from '../../common/default_namespace'; -import { name } from '../../common/name'; -import { description } from '../../common/description'; -import { namespace_type } from '../../common/namespace_type'; -import { tags } from '../../common/tags'; -import { meta } from '../../common/meta'; -import { list_id } from '../../common/list_id'; -import { item_id } from '../../common/item_id'; -import { id } from '../../common/id'; -import { created_at } from '../../common/created_at'; -import { created_by } from '../../common/created_by'; -import { updated_at } from '../../common/updated_at'; -import { updated_by } from '../../common/updated_by'; -import { _version } from '../../common/underscore_version'; -import { tie_breaker_id } from '../../common/tie_breaker_id'; -import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; -import { exceptionListItemType } from '../../common/exception_list_item_type'; -import { ItemId } from '../../common/item_id'; -import { EntriesArray } from '../../common/entries'; -import { DefaultImportCommentsArray } from '../../common/default_import_comments_array'; -import { ExpireTimeOrUndefined, expireTimeOrUndefined, ImportCommentsArray } from '../../common'; - -/** - * Differences from this and the createExceptionsListItemSchema are - * - item_id is required - * - id is optional (but ignored in the import code - item_id is exclusively used for imports) - * - immutable is optional but if it is any value other than false it will be rejected - * - created_at is optional (but ignored in the import code) - * - updated_at is optional (but ignored in the import code) - * - created_by is optional (but ignored in the import code) - * - updated_by is optional (but ignored in the import code) - */ -export const importExceptionListItemSchema = t.intersection([ - t.exact( - t.type({ - description, - entries: nonEmptyEntriesArray, - item_id, - list_id, - name, - type: exceptionListItemType, - }) - ), - t.exact( - t.partial({ - id, // defaults to undefined if not set during decode - comments: DefaultImportCommentsArray, // defaults to empty array if not set during decode - created_at, // defaults undefined if not set during decode - updated_at, // defaults undefined if not set during decode - created_by, // defaults undefined if not set during decode - updated_by, // defaults undefined if not set during decode - _version, // defaults to undefined if not set during decode - tie_breaker_id, - meta, // defaults to undefined if not set during decode - namespace_type, // defaults to 'single' if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - expire_time: expireTimeOrUndefined, - }) - ), -]); - -export type ImportExceptionListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type ImportExceptionListItemSchemaDecoded = Omit< - ImportExceptionListItemSchema, - 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments' | 'expire_time' -> & { - comments: ImportCommentsArray; - tags: Tags; - item_id: ItemId; - entries: EntriesArray; - namespace_type: NamespaceType; - os_types: OsTypeArray; - expire_time: ExpireTimeOrUndefined; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.mock.ts deleted file mode 100644 index 5bf263beb3720..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ImportExceptionListSchemaDecoded, ImportExceptionsListSchema } from '.'; - -export const getImportExceptionsListSchemaMock = ( - listId = 'detection_list_id' -): ImportExceptionsListSchema => ({ - description: 'some description', - list_id: listId, - name: 'Query with a rule id', - type: 'detection', -}); - -export const getImportExceptionsListSchemaDecodedMock = ( - listId = 'detection_list_id' -): ImportExceptionListSchemaDecoded => ({ - ...getImportExceptionsListSchemaMock(listId), - immutable: false, - meta: undefined, - namespace_type: 'single', - os_types: [], - tags: [], - version: 1, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.test.ts deleted file mode 100644 index 677e089fe1efe..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { importExceptionsListSchema, ImportExceptionsListSchema } from '.'; -import { - getImportExceptionsListSchemaMock, - getImportExceptionsListSchemaDecodedMock, -} from './index.mock'; - -describe('import_list_item_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getImportExceptionsListSchemaMock(); - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getImportExceptionsListSchemaDecodedMock()); - }); - - test('it should NOT accept an undefined for "list_id"', () => { - const payload: Partial> = - getImportExceptionsListSchemaMock(); - delete payload.list_id; - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "description"', () => { - const payload: Partial> = - getImportExceptionsListSchemaMock(); - delete payload.description; - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "name"', () => { - const payload: Partial> = - getImportExceptionsListSchemaMock(); - delete payload.name; - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "type"', () => { - const payload: Partial> = - getImportExceptionsListSchemaMock(); - delete payload.type; - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept value of "true" for "immutable"', () => { - const payload: ImportExceptionsListSchema = { - ...getImportExceptionsListSchemaMock(), - immutable: true, - }; - - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "true" supplied to "immutable"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept any partial fields', () => { - const payload: ImportExceptionsListSchema = { - ...getImportExceptionsListSchemaMock(), - namespace_type: 'single', - immutable: false, - os_types: [], - tags: ['123'], - created_at: '2018-08-24T17:49:30.145142000', - created_by: 'elastic', - updated_at: '2018-08-24T17:49:30.145142000', - updated_by: 'elastic', - version: 3, - tie_breaker_id: '123', - _version: '3', - meta: undefined, - }; - - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ImportExceptionsListSchema & { - extraKey?: string; - } = getImportExceptionsListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = importExceptionsListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.ts deleted file mode 100644 index 9c0584aa267e1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { - DefaultVersionNumber, - DefaultVersionNumberDecoded, - OnlyFalseAllowed, -} from '@kbn/securitysolution-io-ts-types'; - -import { exceptionListType } from '../../common/exception_list'; -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { Tags } from '../../common/tags'; -import { ListId } from '../../common/list_id'; -import { NamespaceType } from '../../common/default_namespace'; -import { name } from '../../common/name'; -import { description } from '../../common/description'; -import { namespace_type } from '../../common/namespace_type'; -import { tags } from '../../common/tags'; -import { meta } from '../../common/meta'; -import { list_id } from '../../common/list_id'; -import { id } from '../../common/id'; -import { created_at } from '../../common/created_at'; -import { created_by } from '../../common/created_by'; -import { updated_at } from '../../common/updated_at'; -import { updated_by } from '../../common/updated_by'; -import { _version } from '../../common/underscore_version'; -import { tie_breaker_id } from '../../common/tie_breaker_id'; - -/** - * Differences from this and the createExceptionsSchema are - * - list_id is required - * - id is optional (but ignored in the import code - list_id is exclusively used for imports) - * - immutable is optional but if it is any value other than false it will be rejected - * - created_at is optional (but ignored in the import code) - * - updated_at is optional (but ignored in the import code) - * - created_by is optional (but ignored in the import code) - * - updated_by is optional (but ignored in the import code) - */ -export const importExceptionsListSchema = t.intersection([ - t.exact( - t.type({ - description, - name, - type: exceptionListType, - list_id, - }) - ), - t.exact( - t.partial({ - id, // defaults to undefined if not set during decode - immutable: OnlyFalseAllowed, - meta, // defaults to undefined if not set during decode - namespace_type, // defaults to 'single' if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - created_at, // defaults "undefined" if not set during decode - updated_at, // defaults "undefined" if not set during decode - created_by, // defaults "undefined" if not set during decode - updated_by, // defaults "undefined" if not set during decode - _version, // defaults to undefined if not set during decode - tie_breaker_id, - version: DefaultVersionNumber, // defaults to numerical 1 if not set during decode - }) - ), -]); - -export type ImportExceptionsListSchema = t.TypeOf; - -// This type is used after a decode since some things are defaults after a decode. -export type ImportExceptionListSchemaDecoded = Omit< - ImportExceptionsListSchema, - 'tags' | 'list_id' | 'namespace_type' | 'os_types' | 'immutable' -> & { - immutable: false; - tags: Tags; - list_id: ListId; - namespace_type: NamespaceType; - os_types: OsTypeArray; - version: DefaultVersionNumberDecoded; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.mock.ts deleted file mode 100644 index 74a2122ff1dc4..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.mock.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ID, TYPE } from '../../constants/index.mock'; - -import { ImportListItemQuerySchema } from '.'; - -export const getImportListItemQuerySchemaMock = (): ImportListItemQuerySchema => ({ - deserializer: undefined, - list_id: LIST_ID, - serializer: undefined, - type: TYPE, - refresh: 'false', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.test.ts deleted file mode 100644 index b0ec4f10af876..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { ImportListItemQuerySchema, importListItemQuerySchema } from '.'; -import { getImportListItemQuerySchemaMock } from './index.mock'; - -describe('import_list_item_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getImportListItemQuerySchemaMock(); - const decoded = importListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "list_id"', () => { - const payload = getImportListItemQuerySchemaMock(); - delete payload.list_id; - const decoded = importListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "type"', () => { - const payload = getImportListItemQuerySchemaMock(); - delete payload.type; - const decoded = importListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "type" and "list_id', () => { - const payload = getImportListItemQuerySchemaMock(); - delete payload.type; - delete payload.list_id; - const decoded = importListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "serializer"', () => { - const payload = getImportListItemQuerySchemaMock(); - delete payload.serializer; - const decoded = importListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "deserializer"', () => { - const payload = getImportListItemQuerySchemaMock(); - delete payload.deserializer; - const decoded = importListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ImportListItemQuerySchema & { - extraKey?: string; - } = getImportListItemQuerySchemaMock(); - payload.extraKey = 'some new value'; - const decoded = importListItemQuerySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.ts deleted file mode 100644 index e34d94c498662..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { deserializer } from '../../common/deserializer'; -import { list_id } from '../../common/list_id'; -import { type } from '../../common/type'; -import { serializer } from '../../common/serializer'; -import { refreshWithWaitFor } from '../../common/refresh'; - -export const importListItemQuerySchema = t.exact( - t.partial({ deserializer, list_id, serializer, type, refresh: refreshWithWaitFor }) -); - -export type ImportListItemQuerySchema = RequiredKeepUndefined< - t.TypeOf ->; -export type ImportListItemQuerySchemaEncoded = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.mock.ts deleted file mode 100644 index 15dd19d4bdefd..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.mock.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ImportListItemSchema } from '.'; - -export const getImportListItemSchemaMock = (): ImportListItemSchema => ({ - file: {}, -}); - -/** - * This is useful for end to end tests, it will return a buffer given a string array - * of things to import. - * @param input Array of strings of things to import - */ -export const getImportListItemAsBuffer = (input: string[]): Buffer => { - return Buffer.from(input.join('\r\n')); -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.test.ts deleted file mode 100644 index c4841f394f8d1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { ImportListItemSchema, importListItemSchema } from '.'; -import { getImportListItemSchemaMock } from './index.mock'; - -describe('import_list_item_schema', () => { - test('it should validate a typical lists request', () => { - const payload = getImportListItemSchemaMock(); - const decoded = importListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for a file', () => { - const payload = getImportListItemSchemaMock(); - // @ts-expect-error - delete payload.file; - const decoded = importListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "file"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ImportListItemSchema & { - extraKey?: string; - } = getImportListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = importListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.ts deleted file mode 100644 index 45dbf838e5871..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { file } from '../../common/file'; - -export const importListItemSchema = t.exact( - t.type({ - file, - }) -); - -export type ImportListItemSchema = RequiredKeepUndefined>; -export type ImportListItemSchemaEncoded = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/index.ts deleted file mode 100644 index 3d21a5ffdcb24..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './create_endpoint_list_item_schema'; -export * from './create_exception_list_item_schema'; -export * from './create_exception_list_schema'; -export * from './create_rule_exception_item_schema'; -export * from './create_list_item_schema'; -export * from './create_list_schema'; -export * from './delete_endpoint_list_item_schema'; -export * from './delete_exception_list_schema'; -export * from './delete_exception_list_item_schema'; -export * from './delete_list_item_schema'; -export * from './delete_list_schema'; -export * from './duplicate_exception_list_query_schema'; -export * from './export_exception_list_query_schema'; -export * from './export_list_item_query_schema'; -export * from './find_endpoint_list_item_schema'; -export * from './find_exception_list_schema'; -export * from './find_exception_list_item_schema'; -export * from './find_list_item_schema'; -export * from './find_list_schema'; -export * from './get_exception_filter_schema'; -export * from './import_list_item_query_schema'; -export * from './import_exception_list_schema'; -export * from './import_exception_item_schema'; -export * from './import_list_item_schema'; -export * from './patch_list_item_schema'; -export * from './patch_list_schema'; -export * from './read_endpoint_list_item_schema'; -export * from './read_exception_list_item_schema'; -export * from './read_exception_list_schema'; -export * from './read_list_item_schema'; -export * from './read_list_schema'; -export * from './summary_exception_list_schema'; -export * from './update_endpoint_list_item_schema'; -export * from './update_exception_list_item_schema'; -export * from './update_exception_list_schema'; -export * from './update_list_item_schema'; -export * from './update_list_schema'; - -// Internal routes -export * from './internal/create_exception_list_schema'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.test.ts deleted file mode 100644 index 4a4a090723c39..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; - -import { ExceptionListTypeEnum } from '../../../common/exception_list'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { internalCreateExceptionListSchema } from '.'; -import { getCreateExceptionListSchemaMock } from '../../create_exception_list_schema/index.mock'; - -describe('create_exception_list_schema', () => { - test('it should accept artifact list_id', () => { - const payload = { - ...getCreateExceptionListSchemaMock(), - list_id: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, - }; - const decoded = internalCreateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - test('it should fail when invalid list_id', () => { - const payload = { - ...getCreateExceptionListSchemaMock(), - list_id: ExceptionListTypeEnum.DETECTION, - }; - const decoded = internalCreateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "detection" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - test('it should accept artifact type', () => { - const payload = { - ...getCreateExceptionListSchemaMock(), - list_id: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, - type: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, - }; - const decoded = internalCreateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - test('it should fail when invalid type', () => { - const payload = { - ...getCreateExceptionListSchemaMock(), - list_id: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, - type: ExceptionListTypeEnum.DETECTION, - }; - const decoded = internalCreateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "detection" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts deleted file mode 100644 index 3aa11ba500502..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ENDPOINT_ARTIFACT_LIST_IDS } from '@kbn/securitysolution-list-constants'; -import * as t from 'io-ts'; - -import { - createExceptionListSchema, - CreateExceptionListSchemaDecoded, -} from '../../create_exception_list_schema'; - -export const internalCreateExceptionListSchema = t.intersection([ - t.exact( - t.type({ - type: t.keyof({ - endpoint: null, - endpoint_events: null, - endpoint_host_isolation_exceptions: null, - endpoint_blocklists: null, - }), - }) - ), - t.exact( - t.partial({ - list_id: t.keyof( - ENDPOINT_ARTIFACT_LIST_IDS.reduce>((mapOfListIds, listId) => { - mapOfListIds[listId] = null; - - return mapOfListIds; - }, {}) - ), - }) - ), - createExceptionListSchema, -]); - -export type InternalCreateExceptionListSchema = t.OutputOf< - typeof internalCreateExceptionListSchema ->; - -// This type is used after a decode since some things are defaults after a decode. -export type InternalCreateExceptionListSchemaDecoded = CreateExceptionListSchemaDecoded; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.mock.ts deleted file mode 100644 index ff156386baa93..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ITEM_ID, META, VALUE } from '../../constants/index.mock'; - -import { PatchListItemSchema } from '.'; - -export const getPathListItemSchemaMock = (): PatchListItemSchema => ({ - id: LIST_ITEM_ID, - meta: META, - value: VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.test.ts deleted file mode 100644 index fddeeaf0055c5..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getPathListItemSchemaMock } from './index.mock'; -import { PatchListItemSchema, patchListItemSchema } from '.'; - -describe('patch_list_item_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getPathListItemSchemaMock(); - const decoded = patchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "id"', () => { - const payload = getPathListItemSchemaMock(); - // @ts-expect-error - delete payload.id; - const decoded = patchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta"', () => { - const payload = getPathListItemSchemaMock(); - delete payload.meta; - const decoded = patchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "value"', () => { - const payload = getPathListItemSchemaMock(); - delete payload.value; - const decoded = patchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "meta" and "value"', () => { - const payload = getPathListItemSchemaMock(); - delete payload.meta; - delete payload.value; - const decoded = patchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: PatchListItemSchema & { extraKey?: string } = getPathListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = patchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.ts deleted file mode 100644 index 96b50702d99b2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { _version } from '../../common/underscore_version'; -import { id } from '../../common/id'; -import { meta } from '../../common/meta'; -import { value } from '../../common/value'; -import { refresh } from '../../common/refresh'; - -export const patchListItemSchema = t.intersection([ - t.exact( - t.type({ - id, - }) - ), - t.exact(t.partial({ _version, meta, value, refresh })), -]); - -export type PatchListItemSchema = t.OutputOf; -export type PatchListItemSchemaDecoded = RequiredKeepUndefined< - t.TypeOf ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.mock.ts deleted file mode 100644 index 818dd4e79e98f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.mock.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DESCRIPTION, LIST_ITEM_ID, META, NAME } from '../../constants/index.mock'; - -import { PatchListSchema } from '.'; - -export const getPathListSchemaMock = (): PatchListSchema => ({ - description: DESCRIPTION, - id: LIST_ITEM_ID, - meta: META, - name: NAME, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.test.ts deleted file mode 100644 index b79bfc8fddd65..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getPathListSchemaMock } from './index.mock'; -import { PatchListSchema, patchListSchema } from '.'; - -describe('patch_list_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getPathListSchemaMock(); - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "id"', () => { - const payload = getPathListSchemaMock(); - // @ts-expect-error - delete payload.id; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta"', () => { - const payload = getPathListSchemaMock(); - delete payload.meta; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "name"', () => { - const payload = getPathListSchemaMock(); - delete payload.name; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "description"', () => { - const payload = getPathListSchemaMock(); - delete payload.description; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "description", "meta", "name', () => { - const payload = getPathListSchemaMock(); - delete payload.description; - delete payload.name; - delete payload.meta; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "description", "meta"', () => { - const payload = getPathListSchemaMock(); - delete payload.description; - delete payload.meta; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "description", "name"', () => { - const payload = getPathListSchemaMock(); - delete payload.description; - delete payload.name; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "meta", "name"', () => { - const payload = getPathListSchemaMock(); - delete payload.meta; - delete payload.name; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: PatchListSchema & { extraKey?: string } = getPathListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = patchListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.ts deleted file mode 100644 index e5c477c844247..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { version } from '@kbn/securitysolution-io-ts-types'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { _version } from '../../common/underscore_version'; -import { meta } from '../../common/meta'; -import { name } from '../../common/name'; -import { description } from '../../common/description'; - -export const patchListSchema = t.intersection([ - t.exact( - t.type({ - id, - }) - ), - t.exact( - t.partial({ - _version, // is undefined if not set during decode - description, // is undefined if not set during decode - meta, // is undefined if not set during decode - name, // is undefined if not set during decode - version, // is undefined if not set during decode - }) - ), -]); - -export type PatchListSchema = t.OutputOf; -export type PatchListSchemaDecoded = RequiredKeepUndefined>; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.mock.ts deleted file mode 100644 index d7850f0cca32e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.mock.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, ITEM_ID } from '../../constants/index.mock'; - -import { ReadEndpointListItemSchema } from '.'; - -export const getReadEndpointListItemSchemaMock = (): ReadEndpointListItemSchema => ({ - id: ID, - item_id: ITEM_ID, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.test.ts deleted file mode 100644 index d9de257a31300..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getReadEndpointListItemSchemaMock } from './index.mock'; -import { ReadEndpointListItemSchema, readEndpointListItemSchema } from '.'; - -describe('read_endpoint_list_item_schema', () => { - test('it should validate a typical list request', () => { - const payload = getReadEndpointListItemSchemaMock(); - const decoded = readEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id"', () => { - const payload = getReadEndpointListItemSchemaMock(); - delete payload.id; - const decoded = readEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "item_id"', () => { - const payload = getReadEndpointListItemSchemaMock(); - delete payload.item_id; - const decoded = readEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept "namespace_type" since endpoint list items do not need it', () => { - const payload: ReadEndpointListItemSchema & { - namespace_type: string; - } = { ...getReadEndpointListItemSchemaMock(), namespace_type: 'single' }; - // @ts-expect-error - delete payload.namespace_type; - const decoded = readEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getReadEndpointListItemSchemaMock()); - }); - - test('it should accept an undefined for "id", "item_id"', () => { - const payload = getReadEndpointListItemSchemaMock(); - delete payload.id; - delete payload.item_id; - const decoded = readEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ReadEndpointListItemSchema & { - extraKey?: string; - } = getReadEndpointListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = readEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.ts deleted file mode 100644 index dbf3a59d79b3a..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { item_id } from '../../common/item_id'; - -export const readEndpointListItemSchema = t.exact( - t.partial({ - id, - item_id, - }) -); - -export type ReadEndpointListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type ReadEndpointListItemSchemaDecoded = RequiredKeepUndefined< - t.TypeOf ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.mock.ts deleted file mode 100644 index 00e72dc68f5fc..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, ITEM_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { ReadExceptionListItemSchema } from '.'; - -export const getReadExceptionListItemSchemaMock = (): ReadExceptionListItemSchema => ({ - id: ID, - item_id: ITEM_ID, - namespace_type: NAMESPACE_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.test.ts deleted file mode 100644 index e1c4615510305..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.test.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getReadExceptionListItemSchemaMock } from './index.mock'; -import { ReadExceptionListItemSchema, readExceptionListItemSchema } from '.'; - -describe('read_exception_list_item_schema', () => { - test('it should validate a typical exception list request', () => { - const payload = getReadExceptionListItemSchemaMock(); - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id"', () => { - const payload = getReadExceptionListItemSchemaMock(); - delete payload.id; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "item_id"', () => { - const payload = getReadExceptionListItemSchemaMock(); - delete payload.item_id; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "namespace_type" but default to "single"', () => { - const payload = getReadExceptionListItemSchemaMock(); - delete payload.namespace_type; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getReadExceptionListItemSchemaMock()); - }); - - test('it should accept an undefined for "id", "item_id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getReadExceptionListItemSchemaMock(); - delete payload.id; - delete payload.namespace_type; - delete payload.item_id; - const output = getReadExceptionListItemSchemaMock(); - delete output.id; - delete output.item_id; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should accept an undefined for "id", "item_id"', () => { - const payload = getReadExceptionListItemSchemaMock(); - delete payload.id; - delete payload.item_id; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getReadExceptionListItemSchemaMock(); - delete payload.id; - delete payload.namespace_type; - const output = getReadExceptionListItemSchemaMock(); - delete output.id; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should accept an undefined for "item_id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getReadExceptionListItemSchemaMock(); - delete payload.namespace_type; - delete payload.item_id; - const output = getReadExceptionListItemSchemaMock(); - delete output.item_id; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ReadExceptionListItemSchema & { - extraKey?: string; - } = getReadExceptionListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = readExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.ts deleted file mode 100644 index 6f54ede5ff51d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NamespaceType } from '../../common/default_namespace'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { item_id } from '../../common/item_id'; -import { namespace_type } from '../../common/namespace_type'; - -export const readExceptionListItemSchema = t.exact( - t.partial({ - id, - item_id, - namespace_type, // defaults to 'single' if not set during decode - }) -); - -export type ReadExceptionListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type ReadExceptionListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'namespace_type' -> & { - namespace_type: NamespaceType; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.mock.ts deleted file mode 100644 index 47fcba01fd95e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { ReadExceptionListSchema } from '.'; - -export const getReadExceptionListSchemaMock = (): ReadExceptionListSchema => ({ - id: ID, - list_id: LIST_ID, - namespace_type: NAMESPACE_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.test.ts deleted file mode 100644 index 2c5a93021b7ca..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.test.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getReadExceptionListSchemaMock } from './index.mock'; -import { ReadExceptionListSchema, readExceptionListSchema } from '.'; - -describe('read_exception_list_schema', () => { - test('it should validate a typical exception list request', () => { - const payload = getReadExceptionListSchemaMock(); - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id"', () => { - const payload = getReadExceptionListSchemaMock(); - delete payload.id; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "list_id"', () => { - const payload = getReadExceptionListSchemaMock(); - delete payload.list_id; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "namespace_type" but default to "single"', () => { - const payload = getReadExceptionListSchemaMock(); - delete payload.namespace_type; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getReadExceptionListSchemaMock()); - }); - - test('it should accept an undefined for "id", "list_id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getReadExceptionListSchemaMock(); - delete payload.id; - delete payload.namespace_type; - delete payload.list_id; - const output = getReadExceptionListSchemaMock(); - delete output.id; - delete output.list_id; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should accept an undefined for "id", "list_id"', () => { - const payload = getReadExceptionListSchemaMock(); - delete payload.id; - delete payload.list_id; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getReadExceptionListSchemaMock(); - delete payload.id; - delete payload.namespace_type; - const output = getReadExceptionListSchemaMock(); - delete output.id; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should accept an undefined for "list_id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getReadExceptionListSchemaMock(); - delete payload.namespace_type; - delete payload.list_id; - const output = getReadExceptionListSchemaMock(); - delete output.list_id; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ReadExceptionListSchema & { - extraKey?: string; - } = getReadExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = readExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.ts deleted file mode 100644 index fb2e66d2f1de2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NamespaceType } from '../../common/default_namespace'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { list_id } from '../../common/list_id'; -import { namespace_type } from '../../common/namespace_type'; - -export const readExceptionListSchema = t.exact( - t.partial({ - id, - list_id, - namespace_type, // defaults to 'single' if not set during decode - }) -); - -export type ReadExceptionListSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type ReadExceptionListSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'namespace_type' -> & { - namespace_type: NamespaceType; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.mock.ts deleted file mode 100644 index d78bb6f44bc78..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ID, LIST_ITEM_ID, VALUE } from '../../constants/index.mock'; - -import { ReadListItemSchema } from '.'; - -export const getReadListItemSchemaMock = (): ReadListItemSchema => ({ - id: LIST_ITEM_ID, - list_id: LIST_ID, - value: VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.test.ts deleted file mode 100644 index 547537afc6735..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getReadListItemSchemaMock } from './index.mock'; -import { ReadListItemSchema, readListItemSchema } from '.'; - -describe('read_list_item_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getReadListItemSchemaMock(); - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id"', () => { - const payload = getReadListItemSchemaMock(); - delete payload.id; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "list_id"', () => { - const payload = getReadListItemSchemaMock(); - delete payload.list_id; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "value"', () => { - const payload = getReadListItemSchemaMock(); - delete payload.value; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id", "list_id", "value"', () => { - const payload = getReadListItemSchemaMock(); - delete payload.id; - delete payload.value; - delete payload.list_id; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id", "list_id"', () => { - const payload = getReadListItemSchemaMock(); - delete payload.id; - delete payload.list_id; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id", "value"', () => { - const payload = getReadListItemSchemaMock(); - delete payload.id; - delete payload.value; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "list_id", "value"', () => { - const payload = getReadListItemSchemaMock(); - delete payload.value; - delete payload.list_id; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ReadListItemSchema & { extraKey?: string } = getReadListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = readListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.ts deleted file mode 100644 index 3b45ebeea6bae..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { list_id } from '../../common/list_id'; -import { value } from '../../common/value'; - -export const readListItemSchema = t.exact(t.partial({ id, list_id, value })); - -export type ReadListItemSchema = t.OutputOf; -export type ReadListItemSchemaDecoded = RequiredKeepUndefined>; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.mock.ts deleted file mode 100644 index 5eecbd49e472a..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.mock.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { LIST_ID } from '../../constants/index.mock'; - -import { ReadListSchema } from '.'; - -export const getReadListSchemaMock = (): ReadListSchema => ({ - id: LIST_ID, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.test.ts deleted file mode 100644 index d26f8206c4985..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getReadListSchemaMock } from './index.mock'; -import { ReadListSchema, readListSchema } from '.'; - -describe('read_list_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getReadListSchemaMock(); - const decoded = readListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "id"', () => { - const payload = getReadListSchemaMock(); - // @ts-expect-error - delete payload.id; - const decoded = readListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ReadListSchema & { extraKey?: string } = getReadListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = readListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.ts deleted file mode 100644 index b9c008287139e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { id } from '../../common/id'; - -export const readListSchema = t.exact( - t.type({ - id, - }) -); - -export type ReadListSchema = t.OutputOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.mock.ts deleted file mode 100644 index 61e8dfbae15fd..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FILTER, ID, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { SummaryExceptionListSchema } from '.'; - -export const getSummaryExceptionListSchemaMock = (): SummaryExceptionListSchema => ({ - filter: FILTER, - id: ID, - list_id: LIST_ID, - namespace_type: NAMESPACE_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.test.ts deleted file mode 100644 index 06db32fa2df30..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getSummaryExceptionListSchemaMock } from './index.mock'; -import { SummaryExceptionListSchema, summaryExceptionListSchema } from '.'; - -describe('summary_exception_list_schema', () => { - test('it should validate a typical exception list request', () => { - const payload = getSummaryExceptionListSchemaMock(); - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "filter"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.filter; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.id; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "list_id"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.list_id; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "namespace_type" but default to "single"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.namespace_type; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getSummaryExceptionListSchemaMock()); - }); - - test('it should accept an undefined for "id", "list_id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.id; - delete payload.namespace_type; - delete payload.list_id; - const output = getSummaryExceptionListSchemaMock(); - delete output.id; - delete output.list_id; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should accept an undefined for "id", "list_id"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.id; - delete payload.list_id; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.id; - delete payload.namespace_type; - const output = getSummaryExceptionListSchemaMock(); - delete output.id; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should accept an undefined for "list_id", "namespace_type" but default "namespace_type" to "single"', () => { - const payload = getSummaryExceptionListSchemaMock(); - delete payload.namespace_type; - delete payload.list_id; - const output = getSummaryExceptionListSchemaMock(); - delete output.list_id; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(output); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: SummaryExceptionListSchema & { - extraKey?: string; - } = getSummaryExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = summaryExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = foldLeftRight(checked); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts deleted file mode 100644 index 2815dfa05b27e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { NamespaceType } from '../../common/default_namespace'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { filter, Filter } from '../../common/filter'; -import { list_id } from '../../common/list_id'; -import { namespace_type } from '../../common/namespace_type'; - -export const summaryExceptionListSchema = t.exact( - t.partial({ - filter, - id, - list_id, - namespace_type, // defaults to 'single' if not set during decode - }) -); - -export type SummaryExceptionListSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type SummaryExceptionListSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'namespace_type' -> & { - namespace_type: NamespaceType; - filter: Filter; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.mock.ts deleted file mode 100644 index 8b34549a8c90f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.mock.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - COMMENTS, - DESCRIPTION, - ENTRIES, - ID, - ITEM_TYPE, - LIST_ITEM_ID, - META, - NAME, - OS_TYPES, - TAGS, -} from '../../constants/index.mock'; - -import { UpdateEndpointListItemSchema } from '.'; - -export const getUpdateEndpointListItemSchemaMock = (): UpdateEndpointListItemSchema => ({ - _version: undefined, - comments: COMMENTS, - description: DESCRIPTION, - entries: ENTRIES, - id: ID, - item_id: LIST_ITEM_ID, - meta: META, - name: NAME, - os_types: OS_TYPES, - tags: TAGS, - type: ITEM_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.test.ts deleted file mode 100644 index f595ecd1ebbed..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.test.ts +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { UpdateEndpointListItemSchema, updateEndpointListItemSchema } from '.'; -import { getUpdateEndpointListItemSchemaMock } from './index.mock'; - -describe('update_endpoint_list_item_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getUpdateEndpointListItemSchemaMock(); - const decoded = updateEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not accept an undefined for "description"', () => { - const payload = getUpdateEndpointListItemSchemaMock(); - // @ts-expect-error - delete payload.description; - const decoded = updateEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept an undefined for "name"', () => { - const payload = getUpdateEndpointListItemSchemaMock(); - // @ts-expect-error - delete payload.name; - const decoded = updateEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept an undefined for "type"', () => { - const payload = getUpdateEndpointListItemSchemaMock(); - // @ts-expect-error - delete payload.type; - const decoded = updateEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept a value for "list_id"', () => { - const payload: UpdateEndpointListItemSchema & { - list_id?: string; - } = getUpdateEndpointListItemSchemaMock(); - payload.list_id = 'some new list_id'; - const decoded = updateEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "list_id"']); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta" but strip it out', () => { - const payload = getUpdateEndpointListItemSchemaMock(); - const outputPayload = getUpdateEndpointListItemSchemaMock(); - delete payload.meta; - const decoded = updateEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete outputPayload.meta; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "comments" but return an array', () => { - const inputPayload = getUpdateEndpointListItemSchemaMock(); - const outputPayload = getUpdateEndpointListItemSchemaMock(); - delete inputPayload.comments; - outputPayload.comments = []; - const decoded = updateEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should NOT accept an undefined for "entries"', () => { - const inputPayload = getUpdateEndpointListItemSchemaMock(); - const outputPayload = getUpdateEndpointListItemSchemaMock(); - // @ts-expect-error - delete inputPayload.entries; - outputPayload.entries = []; - const decoded = updateEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "tags" but return an array', () => { - const inputPayload = getUpdateEndpointListItemSchemaMock(); - const outputPayload = getUpdateEndpointListItemSchemaMock(); - delete inputPayload.tags; - outputPayload.tags = []; - const decoded = updateEndpointListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: UpdateEndpointListItemSchema & { - extraKey?: string; - } = getUpdateEndpointListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = updateEndpointListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.ts deleted file mode 100644 index 7851d80ef2ef9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { DefaultUpdateCommentsArray } from '../../common/default_update_comments_array'; -import { exceptionListItemType } from '../../common/exception_list_item_type'; -import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { description } from '../../common/description'; -import { name } from '../../common/name'; -import { _version } from '../../common/underscore_version'; -import { id } from '../../common/id'; -import { meta } from '../../common/meta'; -import { Tags, tags } from '../../common/tags'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { UpdateCommentsArray } from '../../common/update_comment'; -import { EntriesArray } from '../../common/entries'; - -export const updateEndpointListItemSchema = t.intersection([ - t.exact( - t.type({ - description, - entries: nonEmptyEntriesArray, - name, - type: exceptionListItemType, - }) - ), - t.exact( - t.partial({ - _version, // defaults to undefined if not set during decode - comments: DefaultUpdateCommentsArray, // defaults to empty array if not set during decode - id, // defaults to undefined if not set during decode - item_id: t.union([t.string, t.undefined]), - meta, // defaults to undefined if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - }) - ), -]); - -export type UpdateEndpointListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type UpdateEndpointListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'tags' | 'entries' | 'comments' -> & { - comments: UpdateCommentsArray; - tags: Tags; - entries: EntriesArray; - os_types: OsTypeArray; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.mock.ts deleted file mode 100644 index fce5d2f7e18bc..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.mock.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - COMMENTS, - DESCRIPTION, - ENTRIES, - ID, - ITEM_ID, - ITEM_TYPE, - LIST_ITEM_ID, - META, - NAME, - NAMESPACE_TYPE, - OS_TYPES, - TAGS, -} from '../../constants/index.mock'; - -import { UpdateExceptionListItemSchema } from '.'; - -export const getUpdateExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ - _version: undefined, - comments: COMMENTS, - description: DESCRIPTION, - entries: ENTRIES, - id: ID, - item_id: LIST_ITEM_ID, - meta: META, - name: NAME, - namespace_type: NAMESPACE_TYPE, - os_types: ['linux'], - tags: TAGS, - type: ITEM_TYPE, -}); - -/** - * Useful for end to end tests and other mechanisms which want to fill in the values - * after doing a get of the structure. - */ -export const getUpdateMinimalExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ - description: DESCRIPTION, - entries: ENTRIES, - item_id: ITEM_ID, - name: NAME, - os_types: OS_TYPES, - type: ITEM_TYPE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.test.ts deleted file mode 100644 index 84e9b801c171d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { UpdateExceptionListItemSchema, updateExceptionListItemSchema } from '.'; -import { getUpdateExceptionListItemSchemaMock } from './index.mock'; - -describe('update_exception_list_item_schema', () => { - test('it should validate a typical exception list item request', () => { - const payload = getUpdateExceptionListItemSchemaMock(); - const decoded = updateExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not accept an undefined for "description"', () => { - const payload = getUpdateExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.description; - const decoded = updateExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept an undefined for "name"', () => { - const payload = getUpdateExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.name; - const decoded = updateExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept an undefined for "type"', () => { - const payload = getUpdateExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.type; - const decoded = updateExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept a value for "list_id"', () => { - const payload: UpdateExceptionListItemSchema & { - list_id?: string; - } = getUpdateExceptionListItemSchemaMock(); - payload.list_id = 'some new list_id'; - const decoded = updateExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "list_id"']); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta" but strip it out', () => { - const payload = getUpdateExceptionListItemSchemaMock(); - const outputPayload = getUpdateExceptionListItemSchemaMock(); - delete payload.meta; - const decoded = updateExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete outputPayload.meta; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "comments" but return an array', () => { - const inputPayload = getUpdateExceptionListItemSchemaMock(); - const outputPayload = getUpdateExceptionListItemSchemaMock(); - delete inputPayload.comments; - outputPayload.comments = []; - const decoded = updateExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should NOT accept an undefined for "entries"', () => { - const inputPayload = getUpdateExceptionListItemSchemaMock(); - const outputPayload = getUpdateExceptionListItemSchemaMock(); - // @ts-expect-error - delete inputPayload.entries; - outputPayload.entries = []; - const decoded = updateExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "namespace_type" but return enum "single"', () => { - const inputPayload = getUpdateExceptionListItemSchemaMock(); - const outputPayload = getUpdateExceptionListItemSchemaMock(); - delete inputPayload.namespace_type; - outputPayload.namespace_type = 'single'; - const decoded = updateExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "tags" but return an array', () => { - const inputPayload = getUpdateExceptionListItemSchemaMock(); - const outputPayload = getUpdateExceptionListItemSchemaMock(); - delete inputPayload.tags; - outputPayload.tags = []; - const decoded = updateExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "item_id" and generate a correct body not counting the uuid', () => { - const inputPayload = getUpdateExceptionListItemSchemaMock(); - delete inputPayload.item_id; - const decoded = updateExceptionListItemSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as UpdateExceptionListItemSchema).item_id; - expect(message.schema).toEqual(inputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: UpdateExceptionListItemSchema & { - extraKey?: string; - } = getUpdateExceptionListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = updateExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.ts deleted file mode 100644 index b0190d8fa3883..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { ExceptionListItemEntryArray } from '@kbn/securitysolution-exceptions-common/api'; -import { NamespaceType } from '../../common/default_namespace'; -import { DefaultUpdateCommentsArray } from '../../common/default_update_comments_array'; -import { exceptionListItemType } from '../../common/exception_list_item_type'; -import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { Tags, tags } from '../../common/tags'; -import { UpdateCommentsArray } from '../../common/update_comment'; -import { description } from '../../common/description'; -import { name } from '../../common/name'; -import { _version } from '../../common/underscore_version'; -import { id } from '../../common/id'; -import { item_id } from '../../common/item_id'; -import { meta } from '../../common/meta'; -import { namespace_type } from '../../common/namespace_type'; -import { ExpireTimeOrUndefined, expireTimeOrUndefined } from '../../common'; - -export const updateExceptionListItemSchema = t.intersection([ - t.exact( - t.type({ - description, - entries: nonEmptyEntriesArray, - name, - type: exceptionListItemType, - }) - ), - t.exact( - t.partial({ - _version, // defaults to undefined if not set during decode - comments: DefaultUpdateCommentsArray, // defaults to empty array if not set during decode - expire_time: expireTimeOrUndefined, - id, // defaults to undefined if not set during decode - item_id, - meta, // defaults to undefined if not set during decode - namespace_type, // defaults to 'single' if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - }) - ), -]); - -export type UpdateExceptionListItemSchema = t.OutputOf; - -// This type is used after a decode since some things are defaults after a decode. -export type UpdateExceptionListItemSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'tags' | 'entries' | 'namespace_type' | 'comments' | 'os_types' | 'expire_time' -> & { - comments: UpdateCommentsArray; - tags: Tags; - entries: ExceptionListItemEntryArray; - namespace_type: NamespaceType; - os_types: OsTypeArray; - expire_time: ExpireTimeOrUndefined; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.mock.ts deleted file mode 100644 index ff98cc71f03f4..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DESCRIPTION, ID, LIST_ID, META, NAME, NAMESPACE_TYPE } from '../../constants/index.mock'; - -import { UpdateExceptionListSchema } from '.'; - -export const getUpdateExceptionListSchemaMock = (): UpdateExceptionListSchema => ({ - _version: undefined, - description: DESCRIPTION, - id: ID, - list_id: LIST_ID, - meta: META, - name: NAME, - namespace_type: NAMESPACE_TYPE, - os_types: [], - tags: ['malware'], - type: 'endpoint', -}); - -/** - * Useful for end to end tests and other mechanisms which want to fill in the values - * after doing a get of the structure. - */ -export const getUpdateMinimalExceptionListSchemaMock = (): UpdateExceptionListSchema => ({ - description: DESCRIPTION, - list_id: LIST_ID, - name: NAME, - type: 'endpoint', -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.test.ts deleted file mode 100644 index 4821251f36d14..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { UpdateExceptionListSchema, updateExceptionListSchema } from '.'; -import { getUpdateExceptionListSchemaMock } from './index.mock'; - -describe('update_exception_list_schema', () => { - test('it should validate a typical exception list request', () => { - const payload = getUpdateExceptionListSchemaMock(); - const decoded = updateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not accept an undefined for "description"', () => { - const payload = getUpdateExceptionListSchemaMock(); - // @ts-expect-error - delete payload.description; - const decoded = updateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept an undefined for "name"', () => { - const payload = getUpdateExceptionListSchemaMock(); - // @ts-expect-error - delete payload.name; - const decoded = updateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not accept an undefined for "type"', () => { - const payload = getUpdateExceptionListSchemaMock(); - // @ts-expect-error - delete payload.type; - const decoded = updateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta" but strip it out', () => { - const payload = getUpdateExceptionListSchemaMock(); - const outputPayload = getUpdateExceptionListSchemaMock(); - delete payload.meta; - const decoded = updateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete outputPayload.meta; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "namespace_type" but return enum "single"', () => { - const inputPayload = getUpdateExceptionListSchemaMock(); - const outputPayload = getUpdateExceptionListSchemaMock(); - delete inputPayload.namespace_type; - outputPayload.namespace_type = 'single'; - const decoded = updateExceptionListSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "tags" but return an array', () => { - const inputPayload = getUpdateExceptionListSchemaMock(); - const outputPayload = getUpdateExceptionListSchemaMock(); - delete inputPayload.tags; - outputPayload.tags = []; - const decoded = updateExceptionListSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should accept an undefined for "list_id" and generate a correct body not counting the uuid', () => { - const inputPayload = getUpdateExceptionListSchemaMock(); - delete inputPayload.list_id; - const decoded = updateExceptionListSchema.decode(inputPayload); - const checked = exactCheck(inputPayload, decoded); - const message = pipe(checked, foldLeftRight); - delete (message.schema as UpdateExceptionListSchema).list_id; - expect(message.schema).toEqual(inputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: UpdateExceptionListSchema & { - extraKey?: string; - } = getUpdateExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = updateExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.ts deleted file mode 100644 index 62add37568ba3..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { version } from '@kbn/securitysolution-io-ts-types'; -import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { Tags, tags } from '../../common/tags'; -import { NamespaceType } from '../../common/default_namespace'; -import { description } from '../../common/description'; -import { name } from '../../common/name'; -import { _version } from '../../common/underscore_version'; -import { exceptionListType } from '../../common/exception_list'; -import { id } from '../../common/id'; -import { list_id } from '../../common/list_id'; -import { meta } from '../../common/meta'; -import { namespace_type } from '../../common/namespace_type'; - -export const updateExceptionListSchema = t.intersection([ - t.exact( - t.type({ - description, - name, - type: exceptionListType, - }) - ), - t.exact( - t.partial({ - _version, // defaults to undefined if not set during decode - id, // defaults to undefined if not set during decode - list_id, // defaults to undefined if not set during decode - meta, // defaults to undefined if not set during decode - namespace_type, // defaults to 'single' if not set during decode - os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode - tags, // defaults to empty array if not set during decode - version, // defaults to undefined if not set during decode - }) - ), -]); - -export type UpdateExceptionListSchema = t.OutputOf; - -// This type is used after a decode since the arrays turn into defaults of empty arrays. -export type UpdateExceptionListSchemaDecoded = Omit< - RequiredKeepUndefined>, - 'tags | namespace_type' | 'os_types' -> & { - tags: Tags; - namespace_type: NamespaceType; - os_types: OsTypeArray; -}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.mock.ts deleted file mode 100644 index 9c3b2dbbd7d35..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.mock.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ID, LIST_ITEM_ID, META, VALUE } from '../../constants/index.mock'; - -import { UpdateListItemSchema } from '.'; - -export const getUpdateListItemSchemaMock = (): UpdateListItemSchema => ({ - id: ID, - meta: META, - value: VALUE, -}); - -/** - * Useful for end to end testing - */ -export const getUpdateMinimalListItemSchemaMock = (): UpdateListItemSchema => ({ - id: LIST_ITEM_ID, - value: VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.test.ts deleted file mode 100644 index 6c7637cbde05e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { UpdateListItemSchema, updateListItemSchema } from '.'; -import { getUpdateListItemSchemaMock } from './index.mock'; - -describe('update_list_item_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getUpdateListItemSchemaMock(); - const decoded = updateListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "meta" but strip it out', () => { - const payload = getUpdateListItemSchemaMock(); - const outputPayload = getUpdateListItemSchemaMock(); - delete payload.meta; - const decoded = updateListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete outputPayload.meta; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: UpdateListItemSchema & { - extraKey?: string; - } = getUpdateListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = updateListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.ts deleted file mode 100644 index 613dde36ef0f7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { _version } from '../../common/underscore_version'; -import { id } from '../../common/id'; -import { value } from '../../common/value'; -import { meta } from '../../common/meta'; - -export const updateListItemSchema = t.intersection([ - t.exact( - t.type({ - id, - value, - }) - ), - t.exact( - t.partial({ - _version, // defaults to undefined if not set during decode - meta, // defaults to undefined if not set during decode - }) - ), -]); - -export type UpdateListItemSchema = t.OutputOf; -export type UpdateListItemSchemaDecoded = RequiredKeepUndefined< - t.TypeOf ->; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.mock.ts deleted file mode 100644 index 5f1fc8fe926d5..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.mock.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DESCRIPTION, LIST_ID, META, NAME, _VERSION } from '../../constants/index.mock'; - -import { UpdateListSchema } from '.'; - -export const getUpdateListSchemaMock = (): UpdateListSchema => ({ - _version: _VERSION, - description: DESCRIPTION, - id: LIST_ID, - meta: META, - name: NAME, -}); - -/** - * Useful for end to end tests and other mechanisms which want to fill in the values - * after doing a get of the structure. - */ -export const getUpdateMinimalListSchemaMock = (): UpdateListSchema => ({ - description: DESCRIPTION, - id: LIST_ID, - name: NAME, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.test.ts deleted file mode 100644 index cac97d7c32cf2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { UpdateListSchema, updateListSchema } from '.'; -import { getUpdateListSchemaMock } from './index.mock'; - -describe('update_list_schema', () => { - test('it should validate a typical list request', () => { - const payload = getUpdateListSchemaMock(); - const decoded = updateListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "meta" but strip it out', () => { - const payload = getUpdateListSchemaMock(); - const outputPayload = getUpdateListSchemaMock(); - delete payload.meta; - const decoded = updateListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - delete outputPayload.meta; - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(outputPayload); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: UpdateListSchema & { - extraKey?: string; - } = getUpdateListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = updateListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.ts deleted file mode 100644 index 41ddb81c36e38..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { version } from '@kbn/securitysolution-io-ts-types'; -import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; -import { id } from '../../common/id'; -import { name } from '../../common/name'; -import { description } from '../../common/description'; -import { _version } from '../../common/underscore_version'; -import { meta } from '../../common/meta'; - -export const updateListSchema = t.intersection([ - t.exact( - t.type({ - description, - id, - name, - }) - ), - t.exact( - t.partial({ - _version, // defaults to undefined if not set during decode - meta, // defaults to undefined if not set during decode - version, // defaults to undefined if not set during decode - }) - ), -]); - -export type UpdateListSchema = t.OutputOf; -export type UpdateListSchemaDecoded = RequiredKeepUndefined>; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.mock.ts deleted file mode 100644 index c532dd7401971..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.mock.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { AcknowledgeSchema } from '.'; - -export const getAcknowledgeSchemaResponseMock = (): AcknowledgeSchema => ({ - acknowledged: true, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.test.ts deleted file mode 100644 index 2d3086b023153..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getAcknowledgeSchemaResponseMock } from './index.mock'; -import { AcknowledgeSchema, acknowledgeSchema } from '.'; - -describe('acknowledge_schema', () => { - test('it should validate a typical response', () => { - const payload = getAcknowledgeSchemaResponseMock(); - const decoded = acknowledgeSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - test('it should NOT accept an undefined for "ok"', () => { - const payload = getAcknowledgeSchemaResponseMock(); - // @ts-expect-error - delete payload.acknowledged; - const decoded = acknowledgeSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "acknowledged"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: AcknowledgeSchema & { extraKey?: string } = getAcknowledgeSchemaResponseMock(); - payload.extraKey = 'some new value'; - const decoded = acknowledgeSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.ts deleted file mode 100644 index d506f038534d9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const acknowledgeSchema = t.exact(t.type({ acknowledged: t.boolean })); - -export type AcknowledgeSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.test.ts deleted file mode 100644 index 52c72cf0e8cbc..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { CreateEndpointListSchema, createEndpointListSchema } from '.'; -import { getExceptionListSchemaMock } from '../exception_list_schema/index.mock'; - -describe('create_endpoint_list_schema', () => { - test('it should validate a typical endpoint list response', () => { - const payload = getExceptionListSchemaMock(); - const decoded = createEndpointListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an empty object when an endpoint list already exists', () => { - const payload: CreateEndpointListSchema = {}; - const decoded = createEndpointListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "list_id"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = createEndpointListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'invalid keys "_version,created_at,created_by,description,id,immutable,meta,{},name,namespace_type,os_types,["linux"],tags,["user added string for a tag","malware"],tie_breaker_id,type,updated_at,updated_by,version"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT allow missing fields', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = createEndpointListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors)).length).toEqual(1); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: CreateEndpointListSchema & { - extraKey?: string; - } = getExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = createEndpointListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.ts deleted file mode 100644 index cdcdc8e67e07c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { exceptionListSchema } from '../exception_list_schema'; - -export const createEndpointListSchema = t.union([exceptionListSchema, t.exact(t.type({}))]); - -export type CreateEndpointListSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.mock.ts deleted file mode 100644 index 2c0449ea900ee..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.mock.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - COMMENTS, - DATE_NOW, - DESCRIPTION, - ELASTIC_USER, - ENTRIES, - ITEM_ID, - ITEM_TYPE, - LIST_ID, - META, - NAME, - NAMESPACE_TYPE, - OS_TYPES, - TIE_BREAKER, - USER, -} from '../../constants/index.mock'; - -import { ExceptionListItemSchema } from '.'; - -export const getExceptionListItemSchemaMock = ( - overrides?: Partial -): ExceptionListItemSchema => ({ - _version: undefined, - comments: COMMENTS, - created_at: DATE_NOW, - created_by: USER, - description: DESCRIPTION, - entries: ENTRIES, - expire_time: undefined, - id: '1', - item_id: 'endpoint_list_item', - list_id: 'endpoint_list_id', - meta: META, - name: NAME, - namespace_type: NAMESPACE_TYPE, - os_types: ['linux'], - tags: ['user added string for a tag', 'malware'], - tie_breaker_id: TIE_BREAKER, - type: ITEM_TYPE, - updated_at: DATE_NOW, - updated_by: USER, - ...(overrides || {}), -}); - -/** - * This is useful for end to end tests where we remove the auto generated parts for comparisons - * such as created_at, updated_at, and id. - */ -export const getExceptionListItemResponseMockWithoutAutoGeneratedValues = - (): Partial => ({ - comments: [], - created_by: ELASTIC_USER, - description: DESCRIPTION, - entries: ENTRIES, - item_id: ITEM_ID, - list_id: LIST_ID, - name: NAME, - namespace_type: 'single', - os_types: OS_TYPES, - tags: [], - type: ITEM_TYPE, - updated_by: ELASTIC_USER, - }); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.test.ts deleted file mode 100644 index 9c98d97a596ab..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.test.ts +++ /dev/null @@ -1,242 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getExceptionListItemSchemaMock } from './index.mock'; -import { ExceptionListItemSchema, exceptionListItemSchema } from '.'; - -describe('exception_list_item_schema', () => { - test('it should validate a typical exception list item response', () => { - const payload = getExceptionListItemSchemaMock(); - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "id"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.id; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "list_id"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "item_id"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.item_id; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "item_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "comments"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.comments; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "comments"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "entries"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.entries; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "name"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.name; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "namespace_type" and return "single" as a default value for "namespace_type"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.namespace_type; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect((message.schema as ExceptionListItemSchema).namespace_type).toEqual('single'); - }); - - test('it should NOT accept an undefined for "description"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.description; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta"', () => { - const payload = getExceptionListItemSchemaMock(); - delete payload.meta; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "created_at"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.created_at; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "created_by"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.created_by; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "tie_breaker_id"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.tie_breaker_id; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "tie_breaker_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "type"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.type; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_at"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.updated_at; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_by"', () => { - const payload = getExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.updated_by; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ExceptionListItemSchema & { - extraKey?: string; - } = getExceptionListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = exceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.ts deleted file mode 100644 index 5408aa581bdfa..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { namespace_type } from '../../common/namespace_type'; -import { metaOrUndefined } from '../../common/meta'; -import { name } from '../../common/name'; -import { created_at } from '../../common/created_at'; -import { created_by } from '../../common/created_by'; -import { id } from '../../common/id'; -import { tie_breaker_id } from '../../common/tie_breaker_id'; -import { updated_at } from '../../common/updated_at'; -import { updated_by } from '../../common/updated_by'; -import { list_id } from '../../common/list_id'; -import { description } from '../../common/description'; -import { osTypeArray } from '../../common/os_type'; -import { tags } from '../../common/tags'; -import { _versionOrUndefined } from '../../common/underscore_version'; -import { commentsArray } from '../../common/comment'; -import { entriesArray } from '../../common/entries'; -import { item_id } from '../../common/item_id'; -import { exceptionListItemType } from '../../common/exception_list_item_type'; -import { expireTimeOrUndefined } from '../../common/expire_time'; - -export const exceptionListItemSchema = t.exact( - t.type({ - _version: _versionOrUndefined, - comments: commentsArray, - created_at, - created_by, - description, - entries: entriesArray, - expire_time: expireTimeOrUndefined, - id, - item_id, - list_id, - meta: metaOrUndefined, - name, - namespace_type, - os_types: osTypeArray, - tags, - tie_breaker_id, - type: exceptionListItemType, - updated_at, - updated_by, - }) -); - -export type ExceptionListItemSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.mock.ts deleted file mode 100644 index de2efb85c3379..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.mock.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - DATE_NOW, - DESCRIPTION, - ELASTIC_USER, - ENDPOINT_TYPE, - IMMUTABLE, - LIST_ID, - META, - NAME, - TIE_BREAKER, - USER, - VERSION, - _VERSION, -} from '../../constants/index.mock'; -import { - ENDPOINT_LIST_ID, - ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION, - ENDPOINT_TRUSTED_APPS_LIST_ID, - ENDPOINT_TRUSTED_APPS_LIST_NAME, -} from '@kbn/securitysolution-list-constants'; - -import { ExceptionListSchema } from '.'; - -export const getExceptionListSchemaMock = (): ExceptionListSchema => ({ - _version: _VERSION, - created_at: DATE_NOW, - created_by: USER, - description: DESCRIPTION, - id: '1', - immutable: IMMUTABLE, - list_id: ENDPOINT_LIST_ID, - meta: META, - name: 'Sample Endpoint Exception List', - namespace_type: 'agnostic', - os_types: ['linux'], - tags: ['user added string for a tag', 'malware'], - tie_breaker_id: TIE_BREAKER, - type: ENDPOINT_TYPE, - updated_at: DATE_NOW, - updated_by: 'user_name', - version: VERSION, -}); - -export const getTrustedAppsListSchemaMock = (): ExceptionListSchema => { - return { - ...getExceptionListSchemaMock(), - description: ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION, - list_id: ENDPOINT_TRUSTED_APPS_LIST_ID, - name: ENDPOINT_TRUSTED_APPS_LIST_NAME, - }; -}; - -/** - * This is useful for end to end tests where we remove the auto generated parts for comparisons - * such as created_at, updated_at, and id. - */ -export const getExceptionResponseMockWithoutAutoGeneratedValues = - (): Partial => ({ - created_by: ELASTIC_USER, - description: DESCRIPTION, - immutable: IMMUTABLE, - list_id: LIST_ID, - name: NAME, - namespace_type: 'single', - os_types: [], - tags: [], - type: ENDPOINT_TYPE, - updated_by: ELASTIC_USER, - version: VERSION, - }); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.test.ts deleted file mode 100644 index e8dc043bd6b07..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.test.ts +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getExceptionListSchemaMock } from './index.mock'; -import { ExceptionListSchema, exceptionListSchema } from '.'; - -describe('exception_list_schema', () => { - test('it should validate a typical exception list response', () => { - const payload = getExceptionListSchemaMock(); - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "id"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.id; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "list_id"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "name"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.name; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "namespace_type" and make "namespace_type" that of "single"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.namespace_type; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect((message.schema as ExceptionListSchema).namespace_type).toEqual('single'); - }); - - test('it should NOT accept an undefined for "description"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.description; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta"', () => { - const payload = getExceptionListSchemaMock(); - delete payload.meta; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "created_at"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.created_at; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "created_by"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.created_by; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "tie_breaker_id"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.tie_breaker_id; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "tie_breaker_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "type"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.type; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_at"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.updated_at; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_by"', () => { - const payload = getExceptionListSchemaMock(); - // @ts-expect-error - delete payload.updated_by; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ExceptionListSchema & { - extraKey?: string; - } = getExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = exceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.ts deleted file mode 100644 index 0667153c27776..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { version } from '@kbn/securitysolution-io-ts-types'; -import { _versionOrUndefined } from '../../common/underscore_version'; -import { namespace_type } from '../../common/namespace_type'; -import { metaOrUndefined } from '../../common/meta'; -import { name } from '../../common/name'; -import { created_at } from '../../common/created_at'; -import { created_by } from '../../common/created_by'; -import { id } from '../../common/id'; -import { tie_breaker_id } from '../../common/tie_breaker_id'; -import { immutable } from '../../common/immutable'; -import { updated_at } from '../../common/updated_at'; -import { updated_by } from '../../common/updated_by'; -import { list_id } from '../../common/list_id'; -import { description } from '../../common/description'; -import { osTypeArray } from '../../common/os_type'; -import { exceptionListType } from '../../common/exception_list'; -import { tags } from '../../common/tags'; - -export const exceptionListSchema = t.exact( - t.type({ - _version: _versionOrUndefined, - created_at, - created_by, - description, - id, - immutable, - list_id, - meta: metaOrUndefined, - name, - namespace_type, - os_types: osTypeArray, - tags, - tie_breaker_id, - type: exceptionListType, - updated_at, - updated_by, - version, - }) -); - -export type ExceptionListSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.mock.ts deleted file mode 100644 index 1decbde1374b0..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.mock.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ExceptionListSummarySchema } from '.'; - -export const getListSummaryResponseMock = (): ExceptionListSummarySchema => ({ - windows: 0, - linux: 1, - macos: 2, - total: 3, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.test.ts deleted file mode 100644 index ad1d8b737e46d..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getListSummaryResponseMock } from './index.mock'; -import { ExceptionListSummarySchema, exceptionListSummarySchema } from '.'; - -describe('list_summary_schema', () => { - test('it should validate a typical list summary response', () => { - const payload = getListSummaryResponseMock(); - const decoded = exceptionListSummarySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "windows"', () => { - const payload = getListSummaryResponseMock(); - // @ts-expect-error - delete payload.windows; - const decoded = exceptionListSummarySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "windows"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "linux"', () => { - const payload = getListSummaryResponseMock(); - // @ts-expect-error - delete payload.linux; - const decoded = exceptionListSummarySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "linux"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "macos"', () => { - const payload = getListSummaryResponseMock(); - // @ts-expect-error - delete payload.macos; - const decoded = exceptionListSummarySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "macos"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "total"', () => { - const payload = getListSummaryResponseMock(); - // @ts-expect-error - delete payload.total; - const decoded = exceptionListSummarySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "total"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ExceptionListSummarySchema & { - extraKey?: string; - } = getListSummaryResponseMock(); - payload.extraKey = 'some new value'; - const decoded = exceptionListSummarySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.ts deleted file mode 100644 index a14eaba10b78f..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PositiveInteger } from '@kbn/securitysolution-io-ts-types'; -import * as t from 'io-ts'; - -export const exceptionListSummarySchema = t.exact( - t.type({ - windows: PositiveInteger, - linux: PositiveInteger, - macos: PositiveInteger, - total: PositiveInteger, - }) -); - -export type ExceptionListSummarySchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.mock.ts deleted file mode 100644 index 7f6ec6e8bd5c1..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.mock.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FoundAllListItemsSchema } from '.'; -import { getListItemResponseMock } from '../list_item_schema/index.mock'; - -export const getFoundAllListItemsSchemaMock = (): FoundAllListItemsSchema => ({ - data: [getListItemResponseMock()], - total: 1, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.ts deleted file mode 100644 index f8e6dc43647fd..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { listItemSchema } from '../list_item_schema'; -import { total } from '../../common/total'; - -export const foundAllListItemsSchema = t.exact( - t.type({ - data: t.array(listItemSchema), - total, - }) -); - -export type FoundAllListItemsSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.mock.ts deleted file mode 100644 index 8a7abc59a9cdc..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FoundExceptionListItemSchema } from '.'; -import { getExceptionListItemSchemaMock } from '../exception_list_item_schema/index.mock'; - -export const getFoundExceptionListItemSchemaMock = (): FoundExceptionListItemSchema => ({ - data: [getExceptionListItemSchemaMock()], - page: 1, - per_page: 1, - total: 1, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.test.ts deleted file mode 100644 index eeaeee26fac49..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getFoundExceptionListItemSchemaMock } from './index.mock'; -import { FoundExceptionListItemSchema, foundExceptionListItemSchema } from '.'; -import { ExceptionListItemSchema } from '../exception_list_item_schema'; -import { getExceptionListItemSchemaMock } from '../exception_list_item_schema/index.mock'; - -describe('found_exception_list_item_schema', () => { - test('it should validate a typical exception list response', () => { - const payload = getFoundExceptionListItemSchemaMock(); - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept a malformed exception list item within "data"', () => { - const item: Omit & { - entries?: string; - } = { ...getExceptionListItemSchemaMock(), entries: 'I should be an array' }; - const payload: Omit & { - data?: Array< - Omit & { - entries?: string; - } - >; - } = { ...getFoundExceptionListItemSchemaMock(), data: [item] }; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "I should be an array" supplied to "data,entries"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept a string for "page"', () => { - const payload: Omit & { - page?: string; - } = { ...getFoundExceptionListItemSchemaMock(), page: '1' }; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "page"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept a string for "per_page"', () => { - const payload: Omit & { - per_page?: string; - } = { ...getFoundExceptionListItemSchemaMock(), per_page: '20' }; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "20" supplied to "per_page"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept a string for "total"', () => { - const payload: Omit & { - total?: string; - } = { ...getFoundExceptionListItemSchemaMock(), total: '1' }; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "total"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "page"', () => { - const payload = getFoundExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.page; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "page"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "per_page"', () => { - const payload = getFoundExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.per_page; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "per_page"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "total"', () => { - const payload = getFoundExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.total; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "total"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "data"', () => { - const payload = getFoundExceptionListItemSchemaMock(); - // @ts-expect-error - delete payload.data; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "data"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: FoundExceptionListItemSchema & { - extraKey?: string; - } = getFoundExceptionListItemSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = foundExceptionListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.ts deleted file mode 100644 index 6e34672f3349c..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { page } from '../../common/page'; -import { per_page } from '../../common/per_page'; -import { pitId } from '../../common/pit'; -import { total } from '../../common/total'; -import { exceptionListItemSchema } from '../exception_list_item_schema'; - -export const foundExceptionListItemSchema = t.intersection([ - t.exact( - t.type({ - data: t.array(exceptionListItemSchema), - page, - per_page, - total, - }) - ), - t.exact( - t.partial({ - pit: pitId, - }) - ), -]); - -export type FoundExceptionListItemSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.mock.ts deleted file mode 100644 index 5a4aa9fcbe577..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.mock.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FoundExceptionListSchema } from '.'; -import { getExceptionListSchemaMock } from '../exception_list_schema/index.mock'; - -export const getFoundExceptionListSchemaMock = (): FoundExceptionListSchema => ({ - data: [getExceptionListSchemaMock()], - page: 1, - per_page: 1, - total: 1, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.test.ts deleted file mode 100644 index 07b302c801708..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getFoundExceptionListSchemaMock } from './index.mock'; -import { FoundExceptionListSchema, foundExceptionListSchema } from '.'; -import { getExceptionListSchemaMock } from '../exception_list_schema/index.mock'; -import { ExceptionListSchema } from '../exception_list_schema'; - -describe('exception_list_schema', () => { - test('it should validate a typical exception list response', () => { - const payload = getFoundExceptionListSchemaMock(); - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept a malformed exception list item within "data"', () => { - const item: Omit & { - entries?: string[]; - } = { ...getExceptionListSchemaMock(), entries: ['I should not be here'] }; - const payload: Omit & { - data?: Array< - Omit & { - entries?: string[]; - } - >; - } = { ...getFoundExceptionListSchemaMock(), data: [item] }; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'invalid keys "entries,["I should not be here"]"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept a string for "page"', () => { - const payload: Omit & { - page?: string; - } = { ...getFoundExceptionListSchemaMock(), page: '1' }; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "page"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept a string for "per_page"', () => { - const payload: Omit & { - per_page?: string; - } = { ...getFoundExceptionListSchemaMock(), per_page: '20' }; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "20" supplied to "per_page"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept a string for "total"', () => { - const payload: Omit & { - total?: string; - } = { ...getFoundExceptionListSchemaMock(), total: '1' }; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "total"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "page"', () => { - const payload = getFoundExceptionListSchemaMock(); - // @ts-expect-error - delete payload.page; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "page"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "per_page"', () => { - const payload = getFoundExceptionListSchemaMock(); - // @ts-expect-error - delete payload.per_page; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "per_page"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "total"', () => { - const payload = getFoundExceptionListSchemaMock(); - // @ts-expect-error - delete payload.total; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "total"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "data"', () => { - const payload = getFoundExceptionListSchemaMock(); - // @ts-expect-error - delete payload.data; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "data"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: FoundExceptionListSchema & { - extraKey?: string; - } = getFoundExceptionListSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = foundExceptionListSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.ts deleted file mode 100644 index de4a222b61e78..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { page } from '../../common/page'; -import { per_page } from '../../common/per_page'; -import { pitId } from '../../common/pit'; -import { total } from '../../common/total'; - -import { exceptionListSchema } from '../exception_list_schema'; - -export const foundExceptionListSchema = t.intersection([ - t.exact( - t.type({ - data: t.array(exceptionListSchema), - page, - per_page, - total, - }) - ), - t.exact(t.partial({ pit: pitId })), -]); - -export type FoundExceptionListSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.mock.ts deleted file mode 100644 index 3f20835657432..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.mock.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FoundListItemSchema } from '.'; -import { getListItemResponseMock } from '../list_item_schema/index.mock'; - -export const getFoundListItemSchemaMock = (): FoundListItemSchema => ({ - cursor: 'WzI1LFsiNmE3NmI2OWQtODBkZi00YWIyLThjM2UtODVmNDY2YjA2YTBlIl1d', - data: [getListItemResponseMock()], - page: 1, - per_page: 25, - total: 1, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.ts deleted file mode 100644 index 872a178b2f130..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { listItemSchema } from '../list_item_schema'; -import { cursor } from '../../common/cursor'; -import { page } from '../../common/page'; -import { per_page } from '../../common/per_page'; -import { total } from '../../common/total'; - -export const foundListItemSchema = t.exact( - t.type({ - cursor, - data: t.array(listItemSchema), - page, - per_page, - total, - }) -); - -export type FoundListItemSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.mock.ts deleted file mode 100644 index 232de4d47c156..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.mock.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FoundListSchema } from '.'; -import { getListResponseMock } from '../list_schema/index.mock'; - -export const getFoundListSchemaMock = (): FoundListSchema => ({ - cursor: '123', - data: [getListResponseMock()], - page: 1, - per_page: 1, - total: 1, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.ts deleted file mode 100644 index 6b97b8c73e634..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { listSchema } from '../list_schema'; -import { cursor } from '../../common/cursor'; -import { page } from '../../common/page'; -import { per_page } from '../../common/per_page'; -import { total } from '../../common/total'; - -export const foundListSchema = t.exact( - t.type({ - cursor, - data: t.array(listSchema), - page, - per_page, - total, - }) -); - -export type FoundListSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.mock.ts deleted file mode 100644 index bd654ccde56e8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.mock.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { FoundListsBySizeSchema } from '.'; -import { getListResponseMock } from '../list_schema/index.mock'; - -export const getFoundListsBySizeSchemaMock = (): FoundListsBySizeSchema => ({ - smallLists: [getListResponseMock()], - largeLists: [getListResponseMock()], -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.ts deleted file mode 100644 index b4d41484bf269..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { listSchema } from '../list_schema'; - -export const foundListsBySizeSchema = t.exact( - t.type({ - largeLists: t.array(listSchema), - smallLists: t.array(listSchema), - }) -); - -export type FoundListsBySizeSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.mock.ts deleted file mode 100644 index b1502381013c3..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.mock.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ImportExceptionsResponseSchema } from '.'; - -export const getImportExceptionsResponseSchemaMock = ( - success = 0, - lists = 0, - items = 0 -): ImportExceptionsResponseSchema => ({ - errors: [], - success: true, - success_count: success, - success_exception_lists: true, - success_count_exception_lists: lists, - success_exception_list_items: true, - success_count_exception_list_items: items, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.test.ts deleted file mode 100644 index 81dd87bf19a56..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.test.ts +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { importExceptionsResponseSchema, ImportExceptionsResponseSchema } from '.'; -import { getImportExceptionsResponseSchemaMock } from './index.mock'; - -describe('importExceptionsResponseSchema', () => { - test('it should validate a typical exceptions import response', () => { - const payload = getImportExceptionsResponseSchemaMock(); - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "errors"', () => { - const payload: Partial> = - getImportExceptionsResponseSchemaMock(); - delete payload.errors; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "errors"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "success"', () => { - const payload: Partial> = - getImportExceptionsResponseSchemaMock(); - delete payload.success; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "success"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "success_count"', () => { - const payload: Partial> = - getImportExceptionsResponseSchemaMock(); - delete payload.success_count; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "success_count"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "success_exception_lists"', () => { - const payload: Partial> = - getImportExceptionsResponseSchemaMock(); - delete payload.success_exception_lists; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "success_exception_lists"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "success_count_exception_lists"', () => { - const payload: Partial> = - getImportExceptionsResponseSchemaMock(); - delete payload.success_count_exception_lists; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "success_count_exception_lists"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "success_exception_list_items"', () => { - const payload: Partial> = - getImportExceptionsResponseSchemaMock(); - delete payload.success_exception_list_items; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "success_exception_list_items"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "success_count_exception_list_items"', () => { - const payload: Partial> = - getImportExceptionsResponseSchemaMock(); - delete payload.success_count_exception_list_items; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "success_count_exception_list_items"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ImportExceptionsResponseSchema & { - extraKey?: string; - } = getImportExceptionsResponseSchemaMock(); - payload.extraKey = 'some new value'; - const decoded = importExceptionsResponseSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.ts deleted file mode 100644 index b976ab298e0c7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { PositiveInteger } from '@kbn/securitysolution-io-ts-types'; - -import { id } from '../../common/id'; -import { list_id } from '../../common/list_id'; -import { item_id } from '../../common/item_id'; - -export const bulkErrorErrorSchema = t.exact( - t.type({ - status_code: t.number, - message: t.string, - }) -); - -export const bulkErrorSchema = t.intersection([ - t.exact( - t.type({ - error: bulkErrorErrorSchema, - }) - ), - t.partial({ - id, - list_id, - item_id, - }), -]); - -export type BulkErrorSchema = t.TypeOf; - -export const importExceptionsResponseSchema = t.exact( - t.type({ - errors: t.array(bulkErrorSchema), - success: t.boolean, - success_count: PositiveInteger, - success_exception_lists: t.boolean, - success_count_exception_lists: PositiveInteger, - success_exception_list_items: t.boolean, - success_count_exception_list_items: PositiveInteger, - }) -); - -export type ImportExceptionsResponseSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/index.ts deleted file mode 100644 index 49c42783473d7..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './acknowledge_schema'; -export * from './create_endpoint_list_schema'; -export * from './exception_list_schema'; -export * from './exception_list_item_schema'; -export * from './found_exception_list_item_schema'; -export * from './found_exception_list_schema'; -export * from './found_all_list_items_schema'; -export * from './found_lists_by_size_schema'; -export * from './found_list_item_schema'; -export * from './found_list_schema'; -export * from './import_exceptions_schema'; -export * from './list_item_schema'; -export * from './list_schema'; -export * from './exception_list_summary_schema'; -export * from './list_item_index_exist_schema'; -export * from './search_list_item_schema'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.mock.ts deleted file mode 100644 index eff892b3f00bb..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.mock.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ListItemIndexExistSchema } from '.'; - -export const getListItemIndexExistSchemaResponseMock = (): ListItemIndexExistSchema => ({ - list_index: true, - list_item_index: true, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.test.ts deleted file mode 100644 index 2827cd3627344..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getListItemIndexExistSchemaResponseMock } from './index.mock'; -import { ListItemIndexExistSchema, listItemIndexExistSchema } from '.'; - -describe('list_item_index_exist_schema', () => { - test('it should validate a typical list item request', () => { - const payload = getListItemIndexExistSchemaResponseMock(); - const decoded = listItemIndexExistSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "list_index"', () => { - const payload = getListItemIndexExistSchemaResponseMock(); - // @ts-expect-error - delete payload.list_index; - const decoded = listItemIndexExistSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_index"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "list_item_index"', () => { - const payload = getListItemIndexExistSchemaResponseMock(); - // @ts-expect-error - delete payload.list_item_index; - const decoded = listItemIndexExistSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_item_index"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ListItemIndexExistSchema & { - extraKey?: string; - } = getListItemIndexExistSchemaResponseMock(); - payload.extraKey = 'some new value'; - const decoded = listItemIndexExistSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.ts deleted file mode 100644 index 494af4e3e7590..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -export const listItemIndexExistSchema = t.exact( - t.type({ - list_index: t.boolean, - list_item_index: t.boolean, - }) -); - -export type ListItemIndexExistSchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts deleted file mode 100644 index 22c2e5ae07f61..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ListItemSchema } from '.'; -import { - DATE_NOW, - ELASTIC_USER, - LIST_ID, - LIST_ITEM_ID, - META, - TIE_BREAKER, - TYPE, - USER, - VALUE, -} from '../../constants/index.mock'; - -export const getListItemResponseMock = (): ListItemSchema => ({ - _version: undefined, - '@timestamp': DATE_NOW, - created_at: DATE_NOW, - created_by: USER, - deserializer: undefined, - id: LIST_ITEM_ID, - list_id: LIST_ID, - meta: META, - serializer: undefined, - tie_breaker_id: TIE_BREAKER, - type: TYPE, - updated_at: DATE_NOW, - updated_by: USER, - value: VALUE, -}); - -/** - * This is useful for end to end tests where we remove the auto generated parts for comparisons - * such as created_at, updated_at, and id. - */ -export const getListItemResponseMockWithoutAutoGeneratedValues = (): Partial => ({ - created_by: ELASTIC_USER, - list_id: LIST_ID, - type: TYPE, - updated_by: ELASTIC_USER, - value: VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.test.ts deleted file mode 100644 index 5b4238e136dc6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.test.ts +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getListItemResponseMock } from './index.mock'; -import { ListItemSchema, listItemSchema } from '.'; - -describe('list_item_schema', () => { - test('it should validate a typical list item response', () => { - const payload = getListItemResponseMock(); - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "id"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.id; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "list_id"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.list_id; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "list_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta"', () => { - const payload = getListItemResponseMock(); - delete payload.meta; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "serializer"', () => { - const payload = getListItemResponseMock(); - delete payload.serializer; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "deserializer"', () => { - const payload = getListItemResponseMock(); - delete payload.deserializer; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "created_at"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.created_at; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "created_by"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.created_by; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "tie_breaker_id"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.tie_breaker_id; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "tie_breaker_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "type"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.type; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_at"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.updated_at; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_by"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.updated_by; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "value"', () => { - const payload = getListItemResponseMock(); - // @ts-expect-error - delete payload.value; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "value"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ListItemSchema & { extraKey?: string } = getListItemResponseMock(); - payload.extraKey = 'some new value'; - const decoded = listItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts deleted file mode 100644 index 869ca695fa42e..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; - -import { _versionOrUndefined } from '../../common/underscore_version'; -import { deserializerOrUndefined } from '../../common/deserializer'; -import { metaOrUndefined } from '../../common/meta'; -import { timestampOrUndefined } from '../../common/timestamp'; -import { serializerOrUndefined } from '../../common/serializer'; -import { created_at } from '../../common/created_at'; -import { created_by } from '../../common/created_by'; -import { id } from '../../common/id'; -import { tie_breaker_id } from '../../common/tie_breaker_id'; -import { type } from '../../common/type'; -import { updated_at } from '../../common/updated_at'; -import { updated_by } from '../../common/updated_by'; -import { list_id } from '../../common/list_id'; -import { value } from '../../common/value'; - -export const listItemSchema = t.exact( - t.type({ - _version: _versionOrUndefined, - '@timestamp': timestampOrUndefined, - created_at, - created_by, - deserializer: deserializerOrUndefined, - id, - list_id, - meta: metaOrUndefined, - serializer: serializerOrUndefined, - tie_breaker_id, - type, - updated_at, - updated_by, - value, - }) -); - -export type ListItemSchema = t.TypeOf; - -export const listItemArraySchema = t.array(listItemSchema); -export type ListItemArraySchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts deleted file mode 100644 index 7a0b9e01b87c5..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ListSchema } from '.'; -import { - DATE_NOW, - DESCRIPTION, - ELASTIC_USER, - IMMUTABLE, - LIST_ID, - META, - NAME, - TIE_BREAKER, - TYPE, - USER, - VERSION, -} from '../../constants/index.mock'; - -export const getListResponseMock = (): ListSchema => ({ - _version: undefined, - '@timestamp': DATE_NOW, - created_at: DATE_NOW, - created_by: USER, - description: DESCRIPTION, - deserializer: undefined, - id: LIST_ID, - immutable: IMMUTABLE, - meta: META, - name: NAME, - serializer: undefined, - tie_breaker_id: TIE_BREAKER, - type: TYPE, - updated_at: DATE_NOW, - updated_by: USER, - version: VERSION, -}); - -/** - * This is useful for end to end tests where we remove the auto generated parts for comparisons - * such as created_at, updated_at, and id. - */ -export const getListResponseMockWithoutAutoGeneratedValues = (): Partial => ({ - created_by: ELASTIC_USER, - description: DESCRIPTION, - immutable: IMMUTABLE, - name: NAME, - type: TYPE, - updated_by: ELASTIC_USER, - version: VERSION, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.test.ts deleted file mode 100644 index 17f25de7d8ec2..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.test.ts +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getListResponseMock } from './index.mock'; -import { ListSchema, listSchema } from '.'; - -describe('list_schema', () => { - test('it should validate a typical list response', () => { - const payload = getListResponseMock(); - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "id"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.id; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); - expect(message.schema).toEqual({}); - }); - - test('it should accept an undefined for "meta"', () => { - const payload = getListResponseMock(); - delete payload.meta; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "serializer"', () => { - const payload = getListResponseMock(); - delete payload.serializer; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should accept an undefined for "deserializer"', () => { - const payload = getListResponseMock(); - delete payload.deserializer; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT accept an undefined for "created_at"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.created_at; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "created_by"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.created_by; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "created_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "tie_breaker_id"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.tie_breaker_id; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "tie_breaker_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "type"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.type; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_at"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.updated_at; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_at"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "updated_by"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.updated_by; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "updated_by"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "name"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.name; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "name"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT accept an undefined for "description"', () => { - const payload = getListResponseMock(); - // @ts-expect-error - delete payload.description; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "description"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: ListSchema & { extraKey?: string } = getListResponseMock(); - payload.extraKey = 'some new value'; - const decoded = listSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts deleted file mode 100644 index 5029e55df3244..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { version } from '@kbn/securitysolution-io-ts-types'; -import { _versionOrUndefined } from '../../common/underscore_version'; -import { deserializerOrUndefined } from '../../common/deserializer'; -import { metaOrUndefined } from '../../common/meta'; -import { serializerOrUndefined } from '../../common/serializer'; -import { created_at } from '../../common/created_at'; -import { timestampOrUndefined } from '../../common/timestamp'; -import { created_by } from '../../common/created_by'; -import { description } from '../../common/description'; -import { id } from '../../common/id'; -import { immutable } from '../../common/immutable'; -import { name } from '../../common/name'; -import { tie_breaker_id } from '../../common/tie_breaker_id'; -import { type } from '../../common/type'; -import { updated_at } from '../../common/updated_at'; -import { updated_by } from '../../common/updated_by'; - -export const listSchema = t.exact( - t.type({ - _version: _versionOrUndefined, - '@timestamp': timestampOrUndefined, - created_at, - created_by, - description, - deserializer: deserializerOrUndefined, - id, - immutable, - meta: metaOrUndefined, - name, - serializer: serializerOrUndefined, - tie_breaker_id, - type, - updated_at, - updated_by, - version, - }) -); - -export type ListSchema = t.TypeOf; - -export const listArraySchema = t.array(listSchema); -export type ListArraySchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.mock.ts deleted file mode 100644 index 1cab9a6b827c6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.mock.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { SearchListItemSchema } from '.'; -import { VALUE } from '../../constants/index.mock'; -import { getListItemResponseMock } from '../list_item_schema/index.mock'; - -export const getSearchListItemResponseMock = (): SearchListItemSchema => ({ - items: [getListItemResponseMock()], - value: VALUE, -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.test.ts deleted file mode 100644 index a6604f39b4626..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -import { getSearchListItemResponseMock } from './index.mock'; -import { SearchListItemSchema, searchListItemSchema } from '.'; - -describe('search_list_item_schema', () => { - test('it should validate a typical search list item response', () => { - const payload = getSearchListItemResponseMock(); - const decoded = searchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate with an "undefined" for "items"', () => { - const { items, ...noItems } = getSearchListItemResponseMock(); - const decoded = searchListItemSchema.decode(noItems); - const checked = exactCheck(noItems, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "items"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should not allow an extra key to be sent in', () => { - const payload: SearchListItemSchema & { extraKey?: string } = getSearchListItemResponseMock(); - payload.extraKey = 'some new value'; - const decoded = searchListItemSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); - expect(message.schema).toEqual({}); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts deleted file mode 100644 index c5a07308dd0f8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import * as t from 'io-ts'; -import { listItemArraySchema } from '../list_item_schema'; - -/** - * NOTE: Although this is defined within "response" this does not expose a REST API - * endpoint right now for this particular response. Instead this is only used internally - * for the plugins at this moment. If this changes, please remove this message. - */ -export const searchListItemSchema = t.exact( - t.type({ - items: listItemArraySchema, - value: t.unknown, - }) -); - -export type SearchListItemSchema = t.TypeOf; - -export const searchListItemArraySchema = t.array(searchListItemSchema); -export type SearchListItemArraySchema = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts deleted file mode 100644 index 9a8cd1e4fab56..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts +++ /dev/null @@ -1,244 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { HttpStart } from '@kbn/core-http-browser'; -import type { NotificationsStart } from '@kbn/core-notifications-browser'; -import type { Filter } from '@kbn/es-query'; -import { NamespaceType } from '../common/default_namespace'; -import { ExceptionListType, ExceptionListTypeEnum } from '../common/exception_list'; -import { Page } from '../common/page'; -import { PerPage } from '../common/per_page'; -import { TotalOrUndefined } from '../common/total'; -import { CreateExceptionListItemSchema } from '../request/create_exception_list_item_schema'; -import { CreateExceptionListSchema } from '../request/create_exception_list_schema'; -import { ExceptionListId } from '../request/get_exception_filter_schema'; -import { UpdateExceptionListItemSchema } from '../request/update_exception_list_item_schema'; -import { UpdateExceptionListSchema } from '../request/update_exception_list_schema'; -import { ExceptionListItemSchema } from '../response/exception_list_item_schema'; -import { ExceptionListSchema } from '../response/exception_list_schema'; - -interface BaseParams { - http: HttpStart; - signal: AbortSignal; -} - -export interface DuplicateExceptionListProps extends BaseParams { - listId: string; - namespaceType: NamespaceType; - includeExpiredExceptions: boolean; -} - -export interface ApiListDuplicateProps - extends Omit { - onError: (err: Error) => void; - onSuccess: (newList: ExceptionListSchema) => void; -} - -export interface ExceptionListFilter { - name?: string | null; - list_id?: string | null; - created_by?: string | null; - types?: ExceptionListTypeEnum[] | null; - tags?: string | null; -} - -export interface UseExceptionListsProps { - errorMessage: string; - filterOptions?: ExceptionListFilter; - http: HttpStart; - namespaceTypes: NamespaceType[]; - notifications: NotificationsStart; - initialPagination?: Pagination; - hideLists?: readonly string[]; - initialSort?: Sort; -} - -export interface UseExceptionListProps { - http: HttpStart; - lists: ExceptionListIdentifiers[]; - onError?: (arg: string[]) => void; - filterOptions: FilterExceptionsOptions[]; - pagination?: Pagination; - showDetectionsListsOnly: boolean; - showEndpointListsOnly: boolean; - matchFilters: boolean; - onSuccess?: (arg: UseExceptionListItemsSuccess) => void; - sort?: Sort; -} - -export interface FilterExceptionsOptions { - filter: string; - tags: string[]; -} - -export interface ApiCallMemoProps { - id: string; - namespaceType: NamespaceType; - onError: (arg: Error) => void; - onSuccess: () => void; -} - -// TODO: Switch to use ApiCallMemoProps -// after cleaning up exceptions/api file to -// remove unnecessary validation checks -export interface ApiListExportProps { - id: string; - includeExpiredExceptions: boolean; - listId: string; - namespaceType: NamespaceType; - onError: (err: Error) => void; - onSuccess: (blob: Blob) => void; -} - -export interface Sort { - field: string; - order: string; -} -export interface Pagination { - page: Page; - perPage: PerPage; - total: TotalOrUndefined; -} - -export interface UseExceptionListItemsSuccess { - exceptions: ExceptionListItemSchema[]; - pagination: Pagination; -} - -export interface ExceptionListIdentifiers { - id: string; - listId: string; - namespaceType: NamespaceType; - type: ExceptionListType; -} - -export interface ApiCallFindListsItemsMemoProps { - lists: ExceptionListIdentifiers[]; - pagination: Partial; - showDetectionsListsOnly: boolean; - showEndpointListsOnly: boolean; - filter?: string; - onError: (arg: string[]) => void; - onSuccess: (arg: UseExceptionListItemsSuccess) => void; -} - -export interface ApiCallGetExceptionFilterFromIdsMemoProps extends GetExceptionFilterOptionalProps { - exceptionListIds: ExceptionListId[]; - onError: (arg: string[]) => void; - onSuccess: (arg: Filter) => void; -} - -export interface ApiCallGetExceptionFilterFromExceptionsMemoProps - extends GetExceptionFilterOptionalProps { - exceptions: Array; - onError: (arg: string[]) => void; - onSuccess: (arg: Filter) => void; -} - -export interface ExportExceptionListProps { - http: HttpStart; - id: string; - listId: string; - namespaceType: NamespaceType; - includeExpiredExceptions: boolean; - signal: AbortSignal; -} - -export interface AddEndpointExceptionListProps { - http: HttpStart; - signal: AbortSignal; -} - -export interface UpdateExceptionListItemProps { - http: HttpStart; - listItem: UpdateExceptionListItemSchema; - signal: AbortSignal; -} - -export interface UpdateExceptionListProps { - http: HttpStart; - list: UpdateExceptionListSchema; - signal: AbortSignal; -} - -export interface AddExceptionListItemProps { - http: HttpStart; - listItem: CreateExceptionListItemSchema; - signal: AbortSignal; -} - -export interface AddExceptionListProps { - http: HttpStart; - list: CreateExceptionListSchema; - signal: AbortSignal; -} - -export interface UseExceptionListsSuccess { - exceptions: ExceptionListSchema[]; - pagination: Pagination; -} - -export interface ApiCallFetchExceptionListsProps { - http: HttpStart; - namespaceTypes: string; - pagination: Partial; - sort?: Sort; - filters: string; - signal: AbortSignal; -} - -export interface ApiCallByIdProps { - http: HttpStart; - id: string; - namespaceType: NamespaceType; - signal: AbortSignal; -} - -export interface ApiCallByListIdProps { - http: HttpStart; - listIds: string[]; - namespaceTypes: NamespaceType[]; - pagination: Partial; - search?: string; - filter?: string; - signal: AbortSignal; -} - -export type AddExceptionList = UpdateExceptionListSchema | CreateExceptionListSchema; - -export interface PersistHookProps { - http: HttpStart; - onError: (arg: Error) => void; -} - -export interface ExceptionList extends ExceptionListSchema { - totalItems: number; -} - -export interface GetExceptionFilterOptionalProps { - signal?: AbortSignal; - chunkSize?: number; - alias?: string; - excludeExceptions?: boolean; -} - -export interface GetExceptionFilterFromExceptionListIdsProps - extends GetExceptionFilterOptionalProps { - http: HttpStart; - exceptionListIds: ExceptionListId[]; -} - -export interface GetExceptionFilterFromExceptionsProps extends GetExceptionFilterOptionalProps { - http: HttpStart; - exceptions: Array; -} - -export interface ExceptionFilterResponse { - filter: Filter; -} diff --git a/packages/kbn-securitysolution-io-ts-list-types/tsconfig.json b/packages/kbn-securitysolution-io-ts-list-types/tsconfig.json deleted file mode 100644 index 706aa6e81fc59..0000000000000 --- a/packages/kbn-securitysolution-io-ts-list-types/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": ["jest", "node"] - }, - "include": ["**/*.ts"], - "kbn_references": [ - "@kbn/securitysolution-io-ts-types", - "@kbn/securitysolution-io-ts-utils", - "@kbn/securitysolution-list-constants", - "@kbn/es-query", - "@kbn/core-http-browser", - "@kbn/core-notifications-browser", - "@kbn/securitysolution-exceptions-common" - ], - "exclude": ["target/**/*"] -} diff --git a/packages/kbn-securitysolution-io-ts-types/jest.config.js b/packages/kbn-securitysolution-io-ts-types/jest.config.js deleted file mode 100644 index c6efe620b09f8..0000000000000 --- a/packages/kbn-securitysolution-io-ts-types/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-io-ts-types'], -}; diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_uuid/index.test.ts b/packages/kbn-securitysolution-io-ts-types/src/default_uuid/index.test.ts deleted file mode 100644 index c429529167e52..0000000000000 --- a/packages/kbn-securitysolution-io-ts-types/src/default_uuid/index.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; -import { DefaultUuid } from '.'; -import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('default_uuid', () => { - test('it should validate a regular string', () => { - const payload = '1'; - const decoded = DefaultUuid.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should not validate a number', () => { - const payload = 5; - const decoded = DefaultUuid.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['Invalid value "5" supplied to "DefaultUuid"']); - expect(message.schema).toEqual({}); - }); - - test('it should return a default of a uuid', () => { - const payload = null; - const decoded = DefaultUuid.decode(payload); - const message = pipe(decoded, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toMatch( - /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i - ); - }); -}); diff --git a/packages/kbn-securitysolution-io-ts-types/tsconfig.json b/packages/kbn-securitysolution-io-ts-types/tsconfig.json deleted file mode 100644 index 25b82d38b7dc9..0000000000000 --- a/packages/kbn-securitysolution-io-ts-types/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/securitysolution-io-ts-utils" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-io-ts-utils/jest.config.js b/packages/kbn-securitysolution-io-ts-utils/jest.config.js deleted file mode 100644 index 457ac315951b6..0000000000000 --- a/packages/kbn-securitysolution-io-ts-utils/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-io-ts-utils'], -}; diff --git a/packages/kbn-securitysolution-io-ts-utils/tsconfig.json b/packages/kbn-securitysolution-io-ts-utils/tsconfig.json deleted file mode 100644 index 13f8244edd1ad..0000000000000 --- a/packages/kbn-securitysolution-io-ts-utils/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/datemath" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-list-api/index.ts b/packages/kbn-securitysolution-list-api/index.ts deleted file mode 100644 index fc434f01c7ecb..0000000000000 --- a/packages/kbn-securitysolution-list-api/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/api'; -export * from './src/fp_utils'; -export * from './src/list_api'; -export * from './src/list_item_api'; -export * from './src/types'; diff --git a/packages/kbn-securitysolution-list-api/jest.config.js b/packages/kbn-securitysolution-list-api/jest.config.js deleted file mode 100644 index 434cef2b7ca33..0000000000000 --- a/packages/kbn-securitysolution-list-api/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-list-api'], -}; diff --git a/packages/kbn-securitysolution-list-api/package.json b/packages/kbn-securitysolution-list-api/package.json deleted file mode 100644 index bcb7a79accdc5..0000000000000 --- a/packages/kbn-securitysolution-list-api/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/securitysolution-list-api", - "version": "1.0.0", - "description": "security solution list REST API", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-list-api/src/api/index.ts b/packages/kbn-securitysolution-list-api/src/api/index.ts deleted file mode 100644 index 4bd188672e5a9..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/api/index.ts +++ /dev/null @@ -1,666 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { chain, fromEither, tryCatch } from 'fp-ts/lib/TaskEither'; -import { flow } from 'fp-ts/lib/function'; -import { validateEither } from '@kbn/securitysolution-io-ts-utils'; -import { - CreateEndpointListSchema, - ExceptionListItemSchema, - ExceptionListSchema, - FoundExceptionListItemSchema, - FoundExceptionListSchema, - createEndpointListSchema, - exceptionListItemSchema, - exceptionListSchema, - foundExceptionListItemSchema, - foundExceptionListSchema, - AddEndpointExceptionListProps, - AddExceptionListItemProps, - AddExceptionListProps, - ApiCallByIdProps, - ApiCallByListIdProps, - ApiCallFetchExceptionListsProps, - ExportExceptionListProps, - UpdateExceptionListItemProps, - UpdateExceptionListProps, - GetExceptionFilterFromExceptionListIdsProps, - GetExceptionFilterFromExceptionsProps, - ExceptionFilterResponse, - DuplicateExceptionListProps, -} from '@kbn/securitysolution-io-ts-list-types'; - -import { - ENDPOINT_LIST_URL, - INTERNAL_EXCEPTION_FILTER, - EXCEPTION_LIST_ITEM_URL, - EXCEPTION_LIST_URL, -} from '@kbn/securitysolution-list-constants'; -import { toError, toPromise } from '../fp_utils'; - -const version = '2023-10-31'; - -/** - * Add new ExceptionList - * - * @param http Kibana http service - * @param list exception list to add - * @param signal to cancel request - * - * @throws An error if response is not OK - * - */ -const addExceptionList = async ({ - http, - list, - signal, -}: AddExceptionListProps): Promise => - http.fetch(EXCEPTION_LIST_URL, { - body: JSON.stringify(list), - method: 'POST', - signal, - version, - }); - -const addExceptionListWithValidation = async ({ - http, - list, - signal, -}: AddExceptionListProps): Promise => - flow( - () => - tryCatch( - () => - addExceptionList({ - http, - list, - signal, - }), - toError - ), - chain((response) => fromEither(validateEither(exceptionListSchema, response))), - flow(toPromise) - )(); - -export { addExceptionListWithValidation as addExceptionList }; - -/** - * Add new ExceptionListItem - * - * @param http Kibana http service - * @param listItem exception list item to add - * @param signal to cancel request - * - * @throws An error if response is not OK - * - */ -const addExceptionListItem = async ({ - http, - listItem, - signal, -}: AddExceptionListItemProps): Promise => - http.fetch(EXCEPTION_LIST_ITEM_URL, { - body: JSON.stringify(listItem), - method: 'POST', - signal, - version, - }); - -const addExceptionListItemWithValidation = async ({ - http, - listItem, - signal, -}: AddExceptionListItemProps): Promise => - flow( - () => - tryCatch( - () => - addExceptionListItem({ - http, - listItem, - signal, - }), - toError - ), - chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), - flow(toPromise) - )(); - -export { addExceptionListItemWithValidation as addExceptionListItem }; - -/** - * Update existing ExceptionList - * - * @param http Kibana http service - * @param list exception list to add - * @param signal to cancel request - * - * @throws An error if response is not OK - * - */ -const updateExceptionList = async ({ - http, - list, - signal, -}: UpdateExceptionListProps): Promise => - http.fetch(EXCEPTION_LIST_URL, { - body: JSON.stringify(list), - method: 'PUT', - signal, - version, - }); - -const updateExceptionListWithValidation = async ({ - http, - list, - signal, -}: UpdateExceptionListProps): Promise => - flow( - () => - tryCatch( - () => - updateExceptionList({ - http, - list, - signal, - }), - toError - ), - chain((response) => fromEither(validateEither(exceptionListSchema, response))), - flow(toPromise) - )(); - -export { updateExceptionListWithValidation as updateExceptionList }; - -/** - * Update existing ExceptionListItem - * - * @param http Kibana http service - * @param listItem exception list item to add - * @param signal to cancel request - * - * @throws An error if response is not OK - * - */ -const updateExceptionListItem = async ({ - http, - listItem, - signal, -}: UpdateExceptionListItemProps): Promise => - http.fetch(EXCEPTION_LIST_ITEM_URL, { - body: JSON.stringify(listItem), - method: 'PUT', - signal, - version, - }); - -const updateExceptionListItemWithValidation = async ({ - http, - listItem, - signal, -}: UpdateExceptionListItemProps): Promise => - flow( - () => - tryCatch( - () => - updateExceptionListItem({ - http, - listItem, - signal, - }), - toError - ), - chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), - flow(toPromise) - )(); - -export { updateExceptionListItemWithValidation as updateExceptionListItem }; - -/** - * Fetch all ExceptionLists (optionally by namespaceType) - * - * @param http Kibana http service - * @param namespaceTypes ExceptionList namespace_types of lists to find - * @param filters search bar filters - * @param pagination optional - * @param signal to cancel request - * - * @throws An error if request params or response is not OK - */ -const fetchExceptionLists = async ({ - http, - filters, - namespaceTypes, - pagination, - signal, - sort, -}: ApiCallFetchExceptionListsProps): Promise => { - const query = { - filter: filters || undefined, - namespace_type: namespaceTypes, - page: pagination.page ? `${pagination.page}` : '1', - per_page: pagination.perPage ? `${pagination.perPage}` : '20', - sort_field: sort?.field ? sort?.field : 'exception-list.created_at', - sort_order: sort?.order ? sort?.order : 'desc', - }; - - return http.fetch(`${EXCEPTION_LIST_URL}/_find`, { - method: 'GET', - query, - signal, - version, - }); -}; - -const fetchExceptionListsWithValidation = async ({ - filters, - http, - namespaceTypes, - pagination, - signal, - sort, -}: ApiCallFetchExceptionListsProps): Promise => - flow( - () => - tryCatch( - () => - fetchExceptionLists({ - filters, - http, - namespaceTypes, - pagination, - signal, - sort, - }), - toError - ), - chain((response) => fromEither(validateEither(foundExceptionListSchema, response))), - flow(toPromise) - )(); - -export { fetchExceptionListsWithValidation as fetchExceptionLists }; - -/** - * Fetch an ExceptionList by providing a ExceptionList ID - * - * @param http Kibana http service - * @param id ExceptionList ID (not list_id) - * @param namespaceType ExceptionList namespace_type - * @param signal to cancel request - * - * @throws An error if response is not OK - */ -const fetchExceptionListById = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - http.fetch(EXCEPTION_LIST_URL, { - method: 'GET', - query: { id, namespace_type: namespaceType }, - signal, - version, - }); - -const fetchExceptionListByIdWithValidation = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - flow( - () => - tryCatch( - () => - fetchExceptionListById({ - http, - id, - namespaceType, - signal, - }), - toError - ), - chain((response) => fromEither(validateEither(exceptionListSchema, response))), - flow(toPromise) - )(); - -export { fetchExceptionListByIdWithValidation as fetchExceptionListById }; - -/** - * Fetch an ExceptionList's ExceptionItems by providing a ExceptionList list_id - * - * @param http Kibana http service - * @param listIds ExceptionList list_ids (not ID) - * @param namespaceTypes ExceptionList namespace_types - * @param search optional - simple search string - * @param filter optional - * @param pagination optional - * @param signal to cancel request - * - * @throws An error if response is not OK - */ -const fetchExceptionListsItemsByListIds = async ({ - http, - listIds, - namespaceTypes, - filter, - pagination, - search, - signal, -}: ApiCallByListIdProps): Promise => { - const query = { - list_id: listIds.join(','), - namespace_type: namespaceTypes.join(','), - page: pagination.page ? `${pagination.page}` : '1', - per_page: pagination.perPage ? `${pagination.perPage}` : '20', - search, - sort_field: 'exception-list.created_at', - sort_order: 'desc', - filter, - }; - - return http.fetch(`${EXCEPTION_LIST_ITEM_URL}/_find`, { - method: 'GET', - query, - signal, - version, - }); -}; - -const fetchExceptionListsItemsByListIdsWithValidation = async ({ - filter, - http, - listIds, - namespaceTypes, - pagination, - search, - signal, -}: ApiCallByListIdProps): Promise => - flow( - () => - tryCatch( - () => - fetchExceptionListsItemsByListIds({ - filter, - http, - listIds, - namespaceTypes, - pagination, - search, - signal, - }), - toError - ), - chain((response) => fromEither(validateEither(foundExceptionListItemSchema, response))), - flow(toPromise) - )(); - -export { fetchExceptionListsItemsByListIdsWithValidation as fetchExceptionListsItemsByListIds }; - -/** - * Fetch an ExceptionListItem by providing a ExceptionListItem ID - * - * @param http Kibana http service - * @param id ExceptionListItem ID (not item_id) - * @param namespaceType ExceptionList namespace_type - * @param signal to cancel request - * - * @throws An error if response is not OK - */ -const fetchExceptionListItemById = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - http.fetch(EXCEPTION_LIST_ITEM_URL, { - method: 'GET', - query: { id, namespace_type: namespaceType }, - signal, - version, - }); - -const fetchExceptionListItemByIdWithValidation = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - flow( - () => tryCatch(() => fetchExceptionListItemById({ http, id, namespaceType, signal }), toError), - chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), - flow(toPromise) - )(); - -export { fetchExceptionListItemByIdWithValidation as fetchExceptionListItemById }; - -/** - * Delete an ExceptionList by providing a ExceptionList ID - * - * @param http Kibana http service - * @param id ExceptionList ID (not list_id) - * @param namespaceType ExceptionList namespace_type - * @param signal to cancel request - * - * @throws An error if response is not OK - */ -const deleteExceptionListById = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - http.fetch(EXCEPTION_LIST_URL, { - method: 'DELETE', - query: { id, namespace_type: namespaceType }, - signal, - version, - }); - -const deleteExceptionListByIdWithValidation = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - flow( - () => tryCatch(() => deleteExceptionListById({ http, id, namespaceType, signal }), toError), - chain((response) => fromEither(validateEither(exceptionListSchema, response))), - flow(toPromise) - )(); - -export { deleteExceptionListByIdWithValidation as deleteExceptionListById }; - -/** - * Delete an ExceptionListItem by providing a ExceptionListItem ID - * - * @param http Kibana http service - * @param id ExceptionListItem ID (not item_id) - * @param namespaceType ExceptionList namespace_type - * @param signal to cancel request - * - * @throws An error if response is not OK - */ -const deleteExceptionListItemById = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - http.fetch(EXCEPTION_LIST_ITEM_URL, { - method: 'DELETE', - query: { id, namespace_type: namespaceType }, - signal, - version, - }); - -const deleteExceptionListItemByIdWithValidation = async ({ - http, - id, - namespaceType, - signal, -}: ApiCallByIdProps): Promise => - flow( - () => tryCatch(() => deleteExceptionListItemById({ http, id, namespaceType, signal }), toError), - chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), - flow(toPromise) - )(); - -export { deleteExceptionListItemByIdWithValidation as deleteExceptionListItemById }; - -/** - * Add new Endpoint ExceptionList - * - * @param http Kibana http service - * @param signal to cancel request - * - * @throws An error if response is not OK - * - */ -const addEndpointExceptionList = async ({ - http, - signal, -}: AddEndpointExceptionListProps): Promise => - http.fetch(ENDPOINT_LIST_URL, { - method: 'POST', - signal, - version, - }); - -const addEndpointExceptionListWithValidation = async ({ - http, - signal, -}: AddEndpointExceptionListProps): Promise => - flow( - () => tryCatch(() => addEndpointExceptionList({ http, signal }), toError), - chain((response) => fromEither(validateEither(createEndpointListSchema, response))), - flow(toPromise) - )(); - -export { addEndpointExceptionListWithValidation as addEndpointExceptionList }; - -/** - * Export an ExceptionList by providing a ExceptionList ID - * - * @param http Kibana http service - * @param id ExceptionList ID (not list_id) - * @param includeExpiredExceptions boolean for including expired exceptions - * @param listId ExceptionList LIST_ID (not id) - * @param namespaceType ExceptionList namespace_type - * @param signal to cancel request - * - * @throws An error if response is not OK - */ -export const exportExceptionList = async ({ - http, - id, - includeExpiredExceptions, - listId, - namespaceType, - signal, -}: ExportExceptionListProps): Promise => - http.fetch(`${EXCEPTION_LIST_URL}/_export`, { - method: 'POST', - query: { - id, - list_id: listId, - namespace_type: namespaceType, - include_expired_exceptions: includeExpiredExceptions, - }, - signal, - version, - }); - -/** - * Create a Filter query from an exception list id - * - * @param exceptionListId The id of the exception list from which create a Filter query - * @param signal AbortSignal for cancelling request - * - * @throws An error if response is not OK - */ -export const getExceptionFilterFromExceptionListIds = async ({ - alias, - chunkSize, - exceptionListIds, - excludeExceptions, - http, - signal, -}: GetExceptionFilterFromExceptionListIdsProps): Promise => - http.fetch(INTERNAL_EXCEPTION_FILTER, { - method: 'POST', - version: '1', - body: JSON.stringify({ - exception_list_ids: exceptionListIds, - type: 'exception_list_ids', - alias, - exclude_exceptions: excludeExceptions, - chunk_size: chunkSize, - }), - signal, - }); - -/** - * Create a Filter query from a list of exceptions - * - * @param exceptions Exception items to be made into a `Filter` query - * @param signal AbortSignal for cancelling request - * - * @throws An error if response is not OK - */ -export const getExceptionFilterFromExceptions = async ({ - exceptions, - alias, - excludeExceptions, - http, - chunkSize, - signal, -}: GetExceptionFilterFromExceptionsProps): Promise => - http.fetch(INTERNAL_EXCEPTION_FILTER, { - method: 'POST', - version: '1', - body: JSON.stringify({ - exceptions, - type: 'exception_items', - alias, - exclude_exceptions: excludeExceptions, - chunk_size: chunkSize, - }), - signal, - }); - -/** - * Duplicate an ExceptionList and its items by providing a ExceptionList list_id - * - * @param http Kibana http service - * @param includeExpiredExceptions boolean for including exception items with expired TTL - * @param listId ExceptionList LIST_ID (not id) - * @param namespaceType ExceptionList namespace_type - * @param signal to cancel request - * - * @throws An error if response is not OK - */ -export const duplicateExceptionList = async ({ - http, - includeExpiredExceptions, - listId, - namespaceType, - signal, -}: DuplicateExceptionListProps): Promise => - http.fetch(`${EXCEPTION_LIST_URL}/_duplicate`, { - method: 'POST', - query: { - list_id: listId, - namespace_type: namespaceType, - include_expired_exceptions: includeExpiredExceptions, - }, - signal, - version, - }); diff --git a/packages/kbn-securitysolution-list-api/src/fp_utils/index.test.ts b/packages/kbn-securitysolution-list-api/src/fp_utils/index.test.ts deleted file mode 100644 index 98872f45cb77c..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/fp_utils/index.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { tryCatch } from 'fp-ts/lib/TaskEither'; - -import { toPromise } from '.'; - -describe('toPromise', () => { - it('rejects with left if TaskEither is left', async () => { - const task = tryCatch(() => Promise.reject(new Error('whoops')), String); - - await expect(toPromise(task)).rejects.toEqual('Error: whoops'); - }); - - it('resolves with right if TaskEither is right', async () => { - const task = tryCatch(() => Promise.resolve('success'), String); - - await expect(toPromise(task)).resolves.toEqual('success'); - }); -}); diff --git a/packages/kbn-securitysolution-list-api/src/fp_utils/index.ts b/packages/kbn-securitysolution-list-api/src/fp_utils/index.ts deleted file mode 100644 index 5614a3e7cb8df..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/fp_utils/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { pipe } from 'fp-ts/lib/pipeable'; -import { TaskEither } from 'fp-ts/lib/TaskEither'; -import { fold } from 'fp-ts/lib/Either'; - -// TODO: This is copied in a few other spots and probably should live within its own kbn package -// rather than living here. A package such as kbn-security-solution-fp-utils -export const toPromise = async (taskEither: TaskEither): Promise => - pipe( - await taskEither(), - fold( - (e) => Promise.reject(e), - (a) => Promise.resolve(a) - ) - ); - -export const toError = (e: unknown): Error => (e instanceof Error ? e : new Error(String(e))); diff --git a/packages/kbn-securitysolution-list-api/src/list_api/index.test.ts b/packages/kbn-securitysolution-list-api/src/list_api/index.test.ts deleted file mode 100644 index 6b8698a707aa2..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_api/index.test.ts +++ /dev/null @@ -1,445 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { createListIndex, deleteList, exportList, findLists, importList, readListIndex } from '.'; -import { - ApiPayload, - DeleteListParams, - ExportListParams, - FindListsParams, - ImportListParams, -} from '../types'; - -import { HttpFetchOptions } from '@kbn/core-http-browser'; -import { httpServiceMock } from '@kbn/core-http-browser-mocks'; - -import { getFoundListSchemaMock } from './mocks/response/found_list_schema.mock'; -import { getListResponseMock } from './mocks/response/list_schema.mock'; -import { getListItemIndexExistSchemaResponseMock } from './mocks/response/list_item_index_exist_schema.mock'; -import { getAcknowledgeSchemaResponseMock } from './mocks/response/acknowledge_schema.mock'; - -describe('Value Lists API', () => { - let httpMock: ReturnType; - - beforeEach(() => { - httpMock = httpServiceMock.createStartContract(); - }); - describe('deleteList', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getListResponseMock()); - }); - - it('DELETEs specifying the id as a query parameter', async () => { - const abortCtrl = new AbortController(); - const payload: ApiPayload = { - deleteReferences: false, - id: 'list-id', - ignoreReferences: true, - }; - await deleteList({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists', - expect.objectContaining({ - method: 'DELETE', - query: { deleteReferences: false, id: 'list-id', ignoreReferences: true }, - }) - ); - }); - - it('rejects with an error if request payload is invalid (and does not make API call)', async () => { - const abortCtrl = new AbortController(); - const payload: Omit, 'id'> & { - id: number; - } = { id: 23 }; - - await expect( - deleteList({ - http: httpMock, - ...(payload as unknown as ApiPayload), - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "23" supplied to "id"')); - expect(httpMock.fetch).not.toHaveBeenCalled(); - }); - - it('rejects with an error if response payload is invalid', async () => { - const abortCtrl = new AbortController(); - const payload: ApiPayload = { id: 'list-id' }; - const badResponse = { ...getListResponseMock(), id: undefined }; - httpMock.fetch.mockResolvedValue(badResponse); - - await expect( - deleteList({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "id"')); - }); - }); - describe('findLists', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getFoundListSchemaMock()); - }); - - it('GETs from the lists endpoint', async () => { - const abortCtrl = new AbortController(); - await findLists({ - http: httpMock, - pageIndex: 1, - pageSize: 10, - signal: abortCtrl.signal, - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/_find', - expect.objectContaining({ - method: 'GET', - }) - ); - }); - - it('sends pagination as query parameters', async () => { - const abortCtrl = new AbortController(); - await findLists({ - cursor: 'cursor', - http: httpMock, - pageIndex: 1, - pageSize: 10, - signal: abortCtrl.signal, - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/_find', - expect.objectContaining({ - query: { - cursor: 'cursor', - page: 1, - per_page: 10, - }, - }) - ); - }); - - it('sends sort_field and sort_order as query parameters', async () => { - const abortCtrl = new AbortController(); - await findLists({ - cursor: 'cursor', - http: httpMock, - pageIndex: 1, - pageSize: 10, - signal: abortCtrl.signal, - sortField: 'created_at', - sortOrder: 'desc', - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/_find', - expect.objectContaining({ - query: { - cursor: 'cursor', - page: 1, - per_page: 10, - sort_field: 'created_at', - sort_order: 'desc', - }, - }) - ); - }); - - it('rejects with an error if request payload is invalid (and does not make API call)', async () => { - const abortCtrl = new AbortController(); - const payload: ApiPayload = { - pageIndex: 10, - pageSize: 0, - }; - - await expect( - findLists({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "0" supplied to "per_page"')); - expect(httpMock.fetch).not.toHaveBeenCalled(); - }); - - it('rejects with an error if response payload is invalid', async () => { - const abortCtrl = new AbortController(); - const payload: ApiPayload = { - pageIndex: 1, - pageSize: 10, - }; - const badResponse = { ...getFoundListSchemaMock(), cursor: undefined }; - httpMock.fetch.mockResolvedValue(badResponse); - - await expect( - findLists({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "cursor"')); - }); - }); - describe('importList', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getListResponseMock()); - }); - - it('POSTs the file', async () => { - const abortCtrl = new AbortController(); - const file = new File([], 'name'); - - await importList({ - file, - http: httpMock, - listId: 'my_list', - signal: abortCtrl.signal, - type: 'keyword', - }); - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items/_import', - expect.objectContaining({ - method: 'POST', - }) - ); - - // httpmock's fetch signature is inferred incorrectly - const [[, { body }]] = httpMock.fetch.mock.calls as unknown as Array< - [unknown, HttpFetchOptions] - >; - const actualFile = (body as FormData).get('file'); - expect(actualFile).toEqual(file); - }); - - it('sends type and id as query parameters', async () => { - const abortCtrl = new AbortController(); - const file = new File([], 'name'); - - await importList({ - file, - http: httpMock, - listId: 'my_list', - signal: abortCtrl.signal, - type: 'keyword', - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items/_import', - expect.objectContaining({ - query: { list_id: 'my_list', type: 'keyword' }, - }) - ); - }); - - it('rejects with an error if request body is invalid (and does not make API call)', async () => { - const abortCtrl = new AbortController(); - const payload: ApiPayload = { - file: undefined as unknown as File, - listId: 'list-id', - type: 'ip', - }; - - await expect( - importList({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "file"')); - expect(httpMock.fetch).not.toHaveBeenCalled(); - }); - - it('rejects with an error if request params are invalid (and does not make API call)', async () => { - const abortCtrl = new AbortController(); - const file = new File([], 'name'); - const payload: ApiPayload = { - file, - listId: 'list-id', - type: 'other' as 'ip', - }; - - await expect( - importList({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "other" supplied to "type"')); - expect(httpMock.fetch).not.toHaveBeenCalled(); - }); - - it('rejects with an error if response payload is invalid', async () => { - const abortCtrl = new AbortController(); - const file = new File([], 'name'); - const payload: ApiPayload = { - file, - listId: 'list-id', - type: 'ip', - }; - const badResponse = { ...getListResponseMock(), id: undefined }; - httpMock.fetch.mockResolvedValue(badResponse); - - await expect( - importList({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "id"')); - }); - }); - describe('exportList', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue({}); - }); - - it('POSTs to the export endpoint', async () => { - const abortCtrl = new AbortController(); - - await exportList({ - http: httpMock, - listId: 'my_list', - signal: abortCtrl.signal, - }); - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items/_export', - expect.objectContaining({ - method: 'POST', - }) - ); - }); - - it('sends type and id as query parameters', async () => { - const abortCtrl = new AbortController(); - - await exportList({ - http: httpMock, - listId: 'my_list', - signal: abortCtrl.signal, - }); - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items/_export', - expect.objectContaining({ - query: { list_id: 'my_list' }, - }) - ); - }); - - it('rejects with an error if request params are invalid (and does not make API call)', async () => { - const abortCtrl = new AbortController(); - const payload: ApiPayload = { - listId: 23 as unknown as string, - }; - - await expect( - exportList({ - http: httpMock, - ...payload, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "23" supplied to "list_id"')); - expect(httpMock.fetch).not.toHaveBeenCalled(); - }); - }); - - describe('readListIndex', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getListItemIndexExistSchemaResponseMock()); - }); - - it('GETs the list index', async () => { - const abortCtrl = new AbortController(); - await readListIndex({ - http: httpMock, - signal: abortCtrl.signal, - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/index', - expect.objectContaining({ - method: 'GET', - }) - ); - }); - - it('returns the response when valid', async () => { - const abortCtrl = new AbortController(); - const result = await readListIndex({ - http: httpMock, - signal: abortCtrl.signal, - }); - - expect(result).toEqual(getListItemIndexExistSchemaResponseMock()); - }); - - it('rejects with an error if response payload is invalid', async () => { - const abortCtrl = new AbortController(); - const badResponse = { ...getListItemIndexExistSchemaResponseMock(), list_index: undefined }; - httpMock.fetch.mockResolvedValue(badResponse); - - await expect( - readListIndex({ - http: httpMock, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "list_index"')); - }); - }); - - describe('createListIndex', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getAcknowledgeSchemaResponseMock()); - }); - - it('GETs the list index', async () => { - const abortCtrl = new AbortController(); - await createListIndex({ - http: httpMock, - signal: abortCtrl.signal, - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/index', - expect.objectContaining({ - method: 'POST', - }) - ); - }); - - it('returns the response when valid', async () => { - const abortCtrl = new AbortController(); - const result = await createListIndex({ - http: httpMock, - signal: abortCtrl.signal, - }); - - expect(result).toEqual(getAcknowledgeSchemaResponseMock()); - }); - - it('rejects with an error if response payload is invalid', async () => { - const abortCtrl = new AbortController(); - const badResponse = { acknowledged: undefined }; - httpMock.fetch.mockResolvedValue(badResponse); - - await expect( - createListIndex({ - http: httpMock, - signal: abortCtrl.signal, - }) - ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "acknowledged"')); - }); - }); -}); diff --git a/packages/kbn-securitysolution-list-api/src/list_api/index.ts b/packages/kbn-securitysolution-list-api/src/list_api/index.ts deleted file mode 100644 index 3087ed5333cc4..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_api/index.ts +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { chain, fromEither, map, tryCatch } from 'fp-ts/lib/TaskEither'; -import { flow } from 'fp-ts/lib/function'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { validateEither } from '@kbn/securitysolution-io-ts-utils'; -import { - AcknowledgeSchema, - DeleteListSchemaEncoded, - ExportListItemQuerySchemaEncoded, - FindListSchemaEncoded, - FoundListSchema, - ImportListItemQuerySchemaEncoded, - ImportListItemSchemaEncoded, - ListItemIndexExistSchema, - ListSchema, - ReadListSchema, - acknowledgeSchema, - deleteListSchema, - readListSchema, - exportListItemQuerySchema, - findListSchema, - foundListSchema, - importListItemQuerySchema, - importListItemSchema, - listItemIndexExistSchema, - listSchema, - foundListsBySizeSchema, - FoundListsBySizeSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { - LIST_INDEX, - LIST_ITEM_URL, - LIST_PRIVILEGES_URL, - LIST_URL, - INTERNAL_FIND_LISTS_BY_SIZE, -} from '@kbn/securitysolution-list-constants'; -import { toError, toPromise } from '../fp_utils'; - -import { - ApiParams, - DeleteListParams, - ExportListParams, - FindListsParams, - ImportListParams, - GetListByIdParams, -} from '../types'; - -export type { - ApiParams, - DeleteListParams, - ExportListParams, - FindListsParams, - ImportListParams, -} from '../types'; - -const version = '2023-10-31'; - -const findLists = async ({ - http, - cursor, - page, - // eslint-disable-next-line @typescript-eslint/naming-convention - per_page, - signal, - // eslint-disable-next-line @typescript-eslint/naming-convention - sort_field, - // eslint-disable-next-line @typescript-eslint/naming-convention - sort_order, -}: ApiParams & FindListSchemaEncoded): Promise => { - return http.fetch(`${LIST_URL}/_find`, { - method: 'GET', - query: { - cursor, - page, - per_page, - sort_field, - sort_order, - }, - signal, - version, - }); -}; - -const findListsWithValidation = async ({ - cursor, - http, - pageIndex, - pageSize, - signal, - sortField, - sortOrder, -}: FindListsParams): Promise => - pipe( - { - cursor: cursor != null ? cursor.toString() : undefined, - page: pageIndex != null ? pageIndex.toString() : undefined, - per_page: pageSize != null ? pageSize.toString() : undefined, - sort_field: sortField != null ? sortField.toString() : undefined, - sort_order: sortOrder, - }, - (payload) => fromEither(validateEither(findListSchema, payload)), - chain((payload) => tryCatch(() => findLists({ http, signal, ...payload }), toError)), - chain((response) => fromEither(validateEither(foundListSchema, response))), - flow(toPromise) - ); - -export { findListsWithValidation as findLists }; - -const findListsBySize = async ({ - http, - cursor, - page, - // eslint-disable-next-line @typescript-eslint/naming-convention - per_page, - signal, -}: ApiParams & FindListSchemaEncoded): Promise => { - return http.fetch(`${INTERNAL_FIND_LISTS_BY_SIZE}`, { - method: 'GET', - version: '1', - query: { - cursor, - page, - per_page, - }, - signal, - }); -}; - -const findListsBySizeWithValidation = async ({ - cursor, - http, - pageIndex, - pageSize, - signal, -}: FindListsParams): Promise => - pipe( - { - cursor: cursor != null ? cursor.toString() : undefined, - page: pageIndex != null ? pageIndex.toString() : undefined, - per_page: pageSize != null ? pageSize.toString() : undefined, - }, - (payload) => fromEither(validateEither(findListSchema, payload)), - chain((payload) => tryCatch(() => findListsBySize({ http, signal, ...payload }), toError)), - chain((response) => fromEither(validateEither(foundListsBySizeSchema, response))), - flow(toPromise) - ); - -export { findListsBySizeWithValidation as findListsBySize }; - -const importList = async ({ - file, - http, - // eslint-disable-next-line @typescript-eslint/naming-convention - list_id, - type, - signal, - refresh, -}: ApiParams & - ImportListItemSchemaEncoded & - ImportListItemQuerySchemaEncoded): Promise => { - const formData = new FormData(); - formData.append('file', file as Blob); - - return http.fetch(`${LIST_ITEM_URL}/_import`, { - body: formData, - headers: { 'Content-Type': undefined }, - method: 'POST', - query: { list_id, type, refresh }, - signal, - version, - }); -}; - -const importListWithValidation = async ({ - file, - http, - listId, - type, - signal, - refresh, -}: ImportListParams): Promise => - pipe( - { - list_id: listId, - type, - refresh, - }, - (query) => fromEither(validateEither(importListItemQuerySchema, query)), - chain((query) => - pipe( - fromEither(validateEither(importListItemSchema, { file })), - map((body) => ({ ...body, ...query })) - ) - ), - chain((payload) => tryCatch(() => importList({ http, signal, ...payload }), toError)), - chain((response) => fromEither(validateEither(listSchema, response))), - toPromise - ); - -export { importListWithValidation as importList }; - -const deleteList = async ({ - deleteReferences = false, - http, - id, - ignoreReferences = false, - signal, -}: ApiParams & DeleteListSchemaEncoded): Promise => - http.fetch(LIST_URL, { - method: 'DELETE', - query: { deleteReferences, id, ignoreReferences }, - signal, - version, - }); - -const deleteListWithValidation = async ({ - deleteReferences, - http, - id, - ignoreReferences, - signal, -}: DeleteListParams): Promise => - pipe( - { deleteReferences, id, ignoreReferences }, - (payload) => fromEither(validateEither(deleteListSchema, payload)), - chain((payload) => tryCatch(() => deleteList({ http, signal, ...payload }), toError)), - chain((response) => fromEither(validateEither(listSchema, response))), - flow(toPromise) - ); - -export { deleteListWithValidation as deleteList }; - -const exportList = async ({ - http, - // eslint-disable-next-line @typescript-eslint/naming-convention - list_id, - signal, -}: ApiParams & ExportListItemQuerySchemaEncoded): Promise => - http.fetch(`${LIST_ITEM_URL}/_export`, { - method: 'POST', - query: { list_id }, - signal, - version, - }); - -const exportListWithValidation = async ({ - http, - listId, - signal, -}: ExportListParams): Promise => - pipe( - { list_id: listId }, - (payload) => fromEither(validateEither(exportListItemQuerySchema, payload)), - chain((payload) => tryCatch(() => exportList({ http, signal, ...payload }), toError)), - flow(toPromise) - ); - -export { exportListWithValidation as exportList }; - -const readListIndex = async ({ http, signal }: ApiParams): Promise => - http.fetch(LIST_INDEX, { - method: 'GET', - signal, - version, - }); - -const readListIndexWithValidation = async ({ - http, - signal, -}: ApiParams): Promise => - flow( - () => tryCatch(() => readListIndex({ http, signal }), toError), - chain((response) => fromEither(validateEither(listItemIndexExistSchema, response))), - flow(toPromise) - )(); - -export { readListIndexWithValidation as readListIndex }; - -// TODO add types and validation -export const readListPrivileges = async ({ http, signal }: ApiParams): Promise => - http.fetch(LIST_PRIVILEGES_URL, { - method: 'GET', - signal, - version, - }); - -const createListIndex = async ({ http, signal }: ApiParams): Promise => - http.fetch(LIST_INDEX, { - method: 'POST', - signal, - version, - }); - -const createListIndexWithValidation = async ({ - http, - signal, -}: ApiParams): Promise => - flow( - () => tryCatch(() => createListIndex({ http, signal }), toError), - chain((response) => fromEither(validateEither(acknowledgeSchema, response))), - flow(toPromise) - )(); - -export { createListIndexWithValidation as createListIndex }; - -const getListById = async ({ - http, - signal, - id, -}: ApiParams & ReadListSchema): Promise => { - return http.fetch(`${LIST_URL}`, { - method: 'GET', - query: { - id, - }, - signal, - version, - }); -}; - -const getListByIdWithValidation = async ({ - http, - signal, - id, -}: GetListByIdParams): Promise => - pipe( - { - id, - }, - (payload) => fromEither(validateEither(readListSchema, payload)), - chain((payload) => tryCatch(() => getListById({ http, signal, ...payload }), toError)), - chain((response) => fromEither(validateEither(listSchema, response))), - flow(toPromise) - ); - -export { getListByIdWithValidation as getListById }; diff --git a/packages/kbn-securitysolution-list-api/src/list_api/mocks/constants.mock.ts b/packages/kbn-securitysolution-list-api/src/list_api/mocks/constants.mock.ts deleted file mode 100644 index 3043cc70642c2..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_api/mocks/constants.mock.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export const DATE_NOW = '2020-04-20T15:25:31.830Z'; -export const USER = 'some user'; -export const ELASTIC_USER = 'elastic'; -export const NAME = 'some name'; -export const DESCRIPTION = 'some description'; -export const LIST_ID = 'some-list-id'; -export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; - -export const META = {}; -export const TYPE = 'ip'; - -export const VERSION = 1; -export const IMMUTABLE = false; diff --git a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/acknowledge_schema.mock.ts b/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/acknowledge_schema.mock.ts deleted file mode 100644 index 788fab714e2d2..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/acknowledge_schema.mock.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { AcknowledgeSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export const getAcknowledgeSchemaResponseMock = (): AcknowledgeSchema => ({ - acknowledged: true, -}); diff --git a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/found_list_schema.mock.ts b/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/found_list_schema.mock.ts deleted file mode 100644 index 436ddcd7a83db..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/found_list_schema.mock.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FoundListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { getListResponseMock } from './list_schema.mock'; - -export const getFoundListSchemaMock = (): FoundListSchema => ({ - cursor: '123', - data: [getListResponseMock()], - page: 1, - per_page: 1, - total: 1, -}); diff --git a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_item_index_exist_schema.mock.ts b/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_item_index_exist_schema.mock.ts deleted file mode 100644 index 27a54a5fd96fc..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_item_index_exist_schema.mock.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { ListItemIndexExistSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export const getListItemIndexExistSchemaResponseMock = (): ListItemIndexExistSchema => ({ - list_index: true, - list_item_index: true, -}); diff --git a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts b/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts deleted file mode 100644 index 79ed256419770..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { - DATE_NOW, - DESCRIPTION, - ELASTIC_USER, - IMMUTABLE, - LIST_ID, - META, - NAME, - TIE_BREAKER, - TYPE, - USER, - VERSION, -} from '../constants.mock'; - -export const getListResponseMock = (): ListSchema => ({ - '@timestamp': DATE_NOW, - _version: undefined, - created_at: DATE_NOW, - created_by: USER, - description: DESCRIPTION, - deserializer: undefined, - id: LIST_ID, - immutable: IMMUTABLE, - meta: META, - name: NAME, - serializer: undefined, - tie_breaker_id: TIE_BREAKER, - type: TYPE, - updated_at: DATE_NOW, - updated_by: USER, - version: VERSION, -}); - -/** - * This is useful for end to end tests where we remove the auto generated parts for comparisons - * such as created_at, updated_at, and id. - */ -export const getListResponseMockWithoutAutoGeneratedValues = (): Partial => ({ - created_by: ELASTIC_USER, - description: DESCRIPTION, - immutable: IMMUTABLE, - name: NAME, - type: TYPE, - updated_by: ELASTIC_USER, - version: VERSION, -}); diff --git a/packages/kbn-securitysolution-list-api/src/list_item_api/index.test.ts b/packages/kbn-securitysolution-list-api/src/list_item_api/index.test.ts deleted file mode 100644 index 95e37ec434107..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_item_api/index.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { createListItem, deleteListItem, findListItems, patchListItem } from '.'; -import { httpServiceMock } from '@kbn/core-http-browser-mocks'; -import { - getFoundListSchemaMock, - getCreateListItemResponseMock, - getUpdatedListItemResponseMock, - getDeletedListItemResponseMock, -} from './mocks/response'; - -describe('Value list item API', () => { - let httpMock: ReturnType; - beforeEach(() => { - httpMock = httpServiceMock.createStartContract(); - }); - - describe('findListItems', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getFoundListSchemaMock()); - }); - - it('GETs from the lists endpoint with query params', async () => { - const abortCtrl = new AbortController(); - await findListItems({ - http: httpMock, - pageIndex: 1, - pageSize: 10, - signal: abortCtrl.signal, - filter: '*:*', - listId: 'list_id', - sortField: 'updated_at', - sortOrder: 'asc', - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items/_find', - expect.objectContaining({ - method: 'GET', - query: { - cursor: undefined, - filter: '*:*', - list_id: 'list_id', - page: 1, - per_page: 10, - sort_field: 'updated_at', - sort_order: 'asc', - }, - }) - ); - }); - }); - - describe('createListItem', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getCreateListItemResponseMock()); - }); - - it('POSTs to the lists endpoint with the list item', async () => { - const abortCtrl = new AbortController(); - await createListItem({ - http: httpMock, - signal: abortCtrl.signal, - value: '123', - listId: 'list_id', - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items', - expect.objectContaining({ - method: 'POST', - body: JSON.stringify({ - value: '123', - list_id: 'list_id', - }), - }) - ); - }); - - it('returns the created list item', async () => { - const abortCtrl = new AbortController(); - const result = await createListItem({ - http: httpMock, - signal: abortCtrl.signal, - value: '123', - listId: 'list_id', - }); - - expect(result).toEqual(getCreateListItemResponseMock()); - }); - }); - - describe('patchListItem', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getUpdatedListItemResponseMock()); - }); - - it('PATCH to the lists endpoint with the list item', async () => { - const abortCtrl = new AbortController(); - await patchListItem({ - http: httpMock, - signal: abortCtrl.signal, - id: 'item_id', - value: '123', - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items', - expect.objectContaining({ - method: 'PATCH', - body: JSON.stringify({ - id: 'item_id', - value: '123', - }), - }) - ); - }); - - it('returns the updated list item', async () => { - const abortCtrl = new AbortController(); - const result = await patchListItem({ - http: httpMock, - signal: abortCtrl.signal, - id: 'item_id', - value: '123', - }); - - expect(result).toEqual(getUpdatedListItemResponseMock()); - }); - }); - - describe('deleteListItem', () => { - beforeEach(() => { - httpMock.fetch.mockResolvedValue(getCreateListItemResponseMock()); - }); - - it('DELETE to the lists endpoint with the list item', async () => { - const abortCtrl = new AbortController(); - await deleteListItem({ - http: httpMock, - signal: abortCtrl.signal, - id: 'item_id', - refresh: 'true', - }); - - expect(httpMock.fetch).toHaveBeenCalledWith( - '/api/lists/items', - expect.objectContaining({ - method: 'DELETE', - query: { id: 'item_id', refresh: 'true' }, - }) - ); - }); - - it('returns the deleted list item', async () => { - const abortCtrl = new AbortController(); - const result = await deleteListItem({ - http: httpMock, - signal: abortCtrl.signal, - id: 'item_id', - }); - - expect(result).toEqual(getDeletedListItemResponseMock()); - }); - }); -}); diff --git a/packages/kbn-securitysolution-list-api/src/list_item_api/index.ts b/packages/kbn-securitysolution-list-api/src/list_item_api/index.ts deleted file mode 100644 index 8c6cdc358f70a..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_item_api/index.ts +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - FindListItemSchema, - ListItemSchema, - deleteListItemSchema, - patchListItemSchema, - createListItemSchema, - findListItemSchema, - foundListItemSchema, - listItemSchema, - FoundListItemSchema, - DeleteListItemSchema, - PatchListItemSchema, - CreateListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { chain, fromEither, tryCatch } from 'fp-ts/lib/TaskEither'; -import { flow } from 'fp-ts/lib/function'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { validateEither } from '@kbn/securitysolution-io-ts-utils'; - -import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; -import { - ApiParams, - FindListItemsParams, - DeleteListItemParams, - PatchListItemParams, - CreateListItemParams, -} from '../types'; -import { toError, toPromise } from '../fp_utils'; - -const version = '2023-10-31'; - -/** - * Fetch list items - */ -const findListItems = async ({ - http, - cursor, - page, - // eslint-disable-next-line @typescript-eslint/naming-convention - list_id, - // eslint-disable-next-line @typescript-eslint/naming-convention - per_page, - signal, - // eslint-disable-next-line @typescript-eslint/naming-convention - sort_field, - // eslint-disable-next-line @typescript-eslint/naming-convention - sort_order, - filter, -}: ApiParams & FindListItemSchema): Promise => { - return http.fetch(`${LIST_ITEM_URL}/_find`, { - method: 'GET', - query: { - cursor, - page, - per_page, - sort_field, - sort_order, - list_id, - filter, - }, - signal, - version, - }); -}; - -const findListItemsWithValidation = async ({ - cursor, - http, - pageIndex, - pageSize, - signal, - sortField, - sortOrder, - filter, - listId, -}: FindListItemsParams): Promise => - pipe( - { - cursor: cursor != null ? cursor.toString() : undefined, - page: pageIndex != null ? pageIndex.toString() : undefined, - per_page: pageSize != null ? pageSize.toString() : undefined, - sort_field: sortField != null ? sortField.toString() : undefined, - filter: filter != null ? filter.toString() : undefined, - sort_order: sortOrder, - list_id: listId, - }, - (payload) => fromEither(validateEither(findListItemSchema, payload)), - chain((payload) => tryCatch(() => findListItems({ http, signal, ...payload }), toError)), - chain((response) => fromEither(validateEither(foundListItemSchema, response))), - flow(toPromise) - ); - -export { findListItemsWithValidation as findListItems }; - -const deleteListItem = async ({ - http, - id, - signal, - refresh, -}: ApiParams & DeleteListItemSchema): Promise => - http.fetch(LIST_ITEM_URL, { - method: 'DELETE', - query: { id, refresh }, - signal, - version, - }); - -const deleteListItemWithValidation = async ({ - http, - id, - signal, - refresh, -}: DeleteListItemParams): Promise => - pipe( - { id, refresh }, - (payload) => fromEither(validateEither(deleteListItemSchema, payload)), - chain((payload) => - tryCatch( - () => - deleteListItem({ - http, - signal, - ...payload, - value: undefined, - list_id: undefined, - }), - toError - ) - ), - chain((response) => fromEither(validateEither(listItemSchema, response))), - flow(toPromise) - ); - -export { deleteListItemWithValidation as deleteListItem }; - -const patchListItem = async ({ - http, - id, - signal, - value, - _version, -}: ApiParams & PatchListItemSchema): Promise => - http.fetch(LIST_ITEM_URL, { - method: 'PATCH', - body: JSON.stringify({ id, value, _version }), - signal, - version, - }); - -const patchListItemWithValidation = async ({ - http, - id, - signal, - value, - refresh, - _version, -}: PatchListItemParams): Promise => - pipe( - { id, value, _version, refresh }, - (payload) => fromEither(validateEither(patchListItemSchema, payload)), - chain((payload) => - tryCatch( - () => - patchListItem({ - http, - signal, - ...payload, - }), - toError - ) - ), - chain((response) => fromEither(validateEither(listItemSchema, response))), - flow(toPromise) - ); - -export { patchListItemWithValidation as patchListItem }; - -const createListItem = async ({ - http, - signal, - value, - // eslint-disable-next-line @typescript-eslint/naming-convention - list_id, - refresh, -}: ApiParams & CreateListItemSchema): Promise => - http.fetch(LIST_ITEM_URL, { - method: 'POST', - body: JSON.stringify({ value, list_id, refresh }), - signal, - version, - }); - -const createListItemWithValidation = async ({ - http, - signal, - value, - refresh, - listId, -}: CreateListItemParams): Promise => - pipe( - { list_id: listId, value, refresh }, - (payload) => fromEither(validateEither(createListItemSchema, payload)), - chain((payload) => - tryCatch( - () => - createListItem({ - http, - signal, - ...payload, - }), - toError - ) - ), - chain((response) => fromEither(validateEither(listItemSchema, response))), - flow(toPromise) - ); - -export { createListItemWithValidation as createListItem }; diff --git a/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/index.ts b/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/index.ts deleted file mode 100644 index 5ef4e52adbe88..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FoundListItemSchema, ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { getListItemResponseMock } from './list_item_schema.mock'; - -export const getFoundListSchemaMock = (): FoundListItemSchema => ({ - cursor: '123', - data: [getListItemResponseMock()], - page: 1, - per_page: 1, - total: 1, -}); - -export const getCreateListItemResponseMock = (): ListItemSchema => getListItemResponseMock(); -export const getUpdatedListItemResponseMock = (): ListItemSchema => getListItemResponseMock(); -export const getDeletedListItemResponseMock = (): ListItemSchema => getListItemResponseMock(); diff --git a/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/list_item_schema.mock.ts b/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/list_item_schema.mock.ts deleted file mode 100644 index eb67b97773548..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/list_item_schema.mock.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export const getListItemResponseMock = (): ListItemSchema => ({ - _version: '1', - '@timestamp': '2020-08-11T11:22:13.670Z', - created_at: '2020-08-11T11:22:13.670Z', - created_by: 'elastic', - deserializer: 'some deserializer', - id: 'bpdB3XMBx7pemMHopQ6M', - list_id: 'list_id', - meta: {}, - serializer: 'some serializer', - tie_breaker_id: '17d3befb-dc22-4b3c-a286-b5504c4fbeeb', - type: 'keyword', - updated_at: '2020-08-11T11:22:13.670Z', - updated_by: 'elastic', - value: 'some keyword', -}); diff --git a/packages/kbn-securitysolution-list-api/src/types.ts b/packages/kbn-securitysolution-list-api/src/types.ts deleted file mode 100644 index c78071bb5824f..0000000000000 --- a/packages/kbn-securitysolution-list-api/src/types.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { - SortFieldOrUndefined, - SortOrderOrUndefined, - Type, - Refresh, - RefreshWithWaitFor, -} from '@kbn/securitysolution-io-ts-list-types'; - -// TODO: Replace these with kbn packaged versions once we have those available to us -// These originally came from this location below before moving them to this hacked "any" types: -// import { HttpStart, NotificationsStart } from '../../../../../src/core/public'; -interface HttpStart { - fetch: (...args: any) => any; -} - -export interface ApiParams { - http: HttpStart; - signal: AbortSignal; -} -export type ApiPayload = Omit; - -export interface FindListsParams extends ApiParams { - cursor?: string | undefined; - pageSize: number | undefined; - pageIndex: number | undefined; - sortOrder?: SortOrderOrUndefined; - sortField?: SortFieldOrUndefined; -} - -export interface FindListItemsParams extends ApiParams { - cursor?: string | undefined; - pageSize: number | undefined; - pageIndex: number | undefined; - sortOrder?: SortOrderOrUndefined; - sortField?: SortFieldOrUndefined; - filter: string | undefined; - listId: string; -} - -export interface ImportListParams extends ApiParams { - file: File; - listId: string | undefined; - type: Type | undefined; - refresh?: RefreshWithWaitFor; -} - -export interface DeleteListParams extends ApiParams { - deleteReferences?: boolean; - id: string; - ignoreReferences?: boolean; -} - -export interface DeleteListItemParams extends ApiParams { - refresh?: Refresh; - id: string; -} - -export interface PatchListItemParams extends ApiParams { - refresh?: Refresh; - id: string; - value: string; - _version?: string; -} - -export interface CreateListItemParams extends ApiParams { - refresh?: RefreshWithWaitFor; - value: string; - listId: string; -} - -export interface ExportListParams extends ApiParams { - listId: string; -} - -export interface GetListByIdParams extends ApiParams { - id: string; -} diff --git a/packages/kbn-securitysolution-list-api/tsconfig.json b/packages/kbn-securitysolution-list-api/tsconfig.json deleted file mode 100644 index 2c2ca29316fcd..0000000000000 --- a/packages/kbn-securitysolution-list-api/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/securitysolution-io-ts-list-types", - "@kbn/securitysolution-io-ts-utils", - "@kbn/securitysolution-list-constants", - "@kbn/core-http-browser", - "@kbn/core-http-browser-mocks", - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-list-constants/index.ts b/packages/kbn-securitysolution-list-constants/index.ts deleted file mode 100644 index 6f1e8d01b830a..0000000000000 --- a/packages/kbn-securitysolution-list-constants/index.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { deepFreeze } from '@kbn/std'; - -/** - * Value list routes - */ -export const LIST_URL = '/api/lists'; -export const LIST_INDEX = `${LIST_URL}/index`; -export const LIST_ITEM_URL = `${LIST_URL}/items`; -export const LIST_PRIVILEGES_URL = `${LIST_URL}/privileges`; - -/** - * Internal value list routes - */ -export const INTERNAL_LIST_URL = '/internal/lists'; -export const INTERNAL_FIND_LISTS_BY_SIZE = `${INTERNAL_LIST_URL}/_find_lists_by_size` as const; -export const INTERNAL_EXCEPTION_FILTER = `${INTERNAL_LIST_URL}/_create_filter` as const; - -/** - * Exception list routes - */ -export const EXCEPTION_LIST_URL = '/api/exception_lists'; -export const EXCEPTION_LIST_ITEM_URL = '/api/exception_lists/items'; - -/** - * Internal exception list routes - */ -export const INTERNAL_EXCEPTION_LIST_URL = `/internal${EXCEPTION_LIST_URL}`; -export const INTERNAL_EXCEPTIONS_LIST_ENSURE_CREATED_URL = `${INTERNAL_EXCEPTION_LIST_URL}/_create`; - -/** - * Exception list spaces - */ -export const EXCEPTION_LIST_NAMESPACE_AGNOSTIC = 'exception-list-agnostic'; -export const EXCEPTION_LIST_NAMESPACE = 'exception-list'; - -/** - * Specific routes for the single global space agnostic endpoint list - */ -export const ENDPOINT_LIST_URL = '/api/endpoint_list'; - -/** - * Specific routes for the single global space agnostic endpoint list. These are convenience - * routes where they are going to try and create the global space agnostic endpoint list if it - * does not exist yet or if it was deleted at some point and re-create it before adding items to - * the list - */ -export const ENDPOINT_LIST_ITEM_URL = '/api/endpoint_list/items'; - -/** - * This ID is used for _both_ the Saved Object ID and for the list_id - * for the single global space agnostic endpoint list - */ -export const ENDPOINT_LIST_ID = 'endpoint_list'; - -/** The name of the single global space agnostic endpoint list */ -export const ENDPOINT_LIST_NAME = 'Endpoint Security Exception List'; - -/** The description of the single global space agnostic endpoint list */ -export const ENDPOINT_LIST_DESCRIPTION = 'Endpoint Security Exception List'; - -export const MAX_EXCEPTION_LIST_SIZE = 10000; - -export const MAXIMUM_SMALL_VALUE_LIST_SIZE = 65536; - -export const MAXIMUM_SMALL_IP_RANGE_VALUE_LIST_DASH_SIZE = 200; - -/** - * List definitions for Endpoint Artifact - */ -export const ENDPOINT_ARTIFACT_LISTS = deepFreeze({ - trustedApps: { - id: 'endpoint_trusted_apps', - name: 'Endpoint Security Trusted Apps List', - description: 'Endpoint Security Trusted Apps List', - }, - eventFilters: { - id: 'endpoint_event_filters', - name: 'Endpoint Security Event Filters List', - description: 'Endpoint Security Event Filters List', - }, - hostIsolationExceptions: { - id: 'endpoint_host_isolation_exceptions', - name: 'Endpoint Security Host isolation exceptions List', - description: 'Endpoint Security Host isolation exceptions List', - }, - blocklists: { - id: 'endpoint_blocklists', - name: 'Endpoint Security Blocklists List', - description: 'Endpoint Security Blocklists List', - }, -}); - -/** - * The IDs of all Endpoint artifact lists - */ -export const ENDPOINT_ARTIFACT_LIST_IDS = Object.freeze( - Object.values(ENDPOINT_ARTIFACT_LISTS).map(({ id }) => id) -); - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_TRUSTED_APPS_LIST_ID = ENDPOINT_ARTIFACT_LISTS.trustedApps.id; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_TRUSTED_APPS_LIST_NAME = ENDPOINT_ARTIFACT_LISTS.trustedApps.name; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION = - ENDPOINT_ARTIFACT_LISTS.trustedApps.description; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_EVENT_FILTERS_LIST_ID = ENDPOINT_ARTIFACT_LISTS.eventFilters.id; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_EVENT_FILTERS_LIST_NAME = ENDPOINT_ARTIFACT_LISTS.eventFilters.name; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION = - ENDPOINT_ARTIFACT_LISTS.eventFilters.description; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID = - ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.id; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_NAME = - ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.name; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_DESCRIPTION = - ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.description; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_BLOCKLISTS_LIST_ID = ENDPOINT_ARTIFACT_LISTS.blocklists.id; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_BLOCKLISTS_LIST_NAME = ENDPOINT_ARTIFACT_LISTS.blocklists.name; - -/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ -export const ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION = ENDPOINT_ARTIFACT_LISTS.blocklists.description; diff --git a/packages/kbn-securitysolution-list-constants/package.json b/packages/kbn-securitysolution-list-constants/package.json deleted file mode 100644 index 1b03f95f0f150..0000000000000 --- a/packages/kbn-securitysolution-list-constants/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/securitysolution-list-constants", - "version": "1.0.0", - "description": "security solution list constants to use across plugins such lists, security_solution, cases, etc...", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-list-constants/tsconfig.json b/packages/kbn-securitysolution-list-constants/tsconfig.json deleted file mode 100644 index 0cd8de173ed4f..0000000000000 --- a/packages/kbn-securitysolution-list-constants/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/std" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-list-hooks/index.ts b/packages/kbn-securitysolution-list-hooks/index.ts deleted file mode 100644 index 5ec2cb85d8c23..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/transforms'; -export * from './src/use_api'; -export * from './src/use_create_list_index'; -export * from './src/use_cursor'; -export * from './src/use_delete_list'; -export * from './src/use_exception_lists'; -export * from './src/use_export_list'; -export * from './src/use_find_lists'; -export * from './src/use_find_lists_by_size'; -export * from './src/use_import_list'; -export * from './src/use_persist_exception_item'; -export * from './src/use_persist_exception_list'; -export * from './src/use_read_list_index'; -export * from './src/use_read_list_privileges'; -export * from './src/use_find_list_items'; -export * from './src/use_create_list_item'; -export * from './src/use_delete_list_item'; -export * from './src/use_patch_list_item'; -export * from './src/use_get_list_by_id'; diff --git a/packages/kbn-securitysolution-list-hooks/jest.config.js b/packages/kbn-securitysolution-list-hooks/jest.config.js deleted file mode 100644 index f5fadd8bf399a..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-list-hooks'], -}; diff --git a/packages/kbn-securitysolution-list-hooks/package.json b/packages/kbn-securitysolution-list-hooks/package.json deleted file mode 100644 index 3d9f2019d3f23..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/securitysolution-list-hooks", - "version": "1.0.0", - "description": "Security solution list ReactJS hooks", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-list-hooks/src/constants.ts b/packages/kbn-securitysolution-list-hooks/src/constants.ts deleted file mode 100644 index 333fb40ca4caf..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export const READ_INDEX_QUERY_KEY = ['detectionEngine', 'listIndex']; diff --git a/packages/kbn-securitysolution-list-hooks/src/index.ts b/packages/kbn-securitysolution-list-hooks/src/index.ts deleted file mode 100644 index 852d138b8931d..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './transforms'; -export * from './use_api'; -export * from './use_create_list_index'; -export * from './use_cursor'; -export * from './use_delete_list'; -export * from './use_exception_lists'; -export * from './use_export_list'; -export * from './use_find_lists'; -export * from './use_import_list'; -export * from './use_persist_exception_item'; -export * from './use_persist_exception_list'; -export * from './use_read_list_index'; -export * from './use_read_list_privileges'; -export * from './use_find_list_items'; -export * from './use_create_list_item'; -export * from './use_delete_list_item'; -export * from './use_patch_list_item'; -export * from './use_get_list_by_id'; diff --git a/packages/kbn-securitysolution-list-hooks/src/mocks/constants.mock.ts b/packages/kbn-securitysolution-list-hooks/src/mocks/constants.mock.ts deleted file mode 100644 index 67dcac046c8d2..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/mocks/constants.mock.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - CommentsArray, - EntriesArray, - Entry, - EntryMatch, - EntryNested, - OsTypeArray, -} from '@kbn/securitysolution-io-ts-list-types'; - -export const DATE_NOW = '2020-04-20T15:25:31.830Z'; -export const USER = 'some user'; -export const ELASTIC_USER = 'elastic'; -export const NAME = 'some name'; -export const DESCRIPTION = 'some description'; -export const LIST_ID = 'some-list-id'; -export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; - -export const META = {}; -export const TYPE = 'ip'; - -export const VERSION = 1; -export const IMMUTABLE = false; -// Exception List specific -export const ID = 'uuid_here'; -export const NAMESPACE_TYPE = 'single'; -export const OS_TYPES: OsTypeArray = ['windows']; -export const TAGS = []; -export const UPDATED_COMMENTS = [ - { - comment: 'old comment', - id: 'old_created_id', - }, - { - comment: 'new comment', - id: 'new_id', - }, -]; -export const COMMENTS = []; -export const ENTRIES: EntriesArray = [ - { - entries: [{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }], - field: 'some.parentField', - type: 'nested', - }, - { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, -]; -export const ITEM_ID = 'some-list-item-id'; -export const ITEM_TYPE = 'simple'; -export const LIST_ITEM_ID = 'some-list-item-id'; -// ENTRIES_WITH_IDS should only be used to mock out functionality of a collection of transforms -// that are UI specific and useful for UI concerns that are inserted between the -// API and the actual user interface. In some ways these might be viewed as -// technical debt or to compensate for the differences and preferences -// of how ReactJS might prefer data vs. how we want to model data. -export const ENTRIES_WITH_IDS: EntriesArray = [ - { - entries: [ - { - field: 'nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as EntryMatch & { id: string }, - ], - field: 'some.parentField', - id: '123', - type: 'nested', - } as EntryNested & { id: string }, - { - field: 'some.not.nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as Entry & { id: string }, -]; - -export const COMMENTS_WITH_CREATEDAT_CREATEDBY: CommentsArray = [ - { - comment: 'old comment', - id: 'old_created_id', - created_at: '2022-01-08T15:25:31.830Z', - created_by: 'elastic', - }, - { - comment: 'new comment', - id: 'new_id', - created_at: '2022-05-14T15:25:31.830Z', - created_by: 'elastic', - }, -]; diff --git a/packages/kbn-securitysolution-list-hooks/src/mocks/request/update_exception_list_item_schema.mock.ts b/packages/kbn-securitysolution-list-hooks/src/mocks/request/update_exception_list_item_schema.mock.ts deleted file mode 100644 index 916ce0c81daca..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/mocks/request/update_exception_list_item_schema.mock.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { - DESCRIPTION, - ENTRIES, - ID, - ITEM_ID, - ITEM_TYPE, - LIST_ITEM_ID, - META, - NAME, - NAMESPACE_TYPE, - OS_TYPES, - TAGS, - UPDATED_COMMENTS, -} from '../constants.mock'; - -export const getUpdateExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ - _version: undefined, - comments: UPDATED_COMMENTS, - description: DESCRIPTION, - entries: ENTRIES, - id: ID, - item_id: LIST_ITEM_ID, - meta: META, - name: NAME, - namespace_type: NAMESPACE_TYPE, - os_types: ['linux'], - tags: TAGS, - type: ITEM_TYPE, -}); - -/** - * Useful for end to end tests and other mechanisms which want to fill in the values - * after doing a get of the structure. - */ -export const getUpdateMinimalExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ - description: DESCRIPTION, - entries: ENTRIES, - item_id: ITEM_ID, - name: NAME, - os_types: OS_TYPES, - type: ITEM_TYPE, -}); diff --git a/packages/kbn-securitysolution-list-hooks/src/mocks/response/exception_list_item_schema.mock.ts b/packages/kbn-securitysolution-list-hooks/src/mocks/response/exception_list_item_schema.mock.ts deleted file mode 100644 index 0c5e732a1f301..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/mocks/response/exception_list_item_schema.mock.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { - COMMENTS, - DATE_NOW, - DESCRIPTION, - ELASTIC_USER, - ENTRIES, - ITEM_ID, - ITEM_TYPE, - LIST_ID, - META, - NAME, - NAMESPACE_TYPE, - OS_TYPES, - TIE_BREAKER, - USER, -} from '../constants.mock'; - -export const getExceptionListItemSchemaMock = ( - overrides?: Partial -): ExceptionListItemSchema => ({ - _version: undefined, - comments: COMMENTS, - created_at: DATE_NOW, - created_by: USER, - description: DESCRIPTION, - entries: ENTRIES, - expire_time: undefined, - id: '1', - item_id: 'endpoint_list_item', - list_id: 'endpoint_list_id', - meta: META, - name: NAME, - namespace_type: NAMESPACE_TYPE, - os_types: [], - tags: ['user added string for a tag', 'malware'], - tie_breaker_id: TIE_BREAKER, - type: ITEM_TYPE, - updated_at: DATE_NOW, - updated_by: USER, - ...(overrides || {}), -}); - -/** - * This is useful for end to end tests where we remove the auto generated parts for comparisons - * such as created_at, updated_at, and id. - */ -export const getExceptionListItemResponseMockWithoutAutoGeneratedValues = - (): Partial => ({ - comments: [], - created_by: ELASTIC_USER, - description: DESCRIPTION, - entries: ENTRIES, - item_id: ITEM_ID, - list_id: LIST_ID, - name: NAME, - namespace_type: 'single', - os_types: OS_TYPES, - tags: [], - type: ITEM_TYPE, - updated_by: ELASTIC_USER, - }); diff --git a/packages/kbn-securitysolution-list-hooks/src/mocks/response/found_list_schema.mock.ts b/packages/kbn-securitysolution-list-hooks/src/mocks/response/found_list_schema.mock.ts deleted file mode 100644 index 436ddcd7a83db..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/mocks/response/found_list_schema.mock.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FoundListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { getListResponseMock } from './list_schema.mock'; - -export const getFoundListSchemaMock = (): FoundListSchema => ({ - cursor: '123', - data: [getListResponseMock()], - page: 1, - per_page: 1, - total: 1, -}); diff --git a/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts b/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts deleted file mode 100644 index 79ed256419770..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -import { - DATE_NOW, - DESCRIPTION, - ELASTIC_USER, - IMMUTABLE, - LIST_ID, - META, - NAME, - TIE_BREAKER, - TYPE, - USER, - VERSION, -} from '../constants.mock'; - -export const getListResponseMock = (): ListSchema => ({ - '@timestamp': DATE_NOW, - _version: undefined, - created_at: DATE_NOW, - created_by: USER, - description: DESCRIPTION, - deserializer: undefined, - id: LIST_ID, - immutable: IMMUTABLE, - meta: META, - name: NAME, - serializer: undefined, - tie_breaker_id: TIE_BREAKER, - type: TYPE, - updated_at: DATE_NOW, - updated_by: USER, - version: VERSION, -}); - -/** - * This is useful for end to end tests where we remove the auto generated parts for comparisons - * such as created_at, updated_at, and id. - */ -export const getListResponseMockWithoutAutoGeneratedValues = (): Partial => ({ - created_by: ELASTIC_USER, - description: DESCRIPTION, - immutable: IMMUTABLE, - name: NAME, - type: TYPE, - updated_by: ELASTIC_USER, - version: VERSION, -}); diff --git a/packages/kbn-securitysolution-list-hooks/src/transforms/index.test.ts b/packages/kbn-securitysolution-list-hooks/src/transforms/index.test.ts deleted file mode 100644 index bb0cb6e6e9075..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/transforms/index.test.ts +++ /dev/null @@ -1,299 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { - CreateExceptionListItemSchema, - Entry, - EntryMatch, - EntryNested, - ExceptionListItemSchema, - UpdateExceptionListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { - addIdToExceptionItemEntries, - removeIdFromExceptionItemsEntries, - transformInput, - transformOutput, -} from '../..'; - -import { getCreateExceptionListItemSchemaMock } from '../mocks/request/create_exception_list_item_schema.mock'; -import { getUpdateExceptionListItemSchemaMock } from '../mocks/request/update_exception_list_item_schema.mock'; -import { getExceptionListItemSchemaMock } from '../mocks/response/exception_list_item_schema.mock'; -import { COMMENTS_WITH_CREATEDAT_CREATEDBY, ENTRIES_WITH_IDS } from '../mocks/constants.mock'; - -jest.mock('uuid', () => ({ - v4: jest.fn().mockReturnValue('123'), -})); - -describe('Exceptions transforms', () => { - describe('transformOutput', () => { - it('should return same output as input with stripped ids per entry - CreateExceptionListItemSchema', () => { - const mockCreateExceptionItem = { - ...getCreateExceptionListItemSchemaMock(), - entries: ENTRIES_WITH_IDS, - }; - const output = transformOutput(mockCreateExceptionItem); - const expectedOutput: CreateExceptionListItemSchema = getCreateExceptionListItemSchemaMock(); - - expect(output).toEqual(expectedOutput); - }); - - it('should return same output as input with stripped ids per entry - UpdateExceptionListItemSchema', () => { - const mockUpdateExceptionItem = { - ...getUpdateExceptionListItemSchemaMock(), - entries: ENTRIES_WITH_IDS, - }; - const output = transformOutput(mockUpdateExceptionItem); - const expectedOutput: UpdateExceptionListItemSchema = getUpdateExceptionListItemSchemaMock(); - - expect(output).toEqual(expectedOutput); - }); - it('should return output as input with stripped createdAt and createdBy per entry - UpdateExceptionListItemSchema', () => { - const mockUpdateExceptionItem = { - ...getUpdateExceptionListItemSchemaMock(), - entries: ENTRIES_WITH_IDS, - comments: COMMENTS_WITH_CREATEDAT_CREATEDBY, - }; - const output = transformOutput(mockUpdateExceptionItem); - const expectedOutput: UpdateExceptionListItemSchema = getUpdateExceptionListItemSchemaMock(); - - expect(output).toEqual(expectedOutput); - }); - }); - - describe('transformInput', () => { - it('should return same output as input with added ids per entry', () => { - const mockExceptionItem = getExceptionListItemSchemaMock(); - const output = transformInput(mockExceptionItem); - const expectedOutput: ExceptionListItemSchema = { - ...getExceptionListItemSchemaMock(), - entries: ENTRIES_WITH_IDS, - }; - - expect(output).toEqual(expectedOutput); - }); - }); - - describe('addIdToExceptionItemEntries', () => { - it('should return same output as input with added ids per entry', () => { - const mockExceptionItem: ExceptionListItemSchema = { - ...getExceptionListItemSchemaMock(), - entries: [ - { - field: 'some.not.nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - }; - const output = addIdToExceptionItemEntries(mockExceptionItem); - const expectedOutput: ExceptionListItemSchema = { - ...getExceptionListItemSchemaMock(), - entries: [ - { - field: 'some.not.nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as Entry & { id: string }, - ], - }; - - expect(output).toEqual(expectedOutput); - }); - - it('should return same output as input with added ids per nested entry', () => { - const mockExceptionItem: ExceptionListItemSchema = { - ...getExceptionListItemSchemaMock(), - entries: [ - { - entries: [ - { - field: 'nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - field: 'some.parentField', - type: 'nested', - }, - ], - }; - const output = addIdToExceptionItemEntries(mockExceptionItem); - const expectedOutput: ExceptionListItemSchema = { - ...getExceptionListItemSchemaMock(), - entries: [ - { - entries: [ - { - field: 'nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as EntryMatch & { id: string }, - ], - field: 'some.parentField', - id: '123', - type: 'nested', - } as EntryNested & { id: string }, - ], - }; - - expect(output).toEqual(expectedOutput); - }); - }); - - describe('removeIdFromExceptionItemsEntries', () => { - it('should return same output as input with stripped ids per entry - CreateExceptionListItemSchema', () => { - const mockCreateExceptionItem = { - ...getCreateExceptionListItemSchemaMock(), - entries: [ - { - field: 'some.not.nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as Entry & { id: string }, - ], - }; - const output = removeIdFromExceptionItemsEntries(mockCreateExceptionItem); - const expectedOutput: CreateExceptionListItemSchema = { - ...getCreateExceptionListItemSchemaMock(), - entries: [ - { - field: 'some.not.nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - }; - - expect(output).toEqual(expectedOutput); - }); - - it('should return same output as input with stripped ids per nested entry - CreateExceptionListItemSchema', () => { - const mockCreateExceptionItem = { - ...getCreateExceptionListItemSchemaMock(), - entries: [ - { - entries: [ - { - field: 'nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as EntryMatch & { id: string }, - ], - field: 'some.parentField', - id: '123', - type: 'nested', - } as EntryNested & { id: string }, - ], - }; - const output = removeIdFromExceptionItemsEntries(mockCreateExceptionItem); - const expectedOutput: CreateExceptionListItemSchema = { - ...getCreateExceptionListItemSchemaMock(), - entries: [ - { - entries: [ - { - field: 'nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - field: 'some.parentField', - type: 'nested', - }, - ], - }; - - expect(output).toEqual(expectedOutput); - }); - - it('should return same output as input with stripped ids per entry - UpdateExceptionListItemSchema', () => { - const mockUpdateExceptionItem = { - ...getUpdateExceptionListItemSchemaMock(), - entries: [ - { - field: 'some.not.nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as Entry & { id: string }, - ], - }; - const output = removeIdFromExceptionItemsEntries(mockUpdateExceptionItem); - const expectedOutput: UpdateExceptionListItemSchema = { - ...getUpdateExceptionListItemSchemaMock(), - entries: [ - { - field: 'some.not.nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - }; - - expect(output).toEqual(expectedOutput); - }); - - it('should return same output as input with stripped ids per nested entry - UpdateExceptionListItemSchema', () => { - const mockUpdateExceptionItem = { - ...getUpdateExceptionListItemSchemaMock(), - entries: [ - { - entries: [ - { - field: 'nested.field', - id: '123', - operator: 'included', - type: 'match', - value: 'some value', - } as EntryMatch & { id: string }, - ], - field: 'some.parentField', - id: '123', - type: 'nested', - } as EntryNested & { id: string }, - ], - }; - const output = removeIdFromExceptionItemsEntries(mockUpdateExceptionItem); - const expectedOutput: UpdateExceptionListItemSchema = { - ...getUpdateExceptionListItemSchemaMock(), - entries: [ - { - entries: [ - { - field: 'nested.field', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - field: 'some.parentField', - type: 'nested', - }, - ], - }; - - expect(output).toEqual(expectedOutput); - }); - }); -}); diff --git a/packages/kbn-securitysolution-list-hooks/src/transforms/index.ts b/packages/kbn-securitysolution-list-hooks/src/transforms/index.ts deleted file mode 100644 index c30ea9ad8679c..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/transforms/index.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { flow } from 'fp-ts/lib/function'; -import { addIdToItem, removeIdFromItem } from '@kbn/securitysolution-utils'; -import type { - CreateExceptionListItemSchema, - EntriesArray, - Entry, - ExceptionListItemSchema, - UpdateExceptionListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; - -// These are a collection of transforms that are UI specific and useful for UI concerns -// that are inserted between the API and the actual user interface. In some ways these -// might be viewed as technical debt or to compensate for the differences and preferences -// of how ReactJS might prefer data vs. how we want to model data. Each function should have -// a description giving context around the transform. - -/** - * Transforms the output of exception items to compensate for technical debt or UI concerns such as - * ReactJS preferences for having ids within arrays if the data is not modeled that way. - * - * If you add a new transform of the output called "myNewTransform" do it - * in the form of: - * flow(removeIdFromExceptionItemsEntries, myNewTransform)(exceptionItem) - * - * @param exceptionItem The exceptionItem to transform the output of - * @returns The exceptionItem transformed from the output - */ -export const transformOutput = ( - exceptionItem: UpdateExceptionListItemSchema | ExceptionListItemSchema -): UpdateExceptionListItemSchema | ExceptionListItemSchema => - flow( - removeCreatedAtCreatedByFromCommentsOnUpdate, - removeIdFromExceptionItemsEntries - )(exceptionItem); - -export const transformNewItemOutput = ( - exceptionItem: CreateExceptionListItemSchema -): CreateExceptionListItemSchema => flow(removeIdFromExceptionItemsEntries)(exceptionItem); - -/** - * Transforms the output of rules to compensate for technical debt or UI concerns such as - * ReactJS preferences for having ids within arrays if the data is not modeled that way. - * - * If you add a new transform of the input called "myNewTransform" do it - * in the form of: - * flow(addIdToExceptionItemEntries, myNewTransform)(exceptionItem) - * - * @param exceptionItem The exceptionItem to transform the output of - * @returns The exceptionItem transformed from the output - */ -export const transformInput = (exceptionItem: ExceptionListItemSchema): ExceptionListItemSchema => - flow(addIdToExceptionItemEntries)(exceptionItem); - -/** - * This adds an id to the incoming exception item entries as ReactJS prefers to have - * an id added to them for use as a stable id. Later if we decide to change the data - * model to have id's within the array then this code should be removed. If not, then - * this code should stay as an adapter for ReactJS. - * - * This does break the type system slightly as we are lying a bit to the type system as we return - * the same exceptionItem as we have previously but are augmenting the arrays with an id which TypeScript - * doesn't mind us doing here. However, downstream you will notice that you have an id when the type - * does not indicate it. In that case use (ExceptionItem & { id: string }) temporarily if you're using the id. If you're not, - * you can ignore the id and just use the normal TypeScript with ReactJS. - * - * @param exceptionItem The exceptionItem to add an id to the threat matches. - * @returns exceptionItem The exceptionItem but with id added to the exception item entries - */ -export const addIdToExceptionItemEntries = ( - exceptionItem: ExceptionListItemSchema -): ExceptionListItemSchema => { - const entries = exceptionItem.entries.map((entry) => { - if (entry.type === 'nested') { - return addIdToItem({ - ...entry, - entries: entry.entries.map((nestedEntry) => addIdToItem(nestedEntry)), - }); - } else { - return addIdToItem(entry); - } - }); - return { ...exceptionItem, entries }; -}; - -/** - * This removes an id from the exceptionItem entries as ReactJS prefers to have - * an id added to them for use as a stable id. Later if we decide to change the data - * model to have id's within the array then this code should be removed. If not, then - * this code should stay as an adapter for ReactJS. - * - * @param exceptionItem The exceptionItem to remove an id from the entries. - * @returns exceptionItem The exceptionItem but with id removed from the entries - */ -export const removeIdFromExceptionItemsEntries = ( - exceptionItem: T -): T => { - const { entries } = exceptionItem; - const entriesNoId = entries.map((entry) => { - if (entry.type === 'nested') { - return removeIdFromItem({ - ...entry, - entries: entry.entries.map((nestedEntry) => removeIdFromItem(nestedEntry)), - }); - } else { - return removeIdFromItem(entry); - } - }); - return { ...exceptionItem, entries: entriesNoId }; -}; - -/** - * This removes createdAt, createdBy from the exceptionItem if a comment was added to - * the Exception item, and return the comment message with id to prevent creating the commet - * twice - * @param exceptionItem The exceptionItem to remove createdAt, createdBy from the comments array. - * @returns exceptionItem The exceptionItem with comments do not have createdAt, createdBy. - */ -export const removeCreatedAtCreatedByFromCommentsOnUpdate = ( - exceptionItem: UpdateExceptionListItemSchema | ExceptionListItemSchema -) => { - const { comments } = exceptionItem; - if (!comments || !comments.length) return exceptionItem; - - const entriesNoCreatedAtAndBy = comments.map(({ comment, id }) => ({ - comment, - id, - })); - return { ...exceptionItem, comments: entriesNoCreatedAtAndBy }; -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts deleted file mode 100644 index 4ce917f5ad95b..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useMemo } from 'react'; -import type { - CreateExceptionListItemSchema, - ExceptionListItemSchema, - ExceptionListSchema, - UpdateExceptionListItemSchema, - ApiCallFindListsItemsMemoProps, - ApiCallMemoProps, - ApiListExportProps, - ApiCallGetExceptionFilterFromIdsMemoProps, - ApiCallGetExceptionFilterFromExceptionsMemoProps, - ApiListDuplicateProps, -} from '@kbn/securitysolution-io-ts-list-types'; -import * as Api from '@kbn/securitysolution-list-api'; -import { getIdsAndNamespaces } from '@kbn/securitysolution-list-utils'; -import type { HttpStart } from '@kbn/core-http-browser'; - -import { transformInput, transformNewItemOutput, transformOutput } from '../transforms'; - -export interface ExceptionsApi { - addExceptionListItem: (arg: { - listItem: CreateExceptionListItemSchema; - }) => Promise; - updateExceptionListItem: (arg: { - listItem: UpdateExceptionListItemSchema; - }) => Promise; - deleteExceptionItem: (arg: ApiCallMemoProps) => Promise; - deleteExceptionList: (arg: ApiCallMemoProps) => Promise; - duplicateExceptionList: (arg: ApiListDuplicateProps) => Promise; - getExceptionItem: ( - arg: ApiCallMemoProps & { onSuccess: (arg: ExceptionListItemSchema) => void } - ) => Promise; - getExceptionList: ( - arg: ApiCallMemoProps & { onSuccess: (arg: ExceptionListSchema) => void } - ) => Promise; - getExceptionListsItems: (arg: ApiCallFindListsItemsMemoProps) => Promise; - getExceptionFilterFromIds: (arg: ApiCallGetExceptionFilterFromIdsMemoProps) => Promise; - getExceptionFilterFromExceptions: ( - arg: ApiCallGetExceptionFilterFromExceptionsMemoProps - ) => Promise; - exportExceptionList: (arg: ApiListExportProps) => Promise; -} - -export const useApi = (http: HttpStart): ExceptionsApi => { - return useMemo( - (): ExceptionsApi => ({ - async addExceptionListItem({ - listItem, - }: { - listItem: CreateExceptionListItemSchema; - }): Promise { - const abortCtrl = new AbortController(); - const sanitizedItem: CreateExceptionListItemSchema = transformNewItemOutput(listItem); - - return Api.addExceptionListItem({ - http, - listItem: sanitizedItem, - signal: abortCtrl.signal, - }); - }, - async deleteExceptionItem({ - id, - namespaceType, - onSuccess, - onError, - }: ApiCallMemoProps): Promise { - const abortCtrl = new AbortController(); - - try { - await Api.deleteExceptionListItemById({ - http, - id, - namespaceType, - signal: abortCtrl.signal, - }); - onSuccess(); - } catch (error) { - onError(error); - } - }, - async deleteExceptionList({ - id, - namespaceType, - onSuccess, - onError, - }: ApiCallMemoProps): Promise { - const abortCtrl = new AbortController(); - - try { - await Api.deleteExceptionListById({ - http, - id, - namespaceType, - signal: abortCtrl.signal, - }); - onSuccess(); - } catch (error) { - onError(error); - } - }, - async duplicateExceptionList({ - includeExpiredExceptions, - listId, - namespaceType, - onError, - onSuccess, - }: ApiListDuplicateProps): Promise { - const abortCtrl = new AbortController(); - - try { - const newList = await Api.duplicateExceptionList({ - http, - includeExpiredExceptions, - listId, - namespaceType, - signal: abortCtrl.signal, - }); - onSuccess(newList); - } catch (error) { - onError(error); - } - }, - async exportExceptionList({ - id, - includeExpiredExceptions, - listId, - namespaceType, - onError, - onSuccess, - }: ApiListExportProps): Promise { - const abortCtrl = new AbortController(); - - try { - const blob = await Api.exportExceptionList({ - http, - id, - includeExpiredExceptions, - listId, - namespaceType, - signal: abortCtrl.signal, - }); - onSuccess(blob); - } catch (error) { - onError(error); - } - }, - async getExceptionItem({ - id, - namespaceType, - onSuccess, - onError, - }: ApiCallMemoProps & { onSuccess: (arg: ExceptionListItemSchema) => void }): Promise { - const abortCtrl = new AbortController(); - - try { - const item = transformInput( - await Api.fetchExceptionListItemById({ - http, - id, - namespaceType, - signal: abortCtrl.signal, - }) - ); - onSuccess(item); - } catch (error) { - onError(error); - } - }, - async getExceptionList({ - id, - namespaceType, - onSuccess, - onError, - }: ApiCallMemoProps & { onSuccess: (arg: ExceptionListSchema) => void }): Promise { - const abortCtrl = new AbortController(); - - try { - const list = await Api.fetchExceptionListById({ - http, - id, - namespaceType, - signal: abortCtrl.signal, - }); - onSuccess(list); - } catch (error) { - onError(error); - } - }, - async getExceptionListsItems({ - lists, - filter, - pagination, - showDetectionsListsOnly, - showEndpointListsOnly, - onSuccess, - onError, - }: ApiCallFindListsItemsMemoProps): Promise { - const abortCtrl = new AbortController(); - const { ids, namespaces } = getIdsAndNamespaces({ - lists, - showDetection: showDetectionsListsOnly, - showEndpoint: showEndpointListsOnly, - }); - - try { - if (ids.length > 0 && namespaces.length > 0) { - const { - data, - page, - per_page: perPage, - total, - } = await Api.fetchExceptionListsItemsByListIds({ - filter, - http, - listIds: ids, - namespaceTypes: namespaces, - pagination, - signal: abortCtrl.signal, - }); - onSuccess({ - // This data transform is UI specific and useful for UI concerns - // to compensate for the differences and preferences of how ReactJS might prefer - // data vs. how we want to model data. View `transformInput` for more details - exceptions: data.map((item) => transformInput(item)), - pagination: { - page, - perPage, - total, - }, - }); - } else { - onSuccess({ - exceptions: [], - pagination: { - page: 0, - perPage: pagination.perPage != null ? pagination.perPage : 0, - total: 0, - }, - }); - } - } catch (error) { - onError(error); - } - }, - async getExceptionFilterFromIds({ - exceptionListIds, - chunkSize, - alias, - excludeExceptions, - onSuccess, - onError, - }: ApiCallGetExceptionFilterFromIdsMemoProps): Promise { - const abortCtrl = new AbortController(); - try { - const { filter } = await Api.getExceptionFilterFromExceptionListIds({ - http, - exceptionListIds, - signal: abortCtrl.signal, - chunkSize, - alias, - excludeExceptions, - }); - onSuccess(filter); - } catch (error) { - onError(error); - } - }, - async getExceptionFilterFromExceptions({ - exceptions, - chunkSize, - alias, - excludeExceptions, - onSuccess, - onError, - }: ApiCallGetExceptionFilterFromExceptionsMemoProps): Promise { - const abortCtrl = new AbortController(); - try { - const { filter } = await Api.getExceptionFilterFromExceptions({ - http, - exceptions, - signal: abortCtrl.signal, - chunkSize, - alias, - excludeExceptions, - }); - onSuccess(filter); - } catch (error) { - onError(error); - } - }, - async updateExceptionListItem({ - listItem, - }: { - listItem: UpdateExceptionListItemSchema; - }): Promise { - const abortCtrl = new AbortController(); - const sanitizedItem: UpdateExceptionListItemSchema = transformOutput(listItem); - - return Api.updateExceptionListItem({ - http, - listItem: sanitizedItem, - signal: abortCtrl.signal, - }); - }, - }), - [http] - ); -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts deleted file mode 100644 index 06b87f510796c..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useMutation, useQueryClient } from '@tanstack/react-query'; - -import { createListIndex, ApiParams } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -import { READ_INDEX_QUERY_KEY } from '../constants'; - -const createListIndexWithOptionalSignal = withOptionalSignal(createListIndex); - -export const useCreateListIndex = ({ - http, - onError, -}: { - http: ApiParams['http']; - onError?: (err: unknown) => void; -}) => { - const queryClient = useQueryClient(); - - const { mutate, isLoading, error } = useMutation( - () => createListIndexWithOptionalSignal({ http }), - { - onSuccess: () => { - queryClient.invalidateQueries(READ_INDEX_QUERY_KEY); - }, - onError, - } - ); - - return { - start: mutate, - loading: isLoading, - error, - }; -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_create_list_item/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_create_list_item/index.ts deleted file mode 100644 index 98939d93185d6..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_create_list_item/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { UseMutationOptions } from '@tanstack/react-query'; -import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import type { IHttpFetchError } from '@kbn/core-http-browser'; -import { useMutation } from '@tanstack/react-query'; -import { createListItem } from '@kbn/securitysolution-list-api'; -import type { CreateListItemParams } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -import { useInvalidateListItemQuery } from '../use_find_list_items'; - -const createListItemWithOptionalSignal = withOptionalSignal(createListItem); - -export const CREATE_LIST_ITEM_MUTATION_KEY = ['POST', 'LIST_ITEM_CREATE']; -type CreateListMutationParams = Omit; - -export const useCreateListItemMutation = ( - options?: UseMutationOptions, CreateListMutationParams> -) => { - const invalidateListItemQuery = useInvalidateListItemQuery(); - return useMutation, CreateListMutationParams>( - ({ listId, value, http }) => - createListItemWithOptionalSignal({ listId, value, http, refresh: 'wait_for' }), - { - ...options, - mutationKey: CREATE_LIST_ITEM_MUTATION_KEY, - onSettled: (...args) => { - invalidateListItemQuery(); - if (options?.onSettled) { - options.onSettled(...args); - } - }, - } - ); -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.test.ts b/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.test.ts deleted file mode 100644 index ca94eda81f950..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { renderHook, act } from '@testing-library/react'; - -import { UseCursorProps, useCursor } from '.'; - -describe('useCursor', () => { - it('returns undefined cursor if no values have been set', () => { - const { result } = renderHook((props: UseCursorProps) => useCursor(props), { - initialProps: { pageIndex: 0, pageSize: 0 }, - }); - - expect(result.current[0]).toBeUndefined(); - }); - - it('retrieves a cursor for the next page of a given page size', () => { - const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { - initialProps: { pageIndex: 0, pageSize: 0 }, - }); - rerender({ pageIndex: 1, pageSize: 1 }); - act(() => { - result.current[1]('new_cursor'); - }); - - expect(result.current[0]).toBeUndefined(); - - rerender({ pageIndex: 2, pageSize: 1 }); - expect(result.current[0]).toEqual('new_cursor'); - }); - - it('returns undefined cursor for an unknown search', () => { - const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { - initialProps: { pageIndex: 0, pageSize: 0 }, - }); - act(() => { - result.current[1]('new_cursor'); - }); - - rerender({ pageIndex: 1, pageSize: 2 }); - expect(result.current[0]).toBeUndefined(); - }); - - it('remembers cursor through rerenders', () => { - const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { - initialProps: { pageIndex: 0, pageSize: 0 }, - }); - - rerender({ pageIndex: 1, pageSize: 1 }); - act(() => { - result.current[1]('new_cursor'); - }); - - rerender({ pageIndex: 2, pageSize: 1 }); - expect(result.current[0]).toEqual('new_cursor'); - - rerender({ pageIndex: 0, pageSize: 0 }); - expect(result.current[0]).toBeUndefined(); - - rerender({ pageIndex: 2, pageSize: 1 }); - expect(result.current[0]).toEqual('new_cursor'); - }); - - it('remembers multiple cursors', () => { - const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { - initialProps: { pageIndex: 0, pageSize: 0 }, - }); - - rerender({ pageIndex: 1, pageSize: 1 }); - act(() => { - result.current[1]('new_cursor'); - }); - rerender({ pageIndex: 2, pageSize: 2 }); - act(() => { - result.current[1]('another_cursor'); - }); - - rerender({ pageIndex: 2, pageSize: 1 }); - expect(result.current[0]).toEqual('new_cursor'); - - rerender({ pageIndex: 3, pageSize: 2 }); - expect(result.current[0]).toEqual('another_cursor'); - }); - - it('returns the "nearest" cursor for the given page size', () => { - const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { - initialProps: { pageIndex: 0, pageSize: 0 }, - }); - - rerender({ pageIndex: 1, pageSize: 2 }); - act(() => { - result.current[1]('cursor1'); - }); - rerender({ pageIndex: 2, pageSize: 2 }); - act(() => { - result.current[1]('cursor2'); - }); - rerender({ pageIndex: 3, pageSize: 2 }); - act(() => { - result.current[1]('cursor3'); - }); - - rerender({ pageIndex: 2, pageSize: 2 }); - expect(result.current[0]).toEqual('cursor1'); - - rerender({ pageIndex: 3, pageSize: 2 }); - expect(result.current[0]).toEqual('cursor2'); - - rerender({ pageIndex: 4, pageSize: 2 }); - expect(result.current[0]).toEqual('cursor3'); - - rerender({ pageIndex: 6, pageSize: 2 }); - expect(result.current[0]).toEqual('cursor3'); - }); -}); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.ts deleted file mode 100644 index b8e8df0438828..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useCallback, useState } from 'react'; - -export interface UseCursorProps { - pageIndex: number; - pageSize: number; -} -type Cursor = string | undefined; -type SetCursor = (cursor: Cursor) => void; -type UseCursor = (props: UseCursorProps) => [Cursor, SetCursor]; - -const hash = (props: UseCursorProps): string => JSON.stringify(props); - -export const useCursor: UseCursor = ({ pageIndex, pageSize }) => { - const [cache, setCache] = useState>({}); - - const setCursor = useCallback( - (cursor) => { - setCache({ - ...cache, - [hash({ pageIndex: pageIndex + 1, pageSize })]: cursor, - }); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [pageIndex, pageSize] - ); - - let cursor: Cursor; - for (let i = pageIndex; i >= 0; i--) { - const currentProps = { pageIndex: i, pageSize }; - cursor = cache[hash(currentProps)]; - if (cursor) { - break; - } - } - - return [cursor, setCursor]; -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts deleted file mode 100644 index fe88e19f84892..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { deleteList } from '@kbn/securitysolution-list-api'; -import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -const deleteListWithOptionalSignal = withOptionalSignal(deleteList); - -export const useDeleteList = () => useAsync(deleteListWithOptionalSignal); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_delete_list_item/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_delete_list_item/index.ts deleted file mode 100644 index 63107edda73a9..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_delete_list_item/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { UseMutationOptions } from '@tanstack/react-query'; -import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { useMutation } from '@tanstack/react-query'; -import { deleteListItem } from '@kbn/securitysolution-list-api'; -import type { IHttpFetchError } from '@kbn/core-http-browser'; -import type { DeleteListItemParams } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; -import { useInvalidateListItemQuery } from '../use_find_list_items'; - -const deleteListItemWithOptionalSignal = withOptionalSignal(deleteListItem); - -export const DELETE_LIST_ITEM_MUTATION_KEY = ['POST', ' DELETE_LIST_ITEM_MUTATION']; -type DeleteListMutationParams = Omit; - -export const useDeleteListItemMutation = ( - options?: UseMutationOptions, DeleteListMutationParams> -) => { - const invalidateListItemQuery = useInvalidateListItemQuery(); - return useMutation, DeleteListMutationParams>( - ({ id, http }) => deleteListItemWithOptionalSignal({ id, http }), - { - ...options, - mutationKey: DELETE_LIST_ITEM_MUTATION_KEY, - onSettled: (...args) => { - invalidateListItemQuery(); - if (options?.onSettled) { - options.onSettled(...args); - } - }, - } - ); -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.ts deleted file mode 100644 index 2907de45eba40..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.ts +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import type { - ExceptionListSchema, - UseExceptionListsProps, - Pagination, - Sort, -} from '@kbn/securitysolution-io-ts-list-types'; -import { fetchExceptionLists } from '@kbn/securitysolution-list-api'; - -import { getFilters } from '@kbn/securitysolution-list-utils'; - -export type Func = () => void; -export type ReturnExceptionLists = [ - loading: boolean, - exceptionLists: ExceptionListSchema[], - pagination: Pagination, - setPagination: React.Dispatch>, - fetchLists: Func | null, - sort: Sort, - setSort: React.Dispatch> -]; - -const DEFAULT_PAGINATION = { - page: 1, - perPage: 20, - total: 0, -}; - -const DEFAULT_SORT = { - field: 'created_at', - order: 'desc', -}; - -/** - * Hook for fetching ExceptionLists - * - * @param http Kibana http service - * @param errorMessage message shown to user if error occurs - * @param filterOptions filter by certain fields - * @param namespaceTypes spaces to be searched - * @param notifications kibana service for displaying toasters - * @param hideLists a list of listIds we don't want to query - * @param initialPagination - * - */ -export const useExceptionLists = ({ - errorMessage, - http, - initialPagination = DEFAULT_PAGINATION, - filterOptions = {}, - namespaceTypes, - notifications, - hideLists = [], - initialSort = DEFAULT_SORT, -}: UseExceptionListsProps): ReturnExceptionLists => { - const [exceptionLists, setExceptionLists] = useState([]); - const [pagination, setPagination] = useState(initialPagination); - const [sort, setSort] = useState(initialSort); - const [loading, setLoading] = useState(true); - const abortCtrlRef = useRef(); - - const namespaceTypesAsString = useMemo(() => namespaceTypes.join(','), [namespaceTypes]); - const filters = useMemo( - (): string => - getFilters({ - filters: filterOptions, - namespaceTypes, - hideLists, - }), - [namespaceTypes, filterOptions, hideLists] - ); - - const fetchData = useCallback(async (): Promise => { - try { - setLoading(true); - - abortCtrlRef.current = new AbortController(); - - const { - page, - per_page: perPage, - total, - data, - } = await fetchExceptionLists({ - filters, - http, - namespaceTypes: namespaceTypesAsString, - pagination: { - page: pagination.page, - perPage: pagination.perPage, - }, - sort, - signal: abortCtrlRef.current.signal, - }); - - setPagination({ - page, - perPage, - total, - }); - setExceptionLists(data); - setLoading(false); - } catch (error) { - if (error.name !== 'AbortError') { - notifications.toasts.addError(error, { - title: errorMessage, - }); - setExceptionLists([]); - setPagination(DEFAULT_PAGINATION); - setLoading(false); - } - } - }, [ - errorMessage, - filters, - http, - namespaceTypesAsString, - notifications.toasts, - pagination.page, - pagination.perPage, - sort, - ]); - - useEffect(() => { - fetchData(); - - return (): void => { - abortCtrlRef.current?.abort(); - }; - }, [fetchData]); - - return [loading, exceptionLists, pagination, setPagination, fetchData, sort, setSort]; -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts deleted file mode 100644 index 77a213cc47b9c..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { exportList } from '@kbn/securitysolution-list-api'; -import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -const exportListWithOptionalSignal = withOptionalSignal(exportList); - -export const useExportList = () => useAsync(exportListWithOptionalSignal); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_find_list_items/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_find_list_items/index.ts deleted file mode 100644 index f385408d26fdd..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_find_list_items/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useCallback } from 'react'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; -import { findListItems, ApiParams } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; -import { useCursor } from '../use_cursor'; - -const findListItemsWithOptionalSignal = withOptionalSignal(findListItems); - -const FIND_LIST_ITEMS_QUERY_KEY = 'FIND_LIST_ITEMS'; - -export const useInvalidateListItemQuery = () => { - const queryClient = useQueryClient(); - - return useCallback(() => { - queryClient.invalidateQueries([FIND_LIST_ITEMS_QUERY_KEY], { - refetchType: 'active', - }); - }, [queryClient]); -}; - -export const useFindListItems = ({ - pageIndex, - pageSize, - sortField, - sortOrder, - listId, - filter, - http, -}: { - pageIndex: number; - pageSize: number; - sortField: string; - sortOrder: 'asc' | 'desc'; - listId: string; - filter: string; - http: ApiParams['http']; -}) => { - const [cursor, setCursor] = useCursor({ pageIndex, pageSize }); - return useQuery( - [FIND_LIST_ITEMS_QUERY_KEY, pageIndex, pageSize, sortField, sortOrder, listId, filter], - async ({ signal }) => { - const response = await findListItemsWithOptionalSignal({ - http, - signal, - pageIndex, - pageSize, - sortField, - sortOrder, - listId, - cursor, - filter, - }); - return response; - }, - { - keepPreviousData: true, - refetchOnWindowFocus: false, - retry: false, - onSuccess: (data) => { - if (data?.cursor) { - setCursor(data?.cursor); - } - }, - } - ); -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts b/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts deleted file mode 100644 index fcce54ac3be32..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { waitFor, renderHook, act } from '@testing-library/react'; - -import { useFindLists } from '.'; -import { httpServiceMock } from '@kbn/core-http-browser-mocks'; -import * as Api from '@kbn/securitysolution-list-api'; - -import { getFoundListSchemaMock } from '../mocks/response/found_list_schema.mock'; - -jest.mock('@kbn/securitysolution-list-api'); - -describe('useFindLists', () => { - let httpMock: ReturnType; - - beforeEach(() => { - httpMock = httpServiceMock.createStartContract(); - (Api.findLists as jest.Mock).mockResolvedValue(getFoundListSchemaMock()); - }); - - it('invokes Api.findLists', async () => { - const { result } = renderHook(() => useFindLists()); - act(() => { - result.current.start({ http: httpMock, pageIndex: 1, pageSize: 10 }); - }); - await waitFor(() => - expect(Api.findLists).toHaveBeenCalledWith( - expect.objectContaining({ http: httpMock, pageIndex: 1, pageSize: 10 }) - ) - ); - }); -}); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts deleted file mode 100644 index a33e3ba9f8607..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { findLists } from '@kbn/securitysolution-list-api'; -import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -const findListsWithOptionalSignal = withOptionalSignal(findLists); - -export const useFindLists = () => useAsync(findListsWithOptionalSignal); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_find_lists_by_size/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_find_lists_by_size/index.ts deleted file mode 100644 index 25027ee3901d2..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_find_lists_by_size/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { findListsBySize } from '@kbn/securitysolution-list-api'; -import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -const findListsBySizeWithOptionalSignal = withOptionalSignal(findListsBySize); - -export const useFindListsBySize = () => useAsync(findListsBySizeWithOptionalSignal); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_get_list_by_id/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_get_list_by_id/index.ts deleted file mode 100644 index 030fbcfae829f..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_get_list_by_id/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useQuery } from '@tanstack/react-query'; -import { getListById, ApiParams } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -const getListByIdWithOptionalSignal = withOptionalSignal(getListById); - -const GET_LIST_BY_ID_QUERY_KEY = 'GET_LIST_BY_ID'; -export const useGetListById = ({ http, id }: { http: ApiParams['http']; id: string }) => { - return useQuery( - [GET_LIST_BY_ID_QUERY_KEY, id], - async ({ signal }) => { - const respone = await getListByIdWithOptionalSignal({ http, signal, id }); - return respone; - }, - { - refetchOnWindowFocus: false, - } - ); -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts deleted file mode 100644 index 1bbccd1448017..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { importList } from '@kbn/securitysolution-list-api'; -import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -const importListWithOptionalSignal = withOptionalSignal(importList); - -export const useImportList = () => useAsync(importListWithOptionalSignal); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_patch_list_item/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_patch_list_item/index.ts deleted file mode 100644 index cdae3015cff81..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_patch_list_item/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { UseMutationOptions } from '@tanstack/react-query'; -import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { useMutation } from '@tanstack/react-query'; -import type { PatchListItemParams } from '@kbn/securitysolution-list-api'; -import { patchListItem } from '@kbn/securitysolution-list-api'; -import type { IHttpFetchError } from '@kbn/core-http-browser'; -import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; -import { useInvalidateListItemQuery } from '../use_find_list_items'; - -const patchListItemWithOptionalSignal = withOptionalSignal(patchListItem); - -export const PATCH_LIST_ITEM_MUTATION_KEY = ['PATCH', 'LIST_ITEM_MUTATION']; -type PatchListMutationParams = Omit; - -export const usePatchListItemMutation = ( - options?: UseMutationOptions, PatchListMutationParams> -) => { - const invalidateListItemQuery = useInvalidateListItemQuery(); - return useMutation, PatchListMutationParams>( - ({ id, value, _version, http }: PatchListMutationParams) => - patchListItemWithOptionalSignal({ id, value, http, refresh: 'true', _version }), - { - ...options, - mutationKey: PATCH_LIST_ITEM_MUTATION_KEY, - onSettled: (...args) => { - invalidateListItemQuery(); - if (options?.onSettled) { - options.onSettled(...args); - } - }, - } - ); -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.ts deleted file mode 100644 index 79f8748345fdf..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { Dispatch, useEffect, useRef, useState } from 'react'; -import type { - CreateExceptionListItemSchema, - PersistHookProps, - UpdateExceptionListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { addExceptionListItem, updateExceptionListItem } from '@kbn/securitysolution-list-api'; - -import { transformNewItemOutput, transformOutput } from '../transforms'; - -interface PersistReturnExceptionItem { - isLoading: boolean; - isSaved: boolean; -} - -export type ReturnPersistExceptionItem = [ - PersistReturnExceptionItem, - Dispatch -]; - -// TODO: Add this to @kbn/securitysolution-list-hooks - -/** - * Hook for creating or updating ExceptionListItem - * - * @param http Kibana http service - * @param onError error callback - * - */ -export const usePersistExceptionItem = ({ - http, - onError, -}: PersistHookProps): ReturnPersistExceptionItem => { - const [exceptionListItem, setExceptionItem] = useState< - CreateExceptionListItemSchema | UpdateExceptionListItemSchema | null - >(null); - const [isSaved, setIsSaved] = useState(false); - const [isLoading, setIsLoading] = useState(false); - const isUpdateExceptionItem = (item: unknown): item is UpdateExceptionListItemSchema => - Boolean(item && (item as UpdateExceptionListItemSchema).id != null); - const isSubscribed = useRef(false); - - useEffect(() => { - let abortCtrl: AbortController | null = null; - isSubscribed.current = true; - setIsSaved(false); - - const saveExceptionItem = async (): Promise => { - if (exceptionListItem === null) { - return; - } - - try { - abortCtrl = new AbortController(); - setIsLoading(true); - - if (isUpdateExceptionItem(exceptionListItem)) { - // Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes - // for context around the temporary `id` - const transformedList = transformOutput(exceptionListItem); - - await updateExceptionListItem({ - http, - listItem: transformedList, - signal: abortCtrl.signal, - }); - } else { - // Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes - // for context around the temporary `id` - const transformedList = transformNewItemOutput(exceptionListItem); - - await addExceptionListItem({ - http, - listItem: transformedList, - signal: abortCtrl.signal, - }); - } - - if (isSubscribed.current) { - setIsSaved(true); - } - } catch (error) { - if (isSubscribed.current) { - onError(error); - } - } finally { - if (isSubscribed.current) { - setIsLoading(false); - } - } - }; - - saveExceptionItem(); - - return (): void => { - isSubscribed.current = false; - abortCtrl?.abort(); - }; - }, [http, exceptionListItem, onError]); - - return [{ isLoading, isSaved }, setExceptionItem]; -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.ts deleted file mode 100644 index 8648516d008cc..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { Dispatch, useEffect, useState } from 'react'; -import type { - AddExceptionList, - PersistHookProps, - UpdateExceptionListSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { addExceptionList, updateExceptionList } from '@kbn/securitysolution-list-api'; - -interface PersistReturnExceptionList { - isLoading: boolean; - isSaved: boolean; -} - -export type ReturnPersistExceptionList = [ - PersistReturnExceptionList, - Dispatch -]; - -/** - * Hook for creating or updating ExceptionList - * - * @param http Kibana http service - * @param onError error callback - * - */ -export const usePersistExceptionList = ({ - http, - onError, -}: PersistHookProps): ReturnPersistExceptionList => { - const [exceptionList, setExceptionList] = useState(null); - const [isSaved, setIsSaved] = useState(false); - const [isLoading, setIsLoading] = useState(false); - const isUpdateExceptionList = (item: unknown): item is UpdateExceptionListSchema => - Boolean(item && (item as UpdateExceptionListSchema).id != null); - - useEffect(() => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - setIsSaved(false); - - const saveExceptionList = async (): Promise => { - if (exceptionList != null) { - try { - setIsLoading(true); - if (isUpdateExceptionList(exceptionList)) { - await updateExceptionList({ http, list: exceptionList, signal: abortCtrl.signal }); - } else { - await addExceptionList({ http, list: exceptionList, signal: abortCtrl.signal }); - } - if (isSubscribed) { - setIsSaved(true); - } - } catch (error) { - if (isSubscribed) { - onError(error); - } - } - if (isSubscribed) { - setIsLoading(false); - } - } - }; - - saveExceptionList(); - return (): void => { - isSubscribed = false; - abortCtrl.abort(); - }; - }, [http, exceptionList, onError]); - - return [{ isLoading, isSaved }, setExceptionList]; -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts deleted file mode 100644 index 4853f0a7480a8..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useQuery } from '@tanstack/react-query'; - -import { readListIndex, ApiParams } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -import { READ_INDEX_QUERY_KEY } from '../constants'; - -const readListIndexWithOptionalSignal = withOptionalSignal(readListIndex); - -export const useReadListIndex = ({ - http, - isEnabled, - onError, -}: { - isEnabled: boolean; - http: ApiParams['http']; - onError?: (err: unknown) => void; -}) => { - const query = useQuery( - READ_INDEX_QUERY_KEY, - async ({ signal }) => { - if (!isEnabled) { - return null; - } - - return readListIndexWithOptionalSignal({ http, signal }); - }, - { - onError, - retry: false, - refetchOnWindowFocus: false, - enabled: isEnabled, - staleTime: Infinity, - } - ); - - return { - result: query.data, - loading: query.isFetching, - error: query.error, - }; -}; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts deleted file mode 100644 index 42a055c168085..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { readListPrivileges } from '@kbn/securitysolution-list-api'; -import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; - -const readListPrivilegesWithOptionalSignal = withOptionalSignal(readListPrivileges); - -export const useReadListPrivileges = () => useAsync(readListPrivilegesWithOptionalSignal); diff --git a/packages/kbn-securitysolution-list-hooks/tsconfig.json b/packages/kbn-securitysolution-list-hooks/tsconfig.json deleted file mode 100644 index 53e105e609750..0000000000000 --- a/packages/kbn-securitysolution-list-hooks/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts", - ], - "kbn_references": [ - "@kbn/securitysolution-hook-utils", - "@kbn/securitysolution-io-ts-list-types", - "@kbn/securitysolution-list-api", - "@kbn/securitysolution-list-utils", - "@kbn/securitysolution-utils", - "@kbn/core-http-browser-mocks", - "@kbn/core-http-browser", - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-list-utils/index.ts b/packages/kbn-securitysolution-list-utils/index.ts deleted file mode 100644 index c5999a044a188..0000000000000 --- a/packages/kbn-securitysolution-list-utils/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/autocomplete_operators'; -export * from './src/get_exception_list_type'; -export * from './src/get_filters'; -export * from './src/get_general_filters'; -export * from './src/get_ids_and_namespaces'; -export * from './src/get_saved_object_type'; -export * from './src/get_saved_object_types'; -export * from './src/has_large_value_list'; -export * from './src/helpers'; -export * from './src/types'; diff --git a/packages/kbn-securitysolution-list-utils/jest.config.js b/packages/kbn-securitysolution-list-utils/jest.config.js deleted file mode 100644 index b24a4fa543f78..0000000000000 --- a/packages/kbn-securitysolution-list-utils/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-list-utils'], -}; diff --git a/packages/kbn-securitysolution-list-utils/package.json b/packages/kbn-securitysolution-list-utils/package.json deleted file mode 100644 index e9ace6e302344..0000000000000 --- a/packages/kbn-securitysolution-list-utils/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/securitysolution-list-utils", - "version": "1.0.0", - "description": "security solution list utilities", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts b/packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts deleted file mode 100644 index b4b1eec6be342..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { i18n } from '@kbn/i18n'; -import { - ListOperatorEnum as OperatorEnum, - ListOperatorTypeEnum as OperatorTypeEnum, -} from '@kbn/securitysolution-io-ts-list-types'; -import { OperatorOption } from '../types'; - -export const isOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.isOperatorLabel', { - defaultMessage: 'is', - }), - operator: OperatorEnum.INCLUDED, - type: OperatorTypeEnum.MATCH, - value: 'is', -}; - -export const isNotOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.isNotOperatorLabel', { - defaultMessage: 'is not', - }), - operator: OperatorEnum.EXCLUDED, - type: OperatorTypeEnum.MATCH, - value: 'is_not', -}; - -export const isOneOfOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.isOneOfOperatorLabel', { - defaultMessage: 'is one of', - }), - operator: OperatorEnum.INCLUDED, - type: OperatorTypeEnum.MATCH_ANY, - value: 'is_one_of', -}; - -export const isNotOneOfOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.isNotOneOfOperatorLabel', { - defaultMessage: 'is not one of', - }), - operator: OperatorEnum.EXCLUDED, - type: OperatorTypeEnum.MATCH_ANY, - value: 'is_not_one_of', -}; - -export const existsOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.existsOperatorLabel', { - defaultMessage: 'exists', - }), - operator: OperatorEnum.INCLUDED, - type: OperatorTypeEnum.EXISTS, - value: 'exists', -}; - -export const doesNotExistOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.doesNotExistOperatorLabel', { - defaultMessage: 'does not exist', - }), - operator: OperatorEnum.EXCLUDED, - type: OperatorTypeEnum.EXISTS, - value: 'does_not_exist', -}; - -export const isInListOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.isInListOperatorLabel', { - defaultMessage: 'is in list', - }), - operator: OperatorEnum.INCLUDED, - type: OperatorTypeEnum.LIST, - value: 'is_in_list', -}; - -export const isNotInListOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.isNotInListOperatorLabel', { - defaultMessage: 'is not in list', - }), - operator: OperatorEnum.EXCLUDED, - type: OperatorTypeEnum.LIST, - value: 'is_not_in_list', -}; - -export const matchesOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.matchesOperatorLabel', { - defaultMessage: 'matches', - }), - operator: OperatorEnum.INCLUDED, - type: OperatorTypeEnum.WILDCARD, - value: 'matches', -}; - -export const doesNotMatchOperator: OperatorOption = { - message: i18n.translate('lists.exceptions.doesNotMatchOperatorLabel', { - defaultMessage: 'does not match', - }), - operator: OperatorEnum.EXCLUDED, - type: OperatorTypeEnum.WILDCARD, - value: 'does_not_match', -}; - -export const EVENT_FILTERS_OPERATORS: OperatorOption[] = [ - isOperator, - isNotOperator, - isOneOfOperator, - isNotOneOfOperator, - matchesOperator, - doesNotMatchOperator, -]; - -/* - * !IMPORTANT! - Please only add to this list if it is an operator - * supported by the detection engine. - */ -export const DETECTION_ENGINE_EXCEPTION_OPERATORS: OperatorOption[] = [ - isOperator, - isNotOperator, - isOneOfOperator, - isNotOneOfOperator, - existsOperator, - doesNotExistOperator, - isInListOperator, - isNotInListOperator, - matchesOperator, - doesNotMatchOperator, -]; - -export const ALL_OPERATORS: OperatorOption[] = [ - isOperator, - isNotOperator, - isOneOfOperator, - isNotOneOfOperator, - existsOperator, - doesNotExistOperator, - isInListOperator, - isNotInListOperator, - matchesOperator, - doesNotMatchOperator, -]; - -export const EXCEPTION_OPERATORS_SANS_LISTS: OperatorOption[] = [ - isOperator, - isNotOperator, - isOneOfOperator, - isNotOneOfOperator, - existsOperator, - doesNotExistOperator, - matchesOperator, - doesNotMatchOperator, -]; - -export const EXCEPTION_OPERATORS_ONLY_LISTS: OperatorOption[] = [ - isInListOperator, - isNotInListOperator, -]; diff --git a/packages/kbn-securitysolution-list-utils/src/get_exception_list_type/index.ts b/packages/kbn-securitysolution-list-utils/src/get_exception_list_type/index.ts deleted file mode 100644 index 568436c487dea..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_exception_list_type/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; - -import { exceptionListAgnosticSavedObjectType } from '../types'; - -export const getExceptionListType = ({ - savedObjectType, -}: { - savedObjectType: string; -}): NamespaceType => { - if (savedObjectType === exceptionListAgnosticSavedObjectType) { - return 'agnostic'; - } else { - return 'single'; - } -}; diff --git a/packages/kbn-securitysolution-list-utils/src/get_filters/index.test.ts b/packages/kbn-securitysolution-list-utils/src/get_filters/index.test.ts deleted file mode 100644 index 76b9eeda44f86..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_filters/index.test.ts +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { getFilters } from '.'; - -describe('getFilters', () => { - describe('single', () => { - test('it properly formats when no filters and hide lists contains few list ids', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['single'], - hideLists: ['listId-1', 'listId-2', 'listId-3'], - }); - - expect(filter).toEqual( - '(not exception-list.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3*)' - ); - }); - test('it properly formats when no filters and hide lists contains one list id', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['single'], - hideLists: ['listId-1'], - }); - - expect(filter).toEqual('(not exception-list.attributes.list_id: listId-1*)'); - }); - test('it properly formats when no filters and no hide lists', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['single'], - hideLists: [], - }); - - expect(filter).toEqual(''); - }); - test('it properly formats when filters passed and hide lists contains few list ids', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['single'], - hideLists: ['listId-1', 'listId-2', 'listId-3'], - }); - - expect(filter).toEqual( - '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3*)' - ); - }); - test('it properly formats when filters passed and hide lists contains one list id', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['single'], - hideLists: ['listId-1'], - }); - - expect(filter).toEqual( - '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1*)' - ); - }); - test('it properly formats when filters passed and no hide lists', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['single'], - hideLists: [], - }); - - expect(filter).toEqual( - '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample)' - ); - }); - }); - - describe('agnostic', () => { - test('it properly formats when no filters and hide lists contains few list ids', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['agnostic'], - hideLists: ['listId-1', 'listId-2', 'listId-3'], - }); - - expect(filter).toEqual( - '(not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list-agnostic.attributes.list_id: listId-3*)' - ); - }); - test('it properly formats when no filters and hide lists contains one list id', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['agnostic'], - hideLists: ['listId-1'], - }); - - expect(filter).toEqual('(not exception-list-agnostic.attributes.list_id: listId-1*)'); - }); - test('it properly formats when no filters and no hide lists', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['agnostic'], - hideLists: [], - }); - - expect(filter).toEqual(''); - }); - test('it properly formats when filters passed and hide lists contains few list ids', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['agnostic'], - hideLists: ['listId-1', 'listId-2', 'listId-3'], - }); - - expect(filter).toEqual( - '(exception-list-agnostic.attributes.created_by:moi) AND (exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list-agnostic.attributes.list_id: listId-3*)' - ); - }); - test('it properly formats when filters passed and hide lists contains one list id', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['agnostic'], - hideLists: ['listId-1'], - }); - - expect(filter).toEqual( - '(exception-list-agnostic.attributes.created_by:moi) AND (exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list-agnostic.attributes.list_id: listId-1*)' - ); - }); - test('it properly formats when filters passed and no hide lists', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['agnostic'], - hideLists: [], - }); - - expect(filter).toEqual( - '(exception-list-agnostic.attributes.created_by:moi) AND (exception-list-agnostic.attributes.name.text:Sample)' - ); - }); - }); - - describe('single, agnostic', () => { - test('it properly formats when no filters and hide lists contains few list ids', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['single', 'agnostic'], - hideLists: ['listId-1', 'listId-2', 'listId-3'], - }); - - expect(filter).toEqual( - '(not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2* AND not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3* AND not exception-list-agnostic.attributes.list_id: listId-3*)' - ); - }); - test('it properly formats when no filters and hide lists contains one list id', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['single', 'agnostic'], - hideLists: ['listId-1'], - }); - - expect(filter).toEqual( - '(not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)' - ); - }); - test('it properly formats when no filters and no hide lists', () => { - const filter = getFilters({ - filters: {}, - namespaceTypes: ['single', 'agnostic'], - hideLists: [], - }); - - expect(filter).toEqual(''); - }); - test('it properly formats when filters passed and hide lists contains few list ids', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['single', 'agnostic'], - hideLists: ['listId-1', 'listId-2', 'listId-3'], - }); - - expect(filter).toEqual( - '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2* AND not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3* AND not exception-list-agnostic.attributes.list_id: listId-3*)' - ); - }); - test('it properly formats when filters passed and hide lists contains one list id', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['single', 'agnostic'], - hideLists: ['listId-1'], - }); - - expect(filter).toEqual( - '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)' - ); - }); - test('it properly formats when filters passed and no hide lists', () => { - const filter = getFilters({ - filters: { created_by: 'moi', name: 'Sample' }, - namespaceTypes: ['single', 'agnostic'], - hideLists: [], - }); - - expect(filter).toEqual( - '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample)' - ); - }); - }); -}); diff --git a/packages/kbn-securitysolution-list-utils/src/get_filters/index.ts b/packages/kbn-securitysolution-list-utils/src/get_filters/index.ts deleted file mode 100644 index 6ca3119855b34..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_filters/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ExceptionListFilter, NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; -import { getGeneralFilters } from '../get_general_filters'; -import { getSavedObjectTypes } from '../get_saved_object_types'; -export interface GetFiltersParams { - filters: ExceptionListFilter; - namespaceTypes: NamespaceType[]; - hideLists: readonly string[]; -} - -export const getFilters = ({ filters, namespaceTypes, hideLists }: GetFiltersParams): string => { - const namespaces = getSavedObjectTypes({ namespaceType: namespaceTypes }); - const generalFilters = getGeneralFilters(filters, namespaces); - const hideListsFilters = hideLists.map((listId) => { - const filtersByNamespace = namespaces.map((namespace) => { - return `not ${namespace}.attributes.list_id: ${listId}*`; - }); - return `(${filtersByNamespace.join(' AND ')})`; - }); - - return [generalFilters, ...hideListsFilters] - .filter((filter) => filter.trim() !== '') - .join(' AND '); -}; diff --git a/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.test.ts b/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.test.ts deleted file mode 100644 index b349c57ab3868..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { getGeneralFilters } from '.'; - -describe('getGeneralFilters', () => { - test('it returns empty string if no filters', () => { - const filters = getGeneralFilters({}, ['exception-list']); - - expect(filters).toEqual(''); - }); - - test('it properly formats filters when one namespace type passed in', () => { - const filters = getGeneralFilters({ created_by: 'moi', name: 'Sample' }, ['exception-list']); - - expect(filters).toEqual( - '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample)' - ); - }); - - test('it properly formats filters when two namespace types passed in', () => { - const filters = getGeneralFilters({ created_by: 'moi', name: 'Sample' }, [ - 'exception-list', - 'exception-list-agnostic', - ]); - - expect(filters).toEqual( - '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample)' - ); - }); - - test('it properly formats filters when two types are passed in', () => { - const filters = getGeneralFilters( - { - created_by: 'moi', - name: 'Sample', - types: [ExceptionListTypeEnum.DETECTION, ExceptionListTypeEnum.RULE_DEFAULT], - }, - ['exception-list', 'exception-list-agnostic'] - ); - - expect(filters).toEqual( - '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample) AND (exception-list.attributes.type:detection OR exception-list.attributes.type:rule_default OR exception-list-agnostic.attributes.type:detection OR exception-list-agnostic.attributes.type:rule_default)' - ); - }); -}); diff --git a/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.ts b/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.ts deleted file mode 100644 index cc9b46728cbc4..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ExceptionListFilter } from '@kbn/securitysolution-io-ts-list-types'; -import { isArray } from 'lodash'; -import { get } from 'lodash/fp'; -import { SavedObjectType } from '../types'; - -export const getGeneralFilters = ( - filters: ExceptionListFilter, - namespaceTypes: SavedObjectType[] -): string => { - return Object.keys(filters) - .map((filterKey) => { - const value = get(filterKey, filters); - if (isArray(value) || (value != null && value.trim() !== '')) { - const filtersByNamespace = namespaceTypes - .map((namespace) => { - const fieldToSearch = - filterKey === 'name' ? 'name.text' : filterKey === 'types' ? 'type' : filterKey; - return isArray(value) - ? value.map((val) => `${namespace}.attributes.${fieldToSearch}:${val}`).join(' OR ') - : `${namespace}.attributes.${fieldToSearch}:${value}`; - }) - .join(' OR '); - return `(${filtersByNamespace})`; - } else return null; - }) - .filter((item) => item != null) - .join(' AND '); -}; diff --git a/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.test.ts b/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.test.ts deleted file mode 100644 index df5bedc2d2b49..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { getIdsAndNamespaces } from '.'; - -describe('getIdsAndNamespaces', () => { - test('it returns empty arrays if no lists found', async () => { - const output = getIdsAndNamespaces({ - lists: [], - showDetection: false, - showEndpoint: false, - }); - - expect(output).toEqual({ ids: [], namespaces: [] }); - }); - - test('it returns all lists if "showDetection" and "showEndpoint" are "false"', async () => { - const output = getIdsAndNamespaces({ - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - { - id: 'myListIdEndpoint', - listId: 'list_id_endpoint', - namespaceType: 'agnostic', - type: 'endpoint', - }, - ], - showDetection: false, - showEndpoint: false, - }); - - expect(output).toEqual({ - ids: ['list_id', 'list_id_endpoint'], - namespaces: ['single', 'agnostic'], - }); - }); - - test('it returns only detections lists if "showDetection" is "true"', async () => { - const output = getIdsAndNamespaces({ - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - { - id: 'myListIdEndpoint', - listId: 'list_id_endpoint', - namespaceType: 'agnostic', - type: 'endpoint', - }, - ], - showDetection: true, - showEndpoint: false, - }); - - expect(output).toEqual({ - ids: ['list_id'], - namespaces: ['single'], - }); - }); - - test('it returns only endpoint lists if "showEndpoint" is "true"', async () => { - const output = getIdsAndNamespaces({ - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - { - id: 'myListIdEndpoint', - listId: 'list_id_endpoint', - namespaceType: 'agnostic', - type: 'endpoint', - }, - ], - showDetection: false, - showEndpoint: true, - }); - - expect(output).toEqual({ - ids: ['list_id_endpoint'], - namespaces: ['agnostic'], - }); - }); - - test('it returns only detection lists if both "showEndpoint" and "showDetection" are "true"', async () => { - const output = getIdsAndNamespaces({ - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - { - id: 'myListIdEndpoint', - listId: 'list_id_endpoint', - namespaceType: 'agnostic', - type: 'endpoint', - }, - ], - showDetection: true, - showEndpoint: true, - }); - - expect(output).toEqual({ - ids: ['list_id'], - namespaces: ['single'], - }); - }); -}); diff --git a/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.ts b/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.ts deleted file mode 100644 index bc18dff7d33e1..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ExceptionListIdentifiers, NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; - -export const getIdsAndNamespaces = ({ - lists, - showDetection, - showEndpoint, -}: { - lists: ExceptionListIdentifiers[]; - showDetection: boolean; - showEndpoint: boolean; -}): { ids: string[]; namespaces: NamespaceType[] } => - lists - .filter((list) => { - if (showDetection) { - return list.type === 'detection'; - } else if (showEndpoint) { - return list.type === 'endpoint'; - } else { - return true; - } - }) - .reduce<{ ids: string[]; namespaces: NamespaceType[] }>( - (acc, { listId, namespaceType }) => ({ - ids: [...acc.ids, listId], - namespaces: [...acc.namespaces, namespaceType], - }), - { ids: [], namespaces: [] } - ); diff --git a/packages/kbn-securitysolution-list-utils/src/get_saved_object_type/index.ts b/packages/kbn-securitysolution-list-utils/src/get_saved_object_type/index.ts deleted file mode 100644 index 3e6cd312cb967..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_saved_object_type/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; - -import { - exceptionListAgnosticSavedObjectType, - exceptionListSavedObjectType, - SavedObjectType, -} from '../types'; - -export const getSavedObjectType = ({ - namespaceType, -}: { - namespaceType: NamespaceType; -}): SavedObjectType => { - if (namespaceType === 'agnostic') { - return exceptionListAgnosticSavedObjectType; - } else { - return exceptionListSavedObjectType; - } -}; diff --git a/packages/kbn-securitysolution-list-utils/src/get_saved_object_types/index.ts b/packages/kbn-securitysolution-list-utils/src/get_saved_object_types/index.ts deleted file mode 100644 index ec09fc25bd772..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/get_saved_object_types/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { NamespaceTypeArray } from '@kbn/securitysolution-io-ts-list-types'; - -import { SavedObjectType } from '../types'; -import { getSavedObjectType } from '../get_saved_object_type'; - -export const getSavedObjectTypes = ({ - namespaceType, -}: { - namespaceType: NamespaceTypeArray; -}): SavedObjectType[] => { - return namespaceType.map((singleNamespaceType) => - getSavedObjectType({ namespaceType: singleNamespaceType }) - ); -}; diff --git a/packages/kbn-securitysolution-list-utils/src/has_large_value_list/index.ts b/packages/kbn-securitysolution-list-utils/src/has_large_value_list/index.ts deleted file mode 100644 index ef774b5c8cf11..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/has_large_value_list/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types'; - -export const hasLargeValueList = (entries: EntriesArray): boolean => { - const found = entries.filter(({ type }) => type === 'list'); - return found.length > 0; -}; diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts deleted file mode 100644 index fffcabbf41575..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts +++ /dev/null @@ -1,377 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - getMappingConflictsInfo, - fieldSupportsMatches, - hasWrongOperatorWithWildcard, - hasPartialCodeSignatureEntry, -} from '.'; - -describe('Helpers', () => { - describe('getMappingConflictsInfo', () => { - test('it return null if there are not conflicts', () => { - const field = { - name: 'field1', - type: 'string', - }; - const conflictsInfo = getMappingConflictsInfo(field); - - expect(conflictsInfo).toBeNull(); - }); - test('it groups ".ds-" data stream indices', () => { - const field = { - name: 'field1', - type: 'conflict', - conflictDescriptions: { - text: [ - '.ds-logs-default-2023.01.18-000001', - '.ds-logs-default-2023.01.18-000002', - '.ds-logs-tortilla.process-default-2022.11.20-000011', - '.ds-logs-tortilla.process-default-2022.11.20-000012', - '.ds-logs-tortilla.process-default-2022.11.20-000016', - ], - long: [ - '.ds-logs-default-2023.01.18-000004', - '.ds-logs-default-2023.01.18-000005', - 'partial-.ds-logs-gcp.audit-2021.12.22-000240', - 'partial-.ds-logs-gcp.audit-2021.12.22-000242', - ], - }, - }; - const conflictsInfo = getMappingConflictsInfo(field); - - expect(conflictsInfo).toEqual([ - { - type: 'text', - totalIndexCount: 5, - groupedIndices: [ - { name: 'logs-tortilla.process-default', count: 3 }, - { name: 'logs-default', count: 2 }, - ], - }, - { - type: 'long', - totalIndexCount: 4, - groupedIndices: [ - { name: 'logs-default', count: 2 }, - { name: 'logs-gcp.audit', count: 2 }, - ], - }, - ]); - }); - test('it groups old ".siem-" indices', () => { - const field = { - name: 'field1', - type: 'conflict', - conflictDescriptions: { - text: [ - '.siem-signals-default-000001', - '.siem-signals-default-000002', - '.siem-signals-default-000011', - '.siem-signals-default-000012', - ], - unmapped: [ - '.siem-signals-default-000004', - '.siem-signals-default-000005', - '.siem-signals-default-000240', - ], - }, - }; - const conflictsInfo = getMappingConflictsInfo(field); - - expect(conflictsInfo).toEqual([ - { - type: 'text', - totalIndexCount: 4, - groupedIndices: [{ name: '.siem-signals-default', count: 4 }], - }, - { - type: 'unmapped', - totalIndexCount: 3, - groupedIndices: [{ name: '.siem-signals-default', count: 3 }], - }, - ]); - }); - test('it groups mixed indices', () => { - const field = { - name: 'field1', - type: 'conflict', - conflictDescriptions: { - boolean: [ - '.ds-logs-default-2023.01.18-000001', - '.ds-logs-tortilla.process-default-2022.11.20-000011', - '.ds-logs-tortilla.process-default-2022.11.20-000012', - '.ds-logs-tortilla.process-default-2022.11.20-000016', - '.siem-signals-default-000001', - '.siem-signals-default-000002', - '.siem-signals-default-000012', - 'my-own-index-1', - 'my-own-index-2', - ], - unmapped: [ - '.siem-signals-default-000004', - 'partial-.ds-logs-gcp.audit-2021.12.22-000240', - 'partial-.ds-logs-gcp.audit-2021.12.22-000242', - 'my-own-index-3', - ], - }, - }; - const conflictsInfo = getMappingConflictsInfo(field); - - expect(conflictsInfo).toEqual([ - { - type: 'boolean', - totalIndexCount: 9, - groupedIndices: [ - { name: 'logs-tortilla.process-default', count: 3 }, - { name: '.siem-signals-default', count: 3 }, - { name: 'logs-default', count: 1 }, - { name: 'my-own-index-1', count: 1 }, - { name: 'my-own-index-2', count: 1 }, - ], - }, - { - type: 'unmapped', - totalIndexCount: 4, - groupedIndices: [ - { name: 'logs-gcp.audit', count: 2 }, - { name: '.siem-signals-default', count: 1 }, - { name: 'my-own-index-3', count: 1 }, - ], - }, - ]); - }); - }); - - describe('fieldSupportsMatches', () => { - test('it returns true if esTypes is keyword', () => { - expect( - fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['keyword'] }) - ).toBeTruthy(); - }); - - test('it returns true if one of the esTypes is kibana type string and another is not', () => { - expect( - fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['keyword', 'object'] }) - ).toBeTruthy(); - }); - - test('it returns true if one of the esTypes is keyword', () => { - expect( - fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['keyword', 'unmapped'] }) - ).toBeTruthy(); - }); - - test('it returns true if one of the esTypes is text', () => { - expect( - fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['text', 'unmapped'] }) - ).toBeTruthy(); - }); - - test('it returns true if all of the esTypes is map to kibana type string', () => { - expect( - fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['text', 'keyword'] }) - ).toBeTruthy(); - }); - - test('it returns false if none of the esTypes map to kibana type string', () => { - expect( - fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['bool', 'unmapped'] }) - ).toBeFalsy(); - }); - }); - describe('hasWrongOperatorWithWildcard', () => { - test('it returns true if there is at least one exception entry with a wildcard and the wrong operator', () => { - expect( - hasWrongOperatorWithWildcard([ - { - description: '', - name: '', - type: 'simple', - entries: [{ type: 'match', value: 'withwildcard*', field: '', operator: 'included' }], - }, - ]) - ).toBeTruthy(); - expect( - hasWrongOperatorWithWildcard([ - { - description: '', - name: '', - type: 'simple', - entries: [{ type: 'match', value: 'withwildcard?', field: '', operator: 'included' }], - }, - ]) - ).toBeTruthy(); - }); - - test('it returns true if there are entries joined with an OR that have a wildcard and the wrong operator', () => { - expect( - hasWrongOperatorWithWildcard([ - { - description: '', - name: '', - type: 'simple', - entries: [{ type: 'match', value: 'withwildcard?', field: '', operator: 'included' }], - }, - { - description: '', - name: '', - type: 'simple', - entries: [{ type: 'match', value: 'withwildcard?*', field: '', operator: 'included' }], - }, - ]) - ).toBeTruthy(); - }); - - test('it returns false if there are no exception entries with a wildcard and the wrong operator', () => { - expect( - hasWrongOperatorWithWildcard([ - { - description: '', - name: '', - type: 'simple', - entries: [ - { type: 'match', value: 'nowildcard', field: '', operator: 'excluded' }, - { type: 'wildcard', value: 'withwildcard*?', field: '', operator: 'included' }, - ], - }, - ]) - ).toBeFalsy(); - }); - - test('it returns true if there are nested entries with a wildcard and the wrong operator', () => { - expect( - hasWrongOperatorWithWildcard([ - { - description: '', - name: '', - type: 'simple', - entries: [ - { type: 'match', value: 'nowildcard', field: '', operator: 'excluded' }, - { - field: '', - type: 'nested', - entries: [{ type: 'match', value: 'wildcard?', field: '', operator: 'excluded' }], - }, - ], - }, - ]) - ).toBeTruthy(); - }); - }); - - describe('hasPartialCodeSignatureEntry', () => { - it('returns false if the entry has neither code signature subject name nor trusted field', () => { - expect( - hasPartialCodeSignatureEntry([ - { - description: '', - name: '', - type: 'simple', - os_types: ['windows'], - entries: [{ type: 'match', value: 'asdf', field: 'someField', operator: 'excluded' }], - }, - ]) - ).toBeFalsy(); - }); - it('returns true if the entry has code signature subject name but not trusted field', () => { - expect( - hasPartialCodeSignatureEntry([ - { - description: '', - name: '', - type: 'simple', - os_types: ['windows'], - entries: [ - { - type: 'match', - value: 'asdf', - field: 'process.code_signature.subject_name', - operator: 'excluded', - }, - ], - }, - ]) - ).toBeTruthy(); - }); - it('returns true if the entry has code signature trusted but not the subject name field', () => { - expect( - hasPartialCodeSignatureEntry([ - { - description: '', - name: '', - type: 'simple', - os_types: ['windows'], - entries: [ - { - type: 'match', - value: 'asdf', - field: 'process.code_signature.trusted', - operator: 'excluded', - }, - ], - }, - ]) - ).toBeTruthy(); - }); - it('returns false if the entry has both code signature subject name and trusted field', () => { - expect( - hasPartialCodeSignatureEntry([ - { - description: '', - name: '', - type: 'simple', - os_types: ['windows'], - entries: [ - { - type: 'match', - value: 'asdf', - field: 'process.code_signature.subject_name', - operator: 'excluded', - }, - { - type: 'match', - value: 'true', - field: 'process.code_signature.trusted', - operator: 'excluded', - }, - ], - }, - ]) - ).toBeFalsy(); - }); - it('returns false if the entry has both code signature team_id and trusted fields for mac os', () => { - expect( - hasPartialCodeSignatureEntry([ - { - description: '', - name: '', - type: 'simple', - os_types: ['macos'], - entries: [ - { - type: 'match', - value: 'asdf', - field: 'process.code_signature.team_id', - operator: 'excluded', - }, - { - type: 'match', - value: 'true', - field: 'process.code_signature.trusted', - operator: 'excluded', - }, - ], - }, - ]) - ).toBeFalsy(); - }); - }); -}); diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts deleted file mode 100644 index 8031cfba14f2d..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { v4 as uuidv4 } from 'uuid'; -import { - addIdToItem, - removeIdFromItem, - validateHasWildcardWithWrongOperator, -} from '@kbn/securitysolution-utils'; -import { validate } from '@kbn/securitysolution-io-ts-utils'; -import { - CreateExceptionListItemSchema, - EntriesArray, - Entry, - EntryNested, - ExceptionListType, - ListSchema, - NamespaceType, - ListOperatorEnum as OperatorEnum, - ListOperatorTypeEnum as OperatorTypeEnum, - createExceptionListItemSchema, - entriesList, - entriesNested, - entry, - exceptionListItemSchema, - nestedEntryItem, - CreateRuleExceptionListItemSchema, - createRuleExceptionListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { - DataViewBase, - DataViewFieldBase, - getDataViewFieldSubtypeNested, - isDataViewFieldSubtypeNested, -} from '@kbn/es-query'; -import { castEsToKbnFieldTypeName, KBN_FIELD_TYPES } from '@kbn/field-types'; - -import { - ALL_OPERATORS, - EXCEPTION_OPERATORS_SANS_LISTS, - doesNotExistOperator, - existsOperator, - isNotOperator, - isOneOfOperator, - isOperator, - DETECTION_ENGINE_EXCEPTION_OPERATORS, - isNotOneOfOperator, - isInListOperator, - isNotInListOperator, - matchesOperator, - doesNotMatchOperator, -} from '../autocomplete_operators'; - -import { - BuilderEntry, - CreateExceptionListItemBuilderSchema, - DataViewField, - EmptyEntry, - EmptyNestedEntry, - ExceptionsBuilderExceptionItem, - ExceptionsBuilderReturnExceptionItem, - FormattedBuilderEntry, - OperatorOption, - SavedObjectType, -} from '../types'; - -export const isEntryNested = (item: BuilderEntry): item is EntryNested => { - return (item as EntryNested).entries != null; -}; - -export const filterExceptionItems = ( - exceptions: ExceptionsBuilderExceptionItem[] -): ExceptionsBuilderReturnExceptionItem[] => { - return exceptions.reduce((acc, exception) => { - const entries = exception.entries.reduce((nestedAcc, singleEntry) => { - const strippedSingleEntry = removeIdFromItem(singleEntry); - if (entriesNested.is(strippedSingleEntry)) { - const nestedEntriesArray = strippedSingleEntry.entries.filter((singleNestedEntry) => { - const noIdSingleNestedEntry = removeIdFromItem(singleNestedEntry); - const [validatedNestedEntry] = validate(noIdSingleNestedEntry, nestedEntryItem); - return validatedNestedEntry != null; - }); - const noIdNestedEntries = nestedEntriesArray.map((singleNestedEntry) => - removeIdFromItem(singleNestedEntry) - ); - - const [validatedNestedEntry] = validate( - { ...strippedSingleEntry, entries: noIdNestedEntries }, - entriesNested - ); - - if (validatedNestedEntry != null) { - return [...nestedAcc, { ...singleEntry, entries: nestedEntriesArray }]; - } - return nestedAcc; - } else { - const [validatedEntry] = validate(strippedSingleEntry, entry); - if (validatedEntry != null) { - return [...nestedAcc, singleEntry]; - } - return nestedAcc; - } - }, []); - - if (entries.length === 0) { - return acc; - } - - const item = { ...exception, entries }; - - if (exceptionListItemSchema.is(item)) { - return [...acc, item]; - } else if ( - createExceptionListItemSchema.is(item) || - createRuleExceptionListItemSchema.is(item) - ) { - const { meta, ...rest } = item; - const itemSansMetaId: CreateExceptionListItemSchema | CreateRuleExceptionListItemSchema = { - ...rest, - meta: undefined, - }; - return [...acc, itemSansMetaId]; - } else { - return acc; - } - }, []); -}; - -export const addIdToEntries = (entries: EntriesArray): EntriesArray => { - return entries.map((singleEntry) => { - if (singleEntry.type === 'nested') { - return addIdToItem({ - ...singleEntry, - entries: singleEntry.entries.map((nestedEntry) => addIdToItem(nestedEntry)), - }); - } else { - return addIdToItem(singleEntry); - } - }); -}; - -export const getNewExceptionItem = ({ - listId, - namespaceType, - name, -}: { - listId: string | undefined; - namespaceType: NamespaceType | undefined; - name: string; -}): CreateExceptionListItemBuilderSchema => { - return { - comments: [], - description: `Exception list item`, - entries: addIdToEntries([ - { - field: '', - operator: 'included', - type: 'match', - value: '', - }, - ]), - item_id: undefined, - list_id: listId, - meta: { - temporaryUuid: uuidv4(), - }, - name, - namespace_type: namespaceType, - tags: [], - type: 'simple', - }; -}; - -/** - * Returns the operator type, may not need this if using io-ts types - * - * @param item a single ExceptionItem entry - */ -export const getOperatorType = (item: BuilderEntry): OperatorTypeEnum => { - switch (item.type) { - case 'match': - return OperatorTypeEnum.MATCH; - case 'match_any': - return OperatorTypeEnum.MATCH_ANY; - case 'wildcard': - return OperatorTypeEnum.WILDCARD; - case 'list': - return OperatorTypeEnum.LIST; - default: - return OperatorTypeEnum.EXISTS; - } -}; - -/** - * Determines operator selection (is/is not/is one of, etc.) - * Default operator is "is" - * - * @param item a single ExceptionItem entry - */ -export const getExceptionOperatorSelect = (item: BuilderEntry): OperatorOption => { - if (item.type === 'nested') { - return isOperator; - } else { - const operatorType = getOperatorType(item); - const foundOperator = ALL_OPERATORS.find((operatorOption) => { - return item.operator === operatorOption.operator && operatorType === operatorOption.type; - }); - - return foundOperator != null ? foundOperator : isOperator; - } -}; - -/** - * Returns the fields corresponding value for an entry - * - * @param item a single ExceptionItem entry - */ -export const getEntryValue = (item: BuilderEntry): string | string[] | undefined => { - switch (item.type) { - case OperatorTypeEnum.MATCH: - case OperatorTypeEnum.MATCH_ANY: - case OperatorTypeEnum.WILDCARD: - return item.value; - case OperatorTypeEnum.EXISTS: - return undefined; - case OperatorTypeEnum.LIST: - return item.list.id; - default: - return undefined; - } -}; - -/** - * Determines whether an entire entry, exception item, or entry within a nested - * entry needs to be removed - * - * @param exceptionItem - * @param entryIndex index of given entry, for nested entries, this will correspond - * to their parent index - * @param nestedEntryIndex index of nested entry - * - */ -export const getUpdatedEntriesOnDelete = ( - exceptionItem: ExceptionsBuilderExceptionItem, - entryIndex: number, - nestedParentIndex: number | null -): ExceptionsBuilderExceptionItem => { - const itemOfInterest: BuilderEntry = - exceptionItem.entries[nestedParentIndex != null ? nestedParentIndex : entryIndex]; - - if (nestedParentIndex != null && itemOfInterest.type === OperatorTypeEnum.NESTED) { - const updatedEntryEntries = [ - ...itemOfInterest.entries.slice(0, entryIndex), - ...itemOfInterest.entries.slice(entryIndex + 1), - ]; - - if (updatedEntryEntries.length === 0) { - return { - ...exceptionItem, - entries: [ - ...exceptionItem.entries.slice(0, nestedParentIndex), - ...exceptionItem.entries.slice(nestedParentIndex + 1), - ], - }; - } else { - const { field } = itemOfInterest; - const updatedItemOfInterest: EntryNested | EmptyNestedEntry = { - entries: updatedEntryEntries, - field, - id: itemOfInterest.id != null ? itemOfInterest.id : `${entryIndex}`, - type: OperatorTypeEnum.NESTED, - }; - - return { - ...exceptionItem, - entries: [ - ...exceptionItem.entries.slice(0, nestedParentIndex), - updatedItemOfInterest, - ...exceptionItem.entries.slice(nestedParentIndex + 1), - ], - }; - } - } else { - return { - ...exceptionItem, - entries: [ - ...exceptionItem.entries.slice(0, entryIndex), - ...exceptionItem.entries.slice(entryIndex + 1), - ], - }; - } -}; - -/** - * Returns filtered index patterns based on the field - if a user selects to - * add nested entry, should only show nested fields, if item is the parent - * field of a nested entry, we only display the parent field - * - * @param patterns DataViewBase containing available fields on rule index - * @param item exception item entry - * set to add a nested field - */ -export const getFilteredIndexPatterns = ( - patterns: DataViewBase, - item: FormattedBuilderEntry -): DataViewBase => { - if (item.nested === 'child' && item.parent != null) { - // when user has selected a nested entry, only fields with the common parent are shown - return { - ...patterns, - fields: patterns.fields - .filter((indexField) => { - const subTypeNested = getDataViewFieldSubtypeNested(indexField); - const fieldHasCommonParentPath = - subTypeNested && - item.parent != null && - subTypeNested.nested.path === item.parent.parent.field; - - return fieldHasCommonParentPath; - }) - .map((f) => { - const [fieldNameWithoutParentPath] = f.name.split('.').slice(-1); - return { ...f, name: fieldNameWithoutParentPath }; - }), - }; - } else if (item.nested === 'parent' && item.field != null) { - // when user has selected a nested entry, right above it we show the common parent - return { ...patterns, fields: [item.field] }; - } else if (item.nested === 'parent' && item.field == null) { - // when user selects to add a nested entry, only nested fields are shown as options - return { - ...patterns, - fields: patterns.fields.filter((field) => isDataViewFieldSubtypeNested(field)), - }; - } else { - return patterns; - } -}; - -/** - * Determines proper entry update when user selects new field - * - * @param item - current exception item entry values - * @param newField - newly selected field - * - */ -export const getEntryOnFieldChange = ( - item: FormattedBuilderEntry, - newField: DataViewFieldBase -): { index: number; updatedEntry: BuilderEntry } => { - const { parent, entryIndex, nested } = item; - const newChildFieldValue = newField != null ? newField.name.split('.').slice(-1)[0] : ''; - - if (nested === 'parent') { - // For nested entries, when user first selects to add a nested - // entry, they first see a row similar to what is shown for when - // a user selects "exists", as soon as they make a selection - // we can now identify the 'parent' and 'child' this is where - // we first convert the entry into type "nested" - const subTypeNested = getDataViewFieldSubtypeNested(newField); - const newParentFieldValue = subTypeNested?.nested.path || ''; - - return { - index: entryIndex, - updatedEntry: { - entries: [ - addIdToItem({ - field: newChildFieldValue != null ? newChildFieldValue : '', - operator: isOperator.operator, - type: OperatorTypeEnum.MATCH, - value: '', - }), - ], - field: newParentFieldValue, - id: item.id, - type: OperatorTypeEnum.NESTED, - }, - }; - } else if (nested === 'child' && parent != null) { - return { - index: parent.parentIndex, - updatedEntry: { - ...parent.parent, - entries: [ - ...parent.parent.entries.slice(0, entryIndex), - { - field: newChildFieldValue != null ? newChildFieldValue : '', - id: item.id, - operator: isOperator.operator, - type: OperatorTypeEnum.MATCH, - value: '', - }, - ...parent.parent.entries.slice(entryIndex + 1), - ], - }, - }; - } else { - return { - index: entryIndex, - updatedEntry: { - field: newField != null ? newField.name : '', - id: item.id, - operator: isOperator.operator, - type: OperatorTypeEnum.MATCH, - value: '', - }, - }; - } -}; - -/** - * Determines proper entry update when user updates value - * when operator is of type "list" - * - * @param item - current exception item entry values - * @param newField - newly selected list - * - */ -export const getEntryOnListChange = ( - item: FormattedBuilderEntry, - newField: ListSchema -): { index: number; updatedEntry: BuilderEntry } => { - const { entryIndex, field, operator } = item; - const { id, type } = newField; - - return { - index: entryIndex, - updatedEntry: { - field: field != null ? field.name : '', - id: item.id, - list: { id, type }, - operator: operator.operator, - type: OperatorTypeEnum.LIST, - }, - }; -}; - -/** - * Determines proper entry update when user updates value - * when operator is of type "match_any" - * - * @param item - current exception item entry values - * @param newField - newly entered value - * - */ -export const getEntryOnMatchAnyChange = ( - item: FormattedBuilderEntry, - newField: string[] -): { index: number; updatedEntry: BuilderEntry } => { - const { nested, parent, entryIndex, field, operator } = item; - - if (nested != null && parent != null) { - const fieldName = field != null ? field.name.split('.').slice(-1)[0] : ''; - - return { - index: parent.parentIndex, - updatedEntry: { - ...parent.parent, - entries: [ - ...parent.parent.entries.slice(0, entryIndex), - { - field: fieldName, - id: item.id, - operator: operator.operator, - type: OperatorTypeEnum.MATCH_ANY, - value: newField, - }, - ...parent.parent.entries.slice(entryIndex + 1), - ], - }, - }; - } else { - return { - index: entryIndex, - updatedEntry: { - field: field != null ? field.name : '', - id: item.id, - operator: operator.operator, - type: OperatorTypeEnum.MATCH_ANY, - value: newField, - }, - }; - } -}; - -/** - * Determines proper entry update when user updates value - * when operator is of type "match" - * - * @param item - current exception item entry values - * @param newField - newly entered value - * - */ -export const getEntryOnMatchChange = ( - item: FormattedBuilderEntry, - newField: string -): { index: number; updatedEntry: BuilderEntry } => { - const { nested, parent, entryIndex, field, operator } = item; - - if (nested != null && parent != null) { - const fieldName = field != null ? field.name.split('.').slice(-1)[0] : ''; - - return { - index: parent.parentIndex, - updatedEntry: { - ...parent.parent, - entries: [ - ...parent.parent.entries.slice(0, entryIndex), - { - field: fieldName, - id: item.id, - operator: operator.operator, - type: OperatorTypeEnum.MATCH, - value: newField, - }, - ...parent.parent.entries.slice(entryIndex + 1), - ], - }, - }; - } else { - return { - index: entryIndex, - updatedEntry: { - field: field != null ? field.name : '', - id: item.id, - operator: operator.operator, - type: OperatorTypeEnum.MATCH, - value: newField, - }, - }; - } -}; - -/** - * Determines proper entry update when user updates value - * when operator is of type "wildcard" - * - * @param item - current exception item entry values - * @param newField - newly entered value - * - */ -export const getEntryOnWildcardChange = ( - item: FormattedBuilderEntry, - newField: string -): { index: number; updatedEntry: BuilderEntry } => { - const { nested, parent, entryIndex, field, operator } = item; - - if (nested != null && parent != null) { - const fieldName = field != null ? field.name.split('.').slice(-1)[0] : ''; - - return { - index: parent.parentIndex, - updatedEntry: { - ...parent.parent, - entries: [ - ...parent.parent.entries.slice(0, entryIndex), - { - field: fieldName, - id: item.id, - operator: operator.operator, - type: OperatorTypeEnum.WILDCARD, - value: newField, - }, - ...parent.parent.entries.slice(entryIndex + 1), - ], - }, - }; - } else { - return { - index: entryIndex, - updatedEntry: { - field: field != null ? field.name : '', - id: item.id, - operator: operator.operator, - type: OperatorTypeEnum.WILDCARD, - value: newField, - }, - }; - } -}; - -/** - * On operator change, determines whether value needs to be cleared or not - * - * @param field - * @param selectedOperator - * @param currentEntry - * - */ -export const getEntryFromOperator = ( - selectedOperator: OperatorOption, - currentEntry: FormattedBuilderEntry -): Entry & { id?: string } => { - const isSameOperatorType = currentEntry.operator.type === selectedOperator.type; - const fieldValue = currentEntry.field != null ? currentEntry.field.name : ''; - switch (selectedOperator.type) { - case 'match': - return { - field: fieldValue, - id: currentEntry.id, - operator: selectedOperator.operator, - type: OperatorTypeEnum.MATCH, - value: - isSameOperatorType && typeof currentEntry.value === 'string' ? currentEntry.value : '', - }; - case 'match_any': - return { - field: fieldValue, - id: currentEntry.id, - operator: selectedOperator.operator, - type: OperatorTypeEnum.MATCH_ANY, - value: isSameOperatorType && Array.isArray(currentEntry.value) ? currentEntry.value : [], - }; - case 'list': - return { - field: fieldValue, - id: currentEntry.id, - list: { id: '', type: 'ip' }, - operator: selectedOperator.operator, - type: OperatorTypeEnum.LIST, - }; - case 'wildcard': - return { - field: fieldValue, - id: currentEntry.id, - operator: selectedOperator.operator, - type: OperatorTypeEnum.WILDCARD, - value: - isSameOperatorType && typeof currentEntry.value === 'string' ? currentEntry.value : '', - }; - default: - return { - field: fieldValue, - id: currentEntry.id, - operator: selectedOperator.operator, - type: OperatorTypeEnum.EXISTS, - }; - } -}; - -/** - * Determines proper entry update when user selects new operator - * - * @param item - current exception item entry values - * @param newOperator - newly selected operator - * - */ -export const getEntryOnOperatorChange = ( - item: FormattedBuilderEntry, - newOperator: OperatorOption -): { updatedEntry: BuilderEntry; index: number } => { - const { parent, entryIndex, field, nested } = item; - const newEntry = getEntryFromOperator(newOperator, item); - - if (!entriesList.is(newEntry) && nested != null && parent != null) { - return { - index: parent.parentIndex, - updatedEntry: { - ...parent.parent, - entries: [ - ...parent.parent.entries.slice(0, entryIndex), - { - ...newEntry, - field: field != null ? field.name.split('.').slice(-1)[0] : '', - }, - ...parent.parent.entries.slice(entryIndex + 1), - ], - }, - }; - } else { - return { index: entryIndex, updatedEntry: newEntry }; - } -}; - -export const isKibanaStringType = (type: string) => { - const kbnFieldType = castEsToKbnFieldTypeName(type); - return kbnFieldType === KBN_FIELD_TYPES.STRING; -}; - -export const fieldSupportsMatches = (field: DataViewFieldBase) => { - return field.esTypes?.some(isKibanaStringType); -}; - -/** - * Determines which operators to make available - * - * @param item - * @param listType - * @param isBoolean - * @param includeValueListOperators whether or not to include the 'is in list' and 'is not in list' operators - */ -export const getOperatorOptions = ( - item: FormattedBuilderEntry, - listType: ExceptionListType, - isBoolean: boolean, - includeValueListOperators = true -): OperatorOption[] => { - if (item.nested === 'parent' || item.field == null) { - return [isOperator]; - } else if (listType === 'endpoint') { - if (isBoolean) { - return [isOperator]; - } else { - return fieldSupportsMatches(item.field) - ? [isOperator, isOneOfOperator, matchesOperator, doesNotMatchOperator] - : [isOperator, isOneOfOperator]; - } - } else if (item.nested != null && listType === 'detection') { - return isBoolean ? [isOperator, existsOperator] : [isOperator, isOneOfOperator, existsOperator]; - } else if (isBoolean) { - return [isOperator, isNotOperator, existsOperator, doesNotExistOperator]; - } else if (!includeValueListOperators) { - return fieldSupportsMatches(item.field) - ? EXCEPTION_OPERATORS_SANS_LISTS - : [ - isOperator, - isNotOperator, - isOneOfOperator, - isNotOneOfOperator, - existsOperator, - doesNotExistOperator, - ]; - } else { - return listType === 'detection' - ? fieldSupportsMatches(item.field) - ? DETECTION_ENGINE_EXCEPTION_OPERATORS - : [ - isOperator, - isNotOperator, - isOneOfOperator, - isNotOneOfOperator, - existsOperator, - doesNotExistOperator, - isInListOperator, - isNotInListOperator, - ] - : ALL_OPERATORS; - } -}; - -/** - * Fields of type 'text' do not generate autocomplete values, we want - * to find it's corresponding keyword type (if available) which does - * generate autocomplete values - * - * @param fields DataViewFieldBase fields - * @param selectedField the field name that was selected - * @param isTextType we only want a corresponding keyword field if - * the selected field is of type 'text' - * - */ -export const getCorrespondingKeywordField = ({ - fields, - selectedField, -}: { - fields: DataViewFieldBase[]; - selectedField: string | undefined; -}): DataViewFieldBase | undefined => { - const selectedFieldBits = - selectedField != null && selectedField !== '' ? selectedField.split('.') : []; - const selectedFieldIsTextType = selectedFieldBits.slice(-1)[0] === 'text'; - - if (selectedFieldIsTextType && selectedFieldBits.length > 0) { - const keywordField = selectedFieldBits.slice(0, selectedFieldBits.length - 1).join('.'); - const [foundKeywordField] = fields.filter( - ({ name }) => keywordField !== '' && keywordField === name - ); - return foundKeywordField; - } - - return undefined; -}; - -/** - * Formats the entry into one that is easily usable for the UI, most of the - * complexity was introduced with nested fields - * - * @param patterns DataViewBase containing available fields on rule index - * @param item exception item entry - * @param itemIndex entry index - * @param parent nested entries hold copy of their parent for use in various logic - * @param parentIndex corresponds to the entry index, this might seem obvious, but - * was added to ensure that nested items could be identified with their parent entry - * @param allowCustomFieldOptions determines if field must be found to match in indexPattern or not - */ -export const getFormattedBuilderEntry = ( - indexPattern: DataViewBase, - item: BuilderEntry, - itemIndex: number, - parent: EntryNested | undefined, - parentIndex: number | undefined, - allowCustomFieldOptions: boolean -): FormattedBuilderEntry => { - const { fields } = indexPattern; - const field = parent != null ? `${parent.field}.${item.field}` : item.field; - const [foundField] = fields.filter(({ name }) => field != null && field === name); - const correspondingKeywordField = getCorrespondingKeywordField({ - fields, - selectedField: field, - }); - - if (parent != null && parentIndex != null) { - return { - correspondingKeywordField, - entryIndex: itemIndex, - field: - foundField != null - ? { ...foundField, name: foundField.name.split('.').slice(-1)[0] } - : foundField, - id: item.id != null ? item.id : `${itemIndex}`, - nested: 'child', - operator: getExceptionOperatorSelect(item), - parent: { parent, parentIndex }, - value: getEntryValue(item), - }; - } else { - const fieldToUse = allowCustomFieldOptions - ? foundField ?? { name: item.field, type: 'keyword' } - : foundField; - - return { - correspondingKeywordField, - entryIndex: itemIndex, - field: fieldToUse, - id: item.id != null ? item.id : `${itemIndex}`, - nested: undefined, - operator: getExceptionOperatorSelect(item), - parent: undefined, - value: getEntryValue(item), - }; - } -}; - -/** - * Formats the entries to be easily usable for the UI, most of the - * complexity was introduced with nested fields - * - * @param patterns DataViewBase containing available fields on rule index - * @param entries exception item entries - * @param allowCustomFieldOptions determines if field must be found to match in indexPattern or not - * @param parent nested entries hold copy of their parent for use in various logic - * @param parentIndex corresponds to the entry index, this might seem obvious, but - * was added to ensure that nested items could be identified with their parent entry - */ -export const getFormattedBuilderEntries = ( - indexPattern: DataViewBase, - entries: BuilderEntry[], - allowCustomFieldOptions: boolean, - parent?: EntryNested, - parentIndex?: number -): FormattedBuilderEntry[] => { - return entries.reduce((acc, item, index) => { - const isNewNestedEntry = item.type === 'nested' && item.entries.length === 0; - if (item.type !== 'nested' && !isNewNestedEntry) { - const newItemEntry: FormattedBuilderEntry = getFormattedBuilderEntry( - indexPattern, - item, - index, - parent, - parentIndex, - allowCustomFieldOptions - ); - return [...acc, newItemEntry]; - } else { - const parentEntry: FormattedBuilderEntry = { - correspondingKeywordField: undefined, - entryIndex: index, - field: isNewNestedEntry - ? undefined - : // This type below is really a FieldSpec type from "src/plugins/data/common/index_patterns/fields/types.ts", we cast it here to keep using the DataViewFieldBase interface - ({ - aggregatable: false, - esTypes: ['nested'], - name: item.field != null ? item.field : '', - searchable: false, - type: 'string', - } as DataViewFieldBase), - id: item.id != null ? item.id : `${index}`, - nested: 'parent', - operator: isOperator, - parent: undefined, - value: undefined, - }; - - // User has selected to add a nested field, but not yet selected the field - if (isNewNestedEntry) { - return [...acc, parentEntry]; - } - - if (isEntryNested(item)) { - const nestedItems = getFormattedBuilderEntries( - indexPattern, - item.entries, - allowCustomFieldOptions, - item, - index - ); - - return [...acc, parentEntry, ...nestedItems]; - } - - return [...acc]; - } - }, []); -}; - -export const getDefaultEmptyEntry = (): EmptyEntry => ({ - field: '', - id: uuidv4(), - operator: OperatorEnum.INCLUDED, - type: OperatorTypeEnum.MATCH, - value: '', -}); - -export const getDefaultNestedEmptyEntry = (): EmptyNestedEntry => ({ - entries: [], - field: '', - id: uuidv4(), - type: OperatorTypeEnum.NESTED, -}); - -export const containsValueListEntry = (items: ExceptionsBuilderExceptionItem[]): boolean => - items.some((item) => item.entries.some(({ type }) => type === OperatorTypeEnum.LIST)); - -export const buildShowActiveExceptionsFilter = (savedObjectPrefix: SavedObjectType[]): string => { - const now = new Date().toISOString(); - const filters = savedObjectPrefix.map( - (prefix) => - `${prefix}.attributes.expire_time > "${now}" OR NOT ${prefix}.attributes.expire_time: *` - ); - return filters.join(','); -}; - -export const buildShowExpiredExceptionsFilter = (savedObjectPrefix: SavedObjectType[]): string => { - const now = new Date().toISOString(); - const filters = savedObjectPrefix.map((prefix) => `${prefix}.attributes.expire_time <= "${now}"`); - return filters.join(','); -}; - -const getIndexGroupName = (indexName: string): string => { - // Check whether it is a Data Stream index - const dataStreamExp = /.ds-(.*?)-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-[0-9]{6}/; - let result = indexName.match(dataStreamExp); - if (result && result.length === 2) { - return result[1]; - } - - // Check whether it is an old '.siem' index group - const siemSignalsExp = /.siem-(.*?)-[0-9]{6}/; - result = indexName.match(siemSignalsExp); - if (result && result.length === 2) { - return `.siem-${result[1]}`; - } - - // Otherwise return index name - return indexName; -}; - -export interface FieldConflictsInfo { - /** - * Kibana field type - */ - type: string; - /** - * Total count of the indices of this type - */ - totalIndexCount: number; - /** - * Grouped indices info - */ - groupedIndices: Array<{ - /** - * Index group name (like '.ds-...' or '.siem-signals-...') - */ - name: string; - /** - * Count of indices in the group - */ - count: number; - }>; -} - -export const getMappingConflictsInfo = (field: DataViewField): FieldConflictsInfo[] | null => { - if (!field.conflictDescriptions) { - return null; - } - const conflicts: FieldConflictsInfo[] = []; - for (const [key, value] of Object.entries(field.conflictDescriptions)) { - const groupedIndices: Array<{ - name: string; - count: number; - }> = []; - - // Group indices and calculate count of indices in each group - const groupedInfo: { [key: string]: number } = {}; - value.forEach((index) => { - const groupName = getIndexGroupName(index); - if (!groupedInfo[groupName]) { - groupedInfo[groupName] = 0; - } - groupedInfo[groupName]++; - }); - for (const [name, count] of Object.entries(groupedInfo)) { - groupedIndices.push({ - name, - count, - }); - } - - // Sort groups by the indices count - groupedIndices.sort((group1, group2) => { - return group2.count - group1.count; - }); - - conflicts.push({ - type: key, - totalIndexCount: value.length, - groupedIndices, - }); - } - return conflicts; -}; - -/** - * Given an exceptions list, determine if any entries have an "IS" operator with a wildcard value - */ -export const hasWrongOperatorWithWildcard = ( - items: ExceptionsBuilderReturnExceptionItem[] -): boolean => { - // flattens array of multiple entries added with OR - const multipleEntries = items.flatMap((item) => item.entries); - // flattens nested entries - const allEntries = multipleEntries.flatMap((item) => { - if (item.type === 'nested') { - return item.entries; - } - return item; - }); - - return allEntries.some((e) => { - if (e.type !== 'list' && 'value' in e) { - return validateHasWildcardWithWrongOperator({ - operator: e.type, - value: e.value, - }); - } - }); -}; - -/** - * Event filters helper where given an exceptions list, - * determine if both 'subject_name' and 'trusted' are - * included in an entry with 'code_signature' - */ -export const hasPartialCodeSignatureEntry = ( - items: ExceptionsBuilderReturnExceptionItem[] -): boolean => { - const { os_types: os = ['windows'], entries = [] } = items[0] || {}; - let name = false; - let trusted = false; - - for (const e of entries) { - if (e.type === 'nested' && e.field === 'process.Ext.code_signature') { - const includesNestedName = e.entries.some( - (nestedEntry) => nestedEntry.field === 'subject_name' - ); - const includesNestedTrusted = e.entries.some( - (nestedEntry) => nestedEntry.field === 'trusted' - ); - if (includesNestedName !== includesNestedTrusted) { - return true; - } - } else if ( - e.field === 'process.code_signature.subject_name' || - (os.includes('macos') && e.field === 'process.code_signature.team_id') - ) { - name = true; - } else if (e.field === 'process.code_signature.trusted') { - trusted = true; - } - } - return name !== trusted; -}; diff --git a/packages/kbn-securitysolution-list-utils/src/types/index.ts b/packages/kbn-securitysolution-list-utils/src/types/index.ts deleted file mode 100644 index 97098af88caf4..0000000000000 --- a/packages/kbn-securitysolution-list-utils/src/types/index.ts +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewFieldBase } from '@kbn/es-query'; -import type { - CreateExceptionListItemSchema, - CreateRuleExceptionListItemSchema, - Entry, - EntryExists, - EntryMatch, - EntryMatchAny, - EntryMatchWildcard, - EntryNested, - ExceptionListItemSchema, - ListOperatorEnum as OperatorEnum, - ListOperatorTypeEnum as OperatorTypeEnum, - NamespaceType, -} from '@kbn/securitysolution-io-ts-list-types'; -import { - EXCEPTION_LIST_NAMESPACE, - EXCEPTION_LIST_NAMESPACE_AGNOSTIC, -} from '@kbn/securitysolution-list-constants'; - -export interface DataViewField extends DataViewFieldBase { - conflictDescriptions?: Record; -} - -export interface OperatorOption { - message: string; - value: string; - operator: OperatorEnum; - type: OperatorTypeEnum; -} - -export interface FormattedBuilderEntry { - id: string; - field: DataViewField | undefined; - operator: OperatorOption; - value: string | string[] | undefined; - nested: 'parent' | 'child' | undefined; - entryIndex: number; - parent: { parent: BuilderEntryNested; parentIndex: number } | undefined; - correspondingKeywordField: DataViewFieldBase | undefined; -} - -export interface EmptyEntry { - id: string; - field: string | undefined; - operator: OperatorEnum; - type: OperatorTypeEnum.MATCH | OperatorTypeEnum.MATCH_ANY | OperatorTypeEnum.WILDCARD; - value: string | string[] | undefined; -} - -export interface EmptyListEntry { - id: string; - field: string | undefined; - operator: OperatorEnum; - type: OperatorTypeEnum.LIST; - list: { id: string | undefined; type: string | undefined }; -} - -export interface EmptyNestedEntry { - id: string; - field: string | undefined; - type: OperatorTypeEnum.NESTED; - entries: Array< - | (EntryMatch & { id?: string }) - | (EntryMatchAny & { id?: string }) - | (EntryMatchWildcard & { id?: string }) - | (EntryExists & { id?: string }) - >; -} - -export type BuilderEntry = - | (Entry & { id?: string }) - | EmptyListEntry - | EmptyEntry - | BuilderEntryNested - | EmptyNestedEntry; - -export type BuilderEntryNested = Omit & { - id?: string; - entries: Array< - | (EntryMatch & { id?: string }) - | (EntryMatchAny & { id?: string }) - | (EntryMatchWildcard & { id?: string }) - | (EntryExists & { id?: string }) - >; -}; - -export type ExceptionListItemBuilderSchema = Omit & { - entries: BuilderEntry[]; -}; - -export type CreateExceptionListItemBuilderSchema = Omit< - CreateExceptionListItemSchema, - 'meta' | 'entries' | 'list_id' | 'namespace_type' -> & { - meta: { temporaryUuid: string }; - entries: BuilderEntry[]; - list_id: string | undefined; - namespace_type: NamespaceType | undefined; -}; - -export type ExceptionsBuilderExceptionItem = - | ExceptionListItemBuilderSchema - | CreateExceptionListItemBuilderSchema; - -export type ExceptionsBuilderReturnExceptionItem = - | ExceptionListItemSchema - | CreateExceptionListItemSchema - | CreateRuleExceptionListItemSchema; - -export const exceptionListSavedObjectType = EXCEPTION_LIST_NAMESPACE; -export const exceptionListAgnosticSavedObjectType = EXCEPTION_LIST_NAMESPACE_AGNOSTIC; -export type SavedObjectType = - | typeof EXCEPTION_LIST_NAMESPACE - | typeof EXCEPTION_LIST_NAMESPACE_AGNOSTIC; diff --git a/packages/kbn-securitysolution-list-utils/tsconfig.json b/packages/kbn-securitysolution-list-utils/tsconfig.json deleted file mode 100644 index d75eb1f98314c..0000000000000 --- a/packages/kbn-securitysolution-list-utils/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/es-query", - "@kbn/i18n", - "@kbn/securitysolution-io-ts-list-types", - "@kbn/securitysolution-io-ts-utils", - "@kbn/securitysolution-list-constants", - "@kbn/securitysolution-utils", - "@kbn/field-types" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts deleted file mode 100644 index ce05117c33082..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Create list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { - ListId, - ListName, - ListDescription, - ListType, - ListMetadata, -} from '../model/list_common.gen'; -import { List } from '../model/list_schemas.gen'; - -export type CreateListRequestBody = z.infer; -export const CreateListRequestBody = z.object({ - id: ListId.optional(), - name: ListName, - description: ListDescription, - type: ListType, - serializer: z.string().optional(), - deserializer: z.string().optional(), - meta: ListMetadata.optional(), - version: z.number().int().min(1).optional().default(1), -}); -export type CreateListRequestBodyInput = z.input; - -export type CreateListResponse = z.infer; -export const CreateListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml deleted file mode 100644 index 191e973beba61..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml +++ /dev/null @@ -1,81 +0,0 @@ -openapi: 3.0.0 -info: - title: Create list API endpoint - version: '2023-10-31' -paths: - /api/lists: - post: - x-labels: [serverless, ess] - operationId: CreateList - x-codegen-enabled: true - summary: Create a list - description: Create a new list. - requestBody: - description: List's properties - required: true - content: - application/json: - schema: - type: object - properties: - id: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - name: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' - description: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' - type: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListType' - serializer: - type: string - deserializer: - type: string - meta: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' - version: - type: integer - minimum: 1 - default: 1 - required: - - name - - description - - type - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 409: - description: List already exists response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts b/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts deleted file mode 100644 index 13b5248b92704..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Create list DS API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -export type CreateListIndexResponse = z.infer; -export const CreateListIndexResponse = z.object({ - acknowledged: z.boolean(), -}); diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml b/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml deleted file mode 100644 index c775a9c7d873f..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml +++ /dev/null @@ -1,55 +0,0 @@ -openapi: 3.0.0 -info: - title: Create list DS API endpoint - version: '2023-10-31' -paths: - /api/lists/index: - post: - x-labels: [serverless, ess] - operationId: CreateListIndex - x-codegen-enabled: true - summary: Create list data streams - description: Create `.lists` and `.items` data streams in the relevant space. - responses: - 200: - description: Successful response - content: - application/json: - schema: - type: object - properties: - acknowledged: - type: boolean - required: [acknowledged] - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 409: - description: List data stream exists response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts deleted file mode 100644 index 4ebafd6568571..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Create list item API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListItemId, ListId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; -import { ListItem } from '../model/list_schemas.gen'; - -export type CreateListItemRequestBody = z.infer; -export const CreateListItemRequestBody = z.object({ - id: ListItemId.optional(), - list_id: ListId, - value: ListItemValue, - meta: ListItemMetadata.optional(), - /** - * Determines when changes made by the request are made visible to search - */ - refresh: z.enum(['true', 'false', 'wait_for']).optional(), -}); -export type CreateListItemRequestBodyInput = z.input; - -export type CreateListItemResponse = z.infer; -export const CreateListItemResponse = ListItem; diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml deleted file mode 100644 index 01121d0143925..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml +++ /dev/null @@ -1,82 +0,0 @@ -openapi: 3.0.0 -info: - title: Create list item API endpoint - version: '2023-10-31' -paths: - /api/lists/items: - post: - x-labels: [serverless, ess] - operationId: CreateListItem - x-codegen-enabled: true - summary: Create a list item - description: | - Create a list item and associate it with the specified list. - - All list items in the same list must be the same type. For example, each list item in an `ip` list must define a specific IP address. - > info - > Before creating a list item, you must create a list. - requestBody: - description: List item's properties - required: true - content: - application/json: - schema: - type: object - properties: - id: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' - list_id: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - value: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' - meta: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' - refresh: - type: string - enum: - - 'true' - - 'false' - - wait_for - description: Determines when changes made by the request are made visible to search - required: - - list_id - - value - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 409: - description: List item already exists response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts deleted file mode 100644 index 109e6c58a1163..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Delete list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; -import { BooleanFromString } from '@kbn/zod-helpers'; - -import { ListId } from '../model/list_common.gen'; -import { List } from '../model/list_schemas.gen'; - -export type DeleteListRequestQuery = z.infer; -export const DeleteListRequestQuery = z.object({ - /** - * List's `id` value - */ - id: ListId, - deleteReferences: BooleanFromString.optional().default(false), - ignoreReferences: BooleanFromString.optional().default(false), -}); -export type DeleteListRequestQueryInput = z.input; - -export type DeleteListResponse = z.infer; -export const DeleteListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml deleted file mode 100644 index 7098753636379..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml +++ /dev/null @@ -1,73 +0,0 @@ -openapi: 3.0.0 -info: - title: Delete list API endpoint - version: '2023-10-31' -paths: - /api/lists: - delete: - x-labels: [serverless, ess] - operationId: DeleteList - x-codegen-enabled: true - summary: Delete a list - description: | - Delete a list using the list ID. - > info - > When you delete a list, all of its list items are also deleted. - parameters: - - name: id - in: query - required: true - description: List's `id` value - schema: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - - name: deleteReferences - in: query - required: false - schema: - type: boolean - default: false - - name: ignoreReferences - in: query - required: false - schema: - type: boolean - default: false - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts b/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts deleted file mode 100644 index 314c1e81bc6a9..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Delete list DS API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -export type DeleteListIndexResponse = z.infer; -export const DeleteListIndexResponse = z.object({ - acknowledged: z.boolean(), -}); diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml b/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml deleted file mode 100644 index 4f4b0f00e8817..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml +++ /dev/null @@ -1,55 +0,0 @@ -openapi: 3.0.0 -info: - title: Delete list DS API endpoint - version: '2023-10-31' -paths: - /api/lists/index: - delete: - x-labels: [serverless, ess] - operationId: DeleteListIndex - x-codegen-enabled: true - summary: Delete list data streams - description: Delete the `.lists` and `.items` data streams. - responses: - 200: - description: Successful response - content: - application/json: - schema: - type: object - properties: - acknowledged: - type: boolean - required: [acknowledged] - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List data stream not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml deleted file mode 100644 index 28913259387dd..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml +++ /dev/null @@ -1,82 +0,0 @@ -openapi: 3.0.0 -info: - title: Delete list item API endpoint - version: '2023-10-31' -paths: - /api/lists/items: - delete: - x-labels: [serverless, ess] - operationId: DeleteListItem - x-codegen-enabled: true - summary: Delete a list item - description: Delete a list item using its `id`, or its `list_id` and `value` fields. - parameters: - - name: id - in: query - required: false - description: Required if `list_id` and `value` are not specified - schema: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - - name: list_id - in: query - required: false - description: Required if `id` is not specified - schema: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - - name: value - in: query - required: false - description: Required if `id` is not specified - schema: - type: string - - name: refresh - in: query - required: false - description: Determines when changes made by the request are made visible to search - schema: - type: string - enum: ['true', 'false', 'wait_for'] - default: 'false' - responses: - 200: - description: Successful response - content: - application/json: - schema: - oneOf: - - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' - - type: array - items: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List item not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.gen.ts b/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.gen.ts deleted file mode 100644 index 4e514abefccc2..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.gen.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Export list items API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListId } from '../model/list_common.gen'; - -export type ExportListItemsRequestQuery = z.infer; -export const ExportListItemsRequestQuery = z.object({ - /** - * List's id to export - */ - list_id: ListId, -}); -export type ExportListItemsRequestQueryInput = z.input; diff --git a/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.schema.yaml b/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.schema.yaml deleted file mode 100644 index 8d185a23b64c9..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.schema.yaml +++ /dev/null @@ -1,60 +0,0 @@ -openapi: 3.0.0 -info: - title: Export list items API endpoint - version: '2023-10-31' -paths: - /api/lists/items/_export: - post: - x-labels: [serverless, ess] - operationId: ExportListItems - x-codegen-enabled: true - summary: Export list items - description: Export list item values from the specified list. - parameters: - - name: list_id - in: query - required: true - description: List's id to export - schema: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - responses: - 200: - description: Successful response - content: - application/ndjson: - schema: - type: string - format: binary - description: A `.txt` file containing list items from the specified list - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/index.ts b/packages/kbn-securitysolution-lists-common/api/index.ts deleted file mode 100644 index 27c70d1628109..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './model/list_common.gen'; -export * from './model/list_schemas.gen'; -export * from './create_list_index/create_list_index.gen'; -export * from './create_list_item/create_list_item.gen'; -export * from './create_list/create_list.gen'; -export * from './delete_list_index/delete_list_index.gen'; -export * from './delete_list_item/delete_list_item.gen'; -export * from './delete_list/delete_list.gen'; -export * from './find_list_items/find_list_items.gen'; -export * from './find_lists/find_lists.gen'; -export * from './export_list_items/export_list_items.gen'; -export * from './import_list_items/import_list_items.gen'; -export * from './patch_list_item/patch_list_item.gen'; -export * from './patch_list/patch_list.gen'; -export * from './read_list_index/read_list_index.gen'; -export * from './read_list_item/read_list_item.gen'; -export * from './read_list/read_list.gen'; -export * from './update_list_item/update_list_item.gen'; -export * from './update_list/update_list.gen'; diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml b/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml deleted file mode 100644 index 6fb160105bb5a..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml +++ /dev/null @@ -1,59 +0,0 @@ -openapi: 3.0.0 -info: - title: Common List Attributes - version: 'not applicable' -paths: {} -components: - schemas: - ListId: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - - ListType: - type: string - enum: - - binary - - boolean - - byte - - date - - date_nanos - - date_range - - double - - double_range - - float - - float_range - - geo_point - - geo_shape - - half_float - - integer - - integer_range - - ip - - ip_range - - keyword - - long - - long_range - - shape - - short - - text - - ListName: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - - ListDescription: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - - ListMetadata: - type: object - additionalProperties: true - - ListItemId: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - - ListItemValue: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - - ListItemDescription: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - - ListItemMetadata: - type: object - additionalProperties: true diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts deleted file mode 100644 index d7c955e6daac3..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Patch list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListId, ListName, ListDescription, ListMetadata } from '../model/list_common.gen'; -import { List } from '../model/list_schemas.gen'; - -export type PatchListRequestBody = z.infer; -export const PatchListRequestBody = z.object({ - id: ListId, - name: ListName.optional(), - description: ListDescription.optional(), - meta: ListMetadata.optional(), - version: z.number().int().min(1).optional(), - _version: z.string().optional(), -}); -export type PatchListRequestBodyInput = z.input; - -export type PatchListResponse = z.infer; -export const PatchListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml deleted file mode 100644 index b98b34e6347eb..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml +++ /dev/null @@ -1,74 +0,0 @@ -openapi: 3.0.0 -info: - title: Patch list API endpoint - version: '2023-10-31' -paths: - /api/lists: - patch: - x-labels: [serverless, ess] - operationId: PatchList - x-codegen-enabled: true - summary: Patch a list - description: Update specific fields of an existing list using the list ID. - requestBody: - description: List's properties - required: true - content: - application/json: - schema: - type: object - properties: - id: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - name: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' - description: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' - meta: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' - version: - type: integer - minimum: 1 - _version: - type: string - required: - - id - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts deleted file mode 100644 index 9943a9999a898..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Patch list item API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListItemId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; -import { ListItem } from '../model/list_schemas.gen'; - -export type PatchListItemRequestBody = z.infer; -export const PatchListItemRequestBody = z.object({ - id: ListItemId, - value: ListItemValue.optional(), - meta: ListItemMetadata.optional(), - _version: z.string().optional(), - /** - * Determines when changes made by the request are made visible to search - */ - refresh: z.enum(['true', 'false', 'wait_for']).optional(), -}); -export type PatchListItemRequestBodyInput = z.input; - -export type PatchListItemResponse = z.infer; -export const PatchListItemResponse = ListItem; diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml deleted file mode 100644 index f79efc4691dde..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml +++ /dev/null @@ -1,76 +0,0 @@ -openapi: 3.0.0 -info: - title: Patch list item API endpoint - version: '2023-10-31' -paths: - /api/lists/items: - patch: - x-labels: [serverless, ess] - operationId: PatchListItem - x-codegen-enabled: true - summary: Patch a list item - description: Update specific fields of an existing list item using the list item ID. - requestBody: - description: List item's properties - required: true - content: - application/json: - schema: - type: object - properties: - id: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' - value: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' - meta: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' - _version: - type: string - refresh: - type: string - enum: - - 'true' - - 'false' - - wait_for - description: Determines when changes made by the request are made visible to search - required: - - id - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List item not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts b/packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts deleted file mode 100644 index 7bf343d935f2c..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts +++ /dev/null @@ -1,430 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Lists API client for quickstart - * version: Bundle (no version) - */ - -import type { KbnClient } from '@kbn/test'; -import { ToolingLog } from '@kbn/tooling-log'; -import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import { catchAxiosErrorFormatAndThrow } from '@kbn/securitysolution-utils'; - -import type { CreateListIndexResponse } from './create_list_index/create_list_index.gen'; -import type { - CreateListItemRequestBodyInput, - CreateListItemResponse, -} from './create_list_item/create_list_item.gen'; -import type { CreateListRequestBodyInput, CreateListResponse } from './create_list/create_list.gen'; -import type { DeleteListIndexResponse } from './delete_list_index/delete_list_index.gen'; -import type { - DeleteListItemRequestQueryInput, - DeleteListItemResponse, -} from './delete_list_item/delete_list_item.gen'; -import type { - DeleteListRequestQueryInput, - DeleteListResponse, -} from './delete_list/delete_list.gen'; -import type { ExportListItemsRequestQueryInput } from './export_list_items/export_list_items.gen'; -import type { - FindListItemsRequestQueryInput, - FindListItemsResponse, -} from './find_list_items/find_list_items.gen'; -import type { FindListsRequestQueryInput, FindListsResponse } from './find_lists/find_lists.gen'; -import type { - ImportListItemsRequestQueryInput, - ImportListItemsResponse, -} from './import_list_items/import_list_items.gen'; -import type { - PatchListItemRequestBodyInput, - PatchListItemResponse, -} from './patch_list_item/patch_list_item.gen'; -import type { PatchListRequestBodyInput, PatchListResponse } from './patch_list/patch_list.gen'; -import type { ReadListIndexResponse } from './read_list_index/read_list_index.gen'; -import type { - ReadListItemRequestQueryInput, - ReadListItemResponse, -} from './read_list_item/read_list_item.gen'; -import type { ReadListPrivilegesResponse } from './read_list_privileges/read_list_privileges.gen'; -import type { ReadListRequestQueryInput, ReadListResponse } from './read_list/read_list.gen'; -import type { - UpdateListItemRequestBodyInput, - UpdateListItemResponse, -} from './update_list_item/update_list_item.gen'; -import type { UpdateListRequestBodyInput, UpdateListResponse } from './update_list/update_list.gen'; - -export interface ClientOptions { - kbnClient: KbnClient; - log: ToolingLog; -} - -export class Client { - readonly kbnClient: KbnClient; - readonly log: ToolingLog; - - constructor(options: ClientOptions) { - this.kbnClient = options.kbnClient; - this.log = options.log; - } - /** - * Create a new list. - */ - async createList(props: CreateListProps) { - this.log.info(`${new Date().toISOString()} Calling API CreateList`); - return this.kbnClient - .request({ - path: '/api/lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Create `.lists` and `.items` data streams in the relevant space. - */ - async createListIndex() { - this.log.info(`${new Date().toISOString()} Calling API CreateListIndex`); - return this.kbnClient - .request({ - path: '/api/lists/index', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Create a list item and associate it with the specified list. - -All list items in the same list must be the same type. For example, each list item in an `ip` list must define a specific IP address. -> info -> Before creating a list item, you must create a list. - - */ - async createListItem(props: CreateListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API CreateListItem`); - return this.kbnClient - .request({ - path: '/api/lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Delete a list using the list ID. -> info -> When you delete a list, all of its list items are also deleted. - - */ - async deleteList(props: DeleteListProps) { - this.log.info(`${new Date().toISOString()} Calling API DeleteList`); - return this.kbnClient - .request({ - path: '/api/lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'DELETE', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Delete the `.lists` and `.items` data streams. - */ - async deleteListIndex() { - this.log.info(`${new Date().toISOString()} Calling API DeleteListIndex`); - return this.kbnClient - .request({ - path: '/api/lists/index', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'DELETE', - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Delete a list item using its `id`, or its `list_id` and `value` fields. - */ - async deleteListItem(props: DeleteListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API DeleteListItem`); - return this.kbnClient - .request({ - path: '/api/lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'DELETE', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Export list item values from the specified list. - */ - async exportListItems(props: ExportListItemsProps) { - this.log.info(`${new Date().toISOString()} Calling API ExportListItems`); - return this.kbnClient - .request({ - path: '/api/lists/items/_export', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get all list items in the specified list. - */ - async findListItems(props: FindListItemsProps) { - this.log.info(`${new Date().toISOString()} Calling API FindListItems`); - return this.kbnClient - .request({ - path: '/api/lists/items/_find', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get a paginated subset of lists. By default, the first page is returned, with 20 results per page. - */ - async findLists(props: FindListsProps) { - this.log.info(`${new Date().toISOString()} Calling API FindLists`); - return this.kbnClient - .request({ - path: '/api/lists/_find', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Import list items from a TXT or CSV file. The maximum file size is 9 million bytes. - -You can import items to a new or existing list. - - */ - async importListItems(props: ImportListItemsProps) { - this.log.info(`${new Date().toISOString()} Calling API ImportListItems`); - return this.kbnClient - .request({ - path: '/api/lists/items/_import', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'POST', - body: props.attachment, - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Update specific fields of an existing list using the list ID. - */ - async patchList(props: PatchListProps) { - this.log.info(`${new Date().toISOString()} Calling API PatchList`); - return this.kbnClient - .request({ - path: '/api/lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'PATCH', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Update specific fields of an existing list item using the list item ID. - */ - async patchListItem(props: PatchListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API PatchListItem`); - return this.kbnClient - .request({ - path: '/api/lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'PATCH', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get the details of a list using the list ID. - */ - async readList(props: ReadListProps) { - this.log.info(`${new Date().toISOString()} Calling API ReadList`); - return this.kbnClient - .request({ - path: '/api/lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Verify that `.lists` and `.items` data streams exist. - */ - async readListIndex() { - this.log.info(`${new Date().toISOString()} Calling API ReadListIndex`); - return this.kbnClient - .request({ - path: '/api/lists/index', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Get the details of a list item. - */ - async readListItem(props: ReadListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API ReadListItem`); - return this.kbnClient - .request({ - path: '/api/lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - - query: props.query, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - async readListPrivileges() { - this.log.info(`${new Date().toISOString()} Calling API ReadListPrivileges`); - return this.kbnClient - .request({ - path: '/api/lists/privileges', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'GET', - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Update a list using the list ID. The original list is replaced, and all unspecified fields are deleted. -> info -> You cannot modify the `id` value. - - */ - async updateList(props: UpdateListProps) { - this.log.info(`${new Date().toISOString()} Calling API UpdateList`); - return this.kbnClient - .request({ - path: '/api/lists', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'PUT', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } - /** - * Update a list item using the list item ID. The original list item is replaced, and all unspecified fields are deleted. -> info -> You cannot modify the `id` value. - - */ - async updateListItem(props: UpdateListItemProps) { - this.log.info(`${new Date().toISOString()} Calling API UpdateListItem`); - return this.kbnClient - .request({ - path: '/api/lists/items', - headers: { - [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', - }, - method: 'PUT', - body: props.body, - }) - .catch(catchAxiosErrorFormatAndThrow); - } -} - -export interface CreateListProps { - body: CreateListRequestBodyInput; -} -export interface CreateListItemProps { - body: CreateListItemRequestBodyInput; -} -export interface DeleteListProps { - query: DeleteListRequestQueryInput; -} -export interface DeleteListItemProps { - query: DeleteListItemRequestQueryInput; -} -export interface ExportListItemsProps { - query: ExportListItemsRequestQueryInput; -} -export interface FindListItemsProps { - query: FindListItemsRequestQueryInput; -} -export interface FindListsProps { - query: FindListsRequestQueryInput; -} -export interface ImportListItemsProps { - query: ImportListItemsRequestQueryInput; - attachment: FormData; -} -export interface PatchListProps { - body: PatchListRequestBodyInput; -} -export interface PatchListItemProps { - body: PatchListItemRequestBodyInput; -} -export interface ReadListProps { - query: ReadListRequestQueryInput; -} -export interface ReadListItemProps { - query: ReadListItemRequestQueryInput; -} -export interface UpdateListProps { - body: UpdateListRequestBodyInput; -} -export interface UpdateListItemProps { - body: UpdateListItemRequestBodyInput; -} diff --git a/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts deleted file mode 100644 index d744eb15c9b50..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Read list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListId } from '../model/list_common.gen'; -import { List } from '../model/list_schemas.gen'; - -export type ReadListRequestQuery = z.infer; -export const ReadListRequestQuery = z.object({ - /** - * List's `id` value - */ - id: ListId, -}); -export type ReadListRequestQueryInput = z.input; - -export type ReadListResponse = z.infer; -export const ReadListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml deleted file mode 100644 index d932e16f528a5..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml +++ /dev/null @@ -1,58 +0,0 @@ -openapi: 3.0.0 -info: - title: Read list API endpoint - version: '2023-10-31' -paths: - /api/lists: - get: - x-labels: [serverless, ess] - operationId: ReadList - x-codegen-enabled: true - summary: Get list details - description: Get the details of a list using the list ID. - parameters: - - name: id - in: query - required: true - description: List's `id` value - schema: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts b/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts deleted file mode 100644 index 8a5068f72f234..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Read list DS existence status API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -export type ReadListIndexResponse = z.infer; -export const ReadListIndexResponse = z.object({ - list_index: z.boolean(), - list_item_index: z.boolean(), -}); diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml b/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml deleted file mode 100644 index b675264600157..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml +++ /dev/null @@ -1,57 +0,0 @@ -openapi: 3.0.0 -info: - title: Read list DS existence status API endpoint - version: '2023-10-31' -paths: - /api/lists/index: - get: - x-labels: [serverless, ess] - operationId: ReadListIndex - x-codegen-enabled: true - summary: Get status of list data streams - description: Verify that `.lists` and `.items` data streams exist. - responses: - 200: - description: Successful response - content: - application/json: - schema: - type: object - properties: - list_index: - type: boolean - list_item_index: - type: boolean - required: [list_index, list_item_index] - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List data stream(s) not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts deleted file mode 100644 index cd0c1d8fca26d..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Read list item API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListId } from '../model/list_common.gen'; -import { ListItem } from '../model/list_schemas.gen'; - -export type ReadListItemRequestQuery = z.infer; -export const ReadListItemRequestQuery = z.object({ - /** - * Required if `list_id` and `value` are not specified - */ - id: ListId.optional(), - /** - * Required if `id` is not specified - */ - list_id: ListId.optional(), - /** - * Required if `id` is not specified - */ - value: z.string().optional(), -}); -export type ReadListItemRequestQueryInput = z.input; - -export type ReadListItemResponse = z.infer; -export const ReadListItemResponse = z.union([ListItem, z.array(ListItem)]); diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml deleted file mode 100644 index 4d686f5452e0c..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml +++ /dev/null @@ -1,74 +0,0 @@ -openapi: 3.0.0 -info: - title: Read list item API endpoint - version: '2023-10-31' -paths: - /api/lists/items: - get: - x-labels: [serverless, ess] - operationId: ReadListItem - x-codegen-enabled: true - summary: Get a list item - description: Get the details of a list item. - parameters: - - name: id - in: query - required: false - description: Required if `list_id` and `value` are not specified - schema: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - - name: list_id - in: query - required: false - description: Required if `id` is not specified - schema: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - - name: value - in: query - required: false - description: Required if `id` is not specified - schema: - type: string - responses: - 200: - description: Successful response - content: - application/json: - schema: - oneOf: - - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' - - type: array - items: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List item not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts deleted file mode 100644 index f5eb085fe4aa5..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Update list API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListId, ListName, ListDescription, ListMetadata } from '../model/list_common.gen'; -import { List } from '../model/list_schemas.gen'; - -export type UpdateListRequestBody = z.infer; -export const UpdateListRequestBody = z.object({ - id: ListId, - name: ListName, - description: ListDescription, - meta: ListMetadata.optional(), - version: z.number().int().min(1).optional(), - _version: z.string().optional(), -}); -export type UpdateListRequestBodyInput = z.input; - -export type UpdateListResponse = z.infer; -export const UpdateListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml deleted file mode 100644 index c41b52427b63d..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml +++ /dev/null @@ -1,79 +0,0 @@ -openapi: 3.0.0 -info: - title: Update list API endpoint - version: '2023-10-31' -paths: - /api/lists: - put: - x-labels: [serverless, ess] - operationId: UpdateList - x-codegen-enabled: true - summary: Update a list - description: | - Update a list using the list ID. The original list is replaced, and all unspecified fields are deleted. - > info - > You cannot modify the `id` value. - requestBody: - description: List's properties - required: true - content: - application/json: - schema: - type: object - properties: - id: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' - name: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' - description: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' - meta: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' - version: - type: integer - minimum: 1 - _version: - type: string - required: - - id - - name - - description - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts deleted file mode 100644 index 052c4c979e844..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Update list item API endpoint - * version: 2023-10-31 - */ - -import { z } from '@kbn/zod'; - -import { ListItemId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; -import { ListItem } from '../model/list_schemas.gen'; - -export type UpdateListItemRequestBody = z.infer; -export const UpdateListItemRequestBody = z.object({ - id: ListItemId, - value: ListItemValue, - meta: ListItemMetadata.optional(), - _version: z.string().optional(), -}); -export type UpdateListItemRequestBodyInput = z.input; - -export type UpdateListItemResponse = z.infer; -export const UpdateListItemResponse = ListItem; diff --git a/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml deleted file mode 100644 index 6b05e01f35aab..0000000000000 --- a/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml +++ /dev/null @@ -1,73 +0,0 @@ -openapi: 3.0.0 -info: - title: Update list item API endpoint - version: '2023-10-31' -paths: - /api/lists/items: - put: - x-labels: [serverless, ess] - operationId: UpdateListItem - x-codegen-enabled: true - summary: Update a list item - description: | - Update a list item using the list item ID. The original list item is replaced, and all unspecified fields are deleted. - > info - > You cannot modify the `id` value. - requestBody: - description: List item's properties - required: true - content: - application/json: - schema: - type: object - properties: - id: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' - value: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' - meta: - $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' - _version: - type: string - required: - - id - - value - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' - 400: - description: Invalid input data response - content: - application/json: - schema: - oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 401: - description: Unsuccessful authentication response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 403: - description: Not enough privileges response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - 404: - description: List item not found response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' - 500: - description: Internal server error response - content: - application/json: - schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/package.json b/packages/kbn-securitysolution-lists-common/package.json deleted file mode 100644 index 624c2709ea737..0000000000000 --- a/packages/kbn-securitysolution-lists-common/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "description": "Security Solution Lists common package", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "name": "@kbn/securitysolution-lists-common", - "private": true, - "version": "1.0.0", - "scripts": { - "openapi:generate": "node scripts/openapi_generate", - "openapi:bundle": "node scripts/openapi_bundle" - } -} diff --git a/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js b/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js deleted file mode 100644 index 7a61724759178..0000000000000 --- a/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -require('../../../src/setup_node_env'); -const { join, resolve } = require('path'); -const { bundle } = require('@kbn/openapi-bundler'); - -const ROOT = resolve(__dirname, '..'); - -(async () => { - await bundle({ - sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), - outputFilePath: join( - ROOT, - 'docs/openapi/serverless/security_solution_lists_api_{version}.bundled.schema.yaml' - ), - options: { - includeLabels: ['serverless'], - prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/lists_serverless.info.yaml'), - }, - }); - - await bundle({ - sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), - outputFilePath: join( - ROOT, - 'docs/openapi/ess/security_solution_lists_api_{version}.bundled.schema.yaml' - ), - options: { - includeLabels: ['ess'], - prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/lists_ess.info.yaml'), - }, - }); -})(); diff --git a/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js b/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js deleted file mode 100644 index 7adc36ed32cab..0000000000000 --- a/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -require('../../../src/setup_node_env'); -const { join, resolve } = require('path'); -const { generate } = require('@kbn/openapi-generator'); -const { REPO_ROOT } = require('@kbn/repo-info'); - -const ROOT = resolve(__dirname, '..'); - -(async () => { - await generate({ - title: 'OpenAPI Lists API Schemas', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'zod_operation_schema', - }); - - await generate({ - title: 'Lists API client for tests', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'api_client_supertest', - skipLinting: true, - bundle: { - outFile: join( - REPO_ROOT, - 'x-pack/test/api_integration/services/security_solution_lists_api.gen.ts' - ), - }, - }); - - await generate({ - title: 'Lists API client for quickstart', - rootDir: ROOT, - sourceGlob: './api/**/*.schema.yaml', - templateName: 'api_client_quickstart', - skipLinting: true, - bundle: { - outFile: join( - REPO_ROOT, - 'packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts' - ), - }, - }); -})(); diff --git a/packages/kbn-securitysolution-lists-common/tsconfig.json b/packages/kbn-securitysolution-lists-common/tsconfig.json deleted file mode 100644 index e8149be083552..0000000000000 --- a/packages/kbn-securitysolution-lists-common/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "outDir": "target/types", - "types": ["jest", "node"] - }, - "exclude": ["target/**/*"], - "extends": "../../tsconfig.base.json", - "include": ["**/*.ts"], - "kbn_references": [ - "@kbn/zod-helpers", - "@kbn/openapi-common", - "@kbn/test", - "@kbn/tooling-log", - "@kbn/core-http-common", - "@kbn/securitysolution-utils", - "@kbn/zod", - ] -} diff --git a/packages/kbn-securitysolution-rules/tsconfig.json b/packages/kbn-securitysolution-rules/tsconfig.json deleted file mode 100644 index 9bd4f35cf62a7..0000000000000 --- a/packages/kbn-securitysolution-rules/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-t-grid/index.ts b/packages/kbn-securitysolution-t-grid/index.ts deleted file mode 100644 index fb5ebc443ccda..0000000000000 --- a/packages/kbn-securitysolution-t-grid/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/constants'; -export * from './src/utils'; -// eslint-disable-next-line @kbn/imports/no_boundary_crossing -export * from './src/mock'; diff --git a/packages/kbn-securitysolution-t-grid/package.json b/packages/kbn-securitysolution-t-grid/package.json deleted file mode 100644 index b262a21e7dc62..0000000000000 --- a/packages/kbn-securitysolution-t-grid/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/securitysolution-t-grid", - "version": "1.0.0", - "description": "security solution t-grid packages will allow sharing components between timelines and security_solution plugin until we transfer all functionality to timelines plugin", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-t-grid/src/constants/index.ts b/packages/kbn-securitysolution-t-grid/src/constants/index.ts deleted file mode 100644 index 3ff541240a8c0..0000000000000 --- a/packages/kbn-securitysolution-t-grid/src/constants/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export const HIGHLIGHTED_DROP_TARGET_CLASS_NAME = 'highlighted-drop-target'; -export const EMPTY_PROVIDERS_GROUP_CLASS_NAME = 'empty-providers-group'; - -/** The draggable will move this many pixels via the keyboard when the arrow key is pressed */ -export const KEYBOARD_DRAG_OFFSET = 20; - -export const DRAGGABLE_KEYBOARD_WRAPPER_CLASS_NAME = 'draggable-keyboard-wrapper'; - -export const ROW_RENDERER_CLASS_NAME = 'row-renderer'; - -export const NOTES_CONTAINER_CLASS_NAME = 'notes-container'; - -export const NOTE_CONTENT_CLASS_NAME = 'note-content'; - -/** This class is added to the document body while dragging */ -export const IS_DRAGGING_CLASS_NAME = 'is-dragging'; - -export const HOVER_ACTIONS_ALWAYS_SHOW_CLASS_NAME = 'hover-actions-always-show'; diff --git a/packages/kbn-securitysolution-t-grid/src/mock/index.ts b/packages/kbn-securitysolution-t-grid/src/mock/index.ts deleted file mode 100644 index 51a5726d914f0..0000000000000 --- a/packages/kbn-securitysolution-t-grid/src/mock/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './mock_event_details'; diff --git a/packages/kbn-securitysolution-t-grid/src/utils/api/index.ts b/packages/kbn-securitysolution-t-grid/src/utils/api/index.ts deleted file mode 100644 index 8f7588fdeafd3..0000000000000 --- a/packages/kbn-securitysolution-t-grid/src/utils/api/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { has } from 'lodash/fp'; - -export interface AppError extends Error { - body: { - message: string; - }; -} - -export interface KibanaError extends AppError { - body: { - message: string; - statusCode: number; - }; -} - -export interface SecurityAppError extends AppError { - body: { - message: string; - status_code: number; - }; -} - -export const isKibanaError = (error: unknown): error is KibanaError => - has('message', error) && has('body.message', error) && has('body.statusCode', error); - -export const isSecurityAppError = (error: unknown): error is SecurityAppError => - has('message', error) && has('body.message', error) && has('body.status_code', error); - -export const isAppError = (error: unknown): error is AppError => - isKibanaError(error) || isSecurityAppError(error); - -export const isNotFoundError = (error: unknown) => - (isKibanaError(error) && error.body.statusCode === 404) || - (isSecurityAppError(error) && error.body.status_code === 404); diff --git a/packages/kbn-securitysolution-t-grid/src/utils/drag_and_drop/index.ts b/packages/kbn-securitysolution-t-grid/src/utils/drag_and_drop/index.ts deleted file mode 100644 index 9b7f4bf6ed7dd..0000000000000 --- a/packages/kbn-securitysolution-t-grid/src/utils/drag_and_drop/index.ts +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { DropResult } from '@hello-pangea/dnd'; - -export const draggableIdPrefix = 'draggableId'; - -export const droppableIdPrefix = 'droppableId'; - -export const draggableContentPrefix = `${draggableIdPrefix}.content.`; - -export const draggableTimelineProvidersPrefix = `${draggableIdPrefix}.timelineProviders.`; - -export const draggableFieldPrefix = `${draggableIdPrefix}.field.`; - -export const droppableContentPrefix = `${droppableIdPrefix}.content.`; - -export const droppableFieldPrefix = `${droppableIdPrefix}.field.`; - -export const droppableTimelineProvidersPrefix = `${droppableIdPrefix}.timelineProviders.`; - -export const droppableTimelineColumnsPrefix = `${droppableIdPrefix}.timelineColumns.`; - -export const droppableTimelineFlyoutBottomBarPrefix = `${droppableIdPrefix}.flyoutButton.`; - -export const getDraggableId = (dataProviderId: string): string => - `${draggableContentPrefix}${dataProviderId}`; - -export const getDraggableFieldId = ({ - contextId, - fieldId, -}: { - contextId: string; - fieldId: string; -}): string => `${draggableFieldPrefix}${escapeContextId(contextId)}.${escapeFieldId(fieldId)}`; - -export const getTimelineProviderDroppableId = ({ - groupIndex, - timelineId, -}: { - groupIndex: number; - timelineId: string; -}): string => `${droppableTimelineProvidersPrefix}${timelineId}.group.${groupIndex}`; - -export const getTimelineProviderDraggableId = ({ - dataProviderId, - groupIndex, - timelineId, -}: { - dataProviderId: string; - groupIndex: number; - timelineId: string; -}): string => - `${draggableTimelineProvidersPrefix}${timelineId}.group.${groupIndex}.${dataProviderId}`; - -export const getDroppableId = (visualizationPlaceholderId: string): string => - `${droppableContentPrefix}${visualizationPlaceholderId}`; - -export const sourceIsContent = (result: DropResult): boolean => - result.source.droppableId.startsWith(droppableContentPrefix); - -export const sourceAndDestinationAreSameTimelineProviders = (result: DropResult): boolean => { - const regex = /^droppableId\.timelineProviders\.(\S+)\./; - const sourceMatches = result.source.droppableId.match(regex) || []; - const destinationMatches = - (result.destination && result.destination.droppableId.match(regex)) || []; - - return ( - sourceMatches.length >= 2 && - destinationMatches.length >= 2 && - sourceMatches[1] === destinationMatches[1] - ); -}; - -export const draggableIsContent = (result: DropResult | { draggableId: string }): boolean => - result.draggableId.startsWith(draggableContentPrefix); - -export const draggableIsField = (result: DropResult | { draggableId: string }): boolean => - result.draggableId.startsWith(draggableFieldPrefix); - -export const reasonIsDrop = (result: DropResult): boolean => result.reason === 'DROP'; - -export const destinationIsTimelineProviders = (result: DropResult): boolean => - result.destination != null && - result.destination.droppableId.startsWith(droppableTimelineProvidersPrefix); - -export const destinationIsTimelineColumns = (result: DropResult): boolean => - result.destination != null && - result.destination.droppableId.startsWith(droppableTimelineColumnsPrefix); - -export const destinationIsTimelineButton = (result: DropResult): boolean => - result.destination != null && - result.destination.droppableId.startsWith(droppableTimelineFlyoutBottomBarPrefix); - -export const getProviderIdFromDraggable = (result: DropResult): string => - result.draggableId.substring(result.draggableId.lastIndexOf('.') + 1); - -export const getFieldIdFromDraggable = (result: DropResult): string => - unEscapeFieldId(result.draggableId.substring(result.draggableId.lastIndexOf('.') + 1)); - -export const escapeDataProviderId = (path: string) => path.replace(/\./g, '_'); - -export const escapeContextId = (path: string) => path.replace(/\./g, '_'); - -export const escapeFieldId = (path: string) => path.replace(/\./g, '!!!DOT!!!'); - -export const unEscapeFieldId = (path: string) => path.replace(/!!!DOT!!!/g, '.'); - -export const providerWasDroppedOnTimeline = (result: DropResult): boolean => - reasonIsDrop(result) && - draggableIsContent(result) && - sourceIsContent(result) && - destinationIsTimelineProviders(result); - -export const userIsReArrangingProviders = (result: DropResult): boolean => - reasonIsDrop(result) && sourceAndDestinationAreSameTimelineProviders(result); - -export const fieldWasDroppedOnTimelineColumns = (result: DropResult): boolean => - reasonIsDrop(result) && draggableIsField(result) && destinationIsTimelineColumns(result); - -/** - * Prevents fields from being dragged or dropped to any area other than column - * header drop zone in the timeline - */ -export const DRAG_TYPE_FIELD = 'drag-type-field'; - -/** This class is added to the document body while timeline field dragging */ -export const IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME = 'is-timeline-field-dragging'; diff --git a/packages/kbn-securitysolution-t-grid/src/utils/index.ts b/packages/kbn-securitysolution-t-grid/src/utils/index.ts deleted file mode 100644 index c921565845e90..0000000000000 --- a/packages/kbn-securitysolution-t-grid/src/utils/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './api'; -export * from './drag_and_drop'; diff --git a/packages/kbn-securitysolution-t-grid/tsconfig.json b/packages/kbn-securitysolution-t-grid/tsconfig.json deleted file mode 100644 index 9bd4f35cf62a7..0000000000000 --- a/packages/kbn-securitysolution-t-grid/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/kbn-securitysolution-utils/index.ts b/packages/kbn-securitysolution-utils/index.ts deleted file mode 100644 index 8769a281e2201..0000000000000 --- a/packages/kbn-securitysolution-utils/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './src/add_remove_id_to_item'; -export * from './src/axios'; -export * from './src/transform_data_to_ndjson'; -export * from './src/path_validations'; -export * from './src/esql'; -export * from './src/debounce_async/debounce_async'; diff --git a/packages/kbn-securitysolution-utils/jest.config.js b/packages/kbn-securitysolution-utils/jest.config.js deleted file mode 100644 index 43e3bc62c156e..0000000000000 --- a/packages/kbn-securitysolution-utils/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-securitysolution-utils'], -}; diff --git a/packages/kbn-securitysolution-utils/package.json b/packages/kbn-securitysolution-utils/package.json deleted file mode 100644 index 2e18ecbc76425..0000000000000 --- a/packages/kbn-securitysolution-utils/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/securitysolution-utils", - "version": "1.0.0", - "description": "security solution utilities to use across plugins such lists, security_solution, cases, etc...", - "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0", - "private": true, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.test.ts b/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.test.ts deleted file mode 100644 index 462f1245500ec..0000000000000 --- a/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { addIdToItem, removeIdFromItem } from '.'; - -jest.mock('uuid', () => ({ - v4: jest.fn().mockReturnValue('123'), -})); - -describe('add_remove_id_to_item', () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('addIdToItem', () => { - test('it adds an id to an empty item', () => { - expect(addIdToItem({})).toEqual({ id: '123' }); - }); - - test('it adds a complex object', () => { - expect( - addIdToItem({ - field: '', - type: 'mapping', - value: '', - }) - ).toEqual({ - id: '123', - field: '', - type: 'mapping', - value: '', - }); - }); - - test('it adds an id to an existing item', () => { - expect(addIdToItem({ test: '456' })).toEqual({ id: '123', test: '456' }); - }); - - test('it does not change the id if it already exists', () => { - expect(addIdToItem({ id: '456' })).toEqual({ id: '456' }); - }); - - test('it returns the same reference if it has an id already', () => { - const obj = { id: '456' }; - expect(addIdToItem(obj)).toBe(obj); - }); - - test('it returns a new reference if it adds an id to an item', () => { - const obj = { test: '456' }; - expect(addIdToItem(obj)).not.toBe(obj); - }); - }); - - describe('removeIdFromItem', () => { - test('it removes an id from an item', () => { - expect(removeIdFromItem({ id: '456' })).toEqual({}); - }); - - test('it returns a new reference if it removes an id from an item', () => { - const obj = { id: '123', test: '456' }; - expect(removeIdFromItem(obj)).not.toBe(obj); - }); - - test('it does not effect an item without an id', () => { - expect(removeIdFromItem({ test: '456' })).toEqual({ test: '456' }); - }); - - test('it returns the same reference if it does not have an id already', () => { - const obj = { test: '456' }; - expect(removeIdFromItem(obj)).toBe(obj); - }); - }); -}); diff --git a/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.ts b/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.ts deleted file mode 100644 index b01a0f7db1ec7..0000000000000 --- a/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { v4 as uuidv4 } from 'uuid'; - -/** - * This is useful for when you have arrays without an ID and need to add one for - * ReactJS keys. I break the types slightly by introducing an id to an arbitrary item - * but then cast it back to the regular type T. - * Usage of this could be considered tech debt as I am adding an ID when the backend - * could be doing the same thing but it depends on how you want to model your data and - * if you view modeling your data with id's to please ReactJS a good or bad thing. - * @param item The item to add an id to. - */ -type NotArray = T extends unknown[] ? never : T; -export const addIdToItem = (item: NotArray): T => { - const maybeId = item as typeof item & { id?: string }; - if (maybeId.id != null) { - return item; - } else { - return { ...item, id: uuidv4() }; - } -}; - -/** - * This is to reverse the id you added to your arrays for ReactJS keys. - * @param item The item to remove the id from. - */ -export const removeIdFromItem = ( - item: NotArray -): - | T - | Pick< - T & { - id?: string | undefined; - }, - Exclude - > => { - const maybeId = item as typeof item & { id?: string }; - if (maybeId.id != null) { - const { id, ...noId } = maybeId; - return noId; - } else { - return item; - } -}; diff --git a/packages/kbn-securitysolution-utils/src/axios/index.ts b/packages/kbn-securitysolution-utils/src/axios/index.ts deleted file mode 100644 index c5c0bbe9d1fda..0000000000000 --- a/packages/kbn-securitysolution-utils/src/axios/index.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { AxiosError } from 'axios'; - -export class FormattedAxiosError extends Error { - public readonly request: { - method: string; - url: string; - data: unknown; - }; - public readonly response: { - status: number; - statusText: string; - data: any; - }; - - constructor(axiosError: AxiosError) { - const method = axiosError.config?.method ?? ''; - const url = axiosError.config?.url ?? ''; - - super( - `${axiosError.message}${ - axiosError?.response?.data ? `: ${JSON.stringify(axiosError?.response?.data)}` : '' - }${url ? `\n(Request: ${method} ${url})` : ''}` - ); - - this.request = { - method, - url, - data: axiosError.config?.data ?? '', - }; - - this.response = { - status: axiosError?.response?.status ?? 0, - statusText: axiosError?.response?.statusText ?? '', - data: axiosError?.response?.data, - }; - - this.name = this.constructor.name; - } - - toJSON() { - return { - message: this.message, - request: this.request, - response: this.response, - }; - } - - toString() { - return JSON.stringify(this.toJSON(), null, 2); - } -} - -/** - * Used with `promise.catch()`, it will format the Axios error to a new error and will re-throw - * @param error - */ -export const catchAxiosErrorFormatAndThrow = (error: Error): never => { - if (error instanceof AxiosError) { - throw new FormattedAxiosError(error); - } - - throw error; -}; diff --git a/packages/kbn-securitysolution-utils/src/client_concurrency/index.ts b/packages/kbn-securitysolution-utils/src/client_concurrency/index.ts deleted file mode 100644 index d3a479b441021..0000000000000 --- a/packages/kbn-securitysolution-utils/src/client_concurrency/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import limit from 'p-limit'; - -/** - * This type is just an async function's type - */ -type RequestFactory = () => Promise; - -/** - * Helper function to call a large number of async functions with limited concurrency. - * Example pattern of how to create functions to pass in: - * - * const ruleCopies = duplicateRuleParams(basicRule, 200); - * const functions = ruleCopies.map((rule) => () => detectionsClient.createRule({ body: rule })); - * - * Note that the `map` call in the example returns a *function* that calls detectionsClient.createRule, it doesn't call createRule immediately. - * - * @param functions Async functions to call with limited concurrency - * @param concurrency Maximum number of concurrent function calls - * @returns Results from all functions passed in - */ -export const concurrentlyExec = async ( - requestFactories: Array>, - concurrency: number = 10 -) => { - const limiter = limit(concurrency); - const promises = requestFactories.map((f) => limiter(f)); - return Promise.all(promises); -}; diff --git a/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.ts b/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.ts deleted file mode 100644 index 99fe653b0e21e..0000000000000 --- a/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/** - * Unlike lodash's debounce, which resolves intermediate calls with the most - * recent value, this implementation waits to resolve intermediate calls until - * the next invocation resolves. - * - * @param fn an async function - * - * @returns A debounced async function that resolves on the next invocation - */ -export function debounceAsync( - fn: (...args: Args) => Result, - intervalMs: number -): (...args: Args) => Promise> { - let timeoutId: ReturnType | undefined; - let resolve: (value: Awaited) => void; - let promise = new Promise>((_resolve) => { - resolve = _resolve; - }); - - return (...args) => { - if (timeoutId) { - clearTimeout(timeoutId); - } - - timeoutId = setTimeout(async () => { - resolve(await fn(...args)); - promise = new Promise((_resolve) => { - resolve = _resolve; - }); - }, intervalMs); - - return promise; - }; -} diff --git a/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.ts b/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.ts deleted file mode 100644 index c9b8474b55969..0000000000000 --- a/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { type ESQLAstQueryExpression, parse } from '@kbn/esql-ast'; - -export const isAggregatingQuery = (astExpression: ESQLAstQueryExpression): boolean => - astExpression.commands.some((command) => command.name === 'stats'); - -/** - * compute if esqlQuery is aggregating/grouping, i.e. using STATS...BY command - * @param esqlQuery - * @returns boolean - */ -export const computeIsESQLQueryAggregating = (esqlQuery: string): boolean => { - const { root } = parse(esqlQuery); - return isAggregatingQuery(root); -}; diff --git a/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.ts b/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.ts deleted file mode 100644 index 7cf69b409d5dc..0000000000000 --- a/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; - -/** - * parses ES|QL query and returns array of indices - */ -export const getIndexListFromEsqlQuery = (query: string | undefined): string[] => { - try { - const indexString = getIndexPatternFromESQLQuery(query); - - return getIndexListFromIndexString(indexString); - } catch (e) { - return []; - } -}; - -/** - * transforms sting of indices, separated by commas to array - * index*, index2* => [index*, index2*] - */ -export const getIndexListFromIndexString = (indexString: string | undefined): string[] => { - if (!indexString) { - return []; - } - return indexString.split(',').map((index) => index.trim()); -}; diff --git a/packages/kbn-securitysolution-utils/src/esql/index.ts b/packages/kbn-securitysolution-utils/src/esql/index.ts deleted file mode 100644 index 930ff246988ea..0000000000000 --- a/packages/kbn-securitysolution-utils/src/esql/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from './compute_if_esql_query_aggregating'; -export * from './get_index_list_from_esql_query'; -export * from './parse_esql_query'; diff --git a/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts b/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts deleted file mode 100644 index e6dfded200072..0000000000000 --- a/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts +++ /dev/null @@ -1,760 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - isPathValid, - hasSimpleExecutableName, - OperatingSystem, - ConditionEntryField, - validateWildcardInput, - validateHasWildcardWithWrongOperator, - validatePotentialWildcardInput, - validateFilePathInput, - WILDCARD_WARNING, - FILEPATH_WARNING, -} from '.'; - -describe('validatePotentialWildcardInput', () => { - it('warns on wildcard when field is file.path.text', () => { - expect( - validatePotentialWildcardInput({ - field: 'file.path.text', - os: OperatingSystem.WINDOWS, - value: 'c:\\path*.exe', - }) - ).toEqual(WILDCARD_WARNING); - }); - it('warns on wildcard when field is not file.path.text', () => { - expect( - validatePotentialWildcardInput({ - field: 'event.category', - os: OperatingSystem.WINDOWS, - value: 'some*value', - }) - ).toEqual(WILDCARD_WARNING); - }); -}); - -describe('validateWildcardInput', () => { - it('warns on wildcard for fields that are not file paths', () => { - expect(validateWildcardInput('*')).toEqual(WILDCARD_WARNING); - }); - it('does not warn if no wildcard', () => { - expect(validateWildcardInput('non-wildcard')).toEqual(undefined); - }); -}); - -describe('validateFilePathInput', () => { - describe('windows', () => { - const os = OperatingSystem.WINDOWS; - - it('does not warn on valid filenames', () => { - expect( - validateFilePathInput({ - os, - value: 'C:\\Windows\\*\\FILENAME.EXE-1231205124.gz', - }) - ).not.toBeDefined(); - expect( - validateFilePathInput({ - os, - value: "C:\\Windows\\*\\test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", - }) - ).toEqual(undefined); - }); - - it('warns on wildcard in file name at the end of the path', () => { - expect(validateFilePathInput({ os, value: 'c:\\path*.exe' })).toEqual(WILDCARD_WARNING); - expect( - validateFilePathInput({ - os, - value: 'C:\\Windows\\*\\FILENAME.EXE-*.gz', - }) - ).toEqual(WILDCARD_WARNING); - }); - - it('warns on unix paths or non-windows paths', () => { - expect(validateFilePathInput({ os, value: '/opt/bin' })).toEqual(FILEPATH_WARNING); - }); - - it('warns on malformed paths', () => { - expect(validateFilePathInput({ os, value: 'c:\\path/opt' })).toEqual(FILEPATH_WARNING); - expect(validateFilePathInput({ os, value: '1242' })).toEqual(FILEPATH_WARNING); - expect(validateFilePathInput({ os, value: 'w12efdfa' })).toEqual(FILEPATH_WARNING); - expect(validateFilePathInput({ os, value: 'c:\\folder\\' })).toEqual(FILEPATH_WARNING); - }); - }); - describe('unix paths', () => { - const os = - parseInt((Math.random() * 2).toString(), 10) === 1 - ? OperatingSystem.MAC - : OperatingSystem.LINUX; - - it('does not warn on valid filenames', () => { - expect( - validateFilePathInput({ - os, - value: '/opt/*/FILENAME.EXE-1231205124.gz', - }) - ).not.toEqual(WILDCARD_WARNING); - expect( - validateFilePathInput({ - os, - value: "/opt/*/test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", - }) - ).not.toEqual(WILDCARD_WARNING); - }); - it('warns on wildcard in file name at the end of the path', () => { - expect(validateFilePathInput({ os, value: '/opt/bin*' })).toEqual(WILDCARD_WARNING); - expect(validateFilePathInput({ os, value: '/opt/FILENAME.EXE-*.gz' })).toEqual( - WILDCARD_WARNING - ); - }); - - it('warns on windows paths', () => { - expect(validateFilePathInput({ os, value: 'd:\\path\\file.exe' })).toEqual(FILEPATH_WARNING); - }); - - it('warns on malformed paths', () => { - expect(validateFilePathInput({ os, value: 'opt/bin\\file.exe' })).toEqual(FILEPATH_WARNING); - expect(validateFilePathInput({ os, value: '1242' })).toEqual(FILEPATH_WARNING); - expect(validateFilePathInput({ os, value: 'w12efdfa' })).toEqual(FILEPATH_WARNING); - expect(validateFilePathInput({ os, value: '/folder/' })).toEqual(FILEPATH_WARNING); - }); - }); -}); - -describe('Wildcard and invalid operator', () => { - it('should return TRUE when operator is not "WILDCARD" and value contains a wildcard', () => { - expect(validateHasWildcardWithWrongOperator({ operator: 'match', value: 'asdf*' })).toEqual( - true - ); - }); - it('should return FALSE when operator is not "WILDCARD" and value does not contain a wildcard', () => { - expect(validateHasWildcardWithWrongOperator({ operator: 'match', value: 'asdf' })).toEqual( - false - ); - }); - it('should return FALSE when operator is "WILDCARD" and value contains a wildcard', () => { - expect(validateHasWildcardWithWrongOperator({ operator: 'wildcard', value: 'asdf*' })).toEqual( - false - ); - }); - it('should return FALSE when operator is "WILDCARD" and value does not contain a wildcard', () => { - expect(validateHasWildcardWithWrongOperator({ operator: 'wildcard', value: 'asdf' })).toEqual( - false - ); - }); -}); - -describe('No Warnings', () => { - it('should not show warnings on non path entries ', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.HASH, - type: 'match', - value: '5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e', - }) - ).toEqual(true); - - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.SIGNER, - type: 'match', - value: '', - }) - ).toEqual(true); - }); -}); - -describe('Unacceptable Windows wildcard paths', () => { - it('should not accept paths that do not have a folder name with a wildcard ', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'c:\\folder', - }) - ).toEqual(false); - }); - - it('should not accept paths that do not have a file name with a wildcard ', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'c:\\path.exe', - }) - ).toEqual(false); - }); - - it('should not accept nested paths that do not have a wildcard', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'c:\\folder\\path.exe', - }) - ).toEqual(false); - }); - - it('should not accept paths with * wildcard and /', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'c:/**/path.exe', - }) - ).toEqual(false); - }); - - it('should not accept paths with ? wildcard and /', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'C:/?indows/pat?', - }) - ).toEqual(false); - }); -}); - -describe('Acceptable Windows wildcard paths', () => { - it('should accept wildcards for folders', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'c:\\**\\path.exe', - }) - ).toEqual(true); - }); - - it('should accept wildcards for folders and files', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'e:\\**\\*.exe', - }) - ).toEqual(true); - }); - - it('should accept paths with single wildcard', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'f:\\*', - }) - ).toEqual(true); - - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'f:\\?', - }) - ).toEqual(true); - }); - - it('should accept paths that have wildcard in filenames', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'a:\\*.*', - }) - ).toEqual(true); - }); - - it('should accept paths with ? as wildcard', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'C:\\?indows\\pat?', - }) - ).toEqual(true); - }); - - it('should accept paths with both ? and * as wildcards', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'C:\\*?', - }) - ).toEqual(true); - }); - - it('should accept paths with multiple wildcards', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'C:\\**', - }) - ).toEqual(true); - - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'C:\\??', - }) - ).toEqual(true); - }); -}); - -describe('Acceptable Windows exact paths', () => { - it('should accept paths when it ends with a folder name', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'match', - value: 'c:\\folder', - }) - ).toEqual(true); - }); - - it('should accept paths when it ends with a file name', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'match', - value: 'c:\\path.exe', - }) - ).toEqual(true); - }); - - it('should accept paths when it ends with a filename in a folder', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'match', - value: 'c:\\folder\\path.exe', - }) - ).toEqual(true); - }); -}); - -describe('Acceptable Windows exact paths with hyphens', () => { - it('should accept paths when paths have folder names with hyphens', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'match', - value: 'c:\\hype-folder-name', - }) - ).toEqual(true); - }); - - it('should accept paths when file names have hyphens', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'match', - value: 'c:\\file-name.exe', - }) - ).toEqual(true); - }); -}); - -describe('Unacceptable Windows exact paths', () => { - it('should not accept paths with /', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'match', - value: 'c:/folder/path.exe', - }) - ).toEqual(false); - }); - - it('should not accept paths not having a in the suffix', () => { - expect( - isPathValid({ - os: OperatingSystem.WINDOWS, - field: ConditionEntryField.PATH, - type: 'match', - value: '\\folder\\path.exe', - }) - ).toEqual(false); - }); -}); - -/// -describe('Unacceptable Mac/Linux wildcard paths', () => { - it('should not accept paths that do not have a folder name with a wildcard ', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/folder', - }) - ).toEqual(false); - }); - - it('should not accept paths that do not have a file name with a wildcard ', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/zip.zip', - }) - ).toEqual(false); - }); - - it('should not accept nested paths that do not have a wildcard', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/opt/pack.tar', - }) - ).toEqual(false); - }); - - it('should not accept paths with * wildcard and \\', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'c:\\**\\path.exe', - }) - ).toEqual(false); - }); - - it('should not accept paths with ? wildcard and \\', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: 'C:\\?indows\\pat?', - }) - ).toEqual(false); - }); -}); - -describe('Acceptable Mac/Linux wildcard paths', () => { - it('should accept wildcards for folders', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/**/file.', - }) - ).toEqual(true); - }); - - it('should accept wildcards for folders and files', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/usr/bi?/*.js', - }) - ).toEqual(true); - }); - - it('should accept paths with single wildcard', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/op*', - }) - ).toEqual(true); - - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/op?', - }) - ).toEqual(true); - }); - - it('should accept paths that have wildcard in filenames', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/*.*', - }) - ).toEqual(true); - }); - - it('should accept paths with ? as wildcard', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/usr/?inux/pat?', - }) - ).toEqual(true); - }); - - it('should accept paths with both ? and * as wildcards', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/usr/*?', - }) - ).toEqual(true); - }); - - it('should accept paths with multiple wildcards', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/usr/**', - }) - ).toEqual(true); - - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'wildcard', - value: '/opt/??', - }) - ).toEqual(true); - }); -}); - -describe('Acceptable Mac/Linux exact paths', () => { - it('should accept paths when it is the root path', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'match', - value: '/', - }) - ).toEqual(true); - }); - - it('should accept paths when it ends with a file name', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'match', - value: '/usr/file.ts', - }) - ).toEqual(true); - }); - - it('should accept paths when it ends with a filename in a folder', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'match', - value: '/opt/z.dmg', - }) - ).toEqual(true); - }); -}); - -describe('Acceptable Mac/Linux exact paths with hyphens', () => { - it('should accept paths when paths have folder names with hyphens', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'match', - value: '/hype-folder-name', - }) - ).toEqual(true); - }); - - it('should accept paths when file names have hyphens', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'match', - value: '/file-name.dmg', - }) - ).toEqual(true); - }); -}); - -describe('Unacceptable Mac/Linux exact paths', () => { - it('should not accept paths with \\', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'match', - value: 'c:\\folder\\path.exe', - }) - ).toEqual(false); - }); - - it('should not accept paths not starting with /', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'match', - value: 'opt/bin', - }) - ).toEqual(false); - }); - - it('should not accept paths ending with /', () => { - expect( - isPathValid({ - os: OperatingSystem.MAC, - field: ConditionEntryField.PATH, - type: 'match', - value: '/opt/bin/', - }) - ).toEqual(false); - }); - - it('should not accept file extensions with hyphens', () => { - expect( - isPathValid({ - os: OperatingSystem.LINUX, - field: ConditionEntryField.PATH, - type: 'match', - value: '/opt/bin/file.d-mg', - }) - ).toEqual(false); - }); -}); - -describe('hasSimpleExecutableName', () => { - it('should return TRUE when MAC/LINUX wildcard paths have an executable name', () => { - const os = - parseInt((Math.random() * 2).toString(), 10) === 1 - ? OperatingSystem.MAC - : OperatingSystem.LINUX; - - expect( - hasSimpleExecutableName({ - os, - type: 'wildcard', - value: '/opt/*/app', - }) - ).toEqual(true); - expect( - hasSimpleExecutableName({ - os, - type: 'wildcard', - value: '/op*/**/app.dmg', - }) - ).toEqual(true); - expect( - hasSimpleExecutableName({ - os, - type: 'wildcard', - value: "/sy*/test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", - }) - ).toEqual(true); - }); - - it('should return FALSE when MAC/LINUX wildcard paths have a wildcard in executable name', () => { - const os = - parseInt((Math.random() * 2).toString(), 10) === 1 - ? OperatingSystem.MAC - : OperatingSystem.LINUX; - - expect( - hasSimpleExecutableName({ - os, - type: 'wildcard', - value: '/op/*/*pp', - }) - ).toEqual(false); - expect( - hasSimpleExecutableName({ - os, - type: 'wildcard', - value: '/op*/b**/ap.m**', - }) - ).toEqual(false); - }); - - it('should return TRUE when WINDOWS wildcards paths have a executable name', () => { - expect( - hasSimpleExecutableName({ - os: OperatingSystem.WINDOWS, - type: 'wildcard', - value: 'c:\\**\\path.exe', - }) - ).toEqual(true); - expect( - hasSimpleExecutableName({ - os: OperatingSystem.WINDOWS, - type: 'wildcard', - value: 'C:\\*\\file-name.path华语 1234.txt', - }) - ).toEqual(true); - expect( - hasSimpleExecutableName({ - os: OperatingSystem.WINDOWS, - type: 'wildcard', - value: "C:\\*\\test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", - }) - ).toEqual(true); - }); - - it('should return FALSE when WINDOWS wildcards paths have a wildcard in executable name', () => { - expect( - hasSimpleExecutableName({ - os: OperatingSystem.WINDOWS, - type: 'wildcard', - value: 'c:\\**\\pa*h.exe', - }) - ).toEqual(false); - }); -}); diff --git a/packages/kbn-securitysolution-utils/src/path_validations/index.ts b/packages/kbn-securitysolution-utils/src/path_validations/index.ts deleted file mode 100644 index 1f1eaf0b01423..0000000000000 --- a/packages/kbn-securitysolution-utils/src/path_validations/index.ts +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { i18n } from '@kbn/i18n'; - -export const WILDCARD_WARNING = i18n.translate('utils.wildcardWarning', { - defaultMessage: `Using wildcards can impact Endpoint performance`, -}); - -export const FILEPATH_WARNING = i18n.translate('utils.filename.pathWarning', { - defaultMessage: `Path may be formed incorrectly; verify value`, -}); - -export enum ConditionEntryField { - HASH = 'process.hash.*', - PATH = 'process.executable.caseless', - SIGNER = 'process.Ext.code_signature', - SIGNER_MAC = 'process.code_signature', -} - -export enum EntryFieldType { - HASH = '.hash.', - EXECUTABLE = '.executable.caseless', - PATH = '.path', - SIGNER = '.code_signature', -} - -export type TrustedAppConditionEntryField = - | 'process.hash.*' - | 'process.executable.caseless' - | 'process.Ext.code_signature' - | 'process.code_signature'; - -export type BlocklistConditionEntryField = - | 'file.hash.*' - | 'file.path' - | 'file.Ext.code_signature' - | 'file.path.caseless'; -export type AllConditionEntryFields = - | TrustedAppConditionEntryField - | BlocklistConditionEntryField - | 'file.path.text'; - -export enum OperatingSystem { - LINUX = 'linux', - MAC = 'macos', - WINDOWS = 'windows', -} - -export type EntryTypes = 'match' | 'wildcard' | 'match_any'; -export type TrustedAppEntryTypes = Extract; -export type EventFiltersTypes = EntryTypes | 'exists' | 'nested'; - -export const validatePotentialWildcardInput = ({ - field = '', - os, - value = '', -}: { - field?: string; - os: OperatingSystem; - value?: string; -}): string | undefined => { - const textInput = value.trim(); - if (field === 'file.path.text') { - return validateFilePathInput({ os, value: textInput }); - } - return validateWildcardInput(textInput); -}; - -export const validateFilePathInput = ({ - os, - value, -}: { - os: OperatingSystem; - value: string; -}): string | undefined => { - const isValidFilePath = isPathValid({ - os, - field: 'file.path.text', - type: 'wildcard', - value, - }); - const hasSimpleFileName = hasSimpleExecutableName({ - os, - type: 'wildcard', - value, - }); - - if (!value.length) { - return FILEPATH_WARNING; - } - - if (isValidFilePath) { - if (hasSimpleFileName !== undefined && !hasSimpleFileName) { - return WILDCARD_WARNING; - } - } else { - return FILEPATH_WARNING; - } -}; - -export const validateWildcardInput = (value: string | string[]): string | undefined => { - const wildcardRegex = /[*?]/; - if (Array.isArray(value)) { - const doesAnyValueContainWildcardInput = value.some((v) => wildcardRegex.test(v)); - if (doesAnyValueContainWildcardInput) { - return WILDCARD_WARNING; - } - } else { - if (wildcardRegex.test(value)) { - return WILDCARD_WARNING; - } - } -}; - -export const validateHasWildcardWithWrongOperator = ({ - operator, - value, -}: { - operator: TrustedAppEntryTypes | EventFiltersTypes; - value: string | string[]; -}): boolean => { - if (operator !== 'wildcard' && validateWildcardInput(value)) { - return true; - } else { - return false; - } -}; - -export const hasSimpleExecutableName = ({ - os, - type, - value, -}: { - os: OperatingSystem; - type: EntryTypes; - value: string; -}): boolean | undefined => { - const separator = os === OperatingSystem.WINDOWS ? '\\' : '/'; - const lastString = value.split(separator).pop(); - if (!lastString) { - return; - } - if (type === 'wildcard') { - return (lastString.split('*').length || lastString.split('?').length) === 1; - } - return true; -}; - -export const isPathValid = ({ - os, - field, - type, - value, -}: { - os: OperatingSystem; - field: AllConditionEntryFields; - type: EntryTypes; - value: string; -}): boolean => { - const pathFields: AllConditionEntryFields[] = [ - 'process.executable.caseless', - 'file.path', - 'file.path.text', - ]; - if (pathFields.includes(field)) { - if (type === 'wildcard') { - return os === OperatingSystem.WINDOWS - ? isWindowsWildcardPathValid(value) - : isLinuxMacWildcardPathValid(value); - } - return doesPathMatchRegex({ value, os }); - } - return true; -}; - -const doesPathMatchRegex = ({ os, value }: { os: OperatingSystem; value: string }): boolean => { - if (os === OperatingSystem.WINDOWS) { - const filePathRegex = - /^[a-z]:(?:|\\\\[^<>:"'/\\|?*]+\\[^<>:"'/\\|?*]+|%\w+%|)[\\](?:[^<>:"'/\\|?*]+[\\/])*([^<>:"'/\\|?*])+$/i; - return filePathRegex.test(value); - } - return /^(\/|(\/[\w\-]+)+|\/[\w\-]+\.[\w]+|(\/[\w-]+)+\/[\w\-]+\.[\w]+)$/i.test(value); -}; - -const isWindowsWildcardPathValid = (path: string): boolean => { - const firstCharacter = path[0]; - const lastCharacter = path.slice(-1); - const trimmedValue = path.trim(); - const hasSlash = /\//.test(trimmedValue); - if (path.length === 0) { - return false; - } else if ( - hasSlash || - trimmedValue.length !== path.length || - firstCharacter === '^' || - lastCharacter === '\\' || - !hasWildcard({ path, isWindowsPath: true }) - ) { - return false; - } else { - return true; - } -}; - -const isLinuxMacWildcardPathValid = (path: string): boolean => { - const firstCharacter = path[0]; - const lastCharacter = path.slice(-1); - const trimmedValue = path.trim(); - if (path.length === 0) { - return false; - } else if ( - trimmedValue.length !== path.length || - firstCharacter !== '/' || - lastCharacter === '/' || - path.length > 1024 === true || - path.includes('//') === true || - !hasWildcard({ path, isWindowsPath: false }) - ) { - return false; - } else { - return true; - } -}; - -const hasWildcard = ({ - path, - isWindowsPath, -}: { - path: string; - isWindowsPath: boolean; -}): boolean => { - for (const pathComponent of path.split(isWindowsPath ? '\\' : '/')) { - if (/[\*|\?]+/.test(pathComponent) === true) { - return true; - } - } - return false; -}; diff --git a/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts b/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts deleted file mode 100644 index 8c4e8289b1dd3..0000000000000 --- a/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { transformDataToNdjson } from '.'; - -export const ANCHOR_DATE = '2020-02-20T03:57:54.037Z'; - -const getRulesSchemaMock = (anchorDate: string = ANCHOR_DATE) => ({ - author: [], - id: '7a7065d7-6e8b-4aae-8d20-c93613dec9f9', - created_at: new Date(anchorDate).toISOString(), - updated_at: new Date(anchorDate).toISOString(), - created_by: 'elastic', - description: 'some description', - enabled: true, - false_positives: ['false positive 1', 'false positive 2'], - from: 'now-6m', - immutable: false, - name: 'Query with a rule id', - query: 'user.name: root or user.name: admin', - references: ['test 1', 'test 2'], - severity: 'high', - severity_mapping: [], - updated_by: 'elastic_kibana', - tags: ['some fake tag 1', 'some fake tag 2'], - to: 'now', - type: 'query', - threat: [], - version: 1, - output_index: '.siem-signals-default', - max_signals: 100, - risk_score: 55, - risk_score_mapping: [], - language: 'kuery', - rule_id: 'query-rule-id', - interval: '5m', - exceptions_list: [], -}); - -describe('transformDataToNdjson', () => { - test('if rules are empty it returns an empty string', () => { - const ruleNdjson = transformDataToNdjson([]); - expect(ruleNdjson).toEqual(''); - }); - - test('single rule will transform with new line ending character for ndjson', () => { - const rule = getRulesSchemaMock(); - const ruleNdjson = transformDataToNdjson([rule]); - expect(ruleNdjson.endsWith('\n')).toBe(true); - }); - - test('multiple rules will transform with two new line ending characters for ndjson', () => { - const result1 = getRulesSchemaMock(); - const result2 = getRulesSchemaMock(); - result2.id = 'some other id'; - result2.rule_id = 'some other id'; - result2.name = 'Some other rule'; - - const ruleNdjson = transformDataToNdjson([result1, result2]); - // this is how we count characters in JavaScript :-) - const count = ruleNdjson.split('\n').length - 1; - expect(count).toBe(2); - }); - - test('you can parse two rules back out without errors', () => { - const result1 = getRulesSchemaMock(); - const result2 = getRulesSchemaMock(); - result2.id = 'some other id'; - result2.rule_id = 'some other id'; - result2.name = 'Some other rule'; - - const ruleNdjson = transformDataToNdjson([result1, result2]); - const ruleStrings = ruleNdjson.split('\n'); - const reParsed1 = JSON.parse(ruleStrings[0]); - const reParsed2 = JSON.parse(ruleStrings[1]); - expect(reParsed1).toEqual(result1); - expect(reParsed2).toEqual(result2); - }); -}); diff --git a/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.ts b/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.ts deleted file mode 100644 index b20606c356efe..0000000000000 --- a/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export const transformDataToNdjson = (data: unknown[]): string => { - if (data.length !== 0) { - const dataString = data.map((item) => JSON.stringify(item)).join('\n'); - return `${dataString}\n`; - } else { - return ''; - } -}; diff --git a/packages/kbn-securitysolution-utils/tsconfig.json b/packages/kbn-securitysolution-utils/tsconfig.json deleted file mode 100644 index d45b0c973af87..0000000000000 --- a/packages/kbn-securitysolution-utils/tsconfig.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/i18n", - "@kbn/esql-utils", - "@kbn/esql-ast", - "@kbn/esql-validation-autocomplete" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 4991ac0dfe44d..c2c24528e3dc7 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -49,7 +49,7 @@ export const storybookAliases = { inventory: 'x-pack/plugins/observability_solution/inventory/.storybook', investigate: 'x-pack/solutions/observability/plugins/investigate_app/.storybook', kibana_react: 'src/plugins/kibana_react/.storybook', - lists: 'x-pack/plugins/lists/.storybook', + lists: 'x-pack/solutions/security/plugins/lists/.storybook', logs_explorer: 'x-pack/plugins/observability_solution/logs_explorer/.storybook', management: 'packages/kbn-management/storybook/config', observability: 'x-pack/solutions/observability/plugins/observability/.storybook', diff --git a/packages/kbn-securitysolution-es-utils/README.md b/src/platform/packages/shared/kbn-securitysolution-es-utils/README.md similarity index 100% rename from packages/kbn-securitysolution-es-utils/README.md rename to src/platform/packages/shared/kbn-securitysolution-es-utils/README.md diff --git a/packages/kbn-securitysolution-es-utils/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/index.ts diff --git a/src/platform/packages/shared/kbn-securitysolution-es-utils/jest.config.js b/src/platform/packages/shared/kbn-securitysolution-es-utils/jest.config.js new file mode 100644 index 0000000000000..3a654a3a269ea --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-es-utils/jest.config.js @@ -0,0 +1,14 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/src/platform/packages/shared/kbn-securitysolution-es-utils'], +}; diff --git a/packages/kbn-securitysolution-es-utils/kibana.jsonc b/src/platform/packages/shared/kbn-securitysolution-es-utils/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-es-utils/kibana.jsonc rename to src/platform/packages/shared/kbn-securitysolution-es-utils/kibana.jsonc diff --git a/packages/kbn-securitysolution-es-utils/package.json b/src/platform/packages/shared/kbn-securitysolution-es-utils/package.json similarity index 100% rename from packages/kbn-securitysolution-es-utils/package.json rename to src/platform/packages/shared/kbn-securitysolution-es-utils/package.json diff --git a/packages/kbn-securitysolution-es-utils/src/bad_request_error/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/bad_request_error/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/bad_request_error/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/bad_request_error/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/create_data_stream/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/create_data_stream/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/create_data_stream/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/create_data_stream/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/decode_version/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/decode_version/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/decode_version/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/decode_version/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_all_index/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_all_index/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/delete_index_template/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_index_template/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/delete_index_template/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_index_template/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_policy/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_policy/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_template/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/delete_template/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/delete_template/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/encode_hit_version/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/encode_hit_version/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/encode_hit_version/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/encode_hit_version/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_bootstrap_index_exists/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_bootstrap_index_exists/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_bootstrap_index_exists/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_bootstrap_index_exists/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_count/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_count/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_exists/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_exists/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_template_exists/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_template_exists/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_index_template_exists/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_index_template_exists/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_template_exists/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/get_template_exists/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/put_mappings/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/put_mappings/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/read_index/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/read_index/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/read_index/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/read_index/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/read_privileges/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/read_privileges/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/set_index_template/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/set_index_template/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/set_index_template/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/set_index_template/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/set_policy/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/set_policy/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/set_policy/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/set_template/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/set_template/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/set_template/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/set_template/index.ts diff --git a/packages/kbn-securitysolution-es-utils/src/transform_error/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/transform_error/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/transform_error/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/transform_error/index.test.ts diff --git a/packages/kbn-securitysolution-es-utils/src/transform_error/index.ts b/src/platform/packages/shared/kbn-securitysolution-es-utils/src/transform_error/index.ts similarity index 100% rename from packages/kbn-securitysolution-es-utils/src/transform_error/index.ts rename to src/platform/packages/shared/kbn-securitysolution-es-utils/src/transform_error/index.ts diff --git a/src/platform/packages/shared/kbn-securitysolution-es-utils/tsconfig.json b/src/platform/packages/shared/kbn-securitysolution-es-utils/tsconfig.json new file mode 100644 index 0000000000000..5a16f6bdaff6c --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-es-utils/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "target/**/*", + ], + "kbn_references": [ + "@kbn/zod-helpers", + "@kbn/zod", + ] +} diff --git a/packages/kbn-securitysolution-io-ts-types/README.md b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/README.md similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/README.md rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/README.md diff --git a/packages/kbn-securitysolution-io-ts-types/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/index.ts diff --git a/src/platform/packages/shared/kbn-securitysolution-io-ts-types/jest.config.js b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/jest.config.js new file mode 100644 index 0000000000000..309c3085d7449 --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/jest.config.js @@ -0,0 +1,14 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/src/platform/packages/shared/kbn-securitysolution-io-ts-types'], +}; diff --git a/packages/kbn-securitysolution-io-ts-types/kibana.jsonc b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/kibana.jsonc rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/kibana.jsonc diff --git a/packages/kbn-securitysolution-io-ts-types/package.json b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/package.json similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/package.json rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/package.json diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_false/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_boolean_true/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_csv_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_csv_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_csv_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_csv_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_csv_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_csv_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_csv_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_csv_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_empty_string/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_empty_string/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_empty_string/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_empty_string/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_empty_string/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_empty_string/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_empty_string/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_empty_string/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_string_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_string_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_string_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_string_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_string_boolean_false/index.ts diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_uuid/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_uuid/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_uuid/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_uuid/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_uuid/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_uuid/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_value/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_value/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_value/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_value/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_value/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_value/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_value/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_value/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_version_number/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_version_number/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_version_number/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_version_number/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/default_version_number/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_version_number/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/default_version_number/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/default_version_number/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/empty_string_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/empty_string_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/empty_string_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/empty_string_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/empty_string_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/empty_string_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/empty_string_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/empty_string_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/enumeration/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/enumeration/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/enumeration/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/enumeration/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/enumeration/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/enumeration/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/enumeration/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/enumeration/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/import_query_schema/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/import_query_schema/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/import_query_schema/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/import_query_schema/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/import_query_schema/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/import_query_schema/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/import_query_schema/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/import_query_schema/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/iso_date_string/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/iso_date_string/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/iso_date_string/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/iso_date_string/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/iso_date_string/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/iso_date_string/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/iso_date_string/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/iso_date_string/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/limited_size_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/limited_size_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/limited_size_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/limited_size_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/limited_size_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/limited_size_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/limited_size_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/limited_size_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_or_nullable_string_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_string/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_string/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_string/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_string/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/non_empty_string_array/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/number_between_zero_and_one_inclusive/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/only_false_allowed/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/operator/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/operator/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/operator/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/operator/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/positive_integer/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/positive_integer/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/positive_integer/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/positive_integer/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/positive_integer_greater_than_zero/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/string_to_positive_number/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/string_to_positive_number/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/string_to_positive_number/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/string_to_positive_number/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/time_duration/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/time_duration/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/time_duration/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/time_duration/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/time_duration/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/time_duration/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/time_duration/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/time_duration/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/uuid/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/uuid/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/uuid/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/uuid/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/uuid/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/uuid/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/uuid/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/uuid/index.ts diff --git a/packages/kbn-securitysolution-io-ts-types/src/version/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/version/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-types/src/version/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-types/src/version/index.ts diff --git a/src/platform/packages/shared/kbn-securitysolution-io-ts-types/tsconfig.json b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/tsconfig.json new file mode 100644 index 0000000000000..6bc8a84da337d --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-io-ts-types/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "kbn_references": [ + "@kbn/securitysolution-io-ts-utils" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-io-ts-utils/README.md b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/README.md similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/README.md rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/README.md diff --git a/packages/kbn-securitysolution-io-ts-utils/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/index.ts diff --git a/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/jest.config.js b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/jest.config.js new file mode 100644 index 0000000000000..cfa70556f4b89 --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/jest.config.js @@ -0,0 +1,14 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/src/platform/packages/shared/kbn-securitysolution-io-ts-utils'], +}; diff --git a/packages/kbn-securitysolution-io-ts-utils/kibana.jsonc b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/kibana.jsonc rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/kibana.jsonc diff --git a/packages/kbn-securitysolution-io-ts-utils/package.json b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/package.json similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/package.json rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/package.json diff --git a/packages/kbn-securitysolution-io-ts-utils/src/exact_check/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/exact_check/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/exact_check/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/exact_check/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/exact_check/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/exact_check/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/exact_check/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/exact_check/index.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/format_errors/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/format_errors/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/format_errors/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/format_errors/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/format_errors/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/format_errors/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/format_errors/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/format_errors/index.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/parse_schedule_dates/index.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/test_utils/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/test_utils/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/test_utils/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/test_utils/index.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/validate/index.test.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/validate/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/validate/index.test.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/validate/index.test.ts diff --git a/packages/kbn-securitysolution-io-ts-utils/src/validate/index.ts b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/validate/index.ts similarity index 100% rename from packages/kbn-securitysolution-io-ts-utils/src/validate/index.ts rename to src/platform/packages/shared/kbn-securitysolution-io-ts-utils/src/validate/index.ts diff --git a/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/tsconfig.json b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/tsconfig.json new file mode 100644 index 0000000000000..ca5354ad56e4f --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-io-ts-utils/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "kbn_references": [ + "@kbn/datemath" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-rules/README.md b/src/platform/packages/shared/kbn-securitysolution-rules/README.md similarity index 100% rename from packages/kbn-securitysolution-rules/README.md rename to src/platform/packages/shared/kbn-securitysolution-rules/README.md diff --git a/packages/kbn-securitysolution-rules/index.ts b/src/platform/packages/shared/kbn-securitysolution-rules/index.ts similarity index 100% rename from packages/kbn-securitysolution-rules/index.ts rename to src/platform/packages/shared/kbn-securitysolution-rules/index.ts diff --git a/packages/kbn-securitysolution-rules/kibana.jsonc b/src/platform/packages/shared/kbn-securitysolution-rules/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-rules/kibana.jsonc rename to src/platform/packages/shared/kbn-securitysolution-rules/kibana.jsonc diff --git a/packages/kbn-securitysolution-rules/package.json b/src/platform/packages/shared/kbn-securitysolution-rules/package.json similarity index 100% rename from packages/kbn-securitysolution-rules/package.json rename to src/platform/packages/shared/kbn-securitysolution-rules/package.json diff --git a/packages/kbn-securitysolution-rules/src/configuration_constants.ts b/src/platform/packages/shared/kbn-securitysolution-rules/src/configuration_constants.ts similarity index 100% rename from packages/kbn-securitysolution-rules/src/configuration_constants.ts rename to src/platform/packages/shared/kbn-securitysolution-rules/src/configuration_constants.ts diff --git a/packages/kbn-securitysolution-rules/src/rule_type_constants.ts b/src/platform/packages/shared/kbn-securitysolution-rules/src/rule_type_constants.ts similarity index 100% rename from packages/kbn-securitysolution-rules/src/rule_type_constants.ts rename to src/platform/packages/shared/kbn-securitysolution-rules/src/rule_type_constants.ts diff --git a/packages/kbn-securitysolution-rules/src/rule_type_mappings.ts b/src/platform/packages/shared/kbn-securitysolution-rules/src/rule_type_mappings.ts similarity index 100% rename from packages/kbn-securitysolution-rules/src/rule_type_mappings.ts rename to src/platform/packages/shared/kbn-securitysolution-rules/src/rule_type_mappings.ts diff --git a/packages/kbn-securitysolution-rules/src/utils.ts b/src/platform/packages/shared/kbn-securitysolution-rules/src/utils.ts similarity index 100% rename from packages/kbn-securitysolution-rules/src/utils.ts rename to src/platform/packages/shared/kbn-securitysolution-rules/src/utils.ts diff --git a/src/platform/packages/shared/kbn-securitysolution-rules/tsconfig.json b/src/platform/packages/shared/kbn-securitysolution-rules/tsconfig.json new file mode 100644 index 0000000000000..131ff3e6bb433 --- /dev/null +++ b/src/platform/packages/shared/kbn-securitysolution-rules/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 9b760a854bb58..e8b6704a950d5 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1160,8 +1160,8 @@ "@kbn/lint-packages-cli/*": ["packages/kbn-lint-packages-cli/*"], "@kbn/lint-ts-projects-cli": ["packages/kbn-lint-ts-projects-cli"], "@kbn/lint-ts-projects-cli/*": ["packages/kbn-lint-ts-projects-cli/*"], - "@kbn/lists-plugin": ["x-pack/plugins/lists"], - "@kbn/lists-plugin/*": ["x-pack/plugins/lists/*"], + "@kbn/lists-plugin": ["x-pack/solutions/security/plugins/lists"], + "@kbn/lists-plugin/*": ["x-pack/solutions/security/plugins/lists/*"], "@kbn/llm-tasks-plugin": ["x-pack/platform/plugins/shared/ai_infra/llm_tasks"], "@kbn/llm-tasks-plugin/*": ["x-pack/platform/plugins/shared/ai_infra/llm_tasks/*"], "@kbn/locator-examples-plugin": ["examples/locator_examples"], @@ -1656,46 +1656,46 @@ "@kbn/security-test-endpoints-plugin/*": ["x-pack/test/security_functional/plugins/test_endpoints/*"], "@kbn/security-ui-components": ["x-pack/packages/security/ui_components"], "@kbn/security-ui-components/*": ["x-pack/packages/security/ui_components/*"], - "@kbn/securitysolution-autocomplete": ["packages/kbn-securitysolution-autocomplete"], - "@kbn/securitysolution-autocomplete/*": ["packages/kbn-securitysolution-autocomplete/*"], + "@kbn/securitysolution-autocomplete": ["x-pack/solutions/security/packages/kbn-securitysolution-autocomplete"], + "@kbn/securitysolution-autocomplete/*": ["x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/*"], "@kbn/securitysolution-data-table": ["x-pack/solutions/security/packages/data_table"], "@kbn/securitysolution-data-table/*": ["x-pack/solutions/security/packages/data_table/*"], "@kbn/securitysolution-ecs": ["src/platform/packages/shared/kbn-securitysolution-ecs"], "@kbn/securitysolution-ecs/*": ["src/platform/packages/shared/kbn-securitysolution-ecs/*"], - "@kbn/securitysolution-endpoint-exceptions-common": ["packages/kbn-securitysolution-endpoint-exceptions-common"], - "@kbn/securitysolution-endpoint-exceptions-common/*": ["packages/kbn-securitysolution-endpoint-exceptions-common/*"], - "@kbn/securitysolution-es-utils": ["packages/kbn-securitysolution-es-utils"], - "@kbn/securitysolution-es-utils/*": ["packages/kbn-securitysolution-es-utils/*"], - "@kbn/securitysolution-exception-list-components": ["packages/kbn-securitysolution-exception-list-components"], - "@kbn/securitysolution-exception-list-components/*": ["packages/kbn-securitysolution-exception-list-components/*"], - "@kbn/securitysolution-exceptions-common": ["packages/kbn-securitysolution-exceptions-common"], - "@kbn/securitysolution-exceptions-common/*": ["packages/kbn-securitysolution-exceptions-common/*"], - "@kbn/securitysolution-hook-utils": ["packages/kbn-securitysolution-hook-utils"], - "@kbn/securitysolution-hook-utils/*": ["packages/kbn-securitysolution-hook-utils/*"], - "@kbn/securitysolution-io-ts-alerting-types": ["packages/kbn-securitysolution-io-ts-alerting-types"], - "@kbn/securitysolution-io-ts-alerting-types/*": ["packages/kbn-securitysolution-io-ts-alerting-types/*"], - "@kbn/securitysolution-io-ts-list-types": ["packages/kbn-securitysolution-io-ts-list-types"], - "@kbn/securitysolution-io-ts-list-types/*": ["packages/kbn-securitysolution-io-ts-list-types/*"], - "@kbn/securitysolution-io-ts-types": ["packages/kbn-securitysolution-io-ts-types"], - "@kbn/securitysolution-io-ts-types/*": ["packages/kbn-securitysolution-io-ts-types/*"], - "@kbn/securitysolution-io-ts-utils": ["packages/kbn-securitysolution-io-ts-utils"], - "@kbn/securitysolution-io-ts-utils/*": ["packages/kbn-securitysolution-io-ts-utils/*"], - "@kbn/securitysolution-list-api": ["packages/kbn-securitysolution-list-api"], - "@kbn/securitysolution-list-api/*": ["packages/kbn-securitysolution-list-api/*"], - "@kbn/securitysolution-list-constants": ["packages/kbn-securitysolution-list-constants"], - "@kbn/securitysolution-list-constants/*": ["packages/kbn-securitysolution-list-constants/*"], - "@kbn/securitysolution-list-hooks": ["packages/kbn-securitysolution-list-hooks"], - "@kbn/securitysolution-list-hooks/*": ["packages/kbn-securitysolution-list-hooks/*"], - "@kbn/securitysolution-list-utils": ["packages/kbn-securitysolution-list-utils"], - "@kbn/securitysolution-list-utils/*": ["packages/kbn-securitysolution-list-utils/*"], - "@kbn/securitysolution-lists-common": ["packages/kbn-securitysolution-lists-common"], - "@kbn/securitysolution-lists-common/*": ["packages/kbn-securitysolution-lists-common/*"], - "@kbn/securitysolution-rules": ["packages/kbn-securitysolution-rules"], - "@kbn/securitysolution-rules/*": ["packages/kbn-securitysolution-rules/*"], - "@kbn/securitysolution-t-grid": ["packages/kbn-securitysolution-t-grid"], - "@kbn/securitysolution-t-grid/*": ["packages/kbn-securitysolution-t-grid/*"], - "@kbn/securitysolution-utils": ["packages/kbn-securitysolution-utils"], - "@kbn/securitysolution-utils/*": ["packages/kbn-securitysolution-utils/*"], + "@kbn/securitysolution-endpoint-exceptions-common": ["x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common"], + "@kbn/securitysolution-endpoint-exceptions-common/*": ["x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/*"], + "@kbn/securitysolution-es-utils": ["src/platform/packages/shared/kbn-securitysolution-es-utils"], + "@kbn/securitysolution-es-utils/*": ["src/platform/packages/shared/kbn-securitysolution-es-utils/*"], + "@kbn/securitysolution-exception-list-components": ["x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components"], + "@kbn/securitysolution-exception-list-components/*": ["x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/*"], + "@kbn/securitysolution-exceptions-common": ["x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common"], + "@kbn/securitysolution-exceptions-common/*": ["x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/*"], + "@kbn/securitysolution-hook-utils": ["x-pack/solutions/security/packages/kbn-securitysolution-hook-utils"], + "@kbn/securitysolution-hook-utils/*": ["x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/*"], + "@kbn/securitysolution-io-ts-alerting-types": ["x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types"], + "@kbn/securitysolution-io-ts-alerting-types/*": ["x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/*"], + "@kbn/securitysolution-io-ts-list-types": ["x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types"], + "@kbn/securitysolution-io-ts-list-types/*": ["x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/*"], + "@kbn/securitysolution-io-ts-types": ["src/platform/packages/shared/kbn-securitysolution-io-ts-types"], + "@kbn/securitysolution-io-ts-types/*": ["src/platform/packages/shared/kbn-securitysolution-io-ts-types/*"], + "@kbn/securitysolution-io-ts-utils": ["src/platform/packages/shared/kbn-securitysolution-io-ts-utils"], + "@kbn/securitysolution-io-ts-utils/*": ["src/platform/packages/shared/kbn-securitysolution-io-ts-utils/*"], + "@kbn/securitysolution-list-api": ["x-pack/solutions/security/packages/kbn-securitysolution-list-api"], + "@kbn/securitysolution-list-api/*": ["x-pack/solutions/security/packages/kbn-securitysolution-list-api/*"], + "@kbn/securitysolution-list-constants": ["x-pack/solutions/security/packages/kbn-securitysolution-list-constants"], + "@kbn/securitysolution-list-constants/*": ["x-pack/solutions/security/packages/kbn-securitysolution-list-constants/*"], + "@kbn/securitysolution-list-hooks": ["x-pack/solutions/security/packages/kbn-securitysolution-list-hooks"], + "@kbn/securitysolution-list-hooks/*": ["x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/*"], + "@kbn/securitysolution-list-utils": ["x-pack/solutions/security/packages/kbn-securitysolution-list-utils"], + "@kbn/securitysolution-list-utils/*": ["x-pack/solutions/security/packages/kbn-securitysolution-list-utils/*"], + "@kbn/securitysolution-lists-common": ["x-pack/solutions/security/packages/kbn-securitysolution-lists-common"], + "@kbn/securitysolution-lists-common/*": ["x-pack/solutions/security/packages/kbn-securitysolution-lists-common/*"], + "@kbn/securitysolution-rules": ["src/platform/packages/shared/kbn-securitysolution-rules"], + "@kbn/securitysolution-rules/*": ["src/platform/packages/shared/kbn-securitysolution-rules/*"], + "@kbn/securitysolution-t-grid": ["x-pack/solutions/security/packages/kbn-securitysolution-t-grid"], + "@kbn/securitysolution-t-grid/*": ["x-pack/solutions/security/packages/kbn-securitysolution-t-grid/*"], + "@kbn/securitysolution-utils": ["x-pack/solutions/security/packages/kbn-securitysolution-utils"], + "@kbn/securitysolution-utils/*": ["x-pack/solutions/security/packages/kbn-securitysolution-utils/*"], "@kbn/server-http-tools": ["packages/kbn-server-http-tools"], "@kbn/server-http-tools/*": ["packages/kbn-server-http-tools/*"], "@kbn/server-route-repository": ["src/platform/packages/shared/kbn-server-route-repository"], diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index a4482fdb8c4a9..dca0f526a8239 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -75,7 +75,7 @@ "xpack.licenseApiGuard": "platform/plugins/private/license_api_guard", "xpack.licenseMgmt": "platform/plugins/shared/license_management", "xpack.licensing": "plugins/licensing", - "xpack.lists": "plugins/lists", + "xpack.lists": "solutions/security/plugins/lists", "xpack.logstash": [ "plugins/logstash" ], diff --git a/x-pack/plugins/lists/jest.config.js b/x-pack/plugins/lists/jest.config.js deleted file mode 100644 index cb9832920183f..0000000000000 --- a/x-pack/plugins/lists/jest.config.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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. - */ - -module.exports = { - collectCoverageFrom: ['/x-pack/plugins/lists/{common,public,server}/**/*.{ts,tsx}'], - coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/lists', - coverageReporters: ['text', 'html'], - preset: '@kbn/test', - rootDir: '../../..', - roots: ['/x-pack/plugins/lists'], -}; diff --git a/x-pack/plugins/lists/tsconfig.json b/x-pack/plugins/lists/tsconfig.json deleted file mode 100644 index 61229d39bdbdd..0000000000000 --- a/x-pack/plugins/lists/tsconfig.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types" - }, - "include": [ - "common/**/*", - "public/**/*", - "server/**/*", - // have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636 - "server/**/*.json" - ], - "kbn_references": [ - "@kbn/core", - "@kbn/spaces-plugin", - "@kbn/security-plugin", - "@kbn/unified-search-plugin", - "@kbn/securitysolution-io-ts-list-types", - "@kbn/securitysolution-list-constants", - "@kbn/securitysolution-list-hooks", - "@kbn/securitysolution-list-api", - "@kbn/securitysolution-lists-common", - "@kbn/securitysolution-exceptions-common", - "@kbn/securitysolution-endpoint-exceptions-common", - "@kbn/kibana-react-plugin", - "@kbn/i18n", - "@kbn/data-plugin", - "@kbn/securitysolution-list-utils", - "@kbn/securitysolution-utils", - "@kbn/es-query", - "@kbn/i18n-react", - "@kbn/securitysolution-autocomplete", - "@kbn/config-schema", - "@kbn/securitysolution-io-ts-utils", - "@kbn/core-http-server", - "@kbn/securitysolution-es-utils", - "@kbn/securitysolution-io-ts-types", - "@kbn/std", - "@kbn/utils", - "@kbn/logging-mocks", - "@kbn/utility-types", - "@kbn/core-elasticsearch-client-server-mocks", - "@kbn/core-saved-objects-server", - "@kbn/zod-helpers", - "@kbn/core-security-server", - "@kbn/core-http-server-mocks", - "@kbn/core-http-server-utils" - ], - "exclude": ["target/**/*"] -} diff --git a/packages/kbn-securitysolution-autocomplete/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/README.md similarity index 100% rename from packages/kbn-securitysolution-autocomplete/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/index.ts new file mode 100644 index 0000000000000..f3768e8cd37f7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +export * from './src/check_empty_value'; +export * from './src/es_field_selector'; +export * from './src/field_value_exists'; +export * from './src/field_value_lists'; +export * from './src/field_value_match'; +export * from './src/field_value_match_any'; +export * from './src/field_value_wildcard'; +export * from './src/filter_field_to_list'; +export * from './src/get_generic_combo_box_props'; +export * from './src/get_operators'; +export * from './src/hooks'; +export * from './src/operator'; +export * from './src/param_is_valid'; +export * from './src/param_contains_space'; + +export { default as autoCompletei18n } from './src/translations'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/jest.config.js new file mode 100644 index 0000000000000..7384086c58710 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete'], +}; diff --git a/packages/kbn-securitysolution-autocomplete/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-autocomplete/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/package.json new file mode 100644 index 0000000000000..fcce028035c42 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/securitysolution-autocomplete", + "version": "1.0.0", + "description": "Security Solution auto complete", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/autocomplete/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/autocomplete/index.mock.ts new file mode 100644 index 0000000000000..2372ad727e9f1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/autocomplete/index.mock.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +// Copied from "src/plugins/data/public/mocks.ts" but without any type information +// TODO: Remove this in favor of the data/public/mocks if/when they become available, https://github.com/elastic/kibana/issues/100715 +export const autocompleteStartMock = { + getQuerySuggestions: jest.fn(), + getValueSuggestions: jest.fn(), + hasQuerySuggestions: jest.fn(), +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.test.ts new file mode 100644 index 0000000000000..4f99799bb468e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.test.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import { checkEmptyValue } from '.'; +import { getField } from '../fields/index.mock'; +import * as i18n from '../translations'; + +describe('check_empty_value', () => { + test('returns no errors if no field has been selected', () => { + const isValid = checkEmptyValue('', undefined, true, false); + + expect(isValid).toBeUndefined(); + }); + + test('returns error string if user has touched a required input and left empty', () => { + const isValid = checkEmptyValue(undefined, getField('@timestamp'), true, true); + + expect(isValid).toEqual(i18n.FIELD_REQUIRED_ERR); + }); + + test('returns no errors if required input is empty but user has not yet touched it', () => { + const isValid = checkEmptyValue(undefined, getField('@timestamp'), true, false); + + expect(isValid).toBeUndefined(); + }); + + test('returns no errors if user has touched an input that is not required and left empty', () => { + const isValid = checkEmptyValue(undefined, getField('@timestamp'), false, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns no errors if user has touched an input that is not required and left empty string', () => { + const isValid = checkEmptyValue('', getField('@timestamp'), false, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns null if input value is not empty string or undefined', () => { + const isValid = checkEmptyValue('hellooo', getField('@timestamp'), false, true); + + expect(isValid).toBeNull(); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.ts new file mode 100644 index 0000000000000..285c91842f2fe --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/check_empty_value/index.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +import { DataViewFieldBase } from '@kbn/es-query'; +import * as i18n from '../translations'; + +/** + * Determines if empty value is ok + */ +export const checkEmptyValue = ( + param: string | undefined, + field: DataViewFieldBase | undefined, + isRequired: boolean, + touched: boolean +): string | undefined | null => { + if (isRequired && touched && (param == null || param.trim() === '')) { + return i18n.FIELD_REQUIRED_ERR; + } + + if ( + field == null || + (isRequired && !touched) || + (!isRequired && (param == null || param === '')) + ) { + return undefined; + } + + return null; +}; diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/__snapshots__/index.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/__snapshots__/index.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/__snapshots__/index.test.tsx.snap diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/disabled_types_with_tooltip_text.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/disabled_types_with_tooltip_text.test.ts new file mode 100644 index 0000000000000..743ba33fbbe53 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/disabled_types_with_tooltip_text.test.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import { disabledTypesWithTooltipText } from '../disabled_types_with_tooltip_text'; + +jest.mock('../../translations', () => ({ + BINARY_TYPE_NOT_SUPPORTED: 'Binary fields are currently unsupported', +})); +describe('disabledTypesWithTooltipText', () => { + it('should return Binary fields are currently unsupported for binary type', () => { + const type = 'binary'; + expect(disabledTypesWithTooltipText[type]).toEqual('Binary fields are currently unsupported'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/index.test.tsx new file mode 100644 index 0000000000000..10db3fcce5f52 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/index.test.tsx @@ -0,0 +1,142 @@ +/* + * 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. + */ + +import React from 'react'; +import { fireEvent, render, waitFor, within } from '@testing-library/react'; +import '@testing-library/jest-dom'; + +import { EsFieldSelector } from '..'; +import { fields, getField } from '../../fields/index.mock'; + +describe('FieldComponent', () => { + it('should render the component enabled and displays the selected field correctly', () => { + const wrapper = render( + + ); + expect(wrapper.container).toMatchSnapshot(); + const comboBox = wrapper.getByTestId('fieldAutocompleteComboBox'); + const input = within(comboBox).getByRole('combobox'); + expect(input).toHaveAttribute('value', 'machine.os.raw'); + }); + it('should render the component disabled if isDisabled is true', () => { + const wrapper = render( + + ); + expect(wrapper.container).toMatchSnapshot(); + expect(wrapper.getByTestId('fieldAutocompleteComboBox').querySelector('input')).toBeDisabled(); + }); + it('should render the loading spinner if isLoading is true when clicked', () => { + const wrapper = render( + + ); + const fieldAutocompleteComboBox = wrapper.getByTestId('fieldAutocompleteComboBox'); + expect(wrapper.container).toMatchSnapshot(); + fireEvent.click(fieldAutocompleteComboBox); + expect(wrapper.getByRole('progressbar')).toBeInTheDocument(); + }); + it('should allow user to clear values if isClearable is true', () => { + const wrapper = render( + + ); + expect(wrapper.container).toMatchSnapshot(); + expect(wrapper.getByTestId('comboBoxClearButton')).toBeInTheDocument(); + }); + it('should change the selected value', async () => { + const wrapper = render( + + ); + const fieldAutocompleteComboBox = wrapper.getByTestId('comboBoxSearchInput'); + fireEvent.change(fieldAutocompleteComboBox, { target: { value: '_source' } }); + expect(fieldAutocompleteComboBox).toHaveValue('_source'); + }); + + it('it allows custom user input if "acceptsCustomOptions" is "true"', async () => { + const mockOnChange = jest.fn(); + const wrapper = render( + + ); + + const fieldAutocompleteComboBox = wrapper.getByTestId('comboBoxSearchInput'); + fireEvent.change(fieldAutocompleteComboBox, { target: { value: 'custom' } }); + await waitFor(() => + expect(wrapper.getByTestId('fieldAutocompleteComboBox')).toHaveTextContent('custom') + ); + }); +}); diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/use_es_field.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/use_es_field.test.ts similarity index 97% rename from packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/use_es_field.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/use_es_field.test.ts index 942ccbc29c38e..1fb07e21fc915 100644 --- a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/use_es_field.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/__tests__/use_es_field.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { DataViewFieldBase } from '@kbn/es-query'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/disabled_types_with_tooltip_text.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/disabled_types_with_tooltip_text.ts new file mode 100644 index 0000000000000..5b24ecb736054 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/disabled_types_with_tooltip_text.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +interface DisabledTypesTextType { + [typeName: string]: string; +} +import * as i18n from '../translations'; + +export const disabledTypesWithTooltipText: DisabledTypesTextType = { + binary: i18n.BINARY_TYPE_NOT_SUPPORTED, +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/index.tsx new file mode 100644 index 0000000000000..8ce7e7ed5507d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/index.tsx @@ -0,0 +1,107 @@ +/* + * 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. + */ + +import React from 'react'; +import { EuiComboBox } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { FieldBaseProps } from './types'; +import { useEsField } from './use_es_field'; + +const AS_PLAIN_TEXT = { asPlainText: true }; + +interface EsFieldSelectorProps extends FieldBaseProps { + isClearable?: boolean; + isDisabled?: boolean; + isLoading?: boolean; + placeholder: string; + acceptsCustomOptions?: boolean; + showMappingConflicts?: boolean; + 'aria-label'?: string; +} + +export function EsFieldSelector({ + fieldInputWidth, + fieldTypeFilter = [], + indexPattern, + isClearable = false, + isDisabled = false, + isLoading = false, + isRequired = false, + onChange, + placeholder, + selectedField, + acceptsCustomOptions = false, + showMappingConflicts = false, + 'aria-label': ariaLabel, +}: EsFieldSelectorProps): JSX.Element { + const { + isInvalid, + comboOptions, + selectedComboOptions, + fieldWidth, + renderFields, + handleTouch, + handleValuesChange, + handleCreateCustomOption, + } = useEsField({ + indexPattern, + fieldTypeFilter, + isRequired, + selectedField, + fieldInputWidth, + showMappingConflicts, + onChange, + }); + + if (acceptsCustomOptions) { + return ( + + ); + } + + return ( + + ); +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/types.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/types.ts new file mode 100644 index 0000000000000..e300df89e1c3c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/types.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; +import { FieldConflictsInfo } from '@kbn/securitysolution-list-utils'; +import { GetGenericComboBoxPropsReturn } from '../get_generic_combo_box_props'; + +export interface FieldBaseProps { + indexPattern: DataViewBase | undefined; + fieldTypeFilter?: string[]; + isRequired?: boolean; + selectedField?: DataViewFieldBase | undefined; + fieldInputWidth?: number; + showMappingConflicts?: boolean; + onChange: (a: DataViewFieldBase[]) => void; +} + +export interface ComboBoxFields { + availableFields: DataViewField[]; + selectedFields: DataViewField[]; +} + +export interface GetFieldComboBoxPropsReturn extends GetGenericComboBoxPropsReturn { + disabledLabelTooltipTexts: { [label: string]: string }; + mappingConflictsTooltipInfo: { [label: string]: FieldConflictsInfo[] }; +} + +export interface DataViewField extends DataViewFieldBase { + esTypes?: string[]; +} diff --git a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/use_es_field.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/use_es_field.tsx similarity index 94% rename from packages/kbn-securitysolution-autocomplete/src/es_field_selector/use_es_field.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/use_es_field.tsx index 615571d989607..1d6b84618af3e 100644 --- a/packages/kbn-securitysolution-autocomplete/src/es_field_selector/use_es_field.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/es_field_selector/use_es_field.tsx @@ -1,14 +1,11 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ -import React from 'react'; -import { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { EuiComboBoxOptionOption, EuiIcon, diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.test.tsx new file mode 100644 index 0000000000000..9fc10f6ba3bc1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.test.tsx @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { AutocompleteFieldExistsComponent } from '.'; + +describe('AutocompleteFieldExistsComponent', () => { + test('it renders field disabled', () => { + const wrapper = mount(); + + expect( + wrapper + .find(`[data-test-subj="valuesAutocompleteComboBox existsComboxBox"] input`) + .prop('disabled') + ).toBeTruthy(); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.tsx new file mode 100644 index 0000000000000..ccd27f559e124 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_exists/index.tsx @@ -0,0 +1,38 @@ +/* + * 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. + */ + +import React from 'react'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; + +const NO_OPTIONS_FOR_EXIST: EuiComboBoxOptionOption[] = []; + +interface AutocompleteFieldExistsProps { + placeholder: string; + rowLabel?: string; + 'aria-label'?: string; +} + +export const AutocompleteFieldExistsComponent: React.FC = ({ + placeholder, + rowLabel, + 'aria-label': ariaLabel, +}): JSX.Element => ( + + + +); + +AutocompleteFieldExistsComponent.displayName = 'AutocompleteFieldExists'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx new file mode 100644 index 0000000000000..30323eba26855 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx @@ -0,0 +1,268 @@ +/* + * 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. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import { waitFor } from '@testing-library/react'; +import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { getField } from '../fields/index.mock'; +import { AutocompleteFieldListsComponent } from '.'; +import { + getListResponseMock, + getFoundListsBySizeSchemaMock, + DATE_NOW, + IMMUTABLE, + VERSION, +} from '../list_schema/index.mock'; + +// TODO: Once these mocks are available, use them instead of hand mocking, https://github.com/elastic/kibana/issues/100715 +// const mockKibanaHttpService = coreMock.createStart().http; +// import { coreMock } from '../../../../../../../../../../src/core/public/mocks'; +const mockKibanaHttpService = jest.fn(); +const mockShowValueListModal = jest.fn(); +const MockedShowValueListModal = (props: unknown) => { + mockShowValueListModal(props); + return <>; +}; +const mockStart = jest.fn(); +const mockKeywordList: ListSchema = { + ...getListResponseMock(), + id: 'keyword_list', + name: 'keyword list', + type: 'keyword', +}; +const mockResult = { ...getFoundListsBySizeSchemaMock() }; +mockResult.smallLists = [...mockResult.smallLists, mockKeywordList]; +mockResult.largeLists = []; +jest.mock('@kbn/securitysolution-list-hooks', () => { + const originalModule = jest.requireActual('@kbn/securitysolution-list-hooks'); + + return { + ...originalModule, + useFindListsBySize: () => ({ + error: undefined, + loading: false, + result: mockResult, + start: mockStart.mockReturnValue(mockResult), + }), + }; +}); + +describe('AutocompleteFieldListsComponent', () => { + test('it renders disabled if "isDisabled" is true', async () => { + const wrapper = mount( + + ); + + expect( + wrapper + .find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] input`) + .prop('disabled') + ).toBeTruthy(); + }); + + test('it renders loading if "isLoading" is true', async () => { + const wrapper = mount( + + ); + + wrapper + .find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] button`) + .at(0) + .simulate('click'); + expect( + wrapper + .find( + `EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteComboBox listsComboxBox-optionsList"]` + ) + .prop('isLoading') + ).toBeTruthy(); + }); + + test('it allows user to clear values if "isClearable" is true', async () => { + const wrapper = mount( + + ); + expect( + wrapper + .find('EuiComboBox[data-test-subj="valuesAutocompleteComboBox listsComboxBox"]') + .prop('options') + ).toEqual([{ label: 'some name', disabled: false }]); + }); + + test('it correctly displays lists that match the selected "keyword" field esType', () => { + const wrapper = mount( + + ); + + wrapper.find('[data-test-subj="comboBoxToggleListButton"] button').simulate('click'); + + expect( + wrapper + .find('EuiComboBox[data-test-subj="valuesAutocompleteComboBox listsComboxBox"]') + .prop('options') + ).toEqual([{ label: 'keyword list', disabled: false }]); + }); + + test('it correctly displays lists that match the selected "ip" field esType', () => { + const wrapper = mount( + + ); + + wrapper.find('[data-test-subj="comboBoxToggleListButton"] button').simulate('click'); + + expect( + wrapper + .find('EuiComboBox[data-test-subj="valuesAutocompleteComboBox listsComboxBox"]') + .prop('options') + ).toEqual([{ label: 'some name', disabled: false }]); + }); + + test('it correctly displays selected list', async () => { + const wrapper = mount( + + ); + + expect( + wrapper + .find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] input`) + .at(0) + .props().value + ).toEqual('some name'); + }); + + test('it invokes "onChange" when option selected', async () => { + const mockOnChange = jest.fn(); + const wrapper = mount( + + ); + + ( + wrapper.find(EuiComboBox).props() as unknown as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + } + ).onChange([{ label: 'some name', disabled: false }]); + + await waitFor(() => { + expect(mockOnChange).toHaveBeenCalledWith({ + '@timestamp': DATE_NOW, + _version: undefined, + created_at: DATE_NOW, + created_by: 'some user', + description: 'some description', + deserializer: undefined, + id: 'some-list-id', + immutable: IMMUTABLE, + meta: {}, + name: 'some name', + serializer: undefined, + tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e', + type: 'ip', + updated_at: DATE_NOW, + updated_by: 'some user', + version: VERSION, + }); + }); + }); + + test('it render the value list modal', async () => { + mockShowValueListModal.mockReset(); + mount( + + ); + + expect(mockShowValueListModal).toHaveBeenCalledWith( + expect.objectContaining({ + children: 'Show value list', + listId: 'some-list-id', + shouldShowContentIfModalNotAvailable: false, + }) + ); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx new file mode 100644 index 0000000000000..480791b001c5f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx @@ -0,0 +1,182 @@ +/* + * 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. + */ + +import React, { ElementType, useCallback, useEffect, useMemo, useState } from 'react'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow, EuiLink, EuiText } from '@elastic/eui'; +import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { useFindListsBySize } from '@kbn/securitysolution-list-hooks'; +import { DataViewFieldBase } from '@kbn/es-query'; +import { getDocLinks } from '@kbn/doc-links'; + +import { filterFieldToList } from '../filter_field_to_list'; +import { getGenericComboBoxProps } from '../get_generic_combo_box_props'; + +// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 +// import { HttpStart } from '@kbn/core/public'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type HttpStart = any; + +import * as i18n from '../translations'; + +const SINGLE_SELECTION = { asPlainText: true }; + +interface AutocompleteFieldListsProps { + httpService: HttpStart; + isClearable: boolean; + isDisabled: boolean; + isLoading: boolean; + onChange: (arg: ListSchema) => void; + placeholder: string; + rowLabel?: string; + selectedField: DataViewFieldBase | undefined; + selectedValue: string | undefined; + allowLargeValueLists?: boolean; + 'aria-label'?: string; + showValueListModal: ElementType; +} + +export interface AutocompleteListsData { + smallLists: ListSchema[]; + largeLists: ListSchema[]; +} + +export const AutocompleteFieldListsComponent: React.FC = ({ + httpService, + isClearable = false, + isDisabled = false, + isLoading = false, + onChange, + placeholder, + rowLabel, + selectedField, + selectedValue, + allowLargeValueLists = false, + 'aria-label': ariaLabel, + showValueListModal, +}): JSX.Element => { + const [error, setError] = useState(undefined); + const [listData, setListData] = useState({ + smallLists: [], + largeLists: [], + }); + const { loading, result, start } = useFindListsBySize(); + const getLabel = useCallback(({ name }: ListSchema) => name, []); + + const optionsMemo = useMemo( + () => filterFieldToList(listData, selectedField), + [listData, selectedField] + ); + const selectedOptionsMemo = useMemo(() => { + if (selectedValue != null) { + const combinedLists = [...listData.smallLists, ...listData.largeLists]; + const list = combinedLists.filter(({ id }) => id === selectedValue); + return list ?? []; + } else { + return []; + } + }, [selectedValue, listData]); + const { comboOptions, labels, selectedComboOptions } = useMemo( + () => + getGenericComboBoxProps({ + getLabel, + options: [...optionsMemo.smallLists, ...optionsMemo.largeLists], + selectedOptions: selectedOptionsMemo, + disabledOptions: allowLargeValueLists ? undefined : optionsMemo.largeLists, // Disable large lists if the rule type doesn't allow it + }), + [optionsMemo, selectedOptionsMemo, getLabel, allowLargeValueLists] + ); + + const handleValuesChange = useCallback( + (newOptions: EuiComboBoxOptionOption[]) => { + const combinedLists = [...optionsMemo.smallLists, ...optionsMemo.largeLists]; + const [newValue] = newOptions.map(({ label }) => combinedLists[labels.indexOf(label)]); + onChange(newValue ?? ''); + }, + [labels, optionsMemo, onChange] + ); + + const setIsTouchedValue = useCallback((): void => { + setError(selectedValue == null ? i18n.FIELD_REQUIRED_ERR : undefined); + }, [selectedValue]); + + useEffect(() => { + if (result != null) { + setListData(result); + } + }, [result]); + + useEffect(() => { + if (selectedField != null && httpService != null) { + start({ + http: httpService, + pageIndex: 1, + pageSize: 500, + }); + } + }, [selectedField, start, httpService]); + + const isLoadingState = useMemo((): boolean => isLoading || loading, [isLoading, loading]); + const ShowValueListModal = showValueListModal; + + const helpText = useMemo(() => { + return ( + <> + {selectedValue && ( + + {i18n.SHOW_VALUE_LIST_MODAL} + + )} + {!allowLargeValueLists && ( + + {i18n.LISTS_TOOLTIP_INFO}{' '} + + {i18n.SEE_DOCUMENTATION} + + + )} + + ); + }, [allowLargeValueLists, selectedValue, ShowValueListModal]); + return ( + + + + ); +}; + +AutocompleteFieldListsComponent.displayName = 'AutocompleteFieldList'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx new file mode 100644 index 0000000000000..8ca17a78764cc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx @@ -0,0 +1,629 @@ +/* + * 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. + */ + +import React from 'react'; +import { ReactWrapper, mount } from 'enzyme'; +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFormHelpText, + EuiSuperSelect, +} from '@elastic/eui'; +import { act, waitFor } from '@testing-library/react'; +import { AutocompleteFieldMatchComponent } from '.'; +import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; +import { fields, getField } from '../fields/index.mock'; +import { autocompleteStartMock } from '../autocomplete/index.mock'; + +jest.mock('../hooks/use_field_value_autocomplete'); +jest.mock('../translations', () => ({ + FIELD_SPACE_WARNING: 'Warning: there is a space', +})); +describe('AutocompleteFieldMatchComponent', () => { + let wrapper: ReactWrapper; + + const getValueSuggestionsMock = jest + .fn() + .mockResolvedValue([false, true, ['value 3', 'value 4'], jest.fn()]); + + const findEuiComboBox = () => + wrapper.find(EuiComboBox).props() as unknown as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + onSearchChange: (a: string) => void; + onCreateOption: (a: string) => void; + }; + + beforeEach(() => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + true, + ['value 1', 'value 2'], + getValueSuggestionsMock, + ]); + }); + + afterEach(() => { + jest.clearAllMocks(); + wrapper.unmount(); + }); + + test('it renders row label if one passed in', () => { + wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="valuesAutocompleteMatchLabel"] label').at(0).text() + ).toEqual('Row Label'); + }); + + test('it renders disabled if "isDisabled" is true', () => { + wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="valuesAutocompleteMatch"] input').prop('disabled') + ).toBeTruthy(); + }); + + test('it renders loading if "isLoading" is true', () => { + wrapper = mount( + + ); + wrapper.find('[data-test-subj="valuesAutocompleteMatch"] button').at(0).simulate('click'); + expect( + wrapper + .find('EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteMatch-optionsList"]') + .prop('isLoading') + ).toBeTruthy(); + }); + + test('it allows user to clear values if "isClearable" is true', () => { + wrapper = mount( + + ); + + expect(wrapper.find(`[data-test-subj="comboBoxClearButton"]`)).toBeTruthy(); + }); + + test('it correctly displays selected value', () => { + wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="valuesAutocompleteMatch"] input').at(0).props().value + ).toEqual('127.0.0.1'); + }); + + test('it invokes "onChange" when new value created', () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + findEuiComboBox().onCreateOption('127.0.0.1'); + + expect(mockOnChange).toHaveBeenCalledWith('127.0.0.1'); + }); + + test('it invokes "onChange" when new value selected', () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + findEuiComboBox().onChange([{ label: 'value 1' }]); + + expect(mockOnChange).toHaveBeenCalledWith('value 1'); + }); + + test('it invokes "onChange" with empty value (i.e. clears selection) when new value searched', () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + act(() => { + findEuiComboBox().onSearchChange('value 12'); + }); + + expect(mockOnChange).toHaveBeenCalledWith(''); + }); + + test('should show the warning helper text if the new value contains spaces when change', async () => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + true, + [' value 1 ', 'value 2'], + getValueSuggestionsMock, + ]); + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + await waitFor(() => findEuiComboBox().onChange([{ label: ' value 1 ' }])); + wrapper.update(); + expect(mockOnChange).toHaveBeenCalledWith(' value 1 '); + + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + }); + + test('it refreshes autocomplete with search query when new value searched', () => { + wrapper = mount( + + ); + act(() => { + findEuiComboBox().onSearchChange('value 1'); + }); + + expect(useFieldValueAutocomplete).toHaveBeenCalledWith({ + autocompleteService: autocompleteStartMock, + fieldValue: '', + indexPattern: { + fields, + id: '1234', + title: 'logstash-*', + }, + operatorType: 'match', + query: 'value 1', + selectedField: getField('machine.os.raw'), + }); + }); + + test('it refreshes autocomplete with search query when input field is cleared', () => { + wrapper = mount( + + ); + + act(() => { + findEuiComboBox().onSearchChange('value 1'); + }); + act(() => { + findEuiComboBox().onSearchChange(''); + }); + + // 1st call is initial render, 2nd call sets the search query: + expect(useFieldValueAutocomplete).toHaveBeenNthCalledWith(2, { + autocompleteService: autocompleteStartMock, + fieldValue: 'windows', + indexPattern: { fields, id: '1234', title: 'logstash-*' }, + operatorType: 'match', + query: 'value 1', + selectedField: getField('machine.os.raw'), + }); + // last call is the refresh when input field is cleared + expect(useFieldValueAutocomplete).toHaveBeenLastCalledWith({ + autocompleteService: autocompleteStartMock, + fieldValue: 'windows', + indexPattern: { fields, id: '1234', title: 'logstash-*' }, + operatorType: 'match', + query: '', + selectedField: getField('machine.os.raw'), + }); + }); + + test('should show the warning helper text if the new value contains spaces when searching a new query', () => { + wrapper = mount( + + ); + act(() => { + findEuiComboBox().onSearchChange(' value 1'); + }); + + wrapper.update(); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); + }); + + test('should show the warning helper text if selectedValue contains spaces when editing', () => { + wrapper = mount( + + ); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); + }); + + test('should not show the warning helper text if selectedValue is falsy', () => { + wrapper = mount( + + ); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeFalsy(); + }); + + describe('boolean type', () => { + const valueSuggestionsMock = jest.fn().mockResolvedValue([false, false, [], jest.fn()]); + + beforeEach(() => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + false, + [], + valueSuggestionsMock, + ]); + }); + + test('it displays only two options - "true" or "false"', () => { + wrapper = mount( + + ); + expect( + wrapper.find('[data-test-subj="valuesAutocompleteMatchBoolean"]').exists() + ).toBeTruthy(); + expect( + wrapper.find('[data-test-subj="valuesAutocompleteMatchBoolean"]').at(0).prop('options') + ).toEqual([ + { + inputDisplay: 'true', + value: 'true', + }, + { + inputDisplay: 'false', + value: 'false', + }, + ]); + }); + + test('it invokes "onChange" with "true" when selected', () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + ( + wrapper.find(EuiSuperSelect).props() as unknown as { + onChange: (a: string) => void; + } + ).onChange('true'); + + expect(mockOnChange).toHaveBeenCalledWith('true'); + }); + + test('it invokes "onChange" with "false" when selected', () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + ( + wrapper.find(EuiSuperSelect).props() as unknown as { + onChange: (a: string) => void; + } + ).onChange('false'); + + expect(mockOnChange).toHaveBeenCalledWith('false'); + }); + }); + + describe('number type', () => { + const valueSuggestionsMock = jest.fn().mockResolvedValue([false, false, [], jest.fn()]); + + beforeEach(() => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + false, + [], + valueSuggestionsMock, + ]); + }); + + test('it number input when field type is number', () => { + wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="valueAutocompleteFieldMatchNumber"]').exists() + ).toBeTruthy(); + }); + + test('it invokes "onChange" with numeric value when inputted', () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + wrapper + .find('[data-test-subj="valueAutocompleteFieldMatchNumber"] input') + .at(0) + .simulate('change', { target: { value: '8' } }); + + expect(mockOnChange).toHaveBeenCalledWith('8'); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx new file mode 100644 index 0000000000000..a938ad2f7a991 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx @@ -0,0 +1,376 @@ +/* + * 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. + */ + +import React, { useCallback, useMemo, useState, useEffect } from 'react'; +import { + EuiSuperSelect, + EuiFormRow, + EuiFieldNumber, + EuiComboBoxOptionOption, + EuiComboBox, +} from '@elastic/eui'; +import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; + +import { uniq } from 'lodash'; + +import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; + +// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 +// import { AutocompleteStart } from '../../../../../../../../../../src/plugins/unified_search/public'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type AutocompleteStart = any; + +import * as i18n from '../translations'; +import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; +import { + getGenericComboBoxProps, + GetGenericComboBoxPropsReturn, +} from '../get_generic_combo_box_props'; +import { paramIsValid } from '../param_is_valid'; +import { paramContainsSpace } from '../param_contains_space'; + +const BOOLEAN_OPTIONS = [ + { inputDisplay: 'true', value: 'true' }, + { inputDisplay: 'false', value: 'false' }, +]; + +const SINGLE_SELECTION = { asPlainText: true }; + +type Warning = string | React.ReactNode; + +interface AutocompleteFieldMatchProps { + placeholder: string; + selectedField: DataViewFieldBase | undefined; + selectedValue: string | undefined; + indexPattern: DataViewBase | undefined; + isLoading?: boolean; + isDisabled?: boolean; + isClearable?: boolean; + isRequired?: boolean; + fieldInputWidth?: number; + rowLabel?: string; + autocompleteService: AutocompleteStart; + onChange: (arg: string) => void; + onError?: (arg: boolean) => void; + onWarning?: (arg: boolean) => void; + warning?: Warning; + 'aria-label'?: string; +} + +export const AutocompleteFieldMatchComponent: React.FC = ({ + placeholder, + rowLabel, + selectedField, + selectedValue, + indexPattern, + isLoading = false, + isDisabled = false, + isClearable = false, + isRequired = false, + fieldInputWidth, + autocompleteService, + onChange, + onError, + onWarning, + warning, + 'aria-label': ariaLabel, +}): JSX.Element => { + const [searchQuery, setSearchQuery] = useState(''); + const [touched, setIsTouched] = useState(false); + const [error, setError] = useState(undefined); + const [showSpacesWarning, setShowSpacesWarning] = useState(false); + const [isLoadingSuggestions, isSuggestingValues, suggestions] = useFieldValueAutocomplete({ + autocompleteService, + fieldValue: selectedValue, + indexPattern, + operatorType: OperatorTypeEnum.MATCH, + query: searchQuery, + selectedField, + }); + const getLabel = useCallback((option: string): string => option, []); + + const optionsMemo = useMemo((): string[] => { + const valueAsStr = String(selectedValue); + return selectedValue != null && selectedValue.trim() !== '' + ? uniq([valueAsStr, ...suggestions]) + : suggestions; + }, [suggestions, selectedValue]); + + const selectedOptionsMemo = useMemo((): string[] => { + const valueAsStr = String(selectedValue); + return selectedValue ? [valueAsStr] : []; + }, [selectedValue]); + + const handleSpacesWarning = useCallback( + (param: string | undefined) => { + if (!param) return setShowSpacesWarning(false); + setShowSpacesWarning(!!paramContainsSpace(param)); + }, + [setShowSpacesWarning] + ); + + const handleError = useCallback( + (err: string | undefined): void => { + setError((existingErr): string | undefined => { + const oldErr = existingErr != null; + const newErr = err != null; + if (oldErr !== newErr && onError != null) { + onError(newErr); + } + + return err; + }); + }, + [setError, onError] + ); + + const handleWarning = useCallback( + (warn: Warning | undefined): void => { + if (onWarning) { + onWarning(warn !== undefined); + } + }, + [onWarning] + ); + + const { comboOptions, labels, selectedComboOptions } = useMemo( + (): GetGenericComboBoxPropsReturn => + getGenericComboBoxProps({ + getLabel, + options: optionsMemo, + selectedOptions: selectedOptionsMemo, + }), + [optionsMemo, selectedOptionsMemo, getLabel] + ); + + const handleValuesChange = useCallback( + (newOptions: EuiComboBoxOptionOption[]): void => { + const [newValue] = newOptions.map(({ label }) => optionsMemo[labels.indexOf(label)]); + + handleSpacesWarning(newValue); + handleError(undefined); + handleWarning(undefined); + onChange(newValue ?? ''); + }, + [handleError, handleWarning, handleSpacesWarning, labels, onChange, optionsMemo] + ); + + const handleSearchChange = useCallback( + (searchVal: string): void => { + if (searchVal !== '' && selectedField != null) { + const err = paramIsValid(searchVal, selectedField, isRequired, touched); + handleError(err); + handleWarning(warning); + + if (!err) handleSpacesWarning(searchVal); + } + + if (searchVal) { + // Clear selected option when user types to allow user to modify value without {backspace} + onChange(''); + } + + // Update search query unconditionally to show correct suggestions even when input is cleared + setSearchQuery(searchVal); + }, + [ + selectedField, + onChange, + isRequired, + touched, + handleError, + handleWarning, + warning, + handleSpacesWarning, + ] + ); + + const handleCreateOption = useCallback( + (option: string): boolean | undefined => { + const err = paramIsValid(option, selectedField, isRequired, touched); + handleError(err); + handleWarning(warning); + + if (err != null) { + // Explicitly reject the user's input + setShowSpacesWarning(false); + return false; + } + + handleSpacesWarning(option); + onChange(option); + return undefined; + }, + [ + isRequired, + onChange, + selectedField, + touched, + handleError, + handleSpacesWarning, + handleWarning, + warning, + ] + ); + + const handleNonComboBoxInputChange = useCallback( + (event: React.ChangeEvent): void => { + const newValue = event.target.value; + onChange(newValue); + }, + [onChange] + ); + + const handleBooleanInputChange = useCallback( + (newOption: string): void => { + onChange(newOption); + }, + [onChange] + ); + + const setIsTouchedValue = useCallback((): void => { + setIsTouched(true); + + const err = paramIsValid(selectedValue, selectedField, isRequired, true); + handleError(err); + handleWarning(warning); + }, [setIsTouched, handleError, selectedValue, selectedField, isRequired, warning, handleWarning]); + + const inputPlaceholder = useMemo((): string => { + if (isLoading || isLoadingSuggestions) { + return i18n.LOADING; + } else if (selectedField == null) { + return i18n.SELECT_FIELD_FIRST; + } else { + return placeholder; + } + }, [isLoading, selectedField, isLoadingSuggestions, placeholder]); + + const isLoadingState = useMemo( + (): boolean => isLoading || isLoadingSuggestions, + [isLoading, isLoadingSuggestions] + ); + + useEffect((): void => { + setError(undefined); + if (onError != null) onError(false); + + handleSpacesWarning(selectedValue); + // Looks like selectedField return new object every time when we for example add "and" entry + // that's why we need to check for name and type here + // Probably we should use some kind of memoization on parent components for entries + }, [selectedField?.name, selectedField?.type, selectedValue, handleSpacesWarning, onError]); + + const defaultInput = useMemo((): JSX.Element => { + return ( + + + + ); + }, [ + rowLabel, + error, + selectedField, + showSpacesWarning, + inputPlaceholder, + isDisabled, + isLoadingState, + isClearable, + comboOptions, + selectedComboOptions, + handleValuesChange, + handleSearchChange, + handleCreateOption, + setIsTouchedValue, + warning, + fieldInputWidth, + ariaLabel, + ]); + + if (!isSuggestingValues && selectedField != null) { + switch (selectedField.type) { + case 'number': + return ( + + 0 + ? parseFloat(selectedValue) + : selectedValue ?? '' + } + onChange={handleNonComboBoxInputChange} + data-test-subj="valueAutocompleteFieldMatchNumber" + style={fieldInputWidth ? { width: `${fieldInputWidth}px` } : {}} + aria-label={ariaLabel} + fullWidth + /> + + ); + case 'boolean': + return ( + + + + ); + default: + return defaultInput; + } + } else { + return defaultInput; + } +}; + +AutocompleteFieldMatchComponent.displayName = 'AutocompleteFieldMatch'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx new file mode 100644 index 0000000000000..33355e2cb382b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx @@ -0,0 +1,398 @@ +/* + * 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. + */ + +import React from 'react'; +import { ReactWrapper, mount } from 'enzyme'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormHelpText } from '@elastic/eui'; +import { act, waitFor } from '@testing-library/react'; + +import { AutocompleteFieldMatchAnyComponent } from '.'; +import { getField, fields } from '../fields/index.mock'; +import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; +import { autocompleteStartMock } from '../autocomplete/index.mock'; + +jest.mock('../hooks/use_field_value_autocomplete', () => { + const actual = jest.requireActual('../hooks/use_field_value_autocomplete'); + return { + ...actual, + useFieldValueAutocomplete: jest.fn(), + }; +}); +jest.mock('../translations', () => ({ + FIELD_SPACE_WARNING: 'Warning: there is a space', +})); + +describe('AutocompleteFieldMatchAnyComponent', () => { + let wrapper: ReactWrapper; + const getValueSuggestionsMock = jest + .fn() + .mockResolvedValue([false, true, ['value 3', 'value 4'], jest.fn()]); + + beforeEach(() => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + true, + ['value 1', 'value 2'], + getValueSuggestionsMock, + ]); + }); + + afterEach(() => { + jest.clearAllMocks(); + wrapper.unmount(); + }); + + test('it renders disabled if "isDisabled" is true', () => { + wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="valuesAutocompleteMatchAny"] input`).prop('disabled') + ).toBeTruthy(); + }); + + test('it renders loading if "isLoading" is true', () => { + wrapper = mount( + + ); + wrapper.find(`[data-test-subj="valuesAutocompleteMatchAny"] button`).at(0).simulate('click'); + expect( + wrapper + .find(`EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteMatchAny-optionsList"]`) + .prop('isLoading') + ).toBeTruthy(); + }); + + test('it allows user to clear values if "isClearable" is true', () => { + wrapper = mount( + + ); + + expect(wrapper.find(`[data-test-subj="comboBoxClearButton"]`)).toBeTruthy(); + }); + + test('it correctly displays selected value', () => { + wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="valuesAutocompleteMatchAny"] EuiComboBoxPill`).at(0).text() + ).toEqual('127.0.0.1'); + }); + + test('it invokes "onChange" when new value created', async () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + ( + wrapper.find(EuiComboBox).props() as unknown as { + onCreateOption: (a: string) => void; + } + ).onCreateOption('127.0.0.1'); + + expect(mockOnChange).toHaveBeenCalledWith(['127.0.0.1']); + }); + + test('it invokes "onChange" when new value selected', async () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + ( + wrapper.find(EuiComboBox).props() as unknown as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + } + ).onChange([{ label: 'value 1' }]); + + expect(mockOnChange).toHaveBeenCalledWith(['value 1']); + }); + + test('it refreshes autocomplete with search query when new value searched', () => { + wrapper = mount( + + ); + act(() => { + ( + wrapper.find(EuiComboBox).props() as unknown as { + onSearchChange: (a: string) => void; + } + ).onSearchChange('value 1'); + }); + expect(useFieldValueAutocomplete).toHaveBeenCalledWith({ + autocompleteService: autocompleteStartMock, + fieldValue: [], + indexPattern: { + fields, + id: '1234', + title: 'logstash-*', + }, + operatorType: 'match_any', + query: 'value 1', + selectedField: getField('machine.os.raw'), + }); + }); + test('should show the warning helper text if the new value contains spaces when change', async () => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + true, + [' value 1 ', 'value 2'], + getValueSuggestionsMock, + ]); + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + await waitFor(() => + ( + wrapper.find(EuiComboBox).props() as unknown as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + } + ).onChange([{ label: ' value 1 ' }]) + ); + wrapper.update(); + expect(mockOnChange).toHaveBeenCalledWith([' value 1 ']); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + }); + test('should show the warning helper text if the new value contains spaces when searching a new query', () => { + wrapper = mount( + + ); + act(() => { + ( + wrapper.find(EuiComboBox).props() as unknown as { + onSearchChange: (a: string) => void; + } + ).onSearchChange(' value 1'); + }); + + wrapper.update(); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); + }); + test('should show the warning helper text if selectedValue contains spaces when editing', () => { + wrapper = mount( + + ); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); + }); + test('should not show the warning helper text if selectedValue is falsy', () => { + wrapper = mount( + + ); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeFalsy(); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx new file mode 100644 index 0000000000000..be7fac088ec1a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx @@ -0,0 +1,252 @@ +/* + * 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. + */ + +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; +import { uniq } from 'lodash'; +import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; + +// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 +// import { AutocompleteStart } from '../../../../../../../../../../src/plugins/unified_search/public'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type AutocompleteStart = any; + +import * as i18n from '../translations'; +import { + getGenericComboBoxProps, + GetGenericComboBoxPropsReturn, +} from '../get_generic_combo_box_props'; +import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; +import { paramIsValid } from '../param_is_valid'; +import { paramContainsSpace } from '../param_contains_space'; + +interface AutocompleteFieldMatchAnyProps { + placeholder: string; + selectedField: DataViewFieldBase | undefined; + selectedValue: string[]; + indexPattern: DataViewBase | undefined; + isLoading: boolean; + isDisabled: boolean; + isClearable: boolean; + isRequired?: boolean; + rowLabel?: string; + autocompleteService: AutocompleteStart; + onChange: (arg: string[]) => void; + onError?: (arg: boolean) => void; + 'aria-label'?: string; +} + +export const AutocompleteFieldMatchAnyComponent: React.FC = ({ + placeholder, + rowLabel, + selectedField, + selectedValue, + indexPattern, + isLoading, + isDisabled = false, + isClearable = false, + isRequired = false, + onChange, + onError, + autocompleteService, + 'aria-label': ariaLabel, +}): JSX.Element => { + const [searchQuery, setSearchQuery] = useState(''); + const [touched, setIsTouched] = useState(false); + const [error, setError] = useState(undefined); + const [showSpacesWarning, setShowSpacesWarning] = useState(false); + const [isLoadingSuggestions, isSuggestingValues, suggestions] = useFieldValueAutocomplete({ + autocompleteService, + fieldValue: selectedValue, + indexPattern, + operatorType: OperatorTypeEnum.MATCH_ANY, + query: searchQuery, + selectedField, + }); + const getLabel = useCallback((option: string): string => option, []); + const optionsMemo = useMemo( + (): string[] => (selectedValue ? uniq([...selectedValue, ...suggestions]) : suggestions), + [suggestions, selectedValue] + ); + const { comboOptions, labels, selectedComboOptions } = useMemo( + (): GetGenericComboBoxPropsReturn => + getGenericComboBoxProps({ + getLabel, + options: optionsMemo, + selectedOptions: selectedValue, + }), + [optionsMemo, selectedValue, getLabel] + ); + const handleSpacesWarning = useCallback( + (params: string[]) => + setShowSpacesWarning(!!params.find((param: string) => paramContainsSpace(param))), + [setShowSpacesWarning] + ); + const handleError = useCallback( + (err: string | undefined): void => { + setError((existingErr): string | undefined => { + const oldErr = existingErr != null; + const newErr = err != null; + if (oldErr !== newErr && onError != null) { + onError(newErr); + } + + return err; + }); + }, + [setError, onError] + ); + + const handleValuesChange = useCallback( + (newOptions: EuiComboBoxOptionOption[]): void => { + const newValues: string[] = newOptions.map(({ label }) => optionsMemo[labels.indexOf(label)]); + handleError(undefined); + handleSpacesWarning(newValues); + onChange(newValues); + }, + [handleError, handleSpacesWarning, labels, onChange, optionsMemo] + ); + + const handleSearchChange = useCallback( + (searchVal: string) => { + if (searchVal === '') { + handleError(undefined); + } + + if (searchVal !== '' && selectedField != null) { + const err = paramIsValid(searchVal, selectedField, isRequired, touched); + handleError(err); + + if (!err) handleSpacesWarning([searchVal]); + + setSearchQuery(searchVal); + } + }, + [handleError, handleSpacesWarning, isRequired, selectedField, touched] + ); + + const handleCreateOption = useCallback( + (option: string): boolean => { + const err = paramIsValid(option, selectedField, isRequired, touched); + handleError(err); + + if (err != null) { + // Explicitly reject the user's input + setShowSpacesWarning(false); + return false; + } + + onChange([...(selectedValue || []), option]); + handleSpacesWarning([option]); + return true; + }, + [handleError, handleSpacesWarning, isRequired, onChange, selectedField, selectedValue, touched] + ); + + const setIsTouchedValue = useCallback((): void => { + handleError(selectedComboOptions.length === 0 ? i18n.FIELD_REQUIRED_ERR : undefined); + setIsTouched(true); + }, [setIsTouched, handleError, selectedComboOptions]); + + const inputPlaceholder = useMemo( + (): string => (isLoading || isLoadingSuggestions ? i18n.LOADING : placeholder), + [isLoading, isLoadingSuggestions, placeholder] + ); + + const isLoadingState = useMemo( + (): boolean => isLoading || isLoadingSuggestions, + [isLoading, isLoadingSuggestions] + ); + useEffect((): void => { + handleSpacesWarning(selectedValue); + }, [selectedField, selectedValue, handleSpacesWarning]); + + const defaultInput = useMemo((): JSX.Element => { + return ( + + + + ); + }, [ + rowLabel, + error, + selectedField, + showSpacesWarning, + inputPlaceholder, + isLoadingState, + isClearable, + isDisabled, + comboOptions, + selectedComboOptions, + handleValuesChange, + handleSearchChange, + handleCreateOption, + setIsTouchedValue, + ariaLabel, + ]); + + if (!isSuggestingValues && selectedField != null) { + switch (selectedField.type) { + case 'number': + return ( + + + + ); + default: + return defaultInput; + } + } + + return defaultInput; +}; + +AutocompleteFieldMatchAnyComponent.displayName = 'AutocompleteFieldMatchAny'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.test.tsx new file mode 100644 index 0000000000000..2c2411f0a0c11 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.test.tsx @@ -0,0 +1,514 @@ +/* + * 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. + */ + +import React from 'react'; +import { ReactWrapper, mount } from 'enzyme'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormHelpText } from '@elastic/eui'; +import { act, waitFor } from '@testing-library/react'; +import { AutocompleteFieldWildcardComponent } from '.'; +import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; +import { fields, getField } from '../fields/index.mock'; +import { autocompleteStartMock } from '../autocomplete/index.mock'; +import { WILDCARD_WARNING, FILEPATH_WARNING } from '@kbn/securitysolution-utils'; + +jest.mock('../hooks/use_field_value_autocomplete'); +jest.mock('../translations', () => ({ + FIELD_SPACE_WARNING: 'Warning: there is a space', +})); +describe('AutocompleteFieldWildcardComponent', () => { + let wrapper: ReactWrapper; + + const getValueSuggestionsMock = jest + .fn() + .mockResolvedValue([false, true, ['value 3', 'value 4'], jest.fn()]); + + beforeEach(() => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + true, + ['value 1', 'value 2'], + getValueSuggestionsMock, + ]); + }); + + afterEach(() => { + jest.clearAllMocks(); + wrapper.unmount(); + }); + + test('it renders row label if one passed in', () => { + wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="valuesAutocompleteWildcardLabel"] label').at(0).text() + ).toEqual('Row Label'); + }); + + test('it renders disabled if "isDisabled" is true', () => { + wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="valuesAutocompleteWildcard"] input').prop('disabled') + ).toBeTruthy(); + }); + + test('it renders loading if "isLoading" is true', () => { + wrapper = mount( + + ); + wrapper.find('[data-test-subj="valuesAutocompleteWildcard"] button').at(0).simulate('click'); + expect( + wrapper + .find('EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteWildcard-optionsList"]') + .prop('isLoading') + ).toBeTruthy(); + }); + + test('it allows user to clear values if "isClearable" is true', () => { + wrapper = mount( + + ); + + expect(wrapper.find(`[data-test-subj="comboBoxClearButton"]`)).toBeTruthy(); + }); + + test('it correctly displays selected value', () => { + wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="valuesAutocompleteWildcard"] input').at(0).props().value + ).toEqual('/opt/*/app.dmg'); + }); + + test('it invokes "onChange" when new value created', async () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + ( + wrapper.find(EuiComboBox).props() as unknown as { + onCreateOption: (a: string) => void; + } + ).onCreateOption('/opt/*/app.dmg'); + + expect(mockOnChange).toHaveBeenCalledWith('/opt/*/app.dmg'); + }); + + test('it invokes "onChange" when new value selected', async () => { + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + ( + wrapper.find(EuiComboBox).props() as unknown as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + } + ).onChange([{ label: 'value 1' }]); + + expect(mockOnChange).toHaveBeenCalledWith('value 1'); + }); + + test('it refreshes autocomplete with search query when new value searched', () => { + wrapper = mount( + + ); + act(() => { + ( + wrapper.find(EuiComboBox).props() as unknown as { + onSearchChange: (a: string) => void; + } + ).onSearchChange('A:\\Some Folder\\inc*.exe'); + }); + + expect(useFieldValueAutocomplete).toHaveBeenCalledWith({ + autocompleteService: autocompleteStartMock, + fieldValue: '', + indexPattern: { + fields, + id: '1234', + title: 'logs-endpoint.events.*', + }, + operatorType: 'wildcard', + query: 'A:\\Some Folder\\inc*.exe', + selectedField: getField('file.path.text'), + }); + }); + + test('it does not invoke "onWarning" when no warning exists', () => { + const mockOnWarning = jest.fn(); + wrapper = mount( + + ); + + act(() => { + ( + wrapper.find(EuiComboBox).props() as unknown as { + onBlur: () => void; + } + ).onBlur(); + }); + + expect(mockOnWarning).not.toHaveBeenCalledWith(true); + }); + + test('it invokes "onWarning" when warning exists', () => { + const mockOnWarning = jest.fn(); + wrapper = mount( + + ); + + act(() => { + ( + wrapper.find(EuiComboBox).props() as unknown as { + onBlur: () => void; + } + ).onBlur(); + }); + + expect(mockOnWarning).toHaveBeenCalledWith(true); + expect( + wrapper + .find('[data-test-subj="valuesAutocompleteWildcardLabel"] div.euiFormHelpText') + .at(0) + .text() + ).toEqual(FILEPATH_WARNING); + }); + + test('it invokes "onWarning" when warning exists and is wildcard warning', () => { + const mockOnWarning = jest.fn(); + wrapper = mount( + + ); + + act(() => { + ( + wrapper.find(EuiComboBox).props() as unknown as { + onBlur: () => void; + } + ).onBlur(); + }); + + expect(mockOnWarning).toHaveBeenCalledWith(true); + const helpText = wrapper + .find('[data-test-subj="valuesAutocompleteWildcardLabel"] div.euiFormHelpText') + .at(0); + expect(helpText.text()).toEqual(WILDCARD_WARNING); + expect(helpText.find('.euiToolTipAnchor')).toBeTruthy(); + }); + test('should show the warning helper text if the new value contains spaces when change', async () => { + (useFieldValueAutocomplete as jest.Mock).mockReturnValue([ + false, + true, + [' value 1 ', 'value 2'], + getValueSuggestionsMock, + ]); + const mockOnChange = jest.fn(); + wrapper = mount( + + ); + + await waitFor(() => + ( + wrapper.find(EuiComboBox).props() as unknown as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + } + ).onChange([{ label: ' value 1 ' }]) + ); + wrapper.update(); + expect(mockOnChange).toHaveBeenCalledWith(' value 1 '); + + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + }); + test('should show the warning helper text if the new value contains spaces when searching a new query', () => { + wrapper = mount( + + ); + act(() => { + ( + wrapper.find(EuiComboBox).props() as unknown as { + onSearchChange: (a: string) => void; + } + ).onSearchChange(' value 1'); + }); + + wrapper.update(); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); + }); + test('should show the warning helper text if selectedValue contains spaces when editing', () => { + wrapper = mount( + + ); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeTruthy(); + expect(euiFormHelptext.text()).toEqual('Warning: there is a space'); + }); + test('should not show the warning helper text if selectedValue is falsy', () => { + wrapper = mount( + + ); + const euiFormHelptext = wrapper.find(EuiFormHelpText); + expect(euiFormHelptext.length).toBeFalsy(); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.tsx new file mode 100644 index 0000000000000..c095578bf0ff0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/field_value_wildcard/index.tsx @@ -0,0 +1,285 @@ +/* + * 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. + */ + +import React, { useCallback, useMemo, useState, useEffect, memo } from 'react'; +import { EuiFormRow, EuiComboBoxOptionOption, EuiComboBox } from '@elastic/eui'; +import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; + +import { uniq } from 'lodash'; + +import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; + +// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 +// import { AutocompleteStart } from '../../../../../../../../../../src/plugins/unified_search/public'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type AutocompleteStart = any; + +import * as i18n from '../translations'; +import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; +import { + getGenericComboBoxProps, + GetGenericComboBoxPropsReturn, +} from '../get_generic_combo_box_props'; +import { paramIsValid } from '../param_is_valid'; +import { paramContainsSpace } from '../param_contains_space'; + +const SINGLE_SELECTION = { asPlainText: true }; + +type Warning = string | React.ReactNode; +interface AutocompleteFieldWildcardProps { + placeholder: string; + selectedField: DataViewFieldBase | undefined; + selectedValue: string | undefined; + indexPattern: DataViewBase | undefined; + isLoading: boolean; + isDisabled?: boolean; + isClearable?: boolean; + isRequired?: boolean; + fieldInputWidth?: number; + rowLabel?: string; + autocompleteService: AutocompleteStart; + onChange: (arg: string) => void; + onError: (arg: boolean) => void; + onWarning: (arg: boolean) => void; + warning?: Warning; + 'aria-label'?: string; +} + +export const AutocompleteFieldWildcardComponent: React.FC = memo( + ({ + autocompleteService, + placeholder, + rowLabel, + selectedField, + selectedValue, + indexPattern, + isLoading, + isDisabled = false, + isClearable = false, + isRequired = false, + fieldInputWidth, + onChange, + onError, + onWarning, + warning, + 'aria-label': ariaLabel, + }): JSX.Element => { + const [searchQuery, setSearchQuery] = useState(''); + const [touched, setIsTouched] = useState(false); + const [error, setError] = useState(undefined); + const [showSpacesWarning, setShowSpacesWarning] = useState(false); + const [isLoadingSuggestions, , suggestions] = useFieldValueAutocomplete({ + autocompleteService, + fieldValue: selectedValue, + indexPattern, + operatorType: OperatorTypeEnum.WILDCARD, + query: searchQuery, + selectedField, + }); + const getLabel = useCallback((option: string): string => option, []); + const optionsMemo = useMemo((): string[] => { + const valueAsStr = String(selectedValue); + return selectedValue != null && selectedValue.trim() !== '' + ? uniq([valueAsStr, ...suggestions]) + : suggestions; + }, [suggestions, selectedValue]); + const selectedOptionsMemo = useMemo((): string[] => { + const valueAsStr = String(selectedValue); + return selectedValue ? [valueAsStr] : []; + }, [selectedValue]); + + const handleSpacesWarning = useCallback( + (param: string | undefined) => { + if (!param) return setShowSpacesWarning(false); + setShowSpacesWarning(!!paramContainsSpace(param)); + }, + [setShowSpacesWarning] + ); + const handleError = useCallback( + (err: string | undefined): void => { + setError((existingErr): string | undefined => { + const oldErr = existingErr != null; + const newErr = err != null; + if (oldErr !== newErr && onError != null) { + onError(newErr); + } + + return err; + }); + }, + [setError, onError] + ); + + const handleWarning = useCallback( + (warn: Warning | undefined): void => { + onWarning(warn !== undefined); + }, + [onWarning] + ); + + const { comboOptions, labels, selectedComboOptions } = useMemo( + (): GetGenericComboBoxPropsReturn => + getGenericComboBoxProps({ + getLabel, + options: optionsMemo, + selectedOptions: selectedOptionsMemo, + }), + [optionsMemo, selectedOptionsMemo, getLabel] + ); + + const handleValuesChange = useCallback( + (newOptions: EuiComboBoxOptionOption[]): void => { + const [newValue] = newOptions.map(({ label }) => optionsMemo[labels.indexOf(label)]); + handleError(undefined); + handleSpacesWarning(newValue); + setShowSpacesWarning(false); + + onChange(newValue ?? ''); + }, + [handleError, handleSpacesWarning, labels, onChange, optionsMemo] + ); + + const handleSearchChange = useCallback( + (searchVal: string): void => { + if (searchVal.trim() !== '' && selectedField != null) { + const err = paramIsValid(searchVal, selectedField, isRequired, touched); + handleError(err); + handleWarning(warning); + if (!err) handleSpacesWarning(searchVal); + + setSearchQuery(searchVal); + } + }, + [handleError, handleSpacesWarning, isRequired, selectedField, touched, warning, handleWarning] + ); + + const handleCreateOption = useCallback( + (option: string): boolean | undefined => { + const err = paramIsValid(option, selectedField, isRequired, touched); + handleError(err); + handleWarning(warning); + + if (err != null) { + // Explicitly reject the user's input + setShowSpacesWarning(false); + return false; + } + + handleSpacesWarning(option); + onChange(option); + return undefined; + }, + [ + isRequired, + handleSpacesWarning, + onChange, + selectedField, + touched, + handleError, + handleWarning, + warning, + ] + ); + + const setIsTouchedValue = useCallback((): void => { + setIsTouched(true); + + const err = paramIsValid(selectedValue, selectedField, isRequired, true); + handleError(err); + handleWarning(warning); + }, [ + setIsTouched, + handleError, + selectedValue, + selectedField, + isRequired, + handleWarning, + warning, + ]); + + const inputPlaceholder = useMemo((): string => { + if (isLoading || isLoadingSuggestions) { + return i18n.LOADING; + } else if (selectedField == null) { + return i18n.SELECT_FIELD_FIRST; + } else { + return placeholder; + } + }, [isLoading, selectedField, isLoadingSuggestions, placeholder]); + + const isLoadingState = useMemo( + (): boolean => isLoading || isLoadingSuggestions, + [isLoading, isLoadingSuggestions] + ); + + useEffect((): void => { + setError(undefined); + if (onError != null) { + onError(false); + } + handleSpacesWarning(selectedValue); + + onWarning(false); + }, [selectedField, selectedValue, onError, onWarning, handleSpacesWarning]); + + const defaultInput = useMemo((): JSX.Element => { + return ( + + + + ); + }, [ + rowLabel, + error, + warning, + showSpacesWarning, + selectedField, + inputPlaceholder, + isDisabled, + isLoadingState, + isClearable, + comboOptions, + selectedComboOptions, + handleValuesChange, + handleSearchChange, + handleCreateOption, + setIsTouchedValue, + fieldInputWidth, + ariaLabel, + ]); + + return defaultInput; + } +); + +AutocompleteFieldWildcardComponent.displayName = 'AutocompleteFieldWildcard'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts new file mode 100644 index 0000000000000..32e9d60197868 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts @@ -0,0 +1,321 @@ +/* + * 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. + */ + +import { DataViewFieldBase } from '@kbn/es-query'; + +// Copied from "src/plugins/data/common/index_patterns/fields/fields.mocks.ts" but with the types changed to "DataViewFieldBase" since that type is compatible. +// TODO: This should move out once those mocks are directly useable or in their own package, https://github.com/elastic/kibana/issues/100715 + +export const fields: DataViewFieldBase[] = [ + { + name: 'bytes', + type: 'number', + esTypes: ['long'], + count: 10, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'ssl', + type: 'boolean', + esTypes: ['boolean'], + count: 20, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: '@timestamp', + type: 'date', + esTypes: ['date'], + count: 30, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'time', + type: 'date', + esTypes: ['date'], + count: 30, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: '@tags', + type: 'string', + esTypes: ['keyword'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'utc_time', + type: 'date', + esTypes: ['date'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'phpmemory', + type: 'number', + esTypes: ['integer'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'ip', + type: 'ip', + esTypes: ['ip'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'request_body', + type: 'attachment', + esTypes: ['attachment'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'point', + type: 'geo_point', + esTypes: ['geo_point'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'area', + type: 'geo_shape', + esTypes: ['geo_shape'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'hashed', + type: 'murmur3', + esTypes: ['murmur3'], + count: 0, + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + name: 'geo.coordinates', + type: 'geo_point', + esTypes: ['geo_point'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'extension', + type: 'string', + esTypes: ['keyword'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'machine.os', + type: 'string', + esTypes: ['text'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: 'machine.os.raw', + type: 'string', + esTypes: ['keyword'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { multi: { parent: 'machine.os' } }, + }, + { + name: 'geo.src', + type: 'string', + esTypes: ['keyword'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: '_id', + type: 'string', + esTypes: ['_id'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: '_type', + type: 'string', + esTypes: ['_type'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: '_source', + type: '_source', + esTypes: ['_source'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: 'non-filterable', + type: 'string', + esTypes: ['text'], + count: 0, + scripted: false, + searchable: false, + aggregatable: true, + readFromDocValues: false, + }, + { + name: 'non-sortable', + type: 'string', + esTypes: ['text'], + count: 0, + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + name: 'custom_user_field', + type: 'conflict', + esTypes: ['long', 'text'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'script string', + type: 'string', + count: 0, + scripted: true, + script: "'i am a string'", + lang: 'expression', + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: 'script number', + type: 'number', + count: 0, + scripted: true, + script: '1234', + lang: 'expression', + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: 'script date', + type: 'date', + count: 0, + scripted: true, + script: '1234', + lang: 'painless', + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: 'script murmur3', + type: 'murmur3', + count: 0, + scripted: true, + script: '1234', + lang: 'expression', + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + name: 'nestedField.child', + type: 'string', + esTypes: ['text'], + count: 0, + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + subType: { nested: { path: 'nestedField' } }, + }, + { + name: 'nestedField.nestedChild.doublyNestedChild', + type: 'string', + esTypes: ['text'], + count: 0, + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + subType: { nested: { path: 'nestedField.nestedChild' } }, + }, + { + name: 'file.path.text', + type: 'string', + esTypes: ['text'], + searchable: true, + aggregatable: false, + subType: { multi: { parent: 'file.path' } }, + }, +] as unknown as DataViewFieldBase[]; + +export const getField = (name: string) => fields.find((field) => field.name === name); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts new file mode 100644 index 0000000000000..3328af4e2fa2c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts @@ -0,0 +1,123 @@ +/* + * 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. + */ + +import { filterFieldToList } from '.'; + +import { getListResponseMock } from '../list_schema/index.mock'; +import { DataViewFieldBase } from '@kbn/es-query'; +import { AutocompleteListsData } from '../field_value_lists'; + +const emptyListData: AutocompleteListsData = { smallLists: [], largeLists: [] }; + +describe('#filterFieldToList', () => { + test('it returns empty list data object if given a undefined for field', () => { + const filter = filterFieldToList(emptyListData, undefined); + expect(filter).toEqual(emptyListData); + }); + + test('it returns empty list data object if filed does not contain esTypes', () => { + const field: DataViewFieldBase = { + name: 'some-name', + type: 'some-type', + }; + const filter = filterFieldToList(emptyListData, field); + expect(filter).toEqual(emptyListData); + }); + + test('it returns filtered lists of ip_range -> ip', () => { + const field: DataViewFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; + const listData: AutocompleteListsData = { + smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], + largeLists: [], + }; + const filter = filterFieldToList(listData, field); + const expected = listData; + expect(filter).toEqual(expected); + }); + + test('it returns filtered lists of ip -> ip', () => { + const field: DataViewFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; + const listData: AutocompleteListsData = { + smallLists: [{ ...getListResponseMock(), type: 'ip' }], + largeLists: [], + }; + const filter = filterFieldToList(listData, field); + const expected = listData; + expect(filter).toEqual(expected); + }); + + test('it returns filtered lists of keyword -> keyword', () => { + const field: DataViewFieldBase & { esTypes: string[] } = { + esTypes: ['keyword'], + name: 'some-name', + type: 'keyword', + }; + const listData: AutocompleteListsData = { + smallLists: [{ ...getListResponseMock(), type: 'keyword' }], + largeLists: [], + }; + const filter = filterFieldToList(listData, field); + const expected = listData; + expect(filter).toEqual(expected); + }); + + test('it returns filtered lists of text -> text', () => { + const field: DataViewFieldBase & { esTypes: string[] } = { + esTypes: ['text'], + name: 'some-name', + type: 'text', + }; + const listData: AutocompleteListsData = { + smallLists: [{ ...getListResponseMock(), type: 'text' }], + largeLists: [], + }; + const filter = filterFieldToList(listData, field); + const expected = listData; + expect(filter).toEqual(expected); + }); + + test('it returns small and large filtered lists of ip_range -> ip', () => { + const field: DataViewFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; + const listData: AutocompleteListsData = { + smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], + largeLists: [{ ...getListResponseMock(), type: 'ip_range' }], + }; + const filter = filterFieldToList(listData, field); + const expected = listData; + expect(filter).toEqual(expected); + }); + + test('it returns 1 filtered lists of ip_range -> ip if the 2nd is not compatible type', () => { + const field: DataViewFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; + const listData: AutocompleteListsData = { + smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], + largeLists: [{ ...getListResponseMock(), type: 'text' }], + }; + const filter = filterFieldToList(listData, field); + const expected: AutocompleteListsData = { + smallLists: [{ ...getListResponseMock(), type: 'ip_range' }], + largeLists: [], + }; + expect(filter).toEqual(expected); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts new file mode 100644 index 0000000000000..a4df119766a96 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts @@ -0,0 +1,39 @@ +/* + * 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. + */ + +import { DataViewFieldBase } from '@kbn/es-query'; +import { typeMatch } from '../type_match'; +import { AutocompleteListsData } from '../field_value_lists'; + +/** + * Given an array of lists and optionally a field this will return all + * the lists that match against the field based on the types from the field + * + * NOTE: That we support one additional property from "FieldSpec" located here: + * src/plugins/data/common/index_patterns/fields/types.ts + * This type property is esTypes. If it exists and is on there we will read off the esTypes. + * @param lists The lists to match against the field + * @param field The field to check against the list to see if they are compatible + */ +export const filterFieldToList = ( + lists: AutocompleteListsData, + field?: DataViewFieldBase & { esTypes?: string[] } +): AutocompleteListsData => { + if (field != null) { + const { esTypes = [] } = field; + return { + smallLists: lists.smallLists.filter(({ type }) => + esTypes.some((esType: string) => typeMatch(type, esType)) + ), + largeLists: lists.largeLists.filter(({ type }) => + esTypes.some((esType: string) => typeMatch(type, esType)) + ), + }; + } else { + return { smallLists: [], largeLists: [] }; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.test.tsx new file mode 100644 index 0000000000000..f333e7c6ebdd2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.test.tsx @@ -0,0 +1,124 @@ +/* + * 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. + */ + +import { getGenericComboBoxProps } from '.'; + +describe('get_generic_combo_box_props', () => { + test('it returns empty arrays if "options" is empty array', () => { + const result = getGenericComboBoxProps({ + options: [], + selectedOptions: ['option1'], + getLabel: (t: string) => t, + }); + + expect(result).toEqual({ comboOptions: [], labels: [], selectedComboOptions: [] }); + }); + + test('it returns formatted props if "options" array is not empty', () => { + const result = getGenericComboBoxProps({ + options: ['option1', 'option2', 'option3'], + selectedOptions: [], + getLabel: (t: string) => t, + }); + + expect(result).toEqual({ + comboOptions: [ + { + label: 'option1', + }, + { + label: 'option2', + }, + { + label: 'option3', + }, + ], + labels: ['option1', 'option2', 'option3'], + selectedComboOptions: [], + }); + }); + + test('it does not return "selectedOptions" items that do not appear in "options"', () => { + const result = getGenericComboBoxProps({ + options: ['option1', 'option2', 'option3'], + selectedOptions: ['option4'], + getLabel: (t: string) => t, + }); + + expect(result).toEqual({ + comboOptions: [ + { + label: 'option1', + }, + { + label: 'option2', + }, + { + label: 'option3', + }, + ], + labels: ['option1', 'option2', 'option3'], + selectedComboOptions: [], + }); + }); + + test('it returns "selectedOptions" items that do appear in "options"', () => { + const result = getGenericComboBoxProps({ + options: ['option1', 'option2', 'option3'], + selectedOptions: ['option2'], + getLabel: (t: string) => t, + }); + + expect(result).toEqual({ + comboOptions: [ + { + label: 'option1', + }, + { + label: 'option2', + }, + { + label: 'option3', + }, + ], + labels: ['option1', 'option2', 'option3'], + selectedComboOptions: [ + { + label: 'option2', + }, + ], + }); + }); + + test('it returns "disabledOptions" items that do appear in "options" as disabled', () => { + const result = getGenericComboBoxProps({ + options: ['option1', 'option2', 'option3'], + selectedOptions: [], + disabledOptions: ['option2'], + getLabel: (t: string) => t, + }); + + expect(result).toEqual({ + comboOptions: [ + { + label: 'option1', + disabled: false, + }, + { + label: 'option2', + disabled: true, + }, + { + label: 'option3', + disabled: false, + }, + ], + labels: ['option1', 'option2', 'option3'], + selectedComboOptions: [], + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.ts new file mode 100644 index 0000000000000..f043fc978836d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_generic_combo_box_props/index.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +import { EuiComboBoxOptionOption } from '@elastic/eui'; + +export interface GetGenericComboBoxPropsReturn { + comboOptions: EuiComboBoxOptionOption[]; + labels: string[]; + selectedComboOptions: EuiComboBoxOptionOption[]; +} + +/** + * Determines the options, selected values and option labels for EUI combo box + * @param options options user can select from + * @param selectedOptions user selection if any + * @param getLabel helper function to know which property to use for labels + */ +export const getGenericComboBoxProps = ({ + getLabel, + options, + selectedOptions, + disabledOptions, +}: { + getLabel: (value: T) => string; + options: T[]; + selectedOptions: T[]; + disabledOptions?: T[]; +}): GetGenericComboBoxPropsReturn => { + const newLabels = options.map(getLabel); + const disabledLabels = disabledOptions?.map(getLabel); + const newComboOptions: EuiComboBoxOptionOption[] = newLabels.map((label) => ({ + label, + disabled: disabledLabels && disabledLabels.length !== 0 && disabledLabels.includes(label), + })); + const newSelectedComboOptions = selectedOptions + .map(getLabel) + .filter((option) => { + return newLabels.indexOf(option) !== -1; + }) + .map((option) => { + return newComboOptions[newLabels.indexOf(option)]; + }); + + return { + comboOptions: newComboOptions, + labels: newLabels, + selectedComboOptions: newSelectedComboOptions, + }; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts new file mode 100644 index 0000000000000..db031a65e0bb7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import { + doesNotExistOperator, + EVENT_FILTERS_OPERATORS, + ALL_OPERATORS, + existsOperator, + isNotOperator, + isOperator, +} from '@kbn/securitysolution-list-utils'; +import { getOperators } from '.'; +import { getField } from '../fields/index.mock'; + +describe('#getOperators', () => { + test('it returns "isOperator" if passed in field is "undefined"', () => { + const operator = getOperators(undefined); + + expect(operator).toEqual([isOperator]); + }); + + test('it returns expected operators when field type is "boolean"', () => { + const operator = getOperators(getField('ssl')); + + expect(operator).toEqual([isOperator, isNotOperator, existsOperator, doesNotExistOperator]); + }); + + test('it returns "isOperator" when field type is "nested"', () => { + const operator = getOperators({ + name: 'nestedField', + scripted: false, + subType: { nested: { path: 'nestedField' } }, + type: 'nested', + }); + + expect(operator).toEqual([isOperator]); + }); + + test('it includes a "matches" operator when field is "file.path.text"', () => { + const operator = getOperators({ + name: 'file.path.text', + type: 'simple', + }); + + expect(operator).toEqual(EVENT_FILTERS_OPERATORS); + }); + + test('it returns all operator types when field type is not null, boolean, or nested', () => { + const operator = getOperators(getField('machine.os.raw')); + + expect(operator).toEqual(ALL_OPERATORS); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts new file mode 100644 index 0000000000000..451d4f5c21a7c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts @@ -0,0 +1,38 @@ +/* + * 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. + */ + +import { DataViewFieldBase } from '@kbn/es-query'; + +import { + ALL_OPERATORS, + EVENT_FILTERS_OPERATORS, + OperatorOption, + doesNotExistOperator, + existsOperator, + isNotOperator, + isOperator, +} from '@kbn/securitysolution-list-utils'; + +/** + * Returns the appropriate operators given a field type + * + * @param field DataViewFieldBase selected field + * + */ +export const getOperators = (field: DataViewFieldBase | undefined): OperatorOption[] => { + if (field == null) { + return [isOperator]; + } else if (field.type === 'boolean') { + return [isOperator, isNotOperator, existsOperator, doesNotExistOperator]; + } else if (field.type === 'nested') { + return [isOperator]; + } else if (field.name === 'file.path.text') { + return EVENT_FILTERS_OPERATORS; + } else { + return ALL_OPERATORS; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/index.ts new file mode 100644 index 0000000000000..e9d4507b14005 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export * from './use_field_value_autocomplete'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts new file mode 100644 index 0000000000000..7d776db124134 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts @@ -0,0 +1,298 @@ +/* + * 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. + */ + +import { waitFor, renderHook } from '@testing-library/react'; +import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; + +import { UseFieldValueAutocompleteReturn, useFieldValueAutocomplete } from '.'; +import { getField } from '../../fields/index.mock'; +import { autocompleteStartMock } from '../../autocomplete/index.mock'; +import { DataViewFieldBase } from '@kbn/es-query'; + +// Copied from "src/plugins/data/common/index_patterns/index_pattern.stub.ts" +// TODO: Remove this in favor of the above if/when it is ported, https://github.com/elastic/kibana/issues/100715 +export const stubIndexPatternWithFields = { + id: '1234', + title: 'logstash-*', + fields: [ + { + name: 'response', + type: 'number', + esTypes: ['integer'], + aggregatable: true, + filterable: true, + searchable: true, + }, + ], +}; + +describe('use_field_value_autocomplete', () => { + const onErrorMock = jest.fn(); + const getValueSuggestionsMock = jest.fn().mockResolvedValue(['value 1', 'value 2']); + + afterEach(() => { + onErrorMock.mockClear(); + getValueSuggestionsMock.mockClear(); + }); + + test('initializes hook', async () => { + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: getValueSuggestionsMock, + }, + fieldValue: '', + indexPattern: undefined, + operatorType: OperatorTypeEnum.MATCH, + query: '', + selectedField: undefined, + }) + ); + await waitFor(() => expect(result.current).toEqual([false, true, [], result.current[3]])); + }); + + test('does not call autocomplete service if "operatorType" is "exists"', async () => { + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: getValueSuggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.EXISTS, + query: '', + selectedField: getField('machine.os'), + }) + ); + + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); + }); + + test('does not call autocomplete service if "selectedField" is undefined', async () => { + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: getValueSuggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.EXISTS, + query: '', + selectedField: undefined, + }) + ); + + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); + }); + + test('does not call autocomplete service if "indexPattern" is undefined', async () => { + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: getValueSuggestionsMock, + }, + fieldValue: '', + indexPattern: undefined, + operatorType: OperatorTypeEnum.EXISTS, + query: '', + selectedField: getField('machine.os'), + }) + ); + + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); + }); + + test('it uses full path name for nested fields to fetch suggestions', async () => { + const suggestionsMock = jest.fn().mockResolvedValue([]); + + const selectedField: DataViewFieldBase | undefined = getField('nestedField.child'); + if (selectedField == null) { + throw new TypeError('selectedField for this test should always be defined'); + } + + const { signal } = new AbortController(); + renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: suggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.MATCH, + query: '', + selectedField: { ...selectedField, name: 'child' }, + }) + ); + + await waitFor(() => + expect(suggestionsMock).toHaveBeenCalledWith({ + field: { ...getField('nestedField.child'), name: 'nestedField.child' }, + indexPattern: { + fields: [ + { + aggregatable: true, + esTypes: ['integer'], + filterable: true, + name: 'response', + searchable: true, + type: 'number', + }, + ], + id: '1234', + title: 'logstash-*', + }, + query: '', + signal, + useTimeRange: false, + }) + ); + }); + + test('returns "isSuggestingValues" of false if field type is boolean', async () => { + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: getValueSuggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.MATCH, + query: '', + selectedField: getField('ssl'), + }) + ); + + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; + + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); + }); + + test('returns "isSuggestingValues" of false to note that autocomplete service is not in use if no autocomplete suggestions available', async () => { + const suggestionsMock = jest.fn().mockResolvedValue([]); + + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: suggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.MATCH, + query: '', + selectedField: getField('bytes'), + }) + ); + + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; + + expect(suggestionsMock).toHaveBeenCalled(); + expect(result.current).toEqual(expectedResult); + }); + }); + + test('returns suggestions', async () => { + const { signal } = new AbortController(); + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: getValueSuggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.MATCH, + query: '', + selectedField: getField('@tags'), + }) + ); + + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [ + false, + true, + ['value 1', 'value 2'], + result.current[3], + ]; + + expect(getValueSuggestionsMock).toHaveBeenCalledWith({ + field: getField('@tags'), + indexPattern: stubIndexPatternWithFields, + query: '', + signal, + useTimeRange: false, + }); + expect(result.current).toEqual(expectedResult); + }); + }); + + test('returns new suggestions on subsequent calls', async () => { + const { result } = renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: getValueSuggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.MATCH, + query: '', + selectedField: getField('@tags'), + }) + ); + + await waitFor(() => expect(result.current[3]).not.toBeNull()); + + // Added check for typescripts sake, if null, + // would not reach below logic as test would stop above + if (result.current[3] != null) { + result.current[3]({ + fieldSelected: getField('@tags'), + patterns: stubIndexPatternWithFields, + searchQuery: '', + value: 'hello', + }); + } + + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [ + false, + true, + ['value 1', 'value 2'], + result.current[3], + ]; + + expect(getValueSuggestionsMock).toHaveBeenCalledTimes(2); + expect(result.current).toEqual(expectedResult); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts new file mode 100644 index 0000000000000..dbbe321014e2b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts @@ -0,0 +1,122 @@ +/* + * 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. + */ + +import { useEffect, useRef, useState } from 'react'; +import { debounce } from 'lodash'; +import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { DataViewBase, DataViewFieldBase, getDataViewFieldSubtypeNested } from '@kbn/es-query'; + +// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 +// import { AutocompleteStart } from '../../../../../../../../../../../src/plugins/unified_search/public'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type AutocompleteStart = any; + +interface FuncArgs { + fieldSelected: DataViewFieldBase | undefined; + patterns: DataViewBase | undefined; + searchQuery: string; + value: string | string[] | undefined; +} + +type Func = (args: FuncArgs) => void; + +export type UseFieldValueAutocompleteReturn = [boolean, boolean, string[], Func | null]; + +export interface UseFieldValueAutocompleteProps { + autocompleteService: AutocompleteStart; + fieldValue: string | string[] | undefined; + indexPattern: DataViewBase | undefined; + operatorType: OperatorTypeEnum; + query: string; + selectedField: DataViewFieldBase | undefined; +} +/** + * Hook for using the field value autocomplete service + */ +export const useFieldValueAutocomplete = ({ + selectedField, + operatorType, + fieldValue, + query, + indexPattern, + autocompleteService, +}: UseFieldValueAutocompleteProps): UseFieldValueAutocompleteReturn => { + const [isLoading, setIsLoading] = useState(false); + const [isSuggestingValues, setIsSuggestingValues] = useState(true); + const [suggestions, setSuggestions] = useState([]); + const updateSuggestions = useRef(null); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + + const fetchSuggestions = debounce( + async ({ fieldSelected, patterns, searchQuery }: FuncArgs) => { + try { + if (isSubscribed) { + if (fieldSelected == null || patterns == null) { + return; + } + + if (fieldSelected.type === 'boolean') { + setIsSuggestingValues(false); + return; + } + + setIsLoading(true); + const subTypeNested = getDataViewFieldSubtypeNested(fieldSelected); + const field = subTypeNested + ? { + ...fieldSelected, + name: `${subTypeNested.nested.path}.${fieldSelected.name}`, + } + : fieldSelected; + + const newSuggestions = await autocompleteService.getValueSuggestions({ + field, + indexPattern: patterns, + query: searchQuery, + signal: abortCtrl.signal, + useTimeRange: false, + }); + + if (newSuggestions.length === 0) { + setIsSuggestingValues(false); + } + + setIsLoading(false); + setSuggestions([...newSuggestions]); + } + } catch (error) { + if (isSubscribed) { + setSuggestions([]); + setIsLoading(false); + } + } + }, + 500 + ); + + if (operatorType !== OperatorTypeEnum.EXISTS) { + fetchSuggestions({ + fieldSelected: selectedField, + patterns: indexPattern, + searchQuery: query, + value: fieldValue, + }); + } + + updateSuggestions.current = fetchSuggestions; + + return (): void => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, [selectedField, operatorType, fieldValue, indexPattern, query, autocompleteService]); + + return [isLoading, isSuggestingValues, suggestions, updateSuggestions.current]; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts new file mode 100644 index 0000000000000..aade602f1950c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts @@ -0,0 +1,60 @@ +/* + * 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. + */ + +import { + FoundListSchema, + ListSchema, + FoundListsBySizeSchema, +} from '@kbn/securitysolution-io-ts-list-types'; + +// TODO: Once this mock is available within packages, use it instead, https://github.com/elastic/kibana/issues/100715 +// import { getFoundListSchemaMock } from '../../../../../../../../lists/common/schemas/response/found_list_schema.mock'; +export const getFoundListSchemaMock = (): FoundListSchema => ({ + cursor: '123', + data: [getListResponseMock()], + page: 1, + per_page: 1, + total: 1, +}); + +export const getFoundListsBySizeSchemaMock = (): FoundListsBySizeSchema => ({ + smallLists: [getListResponseMock()], + largeLists: [getListResponseMock()], +}); + +// TODO: Once these mocks are available from packages use it instead, https://github.com/elastic/kibana/issues/100715 +export const DATE_NOW = '2020-04-20T15:25:31.830Z'; +export const USER = 'some user'; +export const IMMUTABLE = false; +export const VERSION = 1; +export const DESCRIPTION = 'some description'; +export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; +export const LIST_ID = 'some-list-id'; +export const META = {}; +export const TYPE = 'ip'; +export const NAME = 'some name'; + +// TODO: Once this mock is available within packages, use it instead, https://github.com/elastic/kibana/issues/100715 +// import { getListResponseMock } from '../../../../../../../../lists/common/schemas/response/list_schema.mock'; +export const getListResponseMock = (): ListSchema => ({ + '@timestamp': DATE_NOW, + _version: undefined, + created_at: DATE_NOW, + created_by: USER, + description: DESCRIPTION, + deserializer: undefined, + id: LIST_ID, + immutable: IMMUTABLE, + meta: META, + name: NAME, + serializer: undefined, + tie_breaker_id: TIE_BREAKER, + type: TYPE, + updated_at: DATE_NOW, + updated_by: USER, + version: VERSION, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx new file mode 100644 index 0000000000000..eef8738b67c51 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx @@ -0,0 +1,253 @@ +/* + * 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. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import { isNotOperator, isOperator } from '@kbn/securitysolution-list-utils'; + +import { OperatorComponent } from '.'; +import { getField } from '../fields/index.mock'; + +describe('operator', () => { + test('it renders disabled if "isDisabled" is true', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"] input`).prop('disabled') + ).toBeTruthy(); + }); + + test('it renders loading if "isLoading" is true', () => { + const wrapper = mount( + + ); + wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"] button`).at(0).simulate('click'); + expect( + wrapper + .find(`EuiComboBoxOptionsList[data-test-subj="operatorAutocompleteComboBox-optionsList"]`) + .prop('isLoading') + ).toBeTruthy(); + }); + + test('it allows user to clear values if "isClearable" is true', () => { + const wrapper = mount( + + ); + + expect(wrapper.find(`button[data-test-subj="comboBoxClearButton"]`).exists()).toBeTruthy(); + }); + + test('it displays "operatorOptions" if param is passed in with items', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') + ).toEqual([{ label: 'is not' }]); + }); + + test('it does not display "operatorOptions" if param is passed in with no items', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') + ).toEqual([ + { + label: 'is', + }, + { + label: 'is not', + }, + { + label: 'is one of', + }, + { + label: 'is not one of', + }, + { + label: 'exists', + }, + { + label: 'does not exist', + }, + { + label: 'is in list', + }, + { + label: 'is not in list', + }, + { + label: 'matches', + }, + { + label: 'does not match', + }, + ]); + }); + + test('it correctly displays selected operator', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="operatorAutocompleteComboBox"] input').at(0).props().value + ).toEqual('is'); + }); + + test('it only displays subset of operators if field type is nested', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') + ).toEqual([{ label: 'is' }]); + }); + + test('it only displays subset of operators if field type is boolean', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') + ).toEqual([ + { label: 'is' }, + { label: 'is not' }, + { label: 'exists' }, + { label: 'does not exist' }, + ]); + }); + + test('it only displays subset of operators if field name is "file.path.text"', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find(`[data-test-subj="operatorAutocompleteComboBox"]`).at(0).prop('options') + ).toEqual([ + { label: 'is' }, + { label: 'is not' }, + { label: 'is one of' }, + { label: 'is not one of' }, + { label: 'matches' }, + { label: 'does not match' }, + ]); + }); + + test('it invokes "onChange" when option selected', () => { + const mockOnChange = jest.fn(); + const wrapper = mount( + + ); + + ( + wrapper.find(EuiComboBox).props() as unknown as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + } + ).onChange([{ label: 'is not' }]); + + expect(mockOnChange).toHaveBeenCalledWith([ + { message: 'is not', operator: 'excluded', type: 'match', value: 'is_not' }, + ]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx new file mode 100644 index 0000000000000..6c91f7e70b94b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx @@ -0,0 +1,99 @@ +/* + * 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. + */ + +import React, { useCallback, useMemo } from 'react'; +import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import { OperatorOption } from '@kbn/securitysolution-list-utils'; +import { DataViewFieldBase } from '@kbn/es-query'; + +import { getOperators } from '../get_operators'; +import { + getGenericComboBoxProps, + GetGenericComboBoxPropsReturn, +} from '../get_generic_combo_box_props'; + +const AS_PLAIN_TEXT = { asPlainText: true }; + +interface OperatorState { + isClearable: boolean; + isDisabled: boolean; + isLoading: boolean; + onChange: (arg: OperatorOption[]) => void; + operator: OperatorOption; + operatorInputWidth?: number; + operatorOptions?: OperatorOption[]; + placeholder: string; + selectedField: DataViewFieldBase | undefined; + 'aria-label'?: string; +} + +export const OperatorComponent: React.FC = ({ + isClearable = false, + isDisabled = false, + isLoading = false, + onChange, + operator, + operatorOptions, + operatorInputWidth = 150, + placeholder, + selectedField, + 'aria-label': ariaLabel, +}): JSX.Element => { + const getLabel = useCallback(({ message }: OperatorOption): string => message, []); + const optionsMemo = useMemo( + (): OperatorOption[] => + operatorOptions != null && operatorOptions.length > 0 + ? operatorOptions + : getOperators(selectedField), + [operatorOptions, selectedField] + ); + const selectedOptionsMemo = useMemo( + (): OperatorOption[] => (operator ? [operator] : []), + [operator] + ); + const { comboOptions, labels, selectedComboOptions } = useMemo( + (): GetGenericComboBoxPropsReturn => + getGenericComboBoxProps({ + getLabel, + options: optionsMemo, + selectedOptions: selectedOptionsMemo, + }), + [optionsMemo, selectedOptionsMemo, getLabel] + ); + + const handleValuesChange = useCallback( + (newOptions: EuiComboBoxOptionOption[]): void => { + const newValues: OperatorOption[] = newOptions.map( + ({ label }) => optionsMemo[labels.indexOf(label)] + ); + onChange(newValues); + }, + [labels, onChange, optionsMemo] + ); + + const inputWidth = useMemo(() => { + return { width: `${operatorInputWidth}px` }; + }, [operatorInputWidth]); + + return ( + + ); +}; + +OperatorComponent.displayName = 'Operator'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.test.ts new file mode 100644 index 0000000000000..d0571d157ec2b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.test.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import { paramContainsSpace } from '.'; + +describe('param_contains_space', () => { + test('should return true if leading spaces were found', () => { + expect(paramContainsSpace(' test')).toBeTruthy(); + }); + test('should return true if trailing spaces were found', () => { + expect(paramContainsSpace('test ')).toBeTruthy(); + }); + test('should return true if both trailing and leading spaces were found', () => { + expect(paramContainsSpace(' test ')).toBeTruthy(); + }); + test('should return true if tabs was found', () => { + expect(paramContainsSpace('\ttest')).toBeTruthy(); + }); + test('should return false if no spaces were found', () => { + expect(paramContainsSpace('test test')).toBeFalsy(); + }); + test('should return false if param is falsy', () => { + expect(paramContainsSpace('')).toBeFalsy(); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.ts new file mode 100644 index 0000000000000..3d7bb99ae3d05 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_contains_space/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export const paramContainsSpace = (param: string) => param && param.trim().length !== param.length; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.test.ts new file mode 100644 index 0000000000000..f93ad28eb4ad2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.test.ts @@ -0,0 +1,105 @@ +/* + * 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. + */ + +import { paramIsValid } from '.'; +import { getField } from '../fields/index.mock'; +import * as i18n from '../translations'; +import moment from 'moment'; + +describe('params_is_valid', () => { + beforeEach(() => { + // Disable momentJS deprecation warning and it looks like it is not typed either so + // we have to disable the type as well and cannot extend it easily. + ( + moment as unknown as { + suppressDeprecationWarnings: boolean; + } + ).suppressDeprecationWarnings = true; + }); + + afterEach(() => { + // Re-enable momentJS deprecation warning and it looks like it is not typed either so + // we have to disable the type as well and cannot extend it easily. + ( + moment as unknown as { + suppressDeprecationWarnings: boolean; + } + ).suppressDeprecationWarnings = false; + }); + + test('returns no errors if no field has been selected', () => { + const isValid = paramIsValid('', undefined, true, false); + + expect(isValid).toBeUndefined(); + }); + + test('returns error string if user has touched a required input and left empty', () => { + const isValid = paramIsValid(undefined, getField('@timestamp'), true, true); + + expect(isValid).toEqual(i18n.FIELD_REQUIRED_ERR); + }); + + test('returns no errors if required input is empty but user has not yet touched it', () => { + const isValid = paramIsValid(undefined, getField('@timestamp'), true, false); + + expect(isValid).toBeUndefined(); + }); + + test('returns no errors if user has touched an input that is not required and left empty', () => { + const isValid = paramIsValid(undefined, getField('@timestamp'), false, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns no errors if user has touched an input that is not required and left empty string', () => { + const isValid = paramIsValid('', getField('@timestamp'), false, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns no errors if field is of type date and value is valid', () => { + const isValid = paramIsValid('1994-11-05T08:15:30-05:00', getField('@timestamp'), false, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns errors if filed is of type date and value is not valid', () => { + const isValid = paramIsValid('1593478826', getField('@timestamp'), false, true); + + expect(isValid).toEqual(i18n.DATE_ERR); + }); + + test('returns no errors if field is of type number and value is an integer', () => { + const isValid = paramIsValid('4', getField('bytes'), true, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns no errors if field is of type number and value is a float', () => { + const isValid = paramIsValid('4.3', getField('bytes'), true, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns no errors if field is of type number and value is a long', () => { + const isValid = paramIsValid('-9223372036854775808', getField('bytes'), true, true); + + expect(isValid).toBeUndefined(); + }); + + test('returns errors if field is of type number and value is "hello"', () => { + const isValid = paramIsValid('hello', getField('bytes'), true, true); + + expect(isValid).toEqual(i18n.NUMBER_ERR); + }); + + test('returns errors if field is of type number and value is "123abc"', () => { + const isValid = paramIsValid('123abc', getField('bytes'), true, true); + + expect(isValid).toEqual(i18n.NUMBER_ERR); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts new file mode 100644 index 0000000000000..3d091b7a9b21f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import dateMath from '@kbn/datemath'; +import { DataViewFieldBase } from '@kbn/es-query'; +import { checkEmptyValue } from '../check_empty_value'; + +import * as i18n from '../translations'; + +/** + * Very basic validation for values + * @param param the value being checked + * @param field the selected field + * @param isRequired whether or not an empty value is allowed + * @param touched has field been touched by user + * @returns undefined if valid, string with error message if invalid + */ +export const paramIsValid = ( + param: string | undefined, + field: DataViewFieldBase | undefined, + isRequired: boolean, + touched: boolean +): string | undefined => { + if (field == null) { + return undefined; + } + + const emptyValueError = checkEmptyValue(param, field, isRequired, touched); + if (emptyValueError !== null) { + return emptyValueError; + } + + switch (field.type) { + case 'date': + const moment = dateMath.parse(param ?? ''); + const isDate = Boolean(moment && moment.isValid()); + return isDate ? undefined : i18n.DATE_ERR; + case 'number': + const isNum = param != null && param.trim() !== '' && !isNaN(+param); + return isNum ? undefined : i18n.NUMBER_ERR; + default: + return undefined; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/translations/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/translations/index.ts new file mode 100644 index 0000000000000..51790e96ba682 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/translations/index.ts @@ -0,0 +1,79 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const LOADING = i18n.translate('autocomplete.loadingDescription', { + defaultMessage: 'Loading...', +}); + +export const SELECT_FIELD_FIRST = i18n.translate('autocomplete.selectField', { + defaultMessage: 'Please select a field first...', +}); + +export const FIELD_REQUIRED_ERR = i18n.translate('autocomplete.fieldRequiredError', { + defaultMessage: 'Value cannot be empty', +}); + +export const NUMBER_ERR = i18n.translate('autocomplete.invalidNumberError', { + defaultMessage: 'Not a valid number', +}); + +export const DATE_ERR = i18n.translate('autocomplete.invalidDateError', { + defaultMessage: 'Not a valid date', +}); + +export const BINARY_TYPE_NOT_SUPPORTED = i18n.translate('autocomplete.invalidBinaryType', { + defaultMessage: 'Binary fields are currently unsupported', +}); +export const FIELD_SPACE_WARNING = i18n.translate('autocomplete.fieldSpaceWarning', { + defaultMessage: "Warning: Spaces at the start or end of this value aren't being displayed.", +}); + +export const LISTS_TOOLTIP_INFO = i18n.translate('autocomplete.listsTooltipWarning', { + defaultMessage: "Lists that aren't able to be processed by this rule type will be disabled.", +}); + +export const SEE_DOCUMENTATION = i18n.translate('autocomplete.seeDocumentation', { + defaultMessage: 'See Documentation', +}); + +export const FIELD_CONFLICT_INDICES_WARNING_TITLE = i18n.translate( + 'autocomplete.conflictIndicesWarning.title', + { + defaultMessage: 'Mapping Conflict', + } +); + +export const FIELD_CONFLICT_INDICES_WARNING_DESCRIPTION = i18n.translate( + 'autocomplete.conflictIndicesWarning.description', + { + defaultMessage: + 'This field is defined as different types across the following indices or is unmapped. This can cause unexpected query results.', + } +); + +export const CONFLICT_MULTIPLE_INDEX_DESCRIPTION = (name: string, count: number): string => + i18n.translate('autocomplete.conflictIndicesWarning.index.description', { + defaultMessage: '{name} ({count} indices)', + values: { count, name }, + }); + +export const SHOW_VALUE_LIST_MODAL = i18n.translate('autocomplete.showValueListModal', { + defaultMessage: 'Show value list', +}); + +// eslint-disable-next-line import/no-default-export +export default { + LOADING, + SELECT_FIELD_FIRST, + FIELD_REQUIRED_ERR, + NUMBER_ERR, + DATE_ERR, + FIELD_SPACE_WARNING, + BINARY_TYPE_NOT_SUPPORTED, +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/type_match/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/type_match/index.test.ts new file mode 100644 index 0000000000000..74c713f63d360 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/type_match/index.test.ts @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import { typeMatch } from '.'; + +describe('type_match', () => { + test('ip -> ip is true', () => { + expect(typeMatch('ip', 'ip')).toEqual(true); + }); + + test('keyword -> keyword is true', () => { + expect(typeMatch('keyword', 'keyword')).toEqual(true); + }); + + test('text -> text is true', () => { + expect(typeMatch('text', 'text')).toEqual(true); + }); + + test('ip_range -> ip is true', () => { + expect(typeMatch('ip_range', 'ip')).toEqual(true); + }); + + test('date_range -> date is true', () => { + expect(typeMatch('date_range', 'date')).toEqual(true); + }); + + test('double_range -> double is true', () => { + expect(typeMatch('double_range', 'double')).toEqual(true); + }); + + test('float_range -> float is true', () => { + expect(typeMatch('float_range', 'float')).toEqual(true); + }); + + test('integer_range -> integer is true', () => { + expect(typeMatch('integer_range', 'integer')).toEqual(true); + }); + + test('long_range -> long is true', () => { + expect(typeMatch('long_range', 'long')).toEqual(true); + }); + + test('ip -> date is false', () => { + expect(typeMatch('ip', 'date')).toEqual(false); + }); + + test('long -> float is false', () => { + expect(typeMatch('long', 'float')).toEqual(false); + }); + + test('integer -> long is false', () => { + expect(typeMatch('integer', 'long')).toEqual(false); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/type_match/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/type_match/index.ts new file mode 100644 index 0000000000000..0e368127b596c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/src/type_match/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import type { Type } from '@kbn/securitysolution-io-ts-list-types'; + +/** + * Given an input list type and a string based ES type this will match + * if they're exact or if they are compatible with a range + * @param type The type to match against the esType + * @param esType The ES type to match with + */ +export const typeMatch = (type: Type, esType: string): boolean => { + return ( + type === esType || + (type === 'ip_range' && esType === 'ip') || + (type === 'date_range' && esType === 'date') || + (type === 'double_range' && esType === 'double') || + (type === 'float_range' && esType === 'float') || + (type === 'integer_range' && esType === 'integer') || + (type === 'long_range' && esType === 'long') + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/tsconfig.json new file mode 100644 index 0000000000000..e4f0b64736b07 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-autocomplete/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "kbn_references": [ + "@kbn/datemath", + "@kbn/es-query", + "@kbn/i18n", + "@kbn/securitysolution-io-ts-list-types", + "@kbn/securitysolution-list-hooks", + "@kbn/securitysolution-list-utils", + "@kbn/doc-links", + "@kbn/securitysolution-utils", + ], + "exclude": [ + "target/**/*", + ], +} diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/README.md similarity index 100% rename from packages/kbn-securitysolution-endpoint-exceptions-common/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.gen.ts new file mode 100644 index 0000000000000..c8e4f90c347a4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.gen.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create endpoint list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { EndpointList } from '../model/endpoint_list_common.gen'; + +export type CreateEndpointListResponse = z.infer; +export const CreateEndpointListResponse = EndpointList; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.schema.yaml new file mode 100644 index 0000000000000..12b131e728c55 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list/create_endpoint_list.schema.yaml @@ -0,0 +1,45 @@ +openapi: 3.0.0 +info: + title: Create endpoint list API endpoint + version: '2023-10-31' +paths: + /api/endpoint_list: + post: + x-labels: [serverless, ess] + x-codegen-enabled: true + operationId: CreateEndpointList + summary: Create an endpoint exception list + description: Create an endpoint exception list, which groups endpoint exception list items. If an endpoint exception list already exists, an empty response is returned. + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointList' + 400: + description: Invalid input data + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Insufficient privileges + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.gen.ts similarity index 81% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.gen.ts index ed3a60dc08f30..c4ce0697b2372 100644 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.schema.yaml similarity index 79% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.schema.yaml index b90bee75fc073..0393fa3d943eb 100644 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/create_endpoint_list_item/create_endpoint_list_item.schema.yaml @@ -57,29 +57,29 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Insufficient privileges content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 409: description: Endpoint list item already exists content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.gen.ts similarity index 75% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.gen.ts index 5cb5f518494ec..4f268641f93cd 100644 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.schema.yaml new file mode 100644 index 0000000000000..fac5a12ecc5df --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/delete_endpoint_list_item/delete_endpoint_list_item.schema.yaml @@ -0,0 +1,64 @@ +openapi: 3.0.0 +info: + title: Delete endpoint list item API endpoint + version: '2023-10-31' +paths: + /api/endpoint_list/items: + delete: + x-labels: [serverless, ess] + x-codegen-enabled: true + operationId: DeleteEndpointListItem + summary: Delete an endpoint exception list item + description: Delete an endpoint exception list item using the `id` or `item_id` field. + parameters: + - name: id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' + - name: item_id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointListItem' + 400: + description: Invalid input data + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Insufficient privileges + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Endpoint list item not found + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.gen.ts similarity index 83% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.gen.ts index a830572c7b503..5b1e10d9bb04b 100644 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.schema.yaml new file mode 100644 index 0000000000000..35f565bfa27ff --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/find_endpoint_list_item/find_endpoint_list_item.schema.yaml @@ -0,0 +1,113 @@ +openapi: 3.0.0 +info: + title: Find endpoint list items API endpoint + version: '2023-10-31' +paths: + /api/endpoint_list/items/_find: + get: + x-labels: [serverless, ess] + x-codegen-enabled: true + operationId: FindEndpointListItems + summary: Get endpoint exception list items + description: Get a list of all endpoint exception list items. + parameters: + - name: filter + in: query + required: false + description: | + Filters the returned results according to the value of the specified field, + using the `:` syntax. + schema: + $ref: '#/components/schemas/FindEndpointListItemsFilter' + - name: page + in: query + required: false + description: The page number to return + schema: + type: integer + minimum: 0 + - name: per_page + in: query + required: false + description: The number of exception list items to return per page + schema: + type: integer + minimum: 0 + - name: sort_field + in: query + required: false + description: Determines which field is used to sort the results + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + - name: sort_order + in: query + required: false + description: Determines the sort order, which can be `desc` or `asc` + schema: + type: string + enum: [desc, asc] + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointListItem' + page: + type: integer + minimum: 0 + per_page: + type: integer + minimum: 0 + total: + type: integer + minimum: 0 + pit: + type: string + required: + - data + - page + - per_page + - total + 400: + description: Invalid input data + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Insufficient privileges + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Endpoint list not found + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + FindEndpointListItemsFilter: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/index.ts new file mode 100644 index 0000000000000..912af19448e44 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './create_endpoint_list/create_endpoint_list.gen'; +export * from './create_endpoint_list_item/create_endpoint_list_item.gen'; +export * from './read_endpoint_list_item/read_endpoint_list_item.gen'; +export * from './update_endpoint_list_item/update_endpoint_list_item.gen'; +export * from './delete_endpoint_list_item/delete_endpoint_list_item.gen'; +export * from './find_endpoint_list_item/find_endpoint_list_item.gen'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.gen.ts new file mode 100644 index 0000000000000..a68abd53c11c4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.gen.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Common Exception List Attributes + * version: not applicable + */ + +import { z } from '@kbn/zod'; + +import { + ExceptionList, + ExceptionListItem, +} from '@kbn/securitysolution-exceptions-common/api/model/exception_list_common.gen'; + +export type EndpointList = z.infer; +export const EndpointList = z.union([ExceptionList, z.object({}).strict()]); + +export type EndpointListItem = z.infer; +export const EndpointListItem = ExceptionListItem; diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/model/endpoint_list_common.schema.yaml diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.gen.ts similarity index 75% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.gen.ts index 4a9c335b395bc..e2dc38450bbbd 100644 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.schema.yaml new file mode 100644 index 0000000000000..45f0c384c7f09 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/read_endpoint_list_item/read_endpoint_list_item.schema.yaml @@ -0,0 +1,66 @@ +openapi: 3.0.0 +info: + title: Read endpoint list item API endpoint + version: '2023-10-31' +paths: + /api/endpoint_list/items: + get: + x-labels: [serverless, ess] + x-codegen-enabled: true + operationId: ReadEndpointListItem + summary: Get an endpoint exception list item + description: Get the details of an endpoint exception list item using the `id` or `item_id` field. + parameters: + - name: id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' + - name: item_id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../../../kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: array + items: + $ref: '../model/endpoint_list_common.schema.yaml#/components/schemas/EndpointListItem' + 400: + description: Invalid input data + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Insufficient privileges + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Endpoint list item not found + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.gen.ts similarity index 83% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.gen.ts index 0a235ca2ff896..ec86992d58b7b 100644 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.schema.yaml similarity index 80% rename from packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.schema.yaml index 679000674c7b2..cd4cbf0c11d5e 100644 --- a/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/api/update_endpoint_list_item/update_endpoint_list_item.schema.yaml @@ -62,29 +62,29 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Insufficient privileges content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 404: description: Endpoint list item not found content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/ess/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/ess/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/ess/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/ess/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/serverless/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/serverless/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/serverless/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/serverless/security_solution_endpoint_exceptions_api_2023_10_31.bundled.schema.yaml diff --git a/packages/kbn-securitysolution-endpoint-exceptions-common/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-endpoint-exceptions-common/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/package.json new file mode 100644 index 0000000000000..39e6232e4e0f5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/package.json @@ -0,0 +1,11 @@ +{ + "description": "OpenAPI Endpoint Exceptions Common", + "license": "Elastic License 2.0", + "name": "@kbn/securitysolution-endpoint-exceptions-common", + "private": true, + "version": "1.0.0", + "scripts": { + "openapi:generate": "node scripts/openapi_generate", + "openapi:bundle": "node scripts/openapi_bundle" + } +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js new file mode 100644 index 0000000000000..c54e162b6462e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js @@ -0,0 +1,65 @@ +/* + * 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. + */ + +require('../../../../../../src/setup_node_env'); +// eslint-disable-next-line import/no-nodejs-modules +const { join, resolve } = require('path'); +const { bundle } = require('@kbn/openapi-bundler'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await bundle({ + sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), + outputFilePath: join( + ROOT, + 'docs/openapi/serverless/security_solution_endpoint_exceptions_api_{version}.bundled.schema.yaml' + ), + options: { + includeLabels: ['serverless'], + prototypeDocument: { + info: { + title: 'Security Endpoint Exceptions API (Elastic Cloud Serverless)', + description: 'Endpoint Exceptions API allow you to manage Endpoint lists.', + }, + tags: [ + { + name: 'Security Endpoint Exceptions API', + 'x-displayName': 'Security endpoint exceptions', + description: + "Endpoint Exceptions API allows you to manage detection rule endpoint exceptions to prevent a rule from generating an alert from incoming events even when the rule's other criteria are met.", + }, + ], + }, + }, + }); + + await bundle({ + sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), + outputFilePath: join( + ROOT, + 'docs/openapi/ess/security_solution_endpoint_exceptions_api_{version}.bundled.schema.yaml' + ), + options: { + includeLabels: ['ess'], + prototypeDocument: { + info: { + title: 'Security Endpoint Exceptions API (Elastic Cloud and self-hosted)', + description: 'Endpoint Exceptions API allow you to manage Endpoint lists.', + }, + tags: [ + { + name: 'Security Endpoint Exceptions API', + 'x-displayName': 'Security endpoint exceptions', + description: + "Endpoint Exceptions API allows you to manage detection rule endpoint exceptions to prevent a rule from generating an alert from incoming events even when the rule's other criteria are met.", + }, + ], + }, + }, + }); +})(); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_generate.js b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_generate.js new file mode 100644 index 0000000000000..9a303c4f74bef --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_generate.js @@ -0,0 +1,37 @@ +/* + * 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. + */ + +require('../../../../../../src/setup_node_env'); +// eslint-disable-next-line import/no-nodejs-modules +const { join, resolve } = require('path'); +const { generate } = require('@kbn/openapi-generator'); +const { REPO_ROOT } = require('@kbn/repo-info'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await generate({ + title: 'OpenAPI Endpoint Exceptions API Schemas', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'zod_operation_schema', + }); + + await generate({ + title: 'Endpoint Exceptions API client for tests', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'api_client_supertest', + skipLinting: true, + bundle: { + outFile: join( + REPO_ROOT, + 'x-pack/test/api_integration/services/security_solution_endpoint_exceptions_api.gen.ts' + ), + }, + }); +})(); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/tsconfig.json new file mode 100644 index 0000000000000..38f2843b03ad7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "exclude": ["target/**/*"], + "extends": "../../../../../tsconfig.base.json", + "include": ["**/*.ts"], + "kbn_references": [ + "@kbn/securitysolution-exceptions-common", + "@kbn/openapi-common", + "@kbn/zod", + ] +} diff --git a/packages/kbn-securitysolution-exception-list-components/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/README.md similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/index.ts new file mode 100644 index 0000000000000..40277892f1f79 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +export * from './src/search_bar'; +export * from './src/empty_viewer_state'; +export * from './src/pagination/pagination'; +// export * from './src/exceptions_utility/exceptions_utility'; +export * from './src/exception_items'; +export * from './src/exception_item_card'; +export * from './src/value_with_space_warning'; +export * from './src/types'; +export * from './src/list_header'; +export * from './src/header_menu'; +export * from './src/generate_linked_rules_menu_item'; +export * from './src/wildcard_with_wrong_operator_callout'; +export * from './src/partial_code_signature_callout'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/jest.config.js new file mode 100644 index 0000000000000..d9a562b21e875 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/jest.config.js @@ -0,0 +1,29 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: [ + '/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components', + ], + coverageReporters: ['text', 'html'], + collectCoverageFrom: [ + '/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/*.{ts,tsx}', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/*.test', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/types/*', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/*.type', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/*.styles', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/mocks/*', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/*.config', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/translations', + '!/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/**/types/*', + ], + setupFilesAfterEnv: [ + '/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/setup_test.ts', + ], +}; diff --git a/packages/kbn-securitysolution-exception-list-components/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/package.json new file mode 100644 index 0000000000000..f9246cb9353d0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/securitysolution-exception-list-components", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0", + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/setup_test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/setup_test.ts new file mode 100644 index 0000000000000..72e0edd0d07f7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/setup_test.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import '@testing-library/jest-dom'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/assets/images/illustration_product_no_results_magnifying_glass.svg b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/assets/images/illustration_product_no_results_magnifying_glass.svg similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/assets/images/illustration_product_no_results_magnifying_glass.svg rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/assets/images/illustration_product_no_results_magnifying_glass.svg diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/custom.d.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/custom.d.ts new file mode 100644 index 0000000000000..18dda6a910031 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/custom.d.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +declare module '*.svg' { + const content: string; + // eslint-disable-next-line import/no-default-export + export default content; +} diff --git a/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/empty_viewer_state.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/empty_viewer_state.test.tsx similarity index 93% rename from packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/empty_viewer_state.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/empty_viewer_state.test.tsx index 1b711185c526c..7df3f732711a0 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/empty_viewer_state.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/empty_viewer_state.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/index.tsx new file mode 100644 index 0000000000000..2e489cb5dca97 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/empty_viewer_state/index.tsx @@ -0,0 +1,133 @@ +/* + * 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. + */ + +import React, { useMemo } from 'react'; +import type { FC } from 'react'; +import { css } from '@emotion/react'; +import { + EuiSkeletonText, + EuiImage, + EuiEmptyPrompt, + EuiButton, + useEuiTheme, + EuiPanel, +} from '@elastic/eui'; +import type { ExpressionColor } from '@elastic/eui/src/components/expression/expression'; +import type { EuiFacetGroupLayout } from '@elastic/eui/src/components/facet/facet_group'; +import { euiThemeVars } from '@kbn/ui-theme'; +import { ListTypeText, ViewerStatus } from '../types'; +import * as i18n from '../translations'; +import illustration from '../assets/images/illustration_product_no_results_magnifying_glass.svg'; + +interface EmptyViewerStateProps { + title?: string; + body?: string; + buttonText?: string; + listType?: ListTypeText; + isReadOnly: boolean; + viewerStatus: ViewerStatus; + onEmptyButtonStateClick?: () => void | null; +} + +const panelCss = css` + margin: ${euiThemeVars.euiSizeL} 0; + padding: ${euiThemeVars.euiSizeL} 0; +`; +const EmptyViewerStateComponent: FC = ({ + title, + body, + buttonText, + listType, + isReadOnly, + viewerStatus, + onEmptyButtonStateClick, +}) => { + const { euiTheme } = useEuiTheme(); + + const euiEmptyPromptProps = useMemo(() => { + switch (viewerStatus) { + case ViewerStatus.ERROR: { + return { + color: 'danger' as ExpressionColor, + iconType: 'error', + title: ( +

{title || i18n.EMPTY_VIEWER_STATE_ERROR_TITLE}

+ ), + body:

{body || i18n.EMPTY_VIEWER_STATE_ERROR_BODY}

, + 'data-test-subj': 'errorViewerState', + }; + } + case ViewerStatus.EMPTY: + return { + color: 'subdued' as ExpressionColor, + iconType: 'plusInCircle', + iconColor: euiTheme.colors.darkestShade, + title: ( +

{title || i18n.EMPTY_VIEWER_STATE_EMPTY_TITLE}

+ ), + body:

{body || i18n.EMPTY_VIEWER_STATE_EMPTY_BODY}

, + 'data-test-subj': 'emptyViewerState', + actions: [ + + {buttonText || i18n.EMPTY_VIEWER_STATE_EMPTY_VIEWER_BUTTON(listType || 'rule')} + , + ], + }; + case ViewerStatus.EMPTY_SEARCH: + return { + color: 'plain' as ExpressionColor, + layout: 'horizontal' as EuiFacetGroupLayout, + hasBorder: true, + hasShadow: false, + icon: , + title: ( +

+ {title || i18n.EMPTY_VIEWER_STATE_EMPTY_SEARCH_TITLE} +

+ ), + body: ( +

+ {body || i18n.EMPTY_VIEWER_STATE_EMPTY_SEARCH_BODY} +

+ ), + 'data-test-subj': 'emptySearchViewerState', + }; + } + }, [ + viewerStatus, + euiTheme.colors.darkestShade, + title, + body, + onEmptyButtonStateClick, + isReadOnly, + buttonText, + listType, + ]); + + return ( + + + + + + ); +}; + +export const EmptyViewerState = React.memo(EmptyViewerStateComponent); + +EmptyViewerState.displayName = 'EmptyViewerState'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/__snapshots__/comments.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/__snapshots__/comments.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/__snapshots__/comments.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/__snapshots__/comments.test.tsx.snap diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/comments.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/comments.test.tsx similarity index 83% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/comments.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/comments.test.tsx index c8c8e92cd6c70..caf989efcc9ec 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/comments.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/comments.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/index.tsx new file mode 100644 index 0000000000000..76ef48fba0a90 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/comments/index.tsx @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import React, { memo } from 'react'; +import type { EuiCommentProps } from '@elastic/eui'; +import { EuiAccordion, EuiCommentList, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; +import * as i18n from '../translations'; + +const accordionCss = css` + color: ${euiThemeVars.euiColorPrimary}; +`; + +export interface ExceptionItemCardCommentsProps { + comments: EuiCommentProps[]; + dataTestSubj?: string; +} + +export const ExceptionItemCardComments = memo( + ({ comments, dataTestSubj }) => { + if (!comments.length) return null; + return ( + + + {i18n.exceptionItemCardCommentsAccordion(comments.length)} + + } + arrowDisplay="none" + data-test-subj="exceptionItemCardComments" + > + + + + + + ); + } +); + +ExceptionItemCardComments.displayName = 'ExceptionItemCardComments'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.config.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.config.ts similarity index 77% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.config.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.config.ts index fdb545dc2c031..0c826f40f0224 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.config.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.config.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { ListOperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.styles.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.styles.tsx new file mode 100644 index 0000000000000..043e2e2e44850 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.styles.tsx @@ -0,0 +1,36 @@ +/* + * 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. + */ + +import { cx } from '@emotion/css'; +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; + +// TODO check font Roboto Mono +export const nestedGroupSpaceCss = css` + margin-left: ${euiThemeVars.euiSizeXL}; + margin-bottom: ${euiThemeVars.euiSizeXS}; + padding-top: ${euiThemeVars.euiSizeXS}; +`; + +export const borderCss = cx( + 'eui-xScroll', + ` + border: 1px; + border-color: #d3dae6; + border-style: solid; +` +); + +export const valueContainerCss = css` + display: flex; + align-items: center; + margin-left: ${euiThemeVars.euiSizeS}; +`; +export const expressionContainerCss = css` + display: flex; + align-items: center; +`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.test.tsx similarity index 96% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.test.tsx index e19327226de21..6cd3ee06d203a 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/conditions.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { render } from '@testing-library/react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.test.tsx similarity index 93% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.test.tsx index e49d18ec78c49..07de278ace7b3 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { ListOperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.tsx similarity index 85% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.tsx index 2fa113e5a612a..aeca92d4d0031 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.helper.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React, { ElementType } from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.test.tsx similarity index 83% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.test.tsx index 7eb141493ef40..bed784f46b878 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/entry_content.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/index.tsx new file mode 100644 index 0000000000000..7f75694b16d34 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/index.tsx @@ -0,0 +1,81 @@ +/* + * 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. + */ + +import React, { ElementType, FC, memo } from 'react'; +import { EuiExpression, EuiToken, EuiFlexGroup } from '@elastic/eui'; +import { ListOperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { + nestedGroupSpaceCss, + valueContainerCss, + expressionContainerCss, +} from '../conditions.styles'; +import type { Entry } from '../types'; +import * as i18n from '../../translations'; +import { getValue, getValueExpression } from './entry_content.helper'; + +interface EntryContentProps { + entry: Entry; + index: number; + isNestedEntry?: boolean; + dataTestSubj?: string; + showValueListModal: ElementType; +} + +export const EntryContent: FC = memo( + ({ entry, index, isNestedEntry = false, dataTestSubj, showValueListModal }) => { + const { field, type } = entry; + const value = getValue(entry); + const operator = 'operator' in entry ? entry.operator : ''; + + const entryKey = `${field}${type}${value}${index}`; + return ( +
+
+ {isNestedEntry ? ( + + + +
+ + {getValueExpression( + type as ListOperatorTypeEnum, + operator, + value, + showValueListModal + )} +
+
+ ) : ( + <> + + + {getValueExpression( + type as ListOperatorTypeEnum, + operator, + value, + showValueListModal + )} + + )} +
+
+ ); + } +); +EntryContent.displayName = 'EntryContent'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/index.tsx new file mode 100644 index 0000000000000..804af918e4f16 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/index.tsx @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import React, { memo } from 'react'; +import { EuiPanel } from '@elastic/eui'; + +import { borderCss } from './conditions.styles'; +import { EntryContent } from './entry_content'; +import { OsCondition } from './os_conditions'; +import type { CriteriaConditionsProps, Entry } from './types'; + +export const ExceptionItemCardConditions = memo( + ({ os, entries, dataTestSubj, showValueListModal }) => { + return ( + + {os?.length ? : null} + {entries.map((entry: Entry, index: number) => { + const nestedEntries = 'entries' in entry ? entry.entries : []; + return ( +
+ + {nestedEntries?.length + ? nestedEntries.map((nestedEntry: Entry, nestedIndex: number) => ( + + )) + : null} +
+ ); + })} +
+ ); + } +); +ExceptionItemCardConditions.displayName = 'ExceptionItemCardConditions'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/__snapshots__/os_conditions.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/__snapshots__/os_conditions.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/__snapshots__/os_conditions.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/__snapshots__/os_conditions.test.tsx.snap diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/index.tsx new file mode 100644 index 0000000000000..3a2dded6ce2ba --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/index.tsx @@ -0,0 +1,37 @@ +/* + * 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. + */ + +import React, { memo, useMemo } from 'react'; +import { EuiExpression } from '@elastic/eui'; + +import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { OS_LABELS } from '../conditions.config'; +import * as i18n from '../../translations'; + +export interface OsConditionsProps { + dataTestSubj?: string; + os: ExceptionListItemSchema['os_types']; +} + +export const OsCondition = memo(({ os, dataTestSubj }) => { + const osLabel = useMemo(() => { + return os.map((osValue) => OS_LABELS[osValue] ?? osValue).join(', '); + }, [os]); + return osLabel ? ( +
+ + + + +
+ ) : null; +}); +OsCondition.displayName = 'OsCondition'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/os_conditions.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/os_conditions.test.tsx similarity index 82% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/os_conditions.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/os_conditions.test.tsx index 3aea8d5ed0065..a3575c1845227 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/os_conditions.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/os_conditions/os_conditions.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; @@ -35,6 +33,7 @@ describe('OsCondition', () => { expect(wrapper.container).toMatchSnapshot(); }); it('should return any os sent', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any const wrapper = render(); expect(wrapper.getByTestId('osLabel')).toHaveTextContent(i18n.CONDITION_OS); expect(wrapper.getByTestId('osValue')).toHaveTextContent( diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/types.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/types.ts new file mode 100644 index 0000000000000..a69a0f16c1d7b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/types.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +import type { + EntryExists, + EntryList, + EntryMatch, + EntryMatchAny, + EntryMatchWildcard, + EntryNested, + ExceptionListItemSchema, +} from '@kbn/securitysolution-io-ts-list-types'; +import { ElementType } from 'react'; + +export type Entry = + | EntryExists + | EntryList + | EntryMatch + | EntryMatchAny + | EntryMatchWildcard + | EntryNested; + +export type Entries = ExceptionListItemSchema['entries']; +export interface CriteriaConditionsProps { + entries: Entries; + dataTestSubj: string; + os?: ExceptionListItemSchema['os_types']; + showValueListModal: ElementType; +} diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.test.tsx similarity index 94% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.test.tsx index aeaf5755ea1da..b3f06eddec715 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx similarity index 91% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx index 44456a130687d..52d2f730b33b9 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React, { FC, ElementType } from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/header.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/header.test.tsx similarity index 81% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/header.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/header.test.tsx index 5de4f5d729f0c..9127589b5b560 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/header.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/header.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/index.tsx new file mode 100644 index 0000000000000..88eb6233a9350 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/header/index.tsx @@ -0,0 +1,44 @@ +/* + * 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. + */ + +import React, { memo } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; +import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { HeaderMenu } from '../../header_menu'; + +export interface ExceptionItemCardHeaderProps { + item: ExceptionListItemSchema; + actions: Array<{ key: string; icon: string; label: string | boolean; onClick: () => void }>; + disableActions?: boolean; + dataTestSubj: string; +} + +export const ExceptionItemCardHeader = memo( + ({ item, actions, disableActions = false, dataTestSubj }) => { + return ( + + + +

{item.name}

+
+
+ + + +
+ ); + } +); + +ExceptionItemCardHeader.displayName = 'ExceptionItemCardHeader'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/index.ts new file mode 100644 index 0000000000000..2d2b38d288da9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +export * from './conditions'; +export * from './header'; +export * from './meta'; +export * from './comments'; +export * from './exception_item_card'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/__snapshots__/details_info.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/__snapshots__/details_info.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/__snapshots__/details_info.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/__snapshots__/details_info.test.tsx.snap diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/details_info.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/details_info.test.tsx new file mode 100644 index 0000000000000..3950d674a1add --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/details_info.test.tsx @@ -0,0 +1,38 @@ +/* + * 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. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { MetaInfoDetails } from '.'; + +describe('MetaInfoDetails', () => { + it('should render lastUpdate as string', () => { + const wrapper = render( + + ); + expect(wrapper.container).toMatchSnapshot(); + expect(wrapper.getByTestId('MetaInfoDetailslastUpdate')).toHaveTextContent('last update'); + }); + it('should render lastUpdate as JSX Element', () => { + const wrapper = render( + Last update value

} + lastUpdateValue="value" + /> + ); + expect(wrapper.container).toMatchSnapshot(); + expect(wrapper.getByTestId('MetaInfoDetailslastUpdate')).toHaveTextContent('Last update value'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/index.tsx new file mode 100644 index 0000000000000..209ce3b59553c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/index.tsx @@ -0,0 +1,67 @@ +/* + * 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. + */ + +import React, { memo } from 'react'; +import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; +import * as i18n from '../../translations'; + +interface MetaInfoDetailsProps { + label: string; + lastUpdate: JSX.Element | string; + lastUpdateValue?: string; + dataTestSubj?: string; +} + +const euiBadgeFontFamily = css` + font-family: ${euiThemeVars.euiFontFamily}; +`; +export const MetaInfoDetails = memo( + ({ label, lastUpdate, lastUpdateValue, dataTestSubj }) => { + return ( + + + + {label} + + + + + {lastUpdate} + + + {lastUpdateValue != null && ( + <> + + + {i18n.EXCEPTION_ITEM_CARD_META_BY} + + + + + + + {lastUpdateValue} + + + + + + )} + + ); + } +); + +MetaInfoDetails.displayName = 'MetaInfoDetails'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx new file mode 100644 index 0000000000000..8c7734ab51c99 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx @@ -0,0 +1,123 @@ +/* + * 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. + */ + +import React, { memo, useMemo } from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; +import * as i18n from '../translations'; +import type { Rule } from '../../types'; +import { MetaInfoDetails } from './details_info'; +import { HeaderMenu } from '../../header_menu'; +import { generateLinkedRulesMenuItems } from '../../generate_linked_rules_menu_item'; + +const itemCss = css` + border-right: 1px solid #d3dae6; + padding: ${euiThemeVars.euiSizeS} ${euiThemeVars.euiSizeM} ${euiThemeVars.euiSizeS} 0; +`; + +export interface ExceptionItemCardMetaInfoProps { + item: ExceptionListItemSchema; + rules: Rule[]; + dataTestSubj: string; + formattedDateComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common + securityLinkAnchorComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common +} + +export const ExceptionItemCardMetaInfo = memo( + ({ item, rules, dataTestSubj, securityLinkAnchorComponent, formattedDateComponent }) => { + const FormattedDateComponent = formattedDateComponent; + + const referencedLinks = useMemo( + () => + generateLinkedRulesMenuItems({ + dataTestSubj, + linkedRules: rules, + securityLinkAnchorComponent, + }), + [dataTestSubj, rules, securityLinkAnchorComponent] + ); + + const isExpired = useMemo( + () => (item.expire_time ? new Date(item.expire_time) <= new Date() : false), + [item] + ); + + return ( + + {FormattedDateComponent !== null && ( + <> + + + } + lastUpdateValue={item.created_by} + dataTestSubj={`${dataTestSubj || ''}CreatedBy`} + /> + + + + + } + lastUpdateValue={item.updated_by} + dataTestSubj={`${dataTestSubj || ''}UpdatedBy`} + /> + + {item.expire_time != null && ( + <> + + + } + dataTestSubj={`${dataTestSubj || ''}ExpireTime`} + /> + + + )} + + )} + + + + + ); + } +); +ExceptionItemCardMetaInfo.displayName = 'ExceptionItemCardMetaInfo'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/meta.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/meta.test.tsx similarity index 90% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/meta.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/meta.test.tsx index 10570b2637812..f7a94d9d76ff9 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/meta.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/meta.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/translations.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/translations.ts new file mode 100644 index 0000000000000..9b1a64bd6cf40 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/translations.ts @@ -0,0 +1,179 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const exceptionItemCardEditButton = (listType: string) => + i18n.translate('exceptionList-components.exceptions.exceptionItem.card.editItemButton', { + values: { listType }, + defaultMessage: 'Edit {listType} exception', + }); + +export const exceptionItemCardDeleteButton = (listType: string) => + i18n.translate('exceptionList-components.exceptions.exceptionItem.card.deleteItemButton', { + values: { listType }, + defaultMessage: 'Delete {listType} exception', + }); + +export const EXCEPTION_ITEM_CARD_CREATED_LABEL = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.createdLabel', + { + defaultMessage: 'Created', + } +); + +export const EXCEPTION_ITEM_CARD_UPDATED_LABEL = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.updatedLabel', + { + defaultMessage: 'Updated', + } +); + +export const EXCEPTION_ITEM_CARD_EXPIRES_LABEL = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.expiresLabel', + { + defaultMessage: 'Expires at', + } +); + +export const EXCEPTION_ITEM_CARD_EXPIRED_LABEL = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.expiredLabel', + { + defaultMessage: 'Expired at', + } +); + +export const EXCEPTION_ITEM_CARD_META_BY = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.metaDetailsBy', + { + defaultMessage: 'by', + } +); + +export const exceptionItemCardCommentsAccordion = (comments: number) => + i18n.translate('exceptionList-components.exceptions.exceptionItem.card.showCommentsLabel', { + values: { comments }, + defaultMessage: 'Show {comments, plural, =1 {comment} other {comments}} ({comments})', + }); + +export const CONDITION_OPERATOR_TYPE_MATCH = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchOperator', + { + defaultMessage: 'IS', + } +); + +export const CONDITION_OPERATOR_TYPE_NOT_MATCH = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchOperator.not', + { + defaultMessage: 'IS NOT', + } +); + +export const CONDITION_OPERATOR_TYPE_WILDCARD_MATCHES = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.wildcardMatchesOperator', + { + defaultMessage: 'MATCHES', + } +); + +export const CONDITION_OPERATOR_TYPE_WILDCARD_DOES_NOT_MATCH = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.wildcardDoesNotMatchOperator', + { + defaultMessage: 'DOES NOT MATCH', + } +); + +export const CONDITION_OPERATOR_TYPE_NESTED = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.nestedOperator', + { + defaultMessage: 'has', + } +); + +export const CONDITION_OPERATOR_TYPE_MATCH_ANY = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchAnyOperator', + { + defaultMessage: 'is one of', + } +); + +export const CONDITION_OPERATOR_TYPE_NOT_MATCH_ANY = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.matchAnyOperator.not', + { + defaultMessage: 'is not one of', + } +); + +export const CONDITION_OPERATOR_TYPE_EXISTS = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.existsOperator', + { + defaultMessage: 'exists', + } +); + +export const CONDITION_OPERATOR_TYPE_DOES_NOT_EXIST = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.existsOperator.not', + { + defaultMessage: 'does not exist', + } +); + +export const CONDITION_OPERATOR_TYPE_LIST = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.listOperator', + { + defaultMessage: 'included in', + } +); + +export const CONDITION_OPERATOR_TYPE_NOT_IN_LIST = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.listOperator.not', + { + defaultMessage: 'is not included in', + } +); + +export const CONDITION_AND = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.and', + { + defaultMessage: 'AND', + } +); + +export const CONDITION_OS = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.os', + { + defaultMessage: 'OS', + } +); + +export const OS_WINDOWS = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.windows', + { + defaultMessage: 'Windows', + } +); + +export const OS_LINUX = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.linux', + { + defaultMessage: 'Linux', + } +); + +export const OS_MAC = i18n.translate( + 'exceptionList-components.exceptions.exceptionItem.card.conditions.macos', + { + defaultMessage: 'Mac', + } +); + +export const AFFECTED_RULES = (numRules: number) => + i18n.translate('exceptionList-components.exceptions.card.exceptionItem.affectedRules', { + values: { numRules }, + defaultMessage: 'Affects {numRules} {numRules, plural, =1 {rule} other {rules}}', + }); diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.test.ts similarity index 90% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.test.ts index 5c04c87727147..1a144182eeed8 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.ts similarity index 86% rename from packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.ts index 2978dfb12c727..f3da4ec925955 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/use_exception_item_card.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { useCallback, useMemo } from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/exception_items/exception_items.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_items/exception_items.test.tsx similarity index 96% rename from packages/kbn-securitysolution-exception-list-components/src/exception_items/exception_items.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_items/exception_items.test.tsx index e60cff40626ff..936a58b670f52 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/exception_items/exception_items.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_items/exception_items.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_items/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_items/index.tsx new file mode 100644 index 0000000000000..6fde321cfcb93 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_items/index.tsx @@ -0,0 +1,153 @@ +/* + * 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. + */ + +import React, { ElementType } from 'react'; +import { css } from '@emotion/react'; +import type { FC } from 'react'; +import { EuiCommentProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; + +import type { + CommentsArray, + ExceptionListItemSchema, + ExceptionListTypeEnum, +} from '@kbn/securitysolution-io-ts-list-types'; + +import { euiThemeVars } from '@kbn/ui-theme'; +import { EmptyViewerState, ExceptionItemCard, Pagination, PaginationProps } from '../..'; + +import type { + RuleReferences, + ExceptionListItemIdentifiers, + ViewerStatus, + GetExceptionItemProps, +} from '../types'; + +const exceptionItemCss = css` + margin: ${euiThemeVars.euiSize} 0; + &div:first-child { + margin: ${euiThemeVars.euiSizeXS} 0 ${euiThemeVars.euiSize}; + } +`; + +interface ExceptionItemsProps { + lastUpdated: string | number | null; + viewerStatus: ViewerStatus; + isReadOnly: boolean; + emptyViewerTitle?: string; + emptyViewerBody?: string; + emptyViewerButtonText?: string; + exceptions: ExceptionListItemSchema[]; + listType: ExceptionListTypeEnum; + ruleReferences: RuleReferences; + pagination: PaginationProps['pagination']; + editActionLabel?: string; + deleteActionLabel?: string; + dataTestSubj?: string; + securityLinkAnchorComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common + formattedDateComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common + exceptionsUtilityComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common + getFormattedComments: (comments: CommentsArray) => EuiCommentProps[]; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common + onCreateExceptionListItem?: () => void; + onDeleteException: (arg: ExceptionListItemIdentifiers) => void; + onEditExceptionItem: (item: ExceptionListItemSchema) => void; + onPaginationChange: (arg: GetExceptionItemProps) => void; + showValueListModal: ElementType; +} + +const ExceptionItemsComponent: FC = ({ + lastUpdated, + viewerStatus, + isReadOnly, + exceptions, + listType, + ruleReferences, + emptyViewerTitle, + emptyViewerBody, + emptyViewerButtonText, + pagination, + dataTestSubj, + editActionLabel, + deleteActionLabel, + securityLinkAnchorComponent, + exceptionsUtilityComponent, + formattedDateComponent, + getFormattedComments, + onPaginationChange, + onDeleteException, + onEditExceptionItem, + onCreateExceptionListItem, + showValueListModal, +}) => { + const ExceptionsUtility = exceptionsUtilityComponent; + if (!exceptions.length || viewerStatus) + return ( + + ); + const ShowValueListModal = showValueListModal; + return ( + <> + + + + + {exceptions.map((exception) => ( + + + + ))} + + + + + + ); +}; + +ExceptionItemsComponent.displayName = 'ExceptionItemsComponent'; + +export const ExceptionItems = React.memo(ExceptionItemsComponent); + +ExceptionItems.displayName = 'ExceptionsItems'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/__snapshots__/generate_linked_rules_menu_item.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/__snapshots__/generate_linked_rules_menu_item.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/__snapshots__/generate_linked_rules_menu_item.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/__snapshots__/generate_linked_rules_menu_item.test.tsx.snap diff --git a/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/generate_linked_rules_menu_item.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/generate_linked_rules_menu_item.test.tsx similarity index 80% rename from packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/generate_linked_rules_menu_item.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/generate_linked_rules_menu_item.test.tsx index 01f708a0f6bdc..2bf26f551fb06 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/generate_linked_rules_menu_item.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/generate_linked_rules_menu_item.test.tsx @@ -1,15 +1,12 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { render } from '@testing-library/react'; -import { ReactElement } from 'react'; -import { ElementType } from 'react'; +import { ReactElement, ElementType } from 'react'; import { generateLinkedRulesMenuItems } from '.'; import { rules } from '../mocks/rule_references.mock'; import { @@ -45,7 +42,7 @@ describe('generateLinedRulesMenuItems', () => { leftIcon: 'check', }) as ReactElement[]; - result.map((link) => { + result.forEach((link) => { const wrapper = render(link); expect(wrapper.container).toMatchSnapshot(); expect(wrapper.getByTestId('generateLinedRulesMenuItemsTestActionItem1a2b3c')); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx new file mode 100644 index 0000000000000..9187d0975e92a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx @@ -0,0 +1,49 @@ +/* + * 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. + */ + +import React, { ElementType, ReactElement } from 'react'; +import { EuiContextMenuItem, EuiFlexGroup, EuiFlexItem, EuiIcon, IconType } from '@elastic/eui'; +import { Rule } from '../types'; +import { itemContentCss, containerCss } from './menu_link.styles'; + +interface MenuItemLinkedRulesProps { + leftIcon?: IconType; + dataTestSubj?: string; + linkedRules: Rule[]; + securityLinkAnchorComponent: ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common +} + +export const generateLinkedRulesMenuItems = ({ + dataTestSubj, + linkedRules, + securityLinkAnchorComponent, + leftIcon = '', +}: MenuItemLinkedRulesProps): ReactElement[] | null => { + if (!linkedRules.length || securityLinkAnchorComponent === null) return null; + + const SecurityLinkAnchor = securityLinkAnchorComponent; + return linkedRules.map((rule) => { + return ( + 1 ? containerCss : ''} + data-test-subj={`${dataTestSubj || ''}ActionItem${rule.id}`} + key={rule.id} + > + + {leftIcon ? ( + + + + ) : null} + + + + + + ); + }); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/menu_link.styles.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/menu_link.styles.ts new file mode 100644 index 0000000000000..886369b22e23b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/menu_link.styles.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; + +export const containerCss = css` + border-bottom: 1px solid ${euiThemeVars.euiColorLightShade}; +`; + +export const itemContentCss = css` + color: ${euiThemeVars.euiColorPrimary}; + flex-basis: content; +`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx similarity index 93% rename from packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx index 7e14b503721b5..2869b16e3aaa2 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { createEvent, fireEvent, render } from '@testing-library/react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx new file mode 100644 index 0000000000000..bd634b5f6c361 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx @@ -0,0 +1,137 @@ +/* + * 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. + */ + +import React, { FC, ReactElement, useMemo, useState } from 'react'; +import { + EuiButtonEmpty, + EuiButtonEmptyProps, + EuiButtonIcon, + EuiContextMenuItem, + EuiContextMenuPanel, + EuiFlexGroup, + EuiPopover, + PanelPaddingSize, + PopoverAnchorPosition, +} from '@elastic/eui'; + +import { css } from '@emotion/react'; + +export interface Action { + key: string; + icon: string; + label: string | boolean; + disabled?: boolean; + onClick: (e: React.MouseEvent) => void; +} + +interface HeaderMenuComponentProps { + disableActions: boolean; + actions: Action[] | ReactElement[] | null; + text?: string; + iconType?: EuiButtonEmptyProps['iconType']; + iconSide?: EuiButtonEmptyProps['iconSide']; + dataTestSubj?: string; + emptyButton?: boolean; + useCustomActions?: boolean; + anchorPosition?: PopoverAnchorPosition; + panelPaddingSize?: PanelPaddingSize; +} + +const popoverHeightStyle = css` + max-height: 300px; + height: 100%; + overflow-x: hidden; + overflow-y: auto; +`; +const HeaderMenuComponent: FC = ({ + text, + dataTestSubj, + actions, + disableActions, + emptyButton, + useCustomActions, + iconType, + iconSide = 'left', + anchorPosition = 'downCenter', + panelPaddingSize = 's', +}) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const onAffectedRulesClick = () => setIsPopoverOpen((isOpen) => !isOpen); + const onClosePopover = () => setIsPopoverOpen(false); + + const itemActions = useMemo(() => { + if (useCustomActions || actions === null) return actions; + return (actions as Action[]).map((action) => ( + { + onClosePopover(); + if (typeof action.onClick === 'function') action.onClick(e); + }} + > + {action.label} + + )); + }, [actions, dataTestSubj, useCustomActions]); + + return ( + + + {text} + + ) : ( + + {text} + + ) + } + onClick={(e) => e.stopPropagation()} + panelPaddingSize={panelPaddingSize} + isOpen={isPopoverOpen} + closePopover={onClosePopover} + anchorPosition={anchorPosition} + data-test-subj={`${dataTestSubj || ''}Items`} + > + {!itemActions ? null : ( + + )} + + + ); +}; +HeaderMenuComponent.displayName = 'HeaderMenuComponent'; + +export const HeaderMenu = React.memo(HeaderMenuComponent); + +HeaderMenu.displayName = 'HeaderMenu'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/__snapshots__/list_header.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/__snapshots__/list_header.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/__snapshots__/list_header.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/__snapshots__/list_header.test.tsx.snap diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/__snapshots__/edit_modal.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/__snapshots__/edit_modal.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/__snapshots__/edit_modal.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/__snapshots__/edit_modal.test.tsx.snap diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/edit_modal.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/edit_modal.test.tsx similarity index 93% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/edit_modal.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/edit_modal.test.tsx index 39692e35394ec..9b23afaf2089e 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/edit_modal.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/edit_modal.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/index.tsx new file mode 100644 index 0000000000000..fda87a768fd0d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/index.tsx @@ -0,0 +1,109 @@ +/* + * 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. + */ + +import React, { FC } from 'react'; +import { + EuiButton, + EuiButtonEmpty, + EuiFieldText, + EuiForm, + EuiFormRow, + EuiModal, + EuiModalBody, + EuiModalFooter, + EuiModalHeader, + EuiModalHeaderTitle, + EuiTextArea, + EuiProgress, +} from '@elastic/eui'; +import * as i18n from '../../translations'; +import { ListDetails } from '../../types'; +import { useEditModal } from './use_edit_modal'; + +interface EditModalProps { + listDetails: ListDetails; + onSave: (newListDetails: ListDetails) => void; + onCancel: () => void; +} + +const EditModalComponent: FC = ({ listDetails, onSave, onCancel }) => { + const { error, modalFormId, newListDetails, showProgress, onBlur, onSubmit, onChange } = + useEditModal({ + listDetails, + onSave, + }); + return ( + + {showProgress && ( + + )} + + + {i18n.EXCEPTION_LIST_HEADER_EDIT_MODAL_TITLE(listDetails.name)} + + + + + + + + + + + + + + + + + + {i18n.EXCEPTION_LIST_HEADER_EDIT_MODAL_CANCEL_BUTTON} + + + + {i18n.EXCEPTION_LIST_HEADER_EDIT_MODAL_SAVE_BUTTON} + + + + ); +}; +EditModalComponent.displayName = 'EditModalComponent'; + +export const EditModal = React.memo(EditModalComponent); + +EditModal.displayName = 'EditModal'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.test.ts similarity index 81% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.test.ts index 65b532a55c834..a540fdd7704db 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { ChangeEvent, SyntheticEvent } from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.ts similarity index 80% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.ts index 6977b8467b94a..38c60328ef3d2 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/edit_modal/use_edit_modal.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { useGeneratedHtmlId } from '@elastic/eui'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/index.tsx new file mode 100644 index 0000000000000..a6fce88699993 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/index.tsx @@ -0,0 +1,138 @@ +/* + * 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. + */ + +/* eslint-disable react/jsx-no-literals */ + +import React from 'react'; +import type { FC } from 'react'; +import { EuiIcon, EuiPageHeader, EuiText } from '@elastic/eui'; +import * as i18n from '../translations'; +import { textCss, descriptionContainerCss, backTextCss } from './list_header.styles'; +import { MenuItems } from './menu_items'; +import { TextWithEdit } from '../text_with_edit'; +import { EditModal } from './edit_modal'; +import { ListDetails, Rule } from '../types'; +import { useExceptionListHeader } from './use_list_header'; +import { textWithEditContainerCss } from '../text_with_edit/text_with_edit.styles'; + +interface ExceptionListHeaderComponentProps { + name: string; + description?: string; + listId: string; + isReadonly: boolean; + linkedRules: Rule[]; + dataTestSubj?: string; + backOptions: BackOptions; + canUserEditList?: boolean; + securityLinkAnchorComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common + onEditListDetails: (listDetails: ListDetails) => void; + onDeleteList: () => void; + onManageRules: () => void; + onExportList: () => void; + onDuplicateList: () => void; +} + +export interface BackOptions { + pageId: string; + path: string; + dataTestSubj?: string; + onNavigate: (path: string) => void; +} +const ExceptionListHeaderComponent: FC = ({ + name, + description, + listId, + linkedRules, + isReadonly, + dataTestSubj, + securityLinkAnchorComponent, + backOptions, + canUserEditList = true, + onEditListDetails, + onDeleteList, + onManageRules, + onExportList, + onDuplicateList, +}) => { + const { isModalVisible, listDetails, onEdit, onSave, onCancel } = useExceptionListHeader({ + name, + description, + onEditListDetails, + }); + return ( +
+ + } + responsive + data-test-subj={`${dataTestSubj || ''}PageHeader`} + description={ +
+ +
+ {i18n.EXCEPTION_LIST_HEADER_LIST_ID}: + {listId} +
+
+ } + rightSideItems={[ + , + ]} + breadcrumbs={[ + { + text: ( +
+ + {i18n.EXCEPTION_LIST_HEADER_BREADCRUMB} +
+ ), + color: 'primary', + 'aria-current': false, + href: backOptions.path, + onClick: (e) => { + e.preventDefault(); + backOptions.onNavigate(backOptions.path); + }, + }, + ]} + /> + {isModalVisible && ( + + )} +
+ ); +}; + +ExceptionListHeaderComponent.displayName = 'ExceptionListHeaderComponent'; + +export const ExceptionListHeader = React.memo(ExceptionListHeaderComponent); + +ExceptionListHeader.displayName = 'ExceptionListHeader'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.styles.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.styles.ts new file mode 100644 index 0000000000000..7a82cd9bc2893 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.styles.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; + +export const headerMenuCss = css` + border-right: 1px solid #d3dae6; + padding: ${euiThemeVars.euiSizeXS} ${euiThemeVars.euiSizeL} ${euiThemeVars.euiSizeXS} 0; +`; + +export const noLinkedRulesCss = css` + width: max-content; +`; + +export const textCss = css` + font-size: ${euiThemeVars.euiFontSize}; + color: ${euiThemeVars.euiTextSubduedColor}; + margin-left: ${euiThemeVars.euiSizeXS}; +`; +export const descriptionContainerCss = css` + margin-top: -${euiThemeVars.euiSizeL}; + margin-bottom: -${euiThemeVars.euiSizeL}; +`; + +export const backTextCss = css` + font-size: ${euiThemeVars.euiFontSizeXS}; +`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.test.tsx similarity index 94% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.test.tsx index 9ceb648dfa7e1..246e880716087 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/list_header.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/index.tsx new file mode 100644 index 0000000000000..798f737be65db --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/index.tsx @@ -0,0 +1,134 @@ +/* + * 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. + */ + +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui'; +import React, { FC, useMemo } from 'react'; +import { HeaderMenu } from '../../header_menu'; +import { headerMenuCss, noLinkedRulesCss } from '../list_header.styles'; +import * as i18n from '../../translations'; +import { Rule } from '../../types'; +import { generateLinkedRulesMenuItems } from '../../generate_linked_rules_menu_item'; +interface MenuItemsProps { + isReadonly: boolean; + dataTestSubj?: string; + linkedRules: Rule[]; + canUserEditList?: boolean; + securityLinkAnchorComponent: React.ElementType; // This property needs to be removed to avoid the Prop Drilling, once we move all the common components from x-pack/security-solution/common + onDeleteList: () => void; + onManageRules: () => void; + onExportList: () => void; + onDuplicateList: () => void; +} + +const MenuItemsComponent: FC = ({ + dataTestSubj, + linkedRules, + securityLinkAnchorComponent, + isReadonly, + canUserEditList = true, + onDeleteList, + onManageRules, + onExportList, + onDuplicateList, +}) => { + const referencedLinks = useMemo( + () => + generateLinkedRulesMenuItems({ + leftIcon: 'check', + dataTestSubj, + linkedRules, + securityLinkAnchorComponent, + }), + [dataTestSubj, linkedRules, securityLinkAnchorComponent] + ); + return ( + + + {linkedRules.length ? ( + + ) : ( + + {i18n.EXCEPTION_LIST_HEADER_LINKED_RULES(linkedRules.length)} + + )} + + + {canUserEditList && ( + + { + if (typeof onManageRules === 'function') onManageRules(); + }} + > + {i18n.EXCEPTION_LIST_HEADER_LINK_RULES_BUTTON} + + + )} + + { + if (typeof onExportList === 'function') onExportList(); + }, + }, + { + key: '2', + icon: 'copy', + label: i18n.EXCEPTION_LIST_HEADER_DUPLICATE_ACTION, + onClick: () => { + if (typeof onDuplicateList === 'function') onDuplicateList(); + }, + disabled: !canUserEditList, + }, + { + key: '3', + icon: 'trash', + label: i18n.EXCEPTION_LIST_HEADER_DELETE_ACTION, + onClick: () => { + if (typeof onDeleteList === 'function') onDeleteList(); + }, + disabled: !canUserEditList, + }, + ]} + disableActions={isReadonly} + anchorPosition="downCenter" + /> + + + ); +}; + +MenuItemsComponent.displayName = 'MenuItemsComponent'; + +export const MenuItems = React.memo(MenuItemsComponent); + +MenuItems.displayName = 'MenuItems'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/menu_items.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/menu_items.test.tsx similarity index 94% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/menu_items.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/menu_items.test.tsx index 16072bab295ab..8fdf6519cf448 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/menu_items.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/menu_items.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { fireEvent, render } from '@testing-library/react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.test.ts similarity index 86% rename from packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.test.ts index e16681d2b184b..a49ef8f6f560c 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { waitFor, renderHook, act } from '@testing-library/react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.ts new file mode 100644 index 0000000000000..cda4bf346a203 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/use_list_header.ts @@ -0,0 +1,44 @@ +/* + * 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. + */ + +import { useState } from 'react'; +import { ListDetails } from '../types'; + +interface UseExceptionListHeaderProps { + name: string; + description?: string; + onEditListDetails: (listDetails: ListDetails) => void; +} +export const useExceptionListHeader = ({ + name, + description, + onEditListDetails, +}: UseExceptionListHeaderProps) => { + const [isModalVisible, setIsModalVisible] = useState(false); + const [listDetails, setListDetails] = useState({ name, description }); + const onEdit = () => { + setIsModalVisible(true); + }; + const onSave = (newListDetails: ListDetails) => { + setListDetails(newListDetails); + if (typeof onEditListDetails === 'function') onEditListDetails(newListDetails); + setTimeout(() => { + setIsModalVisible(false); + }, 200); + }; + const onCancel = () => { + setIsModalVisible(false); + }; + + return { + isModalVisible, + listDetails, + onEdit, + onSave, + onCancel, + }; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/comments.mock.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/comments.mock.tsx new file mode 100644 index 0000000000000..02767cfb979de --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/comments.mock.tsx @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import React from 'react'; +import type { Comment, CommentsArray } from '@kbn/securitysolution-io-ts-list-types'; + +export const getCommentsMock = (): Comment => ({ + comment: 'some old comment', + created_at: '2020-04-20T15:25:31.830Z', + created_by: 'some user', + id: 'uuid_here', +}); + +export const getCommentsArrayMock = (): CommentsArray => [getCommentsMock(), getCommentsMock()]; + +export const mockGetFormattedComments = () => + getCommentsArrayMock().map((comment) => ({ + username: comment.created_by, + children:

{comment.comment}

, + })); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/entry.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/entry.mock.ts new file mode 100644 index 0000000000000..34a4e98cf981a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/entry.mock.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import { Entry } from '../exception_item_card/conditions/types'; + +export const includedListTypeEntry: Entry = { + field: '', + operator: 'included', + type: 'list', + list: { id: 'list_id', type: 'boolean' }, +}; + +export const includedMatchTypeEntry: Entry = { + field: '', + operator: 'included', + type: 'match', + value: 'matches value', +}; + +export const includedExistsTypeEntry: Entry = { + field: '', + operator: 'included', + type: 'exists', +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/exception_list_item_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/exception_list_item_schema.mock.ts new file mode 100644 index 0000000000000..a34ddc4dd484f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/exception_list_item_schema.mock.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; + +export const getExceptionListItemSchemaMock = ( + overrides?: Partial +): ExceptionListItemSchema => ({ + _version: undefined, + comments: [], + created_at: '2020-04-20T15:25:31.830Z', + created_by: 'some user', + description: 'some description', + entries: [ + { + entries: [ + { field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }, + ], + field: 'some.parentField', + type: 'nested', + }, + { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, + ], + expire_time: undefined, + id: '1', + item_id: 'endpoint_list_item', + list_id: 'endpoint_list_id', + meta: {}, + name: 'some name', + namespace_type: 'single', + os_types: [], + tags: ['user added string for a tag', 'malware'], + tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e', + type: 'simple', + updated_at: '2020-04-20T15:25:31.830Z', + updated_by: 'some user', + ...(overrides || {}), +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/header.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/header.mock.ts new file mode 100644 index 0000000000000..5ee301495e6f5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/header.mock.ts @@ -0,0 +1,38 @@ +/* + * 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. + */ + +export const handleEdit = jest.fn(); +export const handleDelete = jest.fn(); +export const actions = [ + { + key: 'edit', + icon: 'pencil', + label: 'Edit detection exception', + onClick: handleEdit, + }, + { + key: 'delete', + icon: 'trash', + label: 'Delete detection exception', + onClick: handleDelete, + }, +]; +export const actionsWithDisabledDelete = [ + { + key: 'edit', + icon: 'pencil', + label: 'Edit detection exception', + onClick: handleEdit, + }, + { + key: 'delete', + icon: 'trash', + disabled: true, + label: 'Delete detection exception', + onClick: handleDelete, + }, +]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/rule_references.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/rule_references.mock.ts new file mode 100644 index 0000000000000..c4eaff274a741 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/rule_references.mock.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import { Rule, RuleReference } from '../types'; + +export const rules: Rule[] = [ + { + exceptions_list: [ + { + id: '123', + list_id: 'i_exist', + namespace_type: 'single', + type: 'detection', + }, + { + id: '456', + list_id: 'i_exist_2', + namespace_type: 'single', + type: 'detection', + }, + ], + id: '1a2b3c', + name: 'Simple Rule Query', + rule_id: 'rule-2', + }, +]; + +export const ruleReference: RuleReference = { + name: 'endpoint list', + id: 'endpoint_list', + referenced_rules: rules, + listId: 'endpoint_list_id', +}; + +export const ruleReferences = { + endpoint_list_id: ruleReference, +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/security_link_component.mock.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/security_link_component.mock.tsx new file mode 100644 index 0000000000000..03c44d7e91667 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/security_link_component.mock.tsx @@ -0,0 +1,36 @@ +/* + * 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. + */ + +import React, { ReactElement } from 'react'; +import { generateLinkedRulesMenuItems } from '../generate_linked_rules_menu_item'; +import { rules } from './rule_references.mock'; +export const securityLinkAnchorComponentMock = ({ + referenceName, + referenceId, +}: { + referenceName: string; + referenceId: string; +}) => ( +
+); + +export const getSecurityLinkAction = (dataTestSubj: string) => + generateLinkedRulesMenuItems({ + dataTestSubj, + linkedRules: [ + ...rules, + { + exceptions_list: [], + id: '2a2b3c', + name: 'Simple Rule Query 2', + rule_id: 'rule-2', + }, + ], + securityLinkAnchorComponent: securityLinkAnchorComponentMock, + }) as ReactElement[]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/value_list_modal.mock.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/value_list_modal.mock.tsx new file mode 100644 index 0000000000000..e0f9f5d700bed --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/mocks/value_list_modal.mock.tsx @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import React from 'react'; + +export const mockShowValueListModal = jest.fn(); +export const MockedShowValueListModal = (props: { children: React.ReactNode }) => { + mockShowValueListModal(props); + return <>{props.children}; +}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.test.tsx similarity index 84% rename from packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.test.tsx index 5eaab267abb52..1467653d432b2 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { fireEvent, render } from '@testing-library/react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.tsx new file mode 100644 index 0000000000000..e7275c4be2c2e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/pagination.tsx @@ -0,0 +1,49 @@ +/* + * 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. + */ + +import React from 'react'; +import type { FC } from 'react'; +import { EuiTablePagination } from '@elastic/eui'; + +import type { PaginationProps } from '../types'; +import { usePagination } from './use_pagination'; + +const PaginationComponent: FC = ({ + dataTestSubj, + ariaLabel, + pagination, + onPaginationChange, +}) => { + const { + pageIndex, + pageCount, + pageSize, + pageSizeOptions, + + handleItemsPerPageChange, + handlePageIndexChange, + } = usePagination({ pagination, onPaginationChange }); + + return ( + + ); +}; + +PaginationComponent.displayName = 'PaginationComponent'; + +export const Pagination = React.memo(PaginationComponent); + +Pagination.displayName = 'Pagination'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.test.ts similarity index 87% rename from packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.test.ts index e90408f1e161b..2126ace9191b5 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { renderHook, act } from '@testing-library/react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.ts similarity index 76% rename from packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.ts index da96624f8b43a..289d5ebcaa268 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/pagination/use_pagination.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { useCallback, useMemo } from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx new file mode 100644 index 0000000000000..4339d95b6c4cb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; + +import { EuiCallOut } from '@elastic/eui'; + +export const PartialCodeSignatureCallout = () => { + return ( + + + + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx new file mode 100644 index 0000000000000..dd36c16b9bd8d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx @@ -0,0 +1,122 @@ +/* + * 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. + */ + +import React, { useCallback } from 'react'; +import type { FC } from 'react'; + +import type { EuiSearchBarProps, IconType, SearchFilterConfig } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiSearchBar } from '@elastic/eui'; +import type { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import type { GetExceptionItemProps } from '../types'; + +const ITEMS_SCHEMA = { + strict: true, + fields: { + created_by: { + type: 'string', + }, + description: { + type: 'string', + }, + id: { + type: 'string', + }, + item_id: { + type: 'string', + }, + list_id: { + type: 'string', + }, + name: { + type: 'string', + }, + os_types: { + type: 'string', + }, + tags: { + type: 'string', + }, + }, +}; +interface SearchBarProps { + addExceptionButtonText?: string; + placeholdertext?: string; + canAddException?: boolean; // TODO what is the default value + + // TODO: REFACTOR: not to send the listType and handle it in the Parent + // Exception list type used to determine what type of item is + // being created when "onAddExceptionClick" is invoked + listType: ExceptionListTypeEnum; + isSearching?: boolean; + dataTestSubj?: string; + filters?: SearchFilterConfig[]; // TODO about filters + isButtonFilled?: boolean; + buttonIconType?: IconType; + onSearch: (arg: GetExceptionItemProps) => void; + onAddExceptionClick: (type: ExceptionListTypeEnum) => void; +} +const SearchBarComponent: FC = ({ + addExceptionButtonText, + placeholdertext, + canAddException, + listType, + isSearching, + dataTestSubj, + filters = [], + isButtonFilled = true, + buttonIconType, + onSearch, + onAddExceptionClick, +}) => { + const handleOnSearch = useCallback>( + ({ queryText }): void => { + onSearch({ search: queryText }); + }, + [onSearch] + ); + + const handleAddException = useCallback(() => { + // TODO: ASK YARA why we need to send the listType + onAddExceptionClick(listType); + }, [onAddExceptionClick, listType]); + + return ( + + + + + {!canAddException && ( + + + {addExceptionButtonText} + + + )} + + ); +}; + +SearchBarComponent.displayName = 'SearchBarComponent'; + +export const SearchBar = React.memo(SearchBarComponent); + +SearchBar.displayName = 'SearchBar'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/search_bar/search_bar.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/search_bar/search_bar.test.tsx similarity index 88% rename from packages/kbn-securitysolution-exception-list-components/src/search_bar/search_bar.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/search_bar/search_bar.test.tsx index b1eadded0e3f8..a7eaa7ba47ad0 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/search_bar/search_bar.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/search_bar/search_bar.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/__snapshots__/text_with_edit.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/__snapshots__/text_with_edit.test.tsx.snap similarity index 100% rename from packages/kbn-securitysolution-exception-list-components/src/text_with_edit/__snapshots__/text_with_edit.test.tsx.snap rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/__snapshots__/text_with_edit.test.tsx.snap diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/index.tsx new file mode 100644 index 0000000000000..1428dcfa238ea --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/index.tsx @@ -0,0 +1,51 @@ +/* + * 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. + */ + +import React, { FC } from 'react'; +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { Interpolation, Theme } from '@emotion/react'; +import { textWithEditContainerCss, editIconCss } from './text_with_edit.styles'; +interface TextWithEditProps { + isReadonly: boolean; + dataTestSubj?: string; + text: string; + textCss?: Interpolation; + onEdit?: () => void; +} + +const TextWithEditComponent: FC = ({ + isReadonly, + dataTestSubj, + text, + onEdit, + textCss, +}) => { + return ( + + + + {text} + + + + {isReadonly ? null : ( + (typeof onEdit === 'function' ? onEdit() : null)} + /> + )} + + + ); +}; +TextWithEditComponent.displayName = 'TextWithEditComponent'; + +export const TextWithEdit = React.memo(TextWithEditComponent); + +TextWithEdit.displayName = 'TextWithEdit'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.styles.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.styles.ts new file mode 100644 index 0000000000000..d61aaab0f9be6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.styles.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; + +export const textWithEditContainerCss = css` + display: flex; + width: fit-content; + align-items: baseline; + padding-bottom: ${euiThemeVars.euiSizeS}; + h1 { + margin-bottom: 0; + } +`; +export const editIconCss = css` + button { + margin-left: -${euiThemeVars.euiSizeM}; + } +`; diff --git a/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.test.tsx similarity index 84% rename from packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.test.tsx index eab0eb7817d8c..24b5eec6e3350 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/text_with_edit.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { fireEvent, render } from '@testing-library/react'; @@ -35,6 +33,7 @@ describe('TextWithEdit', () => { isReadonly={false} dataTestSubj="TextWithEditTest" text="Test" + // eslint-disable-next-line @typescript-eslint/no-explicit-any onEdit={onEdit as any} /> ); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/translations.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/translations.ts new file mode 100644 index 0000000000000..5660ac3564c7d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/translations.ts @@ -0,0 +1,154 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const EMPTY_VIEWER_STATE_EMPTY_TITLE = i18n.translate( + 'exceptionList-components.empty.viewer.state.empty.title', + { + defaultMessage: 'Add exceptions to this list', + } +); + +export const EMPTY_VIEWER_STATE_EMPTY_BODY = i18n.translate( + 'exceptionList-components.empty.viewer.state.empty.body', + { + defaultMessage: 'There is no exception in your list. Create your first exception.', + } +); +export const EMPTY_VIEWER_STATE_EMPTY_SEARCH_TITLE = i18n.translate( + 'exceptionList-components.empty.viewer.state.empty_search.search.title', + { + defaultMessage: 'No results match your search criteria', + } +); + +export const EMPTY_VIEWER_STATE_EMPTY_SEARCH_BODY = i18n.translate( + 'exceptionList-components.empty.viewer.state.empty_search.body', + { + defaultMessage: 'Try modifying your search', + } +); + +export const EMPTY_VIEWER_STATE_EMPTY_VIEWER_BUTTON = (exceptionType: string) => + i18n.translate('exceptionList-components.empty.viewer.state.empty.viewer_button', { + values: { exceptionType }, + defaultMessage: 'Create {exceptionType} exception', + }); + +export const EMPTY_VIEWER_STATE_ERROR_TITLE = i18n.translate( + 'exceptionList-components.empty.viewer.state.error_title', + { + defaultMessage: 'Unable to load exception items', + } +); + +export const EMPTY_VIEWER_STATE_ERROR_BODY = i18n.translate( + 'exceptionList-components.empty.viewer.state.error_body', + { + defaultMessage: + 'There was an error loading the exception items. Contact your administrator for help.', + } +); +export const EXCEPTION_LIST_HEADER_EXPORT_ACTION = i18n.translate( + 'exceptionList-components.exception_list_header_export_action', + { + defaultMessage: 'Export exception list', + } +); +export const EXCEPTION_LIST_HEADER_DELETE_ACTION = i18n.translate( + 'exceptionList-components.exception_list_header_delete_action', + { + defaultMessage: 'Delete exception list', + } +); +export const EXCEPTION_LIST_HEADER_DUPLICATE_ACTION = i18n.translate( + 'exceptionList-components.exception_list_header_duplicate_action', + { + defaultMessage: 'Duplicate exception list', + } +); +export const EXCEPTION_LIST_HEADER_LINK_RULES_BUTTON = i18n.translate( + 'exceptionList-components.exception_list_header_link_rules_button', + { + defaultMessage: 'Link rules', + } +); + +export const EXCEPTION_LIST_HEADER_LINKED_RULES = (noOfRules: number) => + i18n.translate('exceptionList-components.exception_list_header_linked_rules', { + values: { noOfRules }, + defaultMessage: 'Linked to {noOfRules} rules', + }); + +export const EXCEPTION_LIST_HEADER_BREADCRUMB = i18n.translate( + 'exceptionList-components.exception_list_header_breadcrumb', + { + defaultMessage: 'Shared Exception Lists', + } +); + +export const EXCEPTION_LIST_HEADER_LIST_ID = i18n.translate( + 'exceptionList-components.exception_list_header_list_id', + { + defaultMessage: 'List ID', + } +); + +export const EXCEPTION_LIST_HEADER_NAME = i18n.translate( + 'exceptionList-components.exception_list_header_name', + { + defaultMessage: 'Add a name', + } +); + +export const EXCEPTION_LIST_HEADER_DESCRIPTION = i18n.translate( + 'exceptionList-components.exception_list_header_description', + { + defaultMessage: 'Add a description', + } +); + +export const EXCEPTION_LIST_HEADER_EDIT_MODAL_TITLE = (listName: string) => + i18n.translate('exceptionList-components.exception_list_header_edit_modal_name', { + defaultMessage: 'Edit {listName}', + values: { listName }, + }); + +export const EXCEPTION_LIST_HEADER_EDIT_MODAL_SAVE_BUTTON = i18n.translate( + 'exceptionList-components.exception_list_header_edit_modal_save_button', + { + defaultMessage: 'Save', + } +); + +export const EXCEPTION_LIST_HEADER_EDIT_MODAL_CANCEL_BUTTON = i18n.translate( + 'exceptionList-components.exception_list_header_edit_modal_cancel_button', + { + defaultMessage: 'Cancel', + } +); +export const EXCEPTION_LIST_HEADER_NAME_TEXTBOX = i18n.translate( + 'exceptionList-components.exception_list_header_Name_textbox', + { + defaultMessage: 'Name', + } +); + +export const EXCEPTION_LIST_HEADER_DESCRIPTION_TEXTBOX = i18n.translate( + 'exceptionList-components.exception_list_header_description_textbox', + { + defaultMessage: 'Description (optional)', + } +); + +export const LIST_NAME_REQUIRED_ERROR = i18n.translate( + 'exceptionList-components.exception_list_header_description_textboxexceptionList-components.exception_list_header_name_required_eror', + { + defaultMessage: 'List name cannot be empty', + } +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/types/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/types/index.ts new file mode 100644 index 0000000000000..d628cd0137972 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/types/index.ts @@ -0,0 +1,75 @@ +/* + * 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. + */ + +import { ListArray } from '@kbn/securitysolution-io-ts-list-types'; + +import type { Pagination } from '@elastic/eui'; +import type { NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; + +export interface GetExceptionItemProps { + pagination?: PaginationProps['pagination']; + search?: string; + filters?: string; +} + +export interface PaginationProps { + dataTestSubj?: string; + ariaLabel?: string; + pagination: Pagination & { pageSize: number }; + onPaginationChange: (arg: GetExceptionItemProps) => void; +} + +export enum ViewerStatus { + ERROR = 'error', + EMPTY = 'empty', + EMPTY_SEARCH = 'empty_search', + LOADING = 'loading', + SEARCHING = 'searching', + DELETING = 'deleting', +} + +export interface ExceptionListSummaryProps { + pagination: Pagination; + // Corresponds to last time exception items were fetched + lastUpdated: string | number | null; +} + +export type ViewerFlyoutName = 'addException' | 'editException' | null; + +export interface RuleReferences { + [key: string]: RuleReference; +} + +export interface ExceptionListItemIdentifiers { + id: string; + name: string; + namespaceType: NamespaceType; +} + +export enum ListTypeText { + ENDPOINT = 'endpoint', + DETECTION = 'empty', + RULE_DEFAULT = 'empty_search', +} +export interface Rule { + name: string; + id: string; + rule_id: string; + exceptions_list?: ListArray; +} + +export interface RuleReference { + name: string; + id: string; + referenced_rules: Rule[]; + listId?: string; +} + +export interface ListDetails { + name: string; + description?: string; +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/index.ts new file mode 100644 index 0000000000000..968bc9666b090 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { ValueWithSpaceWarning } from './value_with_space_warning'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.test.ts similarity index 84% rename from packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.test.ts index 51954c0140e61..570399a5ecb23 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { renderHook } from '@testing-library/react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.ts new file mode 100644 index 0000000000000..252f05f4d1020 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/use_value_with_space_warning.ts @@ -0,0 +1,31 @@ +/* + * 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. + */ + +import { paramContainsSpace, autoCompletei18n } from '@kbn/securitysolution-autocomplete'; + +interface UseValueWithSpaceWarningResult { + showSpaceWarningIcon: boolean; + warningText: string; +} +interface UseValueWithSpaceWarningProps { + value: string | string[]; + tooltipIconText?: string; +} + +export const useValueWithSpaceWarning = ({ + value, + tooltipIconText, +}: UseValueWithSpaceWarningProps): UseValueWithSpaceWarningResult => { + const showSpaceWarningIcon = Array.isArray(value) + ? value.find(paramContainsSpace) + : paramContainsSpace(value); + + return { + showSpaceWarningIcon: !!showSpaceWarningIcon, + warningText: tooltipIconText || autoCompletei18n.FIELD_SPACE_WARNING, + }; +}; diff --git a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.test.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.test.tsx similarity index 81% rename from packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.test.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.test.tsx index 8f780181e0528..a500f13af6e16 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.test.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.test.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.tsx similarity index 75% rename from packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.tsx rename to x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.tsx index c736982142b1e..c73a39a516ed8 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.tsx +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.tsx @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import React from 'react'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/wildcard_with_wrong_operator_callout/index.tsx b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/wildcard_with_wrong_operator_callout/index.tsx new file mode 100644 index 0000000000000..b21259f4ed895 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/wildcard_with_wrong_operator_callout/index.tsx @@ -0,0 +1,51 @@ +/* + * 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. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; + +import { EuiCallOut } from '@elastic/eui'; + +export const WildCardWithWrongOperatorCallout = () => { + return ( + +

+ + {i18n.translate( + 'exceptionList-components.wildcardWithWrongOperatorCallout.changeTheOperator', + { defaultMessage: 'Change the operator' } + )} + + ), + matches: ( + + {i18n.translate( + 'exceptionList-components.wildcardWithWrongOperatorCallout.matches', + { defaultMessage: 'matches' } + )} + + ), + }} + /> +

+
+ ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/tsconfig.json new file mode 100644 index 0000000000000..5378a8fbdfe1a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react", + "@emotion/react/types/css-prop" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + "**/*.d.ts" + ], + "kbn_references": [ + "@kbn/securitysolution-io-ts-list-types", + "@kbn/securitysolution-autocomplete", + "@kbn/ui-theme", + "@kbn/i18n", + "@kbn/i18n-react", + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-exceptions-common/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/README.md similarity index 100% rename from packages/kbn-securitysolution-exceptions-common/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/README.md diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.gen.ts similarity index 78% rename from packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.gen.ts index a9acaee37cefa..2c7dc29dd182a 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.schema.yaml similarity index 79% rename from packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.schema.yaml index 5925d0bd923c0..e7a399c2d7a82 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list/create_exception_list.schema.yaml @@ -59,29 +59,29 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 409: description: Exception list already exists response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.gen.ts similarity index 85% rename from packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.gen.ts index 9adf64b6b083f..dba75c11fde83 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.schema.yaml similarity index 78% rename from packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.schema.yaml index 47fa2895d27c6..2913d8c5c07d7 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_exception_list_item/create_exception_list_item.schema.yaml @@ -69,32 +69,32 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 409: description: Exception list item already exists response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: x-codegen-enabled: true @@ -103,7 +103,7 @@ components: type: object properties: comment: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' required: - comment diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.gen.ts similarity index 88% rename from packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.gen.ts index 77437ff51618c..e2fa379cdc528 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.schema.yaml similarity index 78% rename from packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.schema.yaml index 6162d00d78ae8..b7b2db3fabefd 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_rule_exceptions/create_rule_exceptions.schema.yaml @@ -9,7 +9,7 @@ paths: operationId: CreateRuleExceptionListItems x-codegen-enabled: true summary: Create rule exception list items - description: Create exception items that apply to a single detection rule. + description: Create exception items that apply to a single detection rule. parameters: - name: id in: path @@ -45,37 +45,37 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: schemas: RuleId: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/UUID' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/UUID' CreateRuleExceptionListItemComment: type: object properties: comment: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' required: - comment diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.gen.ts new file mode 100644 index 0000000000000..07650ee2d0c01 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.gen.ts @@ -0,0 +1,37 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create shared exception list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { + ExceptionListName, + ExceptionListDescription, + ExceptionList, +} from '../model/exception_list_common.gen'; + +export type CreateSharedExceptionListRequestBody = z.infer< + typeof CreateSharedExceptionListRequestBody +>; +export const CreateSharedExceptionListRequestBody = z.object({ + name: ExceptionListName, + description: ExceptionListDescription, +}); +export type CreateSharedExceptionListRequestBodyInput = z.input< + typeof CreateSharedExceptionListRequestBody +>; + +export type CreateSharedExceptionListResponse = z.infer; +export const CreateSharedExceptionListResponse = ExceptionList; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.schema.yaml new file mode 100644 index 0000000000000..040acca3ebd77 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/create_shared_exceptions_list/create_shared_exceptions_list.schema.yaml @@ -0,0 +1,68 @@ +openapi: 3.0.0 +info: + title: Create shared exception list API endpoint + version: '2023-10-31' +paths: + /api/exceptions/shared: + post: + x-labels: [serverless, ess] + operationId: CreateSharedExceptionList + x-codegen-enabled: true + summary: Create a shared exception list + description: | + An exception list groups exception items and can be associated with detection rules. A shared exception list can apply to multiple detection rules. + > info + > All exception items added to the same list are evaluated using `OR` logic. That is, if any of the items in a list evaluate to `true`, the exception prevents the rule from generating an alert. Likewise, `OR` logic is used for evaluating exceptions when more than one exception list is assigned to a rule. To use the `AND` operator, you can define multiple clauses (`entries`) in a single exception item. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListName' + description: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListDescription' + required: + - name + - description + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: Exception list already exists response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.gen.ts similarity index 75% rename from packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.gen.ts index a12512aab1374..0842dc7c74637 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.schema.yaml new file mode 100644 index 0000000000000..2912070635b8f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list/delete_exception_list.schema.yaml @@ -0,0 +1,70 @@ +openapi: 3.0.0 +info: + title: Delete exception list API endpoint + version: '2023-10-31' +paths: + /api/exception_lists: + delete: + x-labels: [serverless, ess] + operationId: DeleteExceptionList + x-codegen-enabled: true + summary: Delete an exception list + description: Delete an exception list using the `id` or `list_id` field. + parameters: + - name: id + in: query + required: false + description: Either `id` or `list_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' + - name: list_id + in: query + required: false + description: Either `id` or `list_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' + - name: namespace_type + in: query + required: false + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' + default: single + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Exception list not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.gen.ts similarity index 76% rename from packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.gen.ts index a93af0cf3d4c2..429568c33f1c6 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.schema.yaml new file mode 100644 index 0000000000000..05f997307a4ca --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/delete_exception_list_item/delete_exception_list_item.schema.yaml @@ -0,0 +1,70 @@ +openapi: 3.0.0 +info: + title: Delete exception list item API endpoint + version: '2023-10-31' +paths: + /api/exception_lists/items: + delete: + x-labels: [serverless, ess] + operationId: DeleteExceptionListItem + x-codegen-enabled: true + summary: Delete an exception list item + description: Delete an exception list item using the `id` or `item_id` field. + parameters: + - name: id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' + - name: item_id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' + - name: namespace_type + in: query + required: false + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' + default: single + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Exception list item not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.gen.ts similarity index 75% rename from packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.gen.ts index 61de17abe06f8..d259d37b23487 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.schema.yaml new file mode 100644 index 0000000000000..80620c4adf7f7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/duplicate_exception_list/duplicate_exception_list.schema.yaml @@ -0,0 +1,71 @@ +openapi: 3.0.0 +info: + title: Duplicate exception list API endpoint + version: '2023-10-31' +paths: + /api/exception_lists/_duplicate: + post: + x-labels: [serverless, ess] + operationId: DuplicateExceptionList + x-codegen-enabled: true + summary: Duplicate an exception list + description: Duplicate an existing exception list. + parameters: + - name: list_id + in: query + required: true + description: Exception list's human identifier + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' + - name: namespace_type + in: query + required: true + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' + - name: include_expired_exceptions + in: query + required: true + description: Determines whether to include expired exceptions in the exported list + schema: + type: string + enum: ['true', 'false'] + default: 'true' + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 405: + description: Exception list to duplicate not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.gen.ts new file mode 100644 index 0000000000000..280884c7d749d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.gen.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Export exception list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { + ExceptionListId, + ExceptionListHumanId, + ExceptionNamespaceType, +} from '../model/exception_list_common.gen'; + +export type ExportExceptionListRequestQuery = z.infer; +export const ExportExceptionListRequestQuery = z.object({ + /** + * Exception list's identifier + */ + id: ExceptionListId, + /** + * Exception list's human identifier + */ + list_id: ExceptionListHumanId, + namespace_type: ExceptionNamespaceType, + /** + * Determines whether to include expired exceptions in the exported list + */ + include_expired_exceptions: z.enum(['true', 'false']).default('true'), +}); +export type ExportExceptionListRequestQueryInput = z.input; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.schema.yaml new file mode 100644 index 0000000000000..89f97ff8bbe6a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/export_exception_list/export_exception_list.schema.yaml @@ -0,0 +1,79 @@ +openapi: 3.0.0 +info: + title: Export exception list API endpoint + version: '2023-10-31' +paths: + /api/exception_lists/_export: + post: + x-labels: [serverless, ess] + operationId: ExportExceptionList + x-codegen-enabled: true + summary: Export an exception list + description: Export an exception list and its associated items to an NDJSON file. + parameters: + - name: id + in: query + required: true + description: Exception list's identifier + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' + - name: list_id + in: query + required: true + description: Exception list's human identifier + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' + - name: namespace_type + in: query + required: true + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' + - name: include_expired_exceptions + in: query + required: true + description: Determines whether to include expired exceptions in the exported list + schema: + type: string + enum: ['true', 'false'] + default: 'true' + responses: + 200: + description: Successful response + content: + application/ndjson: + schema: + type: string + format: binary + description: A `.ndjson` file containing specified exception list and its items + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Exception list not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.gen.ts similarity index 86% rename from packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.gen.ts index 99ed1b3a31ddc..d7606bbccff37 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.schema.yaml similarity index 77% rename from packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.schema.yaml index e40f780af03ef..6d390e9ecdf69 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_list_items/find_exception_list_items.schema.yaml @@ -65,7 +65,7 @@ paths: required: false description: Determines which field is used to sort the results schema: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - name: sort_order in: query required: false @@ -107,34 +107,34 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 404: description: Exception list not found response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: schemas: FindExceptionListItemsFilter: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' diff --git a/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.gen.ts similarity index 85% rename from packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.gen.ts index 83a68b4232e8b..82f5de2f5a157 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.schema.yaml similarity index 82% rename from packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.schema.yaml index c46dacbab01d0..49017d6d45912 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/find_exception_lists/find_exception_lists.schema.yaml @@ -93,26 +93,26 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: schemas: diff --git a/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.gen.ts similarity index 86% rename from packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.gen.ts index ea24803e79456..738ce79dd97d0 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.schema.yaml similarity index 85% rename from packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.schema.yaml index 8ae3ac1aa2c0c..95bc9ee508e5a 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/import_exceptions/import_exceptions.schema.yaml @@ -92,26 +92,26 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: schemas: diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/index.ts new file mode 100644 index 0000000000000..014fe58cfce09 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +export * from './model/exception_list_common.gen'; +export * from './model/exception_list_item_entry.gen'; +export * from './create_exception_list_item/create_exception_list_item.gen'; +export * from './create_rule_exceptions/create_rule_exceptions.gen'; +export * from './create_shared_exceptions_list/create_shared_exceptions_list.gen'; +export * from './create_exception_list/create_exception_list.gen'; +export * from './delete_exception_list_item/delete_exception_list_item.gen'; +export * from './delete_exception_list/delete_exception_list.gen'; +export * from './duplicate_exception_list/duplicate_exception_list.gen'; +export * from './export_exception_list/export_exception_list.gen'; +export * from './find_exception_list_items/find_exception_list_items.gen'; +export * from './find_exception_lists/find_exception_lists.gen'; +export * from './import_exceptions/import_exceptions.gen'; +export * from './read_exception_list_item/read_exception_list_item.gen'; +export * from './read_exception_list/read_exception_list.gen'; +export * from './read_exception_list_summary/read_exception_list_summary.gen'; +export * from './update_exception_list_item/update_exception_list_item.gen'; +export * from './update_exception_list/update_exception_list.gen'; diff --git a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.gen.ts similarity index 94% rename from packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.gen.ts index 1f2d9e7387da3..2ee44afa69b9f 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml similarity index 83% rename from packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml index ebcecc9c916f7..4ca9326ec6c92 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_common.schema.yaml @@ -7,10 +7,10 @@ components: x-codegen-enabled: true schemas: ExceptionListId: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' ExceptionListHumanId: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' description: Human readable string identifier, e.g. `trusted-linux-processes` ExceptionListType: @@ -122,17 +122,17 @@ components: - updated_by ExceptionListItemId: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' ExceptionListItemHumanId: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' ExceptionListItemType: type: string enum: [simple] ExceptionListItemName: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' ExceptionListItemDescription: type: string @@ -144,7 +144,7 @@ components: ExceptionListItemTags: type: array items: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' ExceptionListItemOsType: type: string @@ -162,19 +162,19 @@ components: type: object properties: id: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' comment: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' created_at: type: string format: date-time created_by: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' updated_at: type: string format: date-time updated_by: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' required: - id - comment @@ -278,7 +278,7 @@ components: comments: $ref: '#/components/schemas/ExceptionListItemCommentArray' version: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' tie_breaker_id: type: string created_at: diff --git a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.gen.ts similarity index 90% rename from packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.gen.ts index 0b7f0233ba429..272e5e7d6c356 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.schema.yaml new file mode 100644 index 0000000000000..ab8c427344a0d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/model/exception_list_item_entry.schema.yaml @@ -0,0 +1,147 @@ +openapi: 3.0.0 +info: + title: Common Exception List Item Entry Attributes + version: 'not applicable' +paths: {} +components: + x-codegen-enabled: true + schemas: + ExceptionListItemEntryOperator: + type: string + enum: [excluded, included] + + ExceptionListItemEntryMatch: + type: object + properties: + type: + type: string + enum: [match] + field: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + value: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + operator: + $ref: '#/components/schemas/ExceptionListItemEntryOperator' + required: + - type + - field + - value + - operator + + ExceptionListItemEntryMatchAny: + type: object + properties: + type: + type: string + enum: [match_any] + field: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + value: + type: array + items: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + minItems: 1 + operator: + $ref: '#/components/schemas/ExceptionListItemEntryOperator' + required: + - type + - field + - value + - operator + + ExceptionListItemEntryList: + type: object + properties: + type: + type: string + enum: [list] + field: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + list: + type: object + properties: + id: + $ref: '../../../kbn-securitysolution-lists-common/api/model/list_common.schema.yaml#/components/schemas/ListId' + type: + $ref: '../../../kbn-securitysolution-lists-common/api/model/list_common.schema.yaml#/components/schemas/ListType' + required: [id, type] + operator: + $ref: '#/components/schemas/ExceptionListItemEntryOperator' + required: + - type + - field + - list + - operator + + ExceptionListItemEntryExists: + type: object + properties: + type: + type: string + enum: [exists] + field: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + operator: + $ref: '#/components/schemas/ExceptionListItemEntryOperator' + required: + - type + - field + - operator + + ExceptionListItemEntryNestedEntryItem: + oneOf: + - $ref: '#/components/schemas/ExceptionListItemEntryMatch' + - $ref: '#/components/schemas/ExceptionListItemEntryMatchAny' + - $ref: '#/components/schemas/ExceptionListItemEntryExists' + + ExceptionListItemEntryNested: + type: object + properties: + type: + type: string + enum: [nested] + field: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + entries: + type: array + items: + $ref: '#/components/schemas/ExceptionListItemEntryNestedEntryItem' + minItems: 1 + required: + - type + - field + - entries + + ExceptionListItemEntryMatchWildcard: + type: object + properties: + type: + type: string + enum: [wildcard] + field: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + value: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + operator: + $ref: '#/components/schemas/ExceptionListItemEntryOperator' + required: + - type + - field + - value + - operator + + ExceptionListItemEntry: + discriminator: + propertyName: type + anyOf: + - $ref: '#/components/schemas/ExceptionListItemEntryMatch' + - $ref: '#/components/schemas/ExceptionListItemEntryMatchAny' + - $ref: '#/components/schemas/ExceptionListItemEntryList' + - $ref: '#/components/schemas/ExceptionListItemEntryExists' + - $ref: '#/components/schemas/ExceptionListItemEntryNested' + - $ref: '#/components/schemas/ExceptionListItemEntryMatchWildcard' + + ExceptionListItemEntryArray: + type: array + items: + $ref: '#/components/schemas/ExceptionListItemEntry' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts new file mode 100644 index 0000000000000..bfa84f18fa7c2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts @@ -0,0 +1,425 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Exceptions API client for quickstart + * version: Bundle (no version) + */ + +import type { KbnClient } from '@kbn/test'; +import { ToolingLog } from '@kbn/tooling-log'; +import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { replaceParams } from '@kbn/openapi-common/shared'; +import { catchAxiosErrorFormatAndThrow } from '@kbn/securitysolution-utils'; + +import type { + CreateExceptionListItemRequestBodyInput, + CreateExceptionListItemResponse, +} from './create_exception_list_item/create_exception_list_item.gen'; +import type { + CreateExceptionListRequestBodyInput, + CreateExceptionListResponse, +} from './create_exception_list/create_exception_list.gen'; +import type { + CreateRuleExceptionListItemsRequestParamsInput, + CreateRuleExceptionListItemsRequestBodyInput, + CreateRuleExceptionListItemsResponse, +} from './create_rule_exceptions/create_rule_exceptions.gen'; +import type { + CreateSharedExceptionListRequestBodyInput, + CreateSharedExceptionListResponse, +} from './create_shared_exceptions_list/create_shared_exceptions_list.gen'; +import type { + DeleteExceptionListItemRequestQueryInput, + DeleteExceptionListItemResponse, +} from './delete_exception_list_item/delete_exception_list_item.gen'; +import type { + DeleteExceptionListRequestQueryInput, + DeleteExceptionListResponse, +} from './delete_exception_list/delete_exception_list.gen'; +import type { + DuplicateExceptionListRequestQueryInput, + DuplicateExceptionListResponse, +} from './duplicate_exception_list/duplicate_exception_list.gen'; +import type { ExportExceptionListRequestQueryInput } from './export_exception_list/export_exception_list.gen'; +import type { + FindExceptionListItemsRequestQueryInput, + FindExceptionListItemsResponse, +} from './find_exception_list_items/find_exception_list_items.gen'; +import type { + FindExceptionListsRequestQueryInput, + FindExceptionListsResponse, +} from './find_exception_lists/find_exception_lists.gen'; +import type { + ImportExceptionListRequestQueryInput, + ImportExceptionListResponse, +} from './import_exceptions/import_exceptions.gen'; +import type { + ReadExceptionListItemRequestQueryInput, + ReadExceptionListItemResponse, +} from './read_exception_list_item/read_exception_list_item.gen'; +import type { + ReadExceptionListSummaryRequestQueryInput, + ReadExceptionListSummaryResponse, +} from './read_exception_list_summary/read_exception_list_summary.gen'; +import type { + ReadExceptionListRequestQueryInput, + ReadExceptionListResponse, +} from './read_exception_list/read_exception_list.gen'; +import type { + UpdateExceptionListItemRequestBodyInput, + UpdateExceptionListItemResponse, +} from './update_exception_list_item/update_exception_list_item.gen'; +import type { + UpdateExceptionListRequestBodyInput, + UpdateExceptionListResponse, +} from './update_exception_list/update_exception_list.gen'; + +export interface ClientOptions { + kbnClient: KbnClient; + log: ToolingLog; +} + +export class Client { + readonly kbnClient: KbnClient; + readonly log: ToolingLog; + + constructor(options: ClientOptions) { + this.kbnClient = options.kbnClient; + this.log = options.log; + } + /** + * An exception list groups exception items and can be associated with detection rules. You can assign detection rules with multiple exception lists. +> info +> All exception items added to the same list are evaluated using `OR` logic. That is, if any of the items in a list evaluate to `true`, the exception prevents the rule from generating an alert. Likewise, `OR` logic is used for evaluating exceptions when more than one exception list is assigned to a rule. To use the `AND` operator, you can define multiple clauses (`entries`) in a single exception item. + + */ + async createExceptionList(props: CreateExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API CreateExceptionList`); + return this.kbnClient + .request({ + path: '/api/exception_lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Create an exception item and associate it with the specified exception list. +> info +> Before creating exception items, you must create an exception list. + + */ + async createExceptionListItem(props: CreateExceptionListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API CreateExceptionListItem`); + return this.kbnClient + .request({ + path: '/api/exception_lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Create exception items that apply to a single detection rule. + */ + async createRuleExceptionListItems(props: CreateRuleExceptionListItemsProps) { + this.log.info(`${new Date().toISOString()} Calling API CreateRuleExceptionListItems`); + return this.kbnClient + .request({ + path: replaceParams('/api/detection_engine/rules/{id}/exceptions', props.params), + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * An exception list groups exception items and can be associated with detection rules. A shared exception list can apply to multiple detection rules. +> info +> All exception items added to the same list are evaluated using `OR` logic. That is, if any of the items in a list evaluate to `true`, the exception prevents the rule from generating an alert. Likewise, `OR` logic is used for evaluating exceptions when more than one exception list is assigned to a rule. To use the `AND` operator, you can define multiple clauses (`entries`) in a single exception item. + + */ + async createSharedExceptionList(props: CreateSharedExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API CreateSharedExceptionList`); + return this.kbnClient + .request({ + path: '/api/exceptions/shared', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Delete an exception list using the `id` or `list_id` field. + */ + async deleteExceptionList(props: DeleteExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API DeleteExceptionList`); + return this.kbnClient + .request({ + path: '/api/exception_lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'DELETE', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Delete an exception list item using the `id` or `item_id` field. + */ + async deleteExceptionListItem(props: DeleteExceptionListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API DeleteExceptionListItem`); + return this.kbnClient + .request({ + path: '/api/exception_lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'DELETE', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Duplicate an existing exception list. + */ + async duplicateExceptionList(props: DuplicateExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API DuplicateExceptionList`); + return this.kbnClient + .request({ + path: '/api/exception_lists/_duplicate', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Export an exception list and its associated items to an NDJSON file. + */ + async exportExceptionList(props: ExportExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API ExportExceptionList`); + return this.kbnClient + .request({ + path: '/api/exception_lists/_export', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get a list of all exception list items in the specified list. + */ + async findExceptionListItems(props: FindExceptionListItemsProps) { + this.log.info(`${new Date().toISOString()} Calling API FindExceptionListItems`); + return this.kbnClient + .request({ + path: '/api/exception_lists/items/_find', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get a list of all exception lists. + */ + async findExceptionLists(props: FindExceptionListsProps) { + this.log.info(`${new Date().toISOString()} Calling API FindExceptionLists`); + return this.kbnClient + .request({ + path: '/api/exception_lists/_find', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Import an exception list and its associated items from an NDJSON file. + */ + async importExceptionList(props: ImportExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API ImportExceptionList`); + return this.kbnClient + .request({ + path: '/api/exception_lists/_import', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.attachment, + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get the details of an exception list using the `id` or `list_id` field. + */ + async readExceptionList(props: ReadExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API ReadExceptionList`); + return this.kbnClient + .request({ + path: '/api/exception_lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get the details of an exception list item using the `id` or `item_id` field. + */ + async readExceptionListItem(props: ReadExceptionListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API ReadExceptionListItem`); + return this.kbnClient + .request({ + path: '/api/exception_lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get a summary of the specified exception list. + */ + async readExceptionListSummary(props: ReadExceptionListSummaryProps) { + this.log.info(`${new Date().toISOString()} Calling API ReadExceptionListSummary`); + return this.kbnClient + .request({ + path: '/api/exception_lists/summary', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Update an exception list using the `id` or `list_id` field. + */ + async updateExceptionList(props: UpdateExceptionListProps) { + this.log.info(`${new Date().toISOString()} Calling API UpdateExceptionList`); + return this.kbnClient + .request({ + path: '/api/exception_lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'PUT', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Update an exception list item using the `id` or `item_id` field. + */ + async updateExceptionListItem(props: UpdateExceptionListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API UpdateExceptionListItem`); + return this.kbnClient + .request({ + path: '/api/exception_lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'PUT', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } +} + +export interface CreateExceptionListProps { + body: CreateExceptionListRequestBodyInput; +} +export interface CreateExceptionListItemProps { + body: CreateExceptionListItemRequestBodyInput; +} +export interface CreateRuleExceptionListItemsProps { + params: CreateRuleExceptionListItemsRequestParamsInput; + body: CreateRuleExceptionListItemsRequestBodyInput; +} +export interface CreateSharedExceptionListProps { + body: CreateSharedExceptionListRequestBodyInput; +} +export interface DeleteExceptionListProps { + query: DeleteExceptionListRequestQueryInput; +} +export interface DeleteExceptionListItemProps { + query: DeleteExceptionListItemRequestQueryInput; +} +export interface DuplicateExceptionListProps { + query: DuplicateExceptionListRequestQueryInput; +} +export interface ExportExceptionListProps { + query: ExportExceptionListRequestQueryInput; +} +export interface FindExceptionListItemsProps { + query: FindExceptionListItemsRequestQueryInput; +} +export interface FindExceptionListsProps { + query: FindExceptionListsRequestQueryInput; +} +export interface ImportExceptionListProps { + query: ImportExceptionListRequestQueryInput; + attachment: FormData; +} +export interface ReadExceptionListProps { + query: ReadExceptionListRequestQueryInput; +} +export interface ReadExceptionListItemProps { + query: ReadExceptionListItemRequestQueryInput; +} +export interface ReadExceptionListSummaryProps { + query: ReadExceptionListSummaryRequestQueryInput; +} +export interface UpdateExceptionListProps { + body: UpdateExceptionListRequestBodyInput; +} +export interface UpdateExceptionListItemProps { + body: UpdateExceptionListItemRequestBodyInput; +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.gen.ts new file mode 100644 index 0000000000000..87db0f9e75623 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.gen.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Read exception list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { + ExceptionListId, + ExceptionListHumanId, + ExceptionNamespaceType, + ExceptionList, +} from '../model/exception_list_common.gen'; + +export type ReadExceptionListRequestQuery = z.infer; +export const ReadExceptionListRequestQuery = z.object({ + /** + * Either `id` or `list_id` must be specified + */ + id: ExceptionListId.optional(), + /** + * Either `id` or `list_id` must be specified + */ + list_id: ExceptionListHumanId.optional(), + namespace_type: ExceptionNamespaceType.optional().default('single'), +}); +export type ReadExceptionListRequestQueryInput = z.input; + +export type ReadExceptionListResponse = z.infer; +export const ReadExceptionListResponse = ExceptionList; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.schema.yaml new file mode 100644 index 0000000000000..e50147083dafe --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list/read_exception_list.schema.yaml @@ -0,0 +1,70 @@ +openapi: 3.0.0 +info: + title: Read exception list API endpoint + version: '2023-10-31' +paths: + /api/exception_lists: + get: + x-labels: [serverless, ess] + operationId: ReadExceptionList + x-codegen-enabled: true + summary: Get exception list details + description: Get the details of an exception list using the `id` or `list_id` field. + parameters: + - name: id + in: query + required: false + description: Either `id` or `list_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' + - name: list_id + in: query + required: false + description: Either `id` or `list_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' + - name: namespace_type + in: query + required: false + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' + default: single + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionList' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Exception list item not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.gen.ts similarity index 75% rename from packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.gen.ts index 4de512301cd83..02f6d10558389 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.schema.yaml new file mode 100644 index 0000000000000..6d7fac7767182 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_item/read_exception_list_item.schema.yaml @@ -0,0 +1,70 @@ +openapi: 3.0.0 +info: + title: Read exception list item API endpoint + version: '2023-10-31' +paths: + /api/exception_lists/items: + get: + x-labels: [serverless, ess] + operationId: ReadExceptionListItem + x-codegen-enabled: true + summary: Get an exception list item + description: Get the details of an exception list item using the `id` or `item_id` field. + parameters: + - name: id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemId' + - name: item_id + in: query + required: false + description: Either `id` or `item_id` must be specified + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItemHumanId' + - name: namespace_type + in: query + required: false + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' + default: single + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Exception list item not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.gen.ts similarity index 79% rename from packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.gen.ts index 3e3230dddb0aa..8807f4b7e7812 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.schema.yaml new file mode 100644 index 0000000000000..02fc3c9c8f6fe --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/read_exception_list_summary/read_exception_list_summary.schema.yaml @@ -0,0 +1,89 @@ +openapi: 3.0.0 +info: + title: Read exception list summary API endpoint + version: '2023-10-31' +paths: + /api/exception_lists/summary: + get: + x-labels: [serverless, ess] + operationId: ReadExceptionListSummary + x-codegen-enabled: true + summary: Get an exception list summary + description: Get a summary of the specified exception list. + parameters: + - name: id + in: query + required: false + description: Exception list's identifier generated upon creation + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListId' + - name: list_id + in: query + required: false + description: Exception list's human readable identifier + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionListHumanId' + - name: namespace_type + in: query + required: false + schema: + $ref: '../model/exception_list_common.schema.yaml#/components/schemas/ExceptionNamespaceType' + default: single + - name: filter + in: query + required: false + description: Search filter clause + schema: + type: string + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + windows: + type: integer + minimum: 0 + linux: + type: integer + minimum: 0 + macos: + type: integer + minimum: 0 + total: + type: integer + minimum: 0 + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: Exception list not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.gen.ts similarity index 79% rename from packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.gen.ts index 2f38661cc9587..fb5fde05dcc85 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.schema.yaml similarity index 77% rename from packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.schema.yaml index 5e8f3dfd8b509..0f7218a86c23f 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list/update_exception_list.schema.yaml @@ -59,29 +59,29 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 404: description: Exception list not found response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.gen.ts similarity index 86% rename from packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.gen.ts index 651c1dc1f2d49..791af5f65e35f 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.schema.yaml similarity index 77% rename from packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.schema.yaml index 2b8182aeb5c34..9adc75141f569 100644 --- a/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/update_exception_list_item/update_exception_list_item.schema.yaml @@ -70,32 +70,32 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 404: description: Exception list item not found response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: x-codegen-enabled: true @@ -104,9 +104,9 @@ components: type: object properties: id: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' comment: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' required: - comment diff --git a/packages/kbn-securitysolution-exceptions-common/docs/openapi/ess/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/docs/openapi/ess/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-exceptions-common/docs/openapi/ess/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/docs/openapi/ess/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml diff --git a/packages/kbn-securitysolution-exceptions-common/docs/openapi/serverless/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/docs/openapi/serverless/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-exceptions-common/docs/openapi/serverless/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/docs/openapi/serverless/security_solution_exceptions_api_2023_10_31.bundled.schema.yaml diff --git a/packages/kbn-securitysolution-exceptions-common/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-exceptions-common/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/package.json new file mode 100644 index 0000000000000..e68c27982b295 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/package.json @@ -0,0 +1,11 @@ +{ + "description": "Security Solution Exceptions common package", + "license": "Elastic License 2.0", + "name": "@kbn/securitysolution-exceptions-common", + "private": true, + "version": "1.0.0", + "scripts": { + "openapi:generate": "node scripts/openapi_generate", + "openapi:bundle": "node scripts/openapi_bundle" + } +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js new file mode 100644 index 0000000000000..996c55ce307d9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +require('../../../../../../src/setup_node_env'); +// eslint-disable-next-line import/no-nodejs-modules +const { join, resolve } = require('path'); +const { bundle } = require('@kbn/openapi-bundler'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await bundle({ + sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), + outputFilePath: join( + ROOT, + 'docs/openapi/serverless/security_solution_exceptions_api_{version}.bundled.schema.yaml' + ), + options: { + includeLabels: ['serverless'], + prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/exceptions_serverless.info.yaml'), + }, + }); + + await bundle({ + sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), + outputFilePath: join( + ROOT, + 'docs/openapi/ess/security_solution_exceptions_api_{version}.bundled.schema.yaml' + ), + options: { + includeLabels: ['ess'], + prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/exceptions_ess.info.yaml'), + }, + }); +})(); diff --git a/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_ess.info.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_ess.info.yaml similarity index 100% rename from packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_ess.info.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_ess.info.yaml diff --git a/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_serverless.info.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_serverless.info.yaml similarity index 100% rename from packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_serverless.info.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle_info/exceptions_serverless.info.yaml diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_generate.js b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_generate.js new file mode 100644 index 0000000000000..92488001b0b3a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_generate.js @@ -0,0 +1,51 @@ +/* + * 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. + */ + +require('../../../../../../src/setup_node_env'); +// eslint-disable-next-line import/no-nodejs-modules +const { join, resolve } = require('path'); +const { generate } = require('@kbn/openapi-generator'); +const { REPO_ROOT } = require('@kbn/repo-info'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await generate({ + title: 'OpenAPI Exceptions API Schemas', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'zod_operation_schema', + }); + + await generate({ + title: 'Exceptions API client for tests', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'api_client_supertest', + skipLinting: true, + bundle: { + outFile: join( + REPO_ROOT, + 'x-pack/test/api_integration/services/security_solution_exceptions_api.gen.ts' + ), + }, + }); + + await generate({ + title: 'Exceptions API client for quickstart', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'api_client_quickstart', + skipLinting: true, + bundle: { + outFile: join( + REPO_ROOT, + 'x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/api/quickstart_client.gen.ts' + ), + }, + }); +})(); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/tsconfig.json new file mode 100644 index 0000000000000..ba5a2c115a336 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "exclude": ["target/**/*"], + "extends": "../../../../../tsconfig.base.json", + "include": ["**/*.ts"], + "kbn_references": [ + "@kbn/openapi-common", + "@kbn/zod-helpers", + "@kbn/securitysolution-lists-common", + "@kbn/test", + "@kbn/tooling-log", + "@kbn/core-http-common", + "@kbn/securitysolution-utils", + "@kbn/zod", + ] +} diff --git a/packages/kbn-securitysolution-hook-utils/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/README.md similarity index 100% rename from packages/kbn-securitysolution-hook-utils/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/index.ts new file mode 100644 index 0000000000000..40ff03e880946 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +export * from './src/types'; +export * from './src/use_async'; +export * from './src/use_is_mounted'; +export * from './src/use_observable'; +export * from './src/with_optional_signal'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/jest.config.js new file mode 100644 index 0000000000000..8238f9f7e97d2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils'], +}; diff --git a/packages/kbn-securitysolution-hook-utils/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-hook-utils/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/package.json new file mode 100644 index 0000000000000..efd415370f23d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/securitysolution-hook-utils", + "version": "1.0.0", + "description": "Security Solution utilities for React hooks", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/types.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/types.ts new file mode 100644 index 0000000000000..1b31cae2a16d4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/types.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +/** + * Represents the state of an asynchronous task, along with an initiator + * function to kick off the work. + */ +export interface Task { + loading: boolean; + error: unknown | undefined; + result: Result | undefined; + start: (...args: Args) => void; +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts new file mode 100644 index 0000000000000..e5420124a0ebc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts @@ -0,0 +1,164 @@ +/* + * 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. + */ + +import { waitFor, renderHook, act } from '@testing-library/react'; + +import { useAsync } from '.'; + +interface TestArgs { + n: number; + s: string; +} + +type TestReturn = Promise; + +describe('useAsync', () => { + /** + * Timeout for both jest tests and for the waitFor. + * jest tests default to 5 seconds and waitFor defaults to 1 second. + * 20_0000 = 20,000 milliseconds = 20 seconds + */ + const timeout = 20_000; + + let fn: jest.Mock; + let args: TestArgs; + + beforeEach(() => { + args = { n: 1, s: 's' }; + fn = jest.fn().mockResolvedValue(false); + }); + + it('does not invoke fn if start was not called', () => { + renderHook(() => useAsync(fn)); + expect(fn).not.toHaveBeenCalled(); + }); + + it( + 'invokes the function when start is called', + async () => { + const { result } = renderHook(() => useAsync(fn)); + + act(() => { + result.current.start(args); + }); + await waitFor(() => expect(fn).toHaveBeenCalled(), { timeout }); + }, + timeout + ); + + it('invokes the function with start args', async () => { + const { result } = renderHook(() => useAsync(fn)); + const expectedArgs = { ...args }; + + act(() => { + result.current.start(args); + }); + await waitFor(() => expect(fn).toHaveBeenCalledWith(expectedArgs), { timeout }); + }); + + it( + 'populates result with the resolved value of the fn', + async () => { + const { result } = renderHook(() => useAsync(fn)); + fn.mockResolvedValue({ resolved: 'value' }); + + act(() => { + result.current.start(args); + }); + await waitFor( + () => { + expect(result.current.result).toEqual({ resolved: 'value' }); + expect(result.current.error).toBeUndefined(); + }, + { timeout } + ); + }, + timeout + ); + + it( + 'populates error if function rejects', + async () => { + fn.mockRejectedValue(new Error('whoops')); + const { result } = renderHook(() => useAsync(fn)); + + act(() => { + result.current.start(args); + }); + + await waitFor( + () => { + expect(result.current.result).toBeUndefined(); + expect(result.current.error).toEqual(new Error('whoops')); + }, + { timeout } + ); + }, + timeout + ); + + it( + 'populates the loading state while the function is pending', + async () => { + let resolve: () => void; + fn.mockImplementation(() => new Promise((_resolve) => (resolve = _resolve))); + + const { result } = renderHook(() => useAsync(fn)); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + + act(() => resolve()); + await waitFor(() => expect(result.current.loading).toBe(false), { timeout }); + }, + timeout + ); + + it( + 'multiple start calls reset state', + async () => { + let resolve: (result: string) => void; + fn.mockImplementation(() => new Promise((_resolve) => (resolve = _resolve))); + + const { result } = renderHook(() => useAsync(fn)); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + + act(() => resolve('result')); + await waitFor( + () => { + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('result'); + }, + { timeout } + ); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + expect(result.current.result).toBe(undefined); + act(() => resolve('result')); + await waitFor( + () => { + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('result'); + }, + { timeout } + ); + }, + timeout + ); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts new file mode 100644 index 0000000000000..027039ac7cca7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts @@ -0,0 +1,54 @@ +/* + * 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. + */ + +import { useCallback, useState } from 'react'; + +import { Task } from '../types'; +import { useIsMounted } from '../use_is_mounted'; + +/** + * + * This hook wraps a promise-returning thunk (task) in order to conditionally + * initiate the work, and automatically provide state corresponding to the + * task's status. + * + * In order to function properly and not rerender unnecessarily, ensure that + * your task is a stable function reference. + * + * @param fn a function returning a promise. + * + * @returns An {@link Task} containing the task's current state along with a + * start callback + */ +export const useAsync = ( + fn: (...args: Args) => Promise +): Task => { + const isMounted = useIsMounted(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(); + const [result, setResult] = useState(); + + const start = useCallback( + (...args: Args) => { + setLoading(true); + setResult(undefined); + setError(undefined); + fn(...args) + .then((r) => isMounted() && setResult(r)) + .catch((e) => isMounted() && setError(e)) + .finally(() => isMounted() && setLoading(false)); + }, + [fn, isMounted] + ); + + return { + error, + loading, + result, + start, + }; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts new file mode 100644 index 0000000000000..52f3a0739f4aa --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +import { renderHook } from '@testing-library/react'; + +import { useIsMounted } from '.'; + +describe('useIsMounted', () => { + it('evaluates to true when mounted', () => { + const { result } = renderHook(() => useIsMounted()); + + expect(result.current()).toEqual(true); + }); + + it('evaluates to false when unmounted', () => { + const { result, unmount } = renderHook(() => useIsMounted()); + + unmount(); + expect(result.current()).toEqual(false); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts new file mode 100644 index 0000000000000..8d325aed1abd6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import { useCallback, useEffect, useRef } from 'react'; + +type GetIsMounted = () => boolean; + +/** + * + * @returns A {@link GetIsMounted} getter function returning whether the component is currently mounted + */ +export const useIsMounted = (): GetIsMounted => { + const isMounted = useRef(false); + const getIsMounted: GetIsMounted = useCallback(() => isMounted.current, []); + const handleCleanup = useCallback(() => { + isMounted.current = false; + }, []); + + useEffect(() => { + isMounted.current = true; + return handleCleanup; + }, [handleCleanup]); + + return getIsMounted; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts new file mode 100644 index 0000000000000..3c6d96e3d3ac2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts @@ -0,0 +1,159 @@ +/* + * 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. + */ + +import { renderHook, act } from '@testing-library/react'; +import { Subject, throwError } from 'rxjs'; + +import { useObservable } from '.'; + +interface TestArgs { + n: number; + s: string; +} + +type TestReturn = Subject; + +describe('useObservable', () => { + let fn: jest.Mock; + let subject: TestReturn; + let args: TestArgs; + + beforeEach(() => { + args = { n: 1, s: 's' }; + subject = new Subject(); + fn = jest.fn().mockReturnValue(subject); + }); + + it('does not invoke fn if start was not called', () => { + renderHook(() => useObservable(fn)); + expect(fn).not.toHaveBeenCalled(); + }); + + it('invokes the function when start is called', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + expect(fn).toHaveBeenCalled(); + }); + + it('invokes the function with start args', () => { + const { result } = renderHook(() => useObservable(fn)); + const expectedArgs = { ...args }; + + act(() => { + result.current.start(args); + }); + + expect(fn).toHaveBeenCalledWith(expectedArgs); + }); + + it('populates result with the next value of the fn', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + act(() => subject.next('value')); + + expect(result.current.result).toEqual('value'); + expect(result.current.error).toBeUndefined(); + }); + + it('populates error if observable throws an error', () => { + const error = new Error('whoops'); + const errorFn = () => throwError(error); + + const { result } = renderHook(() => useObservable(errorFn)); + + act(() => { + result.current.start(); + }); + + expect(result.current.result).toBeUndefined(); + expect(result.current.error).toEqual(error); + }); + + it('populates the loading state while no value has resolved', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + + act(() => subject.next('a value')); + + expect(result.current.loading).toBe(false); + }); + + it('updates result with each resolved value', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + act(() => subject.next('a value')); + expect(result.current.result).toEqual('a value'); + + act(() => subject.next('a subsequent value')); + expect(result.current.result).toEqual('a subsequent value'); + }); + + it('does not update result with values if start has not been called', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => subject.next('a value')); + expect(result.current.result).toBeUndefined(); + + act(() => subject.next('a subsequent value')); + expect(result.current.result).toBeUndefined(); + }); + + it('unsubscribes on unmount', () => { + const { result, unmount } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + expect(subject.observers).toHaveLength(1); + + unmount(); + expect(subject.observers).toHaveLength(0); + }); + + it('multiple start calls reset state', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + + act(() => subject.next('one value')); + + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('one value'); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + expect(result.current.result).toBe(undefined); + + act(() => subject.next('another value')); + + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('another value'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts new file mode 100644 index 0000000000000..b7cd1e2623b78 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts @@ -0,0 +1,91 @@ +/* + * 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. + */ + +import { useCallback, useEffect, useRef, useReducer, Reducer } from 'react'; +import { Observable, Subscription } from 'rxjs'; + +import { useIsMounted } from '../use_is_mounted'; +import { Task } from '../types'; + +interface State { + loading: boolean; + error?: unknown; + result?: T; +} + +export type Action = + | { type: 'setResult'; result: T } + | { type: 'setError'; error: unknown } + | { type: 'load' }; + +function reducer(state: State, action: Action) { + switch (action.type) { + case 'setResult': + return { ...state, result: action.result, loading: false }; + case 'setError': + return { ...state, error: action.error, loading: false }; + case 'load': + return { loading: true, result: undefined, error: undefined }; + } +} + +/** + * + * @param fn function returning an observable + * + * @returns An {@link Async} containing the underlying task's state along with a start callback + */ +export const useObservable = ( + fn: (...args: Args) => Observable +): Task => { + const isMounted = useIsMounted(); + const subRef = useRef(); + const [state, dispatch] = useReducer, Action>>(reducer, { + loading: false, + error: undefined, + result: undefined, + }); + + const start = useCallback( + (...args: Args) => { + if (subRef.current) { + subRef.current.unsubscribe(); + } + dispatch({ type: 'load' }); + + subRef.current = fn(...args).subscribe( + (r) => { + if (isMounted()) { + dispatch({ type: 'setResult', result: r }); + } + }, + (e) => { + if (isMounted()) { + dispatch({ type: 'setError', error: e }); + } + } + ); + }, + [fn, isMounted] + ); + + useEffect( + () => () => { + if (subRef.current) { + subRef.current.unsubscribe(); + } + }, + [] + ); + + return { + result: state.result, + error: state.error, + loading: state.loading, + start, + }; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts new file mode 100644 index 0000000000000..05a1b2fa167a0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import { withOptionalSignal } from '.'; + +type TestFn = ({ number, signal }: { number: number; signal: AbortSignal }) => boolean; + +describe('withOptionalSignal', () => { + it('does not require a signal on the returned function', () => { + const fn = jest.fn().mockReturnValue('hello') as TestFn; + + const wrappedFn = withOptionalSignal(fn); + + expect(wrappedFn({ number: 1 })).toEqual('hello'); + }); + + it('will pass a given signal to the wrapped function', () => { + const fn = jest.fn().mockReturnValue('hello') as TestFn; + const { signal } = new AbortController(); + + const wrappedFn = withOptionalSignal(fn); + + wrappedFn({ number: 1, signal }); + expect(fn).toHaveBeenCalledWith({ number: 1, signal }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts new file mode 100644 index 0000000000000..eadad58804f83 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +interface SignalArgs { + signal: AbortSignal; +} + +export type OptionalSignalArgs = Omit & Partial; + +/** + * + * @param fn an async function receiving an AbortSignal argument + * + * @returns An async function where the AbortSignal argument is optional + */ +export const withOptionalSignal = + (fn: (args: Args) => Result) => + (args: OptionalSignalArgs): Result => { + const signal = args.signal != null ? args.signal : new AbortController().signal; + return fn({ ...args, signal } as Args); + }; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/tsconfig.json new file mode 100644 index 0000000000000..ccdf26c349f09 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-hook-utils/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/README.md similarity index 100% rename from packages/kbn-securitysolution-io-ts-alerting-types/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/index.ts new file mode 100644 index 0000000000000..f5e8f8419b254 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/index.ts @@ -0,0 +1,40 @@ +/* + * 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. + */ + +export * from './src/actions'; +export * from './src/default_actions_array'; +export * from './src/default_export_file_name'; +export * from './src/default_from_string'; +export * from './src/default_interval_string'; +export * from './src/default_language_string'; +export * from './src/default_max_signals_number'; +export * from './src/default_page'; +export * from './src/default_per_page'; +export * from './src/default_risk_score_mapping_array'; +export * from './src/default_severity_mapping_array'; +export * from './src/default_threat_array'; +export * from './src/default_to_string'; +export * from './src/default_uuid'; +export * from './src/frequency'; +export * from './src/language'; +export * from './src/machine_learning_job_id'; +export * from './src/max_signals'; +export * from './src/normalized_ml_job_id'; +export * from './src/references_default_array'; +export * from './src/risk_score'; +export * from './src/risk_score_mapping'; +export * from './src/rule_schedule'; +export * from './src/saved_object_attributes'; +export * from './src/severity'; +export * from './src/severity_mapping'; +export * from './src/threat'; +export * from './src/threat_mapping'; +export * from './src/threat_subtechnique'; +export * from './src/threat_tactic'; +export * from './src/threat_technique'; +export * from './src/throttle'; +export * from './src/type'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/jest.config.js new file mode 100644 index 0000000000000..16223422cbd8d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types'], +}; diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-io-ts-alerting-types/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/package.json new file mode 100644 index 0000000000000..bbe6c163fb5e8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/securitysolution-io-ts-alerting-types", + "version": "1.0.0", + "description": "io ts utilities and types to be shared with plugins from the security solution project", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts new file mode 100644 index 0000000000000..64953a0dc0cdd --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts @@ -0,0 +1,127 @@ +/* + * 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. + */ + +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +import * as t from 'io-ts'; +import { saved_object_attributes } from '../saved_object_attributes'; +import { RuleActionFrequency } from '../frequency'; + +export type RuleActionGroup = t.TypeOf; +export const RuleActionGroup = t.string; + +export type RuleActionId = t.TypeOf; +export const RuleActionId = t.string; + +export type RuleActionTypeId = t.TypeOf; +export const RuleActionTypeId = t.string; + +export type RuleActionUuid = t.TypeOf; +export const RuleActionUuid = NonEmptyString; + +/** + * Params is an "object", since it is a type of RuleActionParams which is action templates. + * @see x-pack/plugins/alerting/common/rule.ts + */ +export type RuleActionParams = t.TypeOf; +export const RuleActionParams = saved_object_attributes; + +export const RuleActionAlertsFilter = t.partial({ + query: t.union([ + t.undefined, + t.intersection([ + t.strict({ + kql: t.string, + filters: t.array( + t.intersection([ + t.type({ + meta: t.partial({ + alias: t.union([t.string, t.null]), + disabled: t.boolean, + negate: t.boolean, + controlledBy: t.string, + group: t.string, + index: t.string, + isMultiIndex: t.boolean, + type: t.string, + key: t.string, + params: t.any, + value: t.string, + }), + }), + t.partial({ + $state: t.type({ store: t.any }), + query: t.record(t.string, t.any), + }), + ]) + ), + }), + t.partial({ dsl: t.string }), + ]), + ]), + timeframe: t.union([ + t.undefined, + t.strict({ + timezone: t.string, + days: t.array( + t.union([ + t.literal(1), + t.literal(2), + t.literal(3), + t.literal(4), + t.literal(5), + t.literal(6), + t.literal(7), + ]) + ), + hours: t.strict({ + start: t.string, + end: t.string, + }), + }), + ]), +}); + +export type RuleAction = t.TypeOf; +export const RuleAction = t.exact( + t.intersection([ + t.type({ + group: RuleActionGroup, + id: RuleActionId, + action_type_id: RuleActionTypeId, + params: RuleActionParams, + }), + t.partial({ + uuid: RuleActionUuid, + alerts_filter: RuleActionAlertsFilter, + frequency: RuleActionFrequency, + }), + ]) +); + +export type RuleActionArray = t.TypeOf; +export const RuleActionArray = t.array(RuleAction); + +export type RuleActionCamel = t.TypeOf; +export const RuleActionCamel = t.exact( + t.intersection([ + t.type({ + group: RuleActionGroup, + id: RuleActionId, + actionTypeId: RuleActionTypeId, + params: RuleActionParams, + }), + t.partial({ + uuid: RuleActionUuid, + alertsFilter: RuleActionAlertsFilter, + frequency: RuleActionFrequency, + }), + ]) +); + +export type RuleActionArrayCamel = t.TypeOf; +export const RuleActionArrayCamel = t.array(RuleActionCamel); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.mock.ts new file mode 100644 index 0000000000000..2747846c74d80 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.mock.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +export const ENTRY_VALUE = 'some host name'; +export const FIELD = 'host.name'; +export const MATCH = 'match'; +export const MATCH_ANY = 'match_any'; +export const OPERATOR = 'included'; +export const NESTED = 'nested'; +export const NESTED_FIELD = 'parent.field'; +export const LIST_ID = 'some-list-id'; +export const LIST = 'list'; +export const TYPE = 'ip'; +export const EXISTS = 'exists'; +export const WILDCARD = 'wildcard'; +export const USER = 'some user'; +export const DATE_NOW = '2020-04-20T15:25:31.830Z'; + +// Exception List specific +export const ID = 'uuid_here'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.ts new file mode 100644 index 0000000000000..ad5a2ba262260 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/constants/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/** + * TODO: Create a kbn-alerting-constants and add this to it. + * @deprecated Use a DEFAULT_MAX_SIGNALS from a kbn-alerting-constants package. + */ +export const DEFAULT_MAX_SIGNALS = 100; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_actions_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_actions_array/index.ts new file mode 100644 index 0000000000000..28ff3053564c9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_actions_array/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { RuleActionArray } from '../actions'; + +export const DefaultActionsArray = new t.Type< + RuleActionArray, + RuleActionArray | undefined, + unknown +>( + 'DefaultActionsArray', + RuleActionArray.is, + (input, context): Either => + input == null ? t.success([]) : RuleActionArray.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.test.ts new file mode 100644 index 0000000000000..009fdb23d3fb7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.test.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultExportFileName } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_export_file_name', () => { + test('it should validate a regular string', () => { + const payload = 'some string'; + const decoded = DefaultExportFileName.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate a number', () => { + const payload = 5; + const decoded = DefaultExportFileName.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultExportFileName"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of "export.ndjson"', () => { + const payload = null; + const decoded = DefaultExportFileName.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual('export.ndjson'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.ts new file mode 100644 index 0000000000000..53f0972baca21 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_export_file_name/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; + +/** + * Types the DefaultExportFileName as: + * - If null or undefined, then a default of "export.ndjson" will be used + */ +export const DefaultExportFileName = new t.Type( + 'DefaultExportFileName', + t.string.is, + (input, context): Either => + input == null ? t.success('export.ndjson') : t.string.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.test.ts new file mode 100644 index 0000000000000..f6c7f91e315ad --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.test.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultFromString } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_from_string', () => { + test('it should validate a from string', () => { + const payload = 'now-20m'; + const decoded = DefaultFromString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate a number', () => { + const payload = 5; + const decoded = DefaultFromString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultFromString"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of "now-6m"', () => { + const payload = null; + const decoded = DefaultFromString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual('now-6m'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.ts new file mode 100644 index 0000000000000..d23bca135d03e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_from_string/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { From } from '../from'; + +/** + * Types the DefaultFromString as: + * - If null or undefined, then a default of the string "now-6m" will be used + */ +export const DefaultFromString = new t.Type( + 'DefaultFromString', + t.string.is, + (input, context): Either => { + if (input == null) { + return t.success('now-6m'); + } + return From.validate(input, context); + }, + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.test.ts new file mode 100644 index 0000000000000..602d6c9ff79e8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.test.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultIntervalString } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_interval_string', () => { + test('it should validate a interval string', () => { + const payload = '20m'; + const decoded = DefaultIntervalString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate a number', () => { + const payload = 5; + const decoded = DefaultIntervalString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultIntervalString"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of "5m"', () => { + const payload = null; + const decoded = DefaultIntervalString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual('5m'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.ts new file mode 100644 index 0000000000000..d743fa773f2ec --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_interval_string/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; + +/** + * Types the DefaultIntervalString as: + * - If null or undefined, then a default of the string "5m" will be used + */ +export const DefaultIntervalString = new t.Type( + 'DefaultIntervalString', + t.string.is, + (input, context): Either => + input == null ? t.success('5m') : t.string.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.test.ts new file mode 100644 index 0000000000000..34e6e65518c71 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.test.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { Language } from '../language'; +import { DefaultLanguageString } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_language_string', () => { + test('it should validate a string', () => { + const payload: Language = 'lucene'; + const decoded = DefaultLanguageString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate a number', () => { + const payload = 5; + const decoded = DefaultLanguageString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultLanguageString"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of "kuery"', () => { + const payload = null; + const decoded = DefaultLanguageString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual('kuery'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.ts new file mode 100644 index 0000000000000..ca557dafecefd --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_language_string/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { language } from '../language'; + +/** + * Types the DefaultLanguageString as: + * - If null or undefined, then a default of the string "kuery" will be used + */ +export const DefaultLanguageString = new t.Type( + 'DefaultLanguageString', + t.string.is, + (input, context): Either => + input == null ? t.success('kuery') : language.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.test.ts new file mode 100644 index 0000000000000..cd4b0aa42953b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.test.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultMaxSignalsNumber } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { DEFAULT_MAX_SIGNALS } from '../constants'; + +describe('default_from_string', () => { + test('it should validate a max signal number', () => { + const payload = 5; + const decoded = DefaultMaxSignalsNumber.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate a string', () => { + const payload = '5'; + const decoded = DefaultMaxSignalsNumber.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultMaxSignals"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate a zero', () => { + const payload = 0; + const decoded = DefaultMaxSignalsNumber.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "0" supplied to "DefaultMaxSignals"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate a negative number', () => { + const payload = -1; + const decoded = DefaultMaxSignalsNumber.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "-1" supplied to "DefaultMaxSignals"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of DEFAULT_MAX_SIGNALS', () => { + const payload = null; + const decoded = DefaultMaxSignalsNumber.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(DEFAULT_MAX_SIGNALS); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.ts new file mode 100644 index 0000000000000..535f9397c7afb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_max_signals_number/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { max_signals } from '../max_signals'; +import { DEFAULT_MAX_SIGNALS } from '../constants'; + +/** + * Types the default max signal: + * - Natural Number (positive integer and not a float), + * - greater than 1 + * - If undefined then it will use DEFAULT_MAX_SIGNALS (100) as the default + */ +export const DefaultMaxSignalsNumber = new t.Type( + 'DefaultMaxSignals', + t.number.is, + (input, context): Either => { + return input == null ? t.success(DEFAULT_MAX_SIGNALS) : max_signals.validate(input, context); + }, + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.test.ts new file mode 100644 index 0000000000000..d9e63e0f9ec14 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.test.ts @@ -0,0 +1,84 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultPage } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_page', () => { + test('it should validate a regular number greater than zero', () => { + const payload = 5; + const decoded = DefaultPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate a string of a number', () => { + const payload = '5'; + const decoded = DefaultPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(5); + }); + + test('it should not validate a junk string', () => { + const payload = 'invalid-string'; + const decoded = DefaultPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "NaN" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate an empty string', () => { + const payload = ''; + const decoded = DefaultPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "NaN" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate a zero', () => { + const payload = 0; + const decoded = DefaultPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "0" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate a negative number', () => { + const payload = -1; + const decoded = DefaultPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "-1" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of 20', () => { + const payload = null; + const decoded = DefaultPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(1); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.ts new file mode 100644 index 0000000000000..6ae23dd8c676f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_page/index.ts @@ -0,0 +1,31 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; + +/** + * Types the DefaultPerPage as: + * - If a string this will convert the string to a number + * - If null or undefined, then a default of 1 will be used + * - If the number is 0 or less this will not validate as it has to be a positive number greater than zero + */ +export const DefaultPage = new t.Type( + 'DefaultPerPage', + t.number.is, + (input, context): Either => { + if (input == null) { + return t.success(1); + } else if (typeof input === 'string') { + return PositiveIntegerGreaterThanZero.validate(parseInt(input, 10), context); + } else { + return PositiveIntegerGreaterThanZero.validate(input, context); + } + }, + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.test.ts new file mode 100644 index 0000000000000..07a6358ba2e89 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.test.ts @@ -0,0 +1,84 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultPerPage } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_per_page', () => { + test('it should validate a regular number greater than zero', () => { + const payload = 5; + const decoded = DefaultPerPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate a string of a number', () => { + const payload = '5'; + const decoded = DefaultPerPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(5); + }); + + test('it should not validate a junk string', () => { + const payload = 'invalid-string'; + const decoded = DefaultPerPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "NaN" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate an empty string', () => { + const payload = ''; + const decoded = DefaultPerPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "NaN" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate a zero', () => { + const payload = 0; + const decoded = DefaultPerPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "0" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not validate a negative number', () => { + const payload = -1; + const decoded = DefaultPerPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "-1" supplied to "DefaultPerPage"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of 20', () => { + const payload = null; + const decoded = DefaultPerPage.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(20); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.ts new file mode 100644 index 0000000000000..320945311d3b6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_per_page/index.ts @@ -0,0 +1,31 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; + +/** + * Types the DefaultPerPage as: + * - If a string this will convert the string to a number + * - If null or undefined, then a default of 20 will be used + * - If the number is 0 or less this will not validate as it has to be a positive number greater than zero + */ +export const DefaultPerPage = new t.Type( + 'DefaultPerPage', + t.number.is, + (input, context): Either => { + if (input == null) { + return t.success(20); + } else if (typeof input === 'string') { + return PositiveIntegerGreaterThanZero.validate(parseInt(input, 10), context); + } else { + return PositiveIntegerGreaterThanZero.validate(input, context); + } + }, + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_risk_score_mapping_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_risk_score_mapping_array/index.ts new file mode 100644 index 0000000000000..a457c827e25f6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_risk_score_mapping_array/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { RiskScoreMapping } from '../risk_score_mapping'; + +/** + * Types the DefaultStringArray as: + * - If null or undefined, then a default RiskScoreMapping array will be set + */ +export const DefaultRiskScoreMappingArray = new t.Type< + RiskScoreMapping, + RiskScoreMapping | undefined, + unknown +>( + 'DefaultRiskScoreMappingArray', + RiskScoreMapping.is, + (input, context): Either => + input == null ? t.success([]) : RiskScoreMapping.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_severity_mapping_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_severity_mapping_array/index.ts new file mode 100644 index 0000000000000..8d7b581146eac --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_severity_mapping_array/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { SeverityMapping } from '../severity_mapping'; + +/** + * Types the DefaultStringArray as: + * - If null or undefined, then a default SeverityMapping array will be set + */ +export const DefaultSeverityMappingArray = new t.Type< + SeverityMapping, + SeverityMapping | undefined, + unknown +>( + 'DefaultSeverityMappingArray', + SeverityMapping.is, + (input, context): Either => + input == null ? t.success([]) : SeverityMapping.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.test.ts new file mode 100644 index 0000000000000..ed42de41effcc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.test.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { Threats } from '../threat'; +import { DefaultThreatArray } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_threat_null', () => { + test('it should validate an empty array', () => { + const payload: Threats = []; + const decoded = DefaultThreatArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of threats', () => { + const payload: Threats = [ + { + framework: 'MITRE ATTACK', + technique: [{ reference: 'https://test.com', name: 'Audio Capture', id: 'T1123' }], + tactic: { reference: 'https://test.com', name: 'Collection', id: 'TA000999' }, + }, + ]; + const decoded = DefaultThreatArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate an array with a number', () => { + const payload = [ + { + framework: 'MITRE ATTACK', + technique: [{ reference: 'https://test.com', name: 'Audio Capture', id: 'T1123' }], + tactic: { reference: 'https://test.com', name: 'Collection', id: 'TA000999' }, + }, + 5, + ]; + const decoded = DefaultThreatArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultThreatArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default empty array if not provided a value', () => { + const payload = null; + const decoded = DefaultThreatArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.ts new file mode 100644 index 0000000000000..8ed8abc587504 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_threat_array/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { threats, Threats } from '../threat'; + +/** + * Types the DefaultThreatArray as: + * - If null or undefined, then an empty array will be set + */ +export const DefaultThreatArray = new t.Type( + 'DefaultThreatArray', + threats.is, + (input, context): Either => + input == null ? t.success([]) : threats.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.test.ts new file mode 100644 index 0000000000000..f87b1c4f24a9e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.test.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultToString } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_to_string', () => { + test('it should validate a to string', () => { + const payload = 'now-5m'; + const decoded = DefaultToString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate a number', () => { + const payload = 5; + const decoded = DefaultToString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultToString"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of "now"', () => { + const payload = null; + const decoded = DefaultToString.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual('now'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.ts new file mode 100644 index 0000000000000..d2e58f423b592 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_to_string/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; + +/** + * Types the DefaultToString as: + * - If null or undefined, then a default of the string "now" will be used + */ +export const DefaultToString = new t.Type( + 'DefaultToString', + t.string.is, + (input, context): Either => + input == null ? t.success('now') : t.string.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.test.ts new file mode 100644 index 0000000000000..ee605a5c4383a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.test.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultUuid } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_uuid', () => { + test('it should validate a regular string', () => { + const payload = '1'; + const decoded = DefaultUuid.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate a number', () => { + const payload = 5; + const decoded = DefaultUuid.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "5" supplied to "DefaultUuid"']); + expect(message.schema).toEqual({}); + }); + + test('it should return a default of a uuid', () => { + const payload = null; + const decoded = DefaultUuid.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i + ); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.ts new file mode 100644 index 0000000000000..b3d6fda5b134a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/default_uuid/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { v4 as uuidv4 } from 'uuid'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +/** + * Types the DefaultUuid as: + * - If null or undefined, then a default string uuidv4() will be + * created otherwise it will be checked just against an empty string + */ +export const DefaultUuid = new t.Type( + 'DefaultUuid', + t.string.is, + (input, context): Either => + input == null ? t.success(uuidv4()) : NonEmptyString.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/frequency/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/frequency/index.ts new file mode 100644 index 0000000000000..318408f145823 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/frequency/index.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RuleActionThrottle } from '../throttle'; + +/** + * Action summary indicates whether we will send a summary notification about all the generate alerts or notification per individual alert + */ +export type RuleActionSummary = t.TypeOf; +export const RuleActionSummary = t.boolean; + +/** + * The condition for throttling the notification: `onActionGroupChange`, `onActiveAlert`, or `onThrottleInterval` + */ +export type RuleActionNotifyWhen = t.TypeOf; +export const RuleActionNotifyWhen = t.union([ + t.literal('onActionGroupChange'), + t.literal('onActiveAlert'), + t.literal('onThrottleInterval'), +]); + +/** + * The action frequency defines when the action runs (for example, only on rule execution or at specific time intervals). + */ +export type RuleActionFrequency = t.TypeOf; +export const RuleActionFrequency = t.type({ + summary: RuleActionSummary, + notifyWhen: RuleActionNotifyWhen, + throttle: t.union([RuleActionThrottle, t.null]), +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/from/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/from/index.ts new file mode 100644 index 0000000000000..d0330fae61404 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/from/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +import { Either } from 'fp-ts/lib/Either'; +import * as t from 'io-ts'; +import { parseScheduleDates } from '@kbn/securitysolution-io-ts-utils'; + +const stringValidator = (input: unknown): input is string => typeof input === 'string'; + +export type From = t.TypeOf; +export const From = new t.Type( + 'From', + t.string.is, + (input, context): Either => { + if (stringValidator(input) && parseScheduleDates(input) == null) { + return t.failure(input, context, 'Failed to parse "from" on rule param'); + } + return t.string.validate(input, context); + }, + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/language/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/language/index.ts new file mode 100644 index 0000000000000..63ad102a41349 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/language/index.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const language = t.keyof({ eql: null, kuery: null, lucene: null, esql: null }); +export type Language = t.TypeOf; + +export const languageOrUndefined = t.union([language, t.undefined]); +export type LanguageOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/machine_learning_job_id/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/machine_learning_job_id/index.ts new file mode 100644 index 0000000000000..8e6453ac7e7b8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/machine_learning_job_id/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +import { machine_learning_job_id_normalized } from '../normalized_ml_job_id'; + +export const machine_learning_job_id = t.union([t.string, machine_learning_job_id_normalized]); +export type MachineLearningJobId = t.TypeOf; + +export const machineLearningJobIdOrUndefined = t.union([machine_learning_job_id, t.undefined]); +export type MachineLearningJobIdOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/max_signals/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/max_signals/index.ts new file mode 100644 index 0000000000000..64ded4827b5eb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/max_signals/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; +import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; + +export const max_signals = PositiveIntegerGreaterThanZero; +export type MaxSignals = t.TypeOf; + +export const maxSignalsOrUndefined = t.union([max_signals, t.undefined]); +export type MaxSignalsOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/normalized_ml_job_id/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/normalized_ml_job_id/index.ts new file mode 100644 index 0000000000000..f81c3da1db5d2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/normalized_ml_job_id/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +import { NonEmptyArray } from '@kbn/securitysolution-io-ts-types'; + +export const machine_learning_job_id_normalized = NonEmptyArray(t.string); +export type MachineLearningJobIdNormalized = t.TypeOf; + +export const machineLearningJobIdNormalizedOrUndefined = t.union([ + machine_learning_job_id_normalized, + t.undefined, +]); +export type MachineLearningJobIdNormalizedOrUndefined = t.TypeOf< + typeof machineLearningJobIdNormalizedOrUndefined +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.test.ts new file mode 100644 index 0000000000000..7c5e9bb29877f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.test.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { ReferencesDefaultArray } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_string_array', () => { + test('it should validate an empty array', () => { + const payload: string[] = []; + const decoded = ReferencesDefaultArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of strings', () => { + const payload = ['value 1', 'value 2']; + const decoded = ReferencesDefaultArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate an array with a number', () => { + const payload = ['value 1', 5]; + const decoded = ReferencesDefaultArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "referencesWithDefaultArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default array entry', () => { + const payload = null; + const decoded = ReferencesDefaultArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.ts new file mode 100644 index 0000000000000..e5ccac3650434 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/references_default_array/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; + +/** + * Types the ReferencesDefaultArray as: + * - If null or undefined, then a default array will be set + */ +export const ReferencesDefaultArray = new t.Type( + 'referencesWithDefaultArray', + t.array(t.string).is, + (input, context): Either => + input == null ? t.success([]) : t.array(t.string).validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.test.ts new file mode 100644 index 0000000000000..b55ef415fbbb5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.test.ts @@ -0,0 +1,60 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { RiskScore } from '.'; + +describe('risk_score', () => { + test('it should validate a positive number', () => { + const payload = 1; + const decoded = RiskScore.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate a zero', () => { + const payload = 0; + const decoded = RiskScore.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT validate a negative number', () => { + const payload = -1; + const decoded = RiskScore.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "-1" supplied to "RiskScore"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT validate a string', () => { + const payload = 'some string'; + const decoded = RiskScore.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "RiskScore"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT validate a risk score greater than 100', () => { + const payload = 101; + const decoded = RiskScore.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "101" supplied to "RiskScore"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.ts new file mode 100644 index 0000000000000..143ea2e727543 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; + +/** + * Types the risk score as: + * - Natural Number (positive integer and not a float), + * - Between the values [0 and 100] inclusive. + */ +export type RiskScore = t.TypeOf; +export const RiskScore = new t.Type( + 'RiskScore', + t.number.is, + (input, context): Either => { + return typeof input === 'number' && Number.isSafeInteger(input) && input >= 0 && input <= 100 + ? t.success(input) + : t.failure(input, context); + }, + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score_mapping/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score_mapping/index.ts new file mode 100644 index 0000000000000..0856806d48989 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/risk_score_mapping/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { operator } from '@kbn/securitysolution-io-ts-types'; +import { RiskScore } from '../risk_score'; + +export type RiskScoreMappingItem = t.TypeOf; +export const RiskScoreMappingItem = t.exact( + t.type({ + field: t.string, + value: t.string, + operator, + risk_score: t.union([RiskScore, t.undefined]), + }) +); + +export type RiskScoreMapping = t.TypeOf; +export const RiskScoreMapping = t.array(RiskScoreMappingItem); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/rule_schedule/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/rule_schedule/index.ts new file mode 100644 index 0000000000000..16bc6dc153104 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/rule_schedule/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { From } from '../from'; + +export type RuleInterval = t.TypeOf; +export const RuleInterval = t.string; // we need a more specific schema + +export type RuleIntervalFrom = t.TypeOf; +export const RuleIntervalFrom = From; + +/** + * TODO: Create a regular expression type or custom date math part type here + */ +export type RuleIntervalTo = t.TypeOf; +export const RuleIntervalTo = t.string; // we need a more specific schema diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/saved_object_attributes/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/saved_object_attributes/index.ts new file mode 100644 index 0000000000000..33db222f098e1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/saved_object_attributes/index.ts @@ -0,0 +1,62 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +/** + * TODO: This type are originally from "src/core/types/saved_objects.ts", once that is package friendly remove + * this copied type. + * + * Don't use this type, it's simply a helper type for {@link SavedObjectAttribute} + * + * @public + */ +export type SavedObjectAttributeSingle = + | string + | number + | boolean + | null + | undefined + | SavedObjectAttributes; + +/** + * TODO: This type are originally from "src/core/types/saved_objects.ts", once that is package friendly remove + * this copied type. + * + * Type definition for a Saved Object attribute value + * + * @public + */ +export type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; + +/** + * TODO: This type are originally from "src/core/types/saved_objects.ts", once that is package friendly remove + * this copied type. + * + * The data for a Saved Object is stored as an object in the `attributes` + * property. + * + * @public + */ +export interface SavedObjectAttributes { + [key: string]: SavedObjectAttribute; +} + +export const saved_object_attribute_single: t.Type = t.recursion( + 'saved_object_attribute_single', + () => t.union([t.string, t.number, t.boolean, t.null, t.undefined, saved_object_attributes]) +); +export const saved_object_attribute: t.Type = t.recursion( + 'saved_object_attribute', + () => t.union([saved_object_attribute_single, t.array(saved_object_attribute_single)]) +); +export const saved_object_attributes: t.Type = t.recursion( + 'saved_object_attributes', + () => t.record(t.string, saved_object_attribute) +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/severity/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/severity/index.ts new file mode 100644 index 0000000000000..1b27423eb0dba --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/severity/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export type Severity = t.TypeOf; +export const Severity = t.keyof({ low: null, medium: null, high: null, critical: null }); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/severity_mapping/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/severity_mapping/index.ts new file mode 100644 index 0000000000000..4256314b32a2c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/severity_mapping/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { operator } from '@kbn/securitysolution-io-ts-types'; +import { Severity } from '../severity'; + +export type SeverityMappingItem = t.TypeOf; +export const SeverityMappingItem = t.exact( + t.type({ + field: t.string, + operator, + value: t.string, + severity: Severity, + }) +); + +export type SeverityMapping = t.TypeOf; +export const SeverityMapping = t.array(SeverityMappingItem); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat/index.ts new file mode 100644 index 0000000000000..4b5b7aa16c2dc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat/index.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; +import { threat_tactic } from '../threat_tactic'; +import { threat_techniques } from '../threat_technique'; + +export const threat_framework = t.string; + +export const threat = t.intersection([ + t.exact( + t.type({ + framework: threat_framework, + tactic: threat_tactic, + }) + ), + t.exact( + t.partial({ + technique: threat_techniques, + }) + ), +]); + +export type Threat = t.TypeOf; + +export const threats = t.array(threat); +export type Threats = t.TypeOf; + +export const threatsOrUndefined = t.union([threats, t.undefined]); +export type ThreatsOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.test.ts new file mode 100644 index 0000000000000..781b5b89ebe6c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.test.ts @@ -0,0 +1,235 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { + concurrent_searches, + items_per_search, + ThreatMapping, + threatMappingEntries, + ThreatMappingEntries, + threat_mapping, +} from '.'; +import { foldLeftRight, getPaths, exactCheck } from '@kbn/securitysolution-io-ts-utils'; + +describe('threat_mapping', () => { + describe('threatMappingEntries', () => { + test('it should validate an entry', () => { + const payload: ThreatMappingEntries = [ + { + field: 'field.one', + type: 'mapping', + value: 'field.one', + }, + ]; + const decoded = threatMappingEntries.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation with an extra entry item', () => { + const payload: Array = [ + { + field: 'field.one', + type: 'mapping', + value: 'field.one', + extra: 'blah', + }, + ]; + const decoded = threatMappingEntries.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extra"']); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation with a non string', () => { + const payload = [ + { + field: 5, + type: 'mapping', + value: 'field.one', + }, + ] as unknown as ThreatMappingEntries[]; + const decoded = threatMappingEntries.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "5" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation with a wrong type', () => { + const payload = [ + { + field: 'field.one', + type: 'invalid', + value: 'field.one', + }, + ] as unknown as ThreatMappingEntries[]; + const decoded = threatMappingEntries.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "invalid" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('threat_mapping', () => { + test('it should validate a threat mapping', () => { + const payload: ThreatMapping = [ + { + entries: [ + { + field: 'field.one', + type: 'mapping', + value: 'field.one', + }, + ], + }, + ]; + const decoded = threat_mapping.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + }); + + test('it should fail validate with an extra key', () => { + const payload: Array = [ + { + entries: [ + { + field: 'field.one', + type: 'mapping', + value: 'field.one', + }, + ], + extra: 'invalid', + }, + ]; + + const decoded = threat_mapping.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extra"']); + expect(message.schema).toEqual({}); + }); + + test('it should fail validate with an extra inner entry', () => { + const payload: Array }> = [ + { + entries: [ + { + field: 'field.one', + type: 'mapping', + value: 'field.one', + extra: 'blah', + }, + ], + }, + ]; + + const decoded = threat_mapping.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extra"']); + expect(message.schema).toEqual({}); + }); + + test('it should fail validate with an extra inner entry with the wrong data type', () => { + const payload = [ + { + entries: [ + { + field: 5, + type: 'mapping', + value: 'field.one', + }, + ], + }, + ] as unknown as ThreatMapping; + + const decoded = threat_mapping.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "entries,field"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validate with empty array', () => { + const payload: string[] = []; + + const decoded = threat_mapping.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "[]" supplied to "NonEmptyArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when concurrent_searches is < 0', () => { + const payload = -1; + const decoded = concurrent_searches.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "-1" supplied to "PositiveIntegerGreaterThanZero"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when concurrent_searches is 0', () => { + const payload = 0; + const decoded = concurrent_searches.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "0" supplied to "PositiveIntegerGreaterThanZero"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when items_per_search is 0', () => { + const payload = 0; + const decoded = items_per_search.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "0" supplied to "PositiveIntegerGreaterThanZero"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when items_per_search is < 0', () => { + const payload = -1; + const decoded = items_per_search.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "-1" supplied to "PositiveIntegerGreaterThanZero"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.ts new file mode 100644 index 0000000000000..3bf4f84aeec8e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_mapping/index.ts @@ -0,0 +1,77 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; +import { + NonEmptyArray, + NonEmptyString, + PositiveIntegerGreaterThanZero, +} from '@kbn/securitysolution-io-ts-types'; +import { language } from '../language'; + +export const threat_query = t.string; +export type ThreatQuery = t.TypeOf; +export const threatQueryOrUndefined = t.union([threat_query, t.undefined]); +export type ThreatQueryOrUndefined = t.TypeOf; + +export const threat_indicator_path = t.string; +export type ThreatIndicatorPath = t.TypeOf; +export const threatIndicatorPathOrUndefined = t.union([threat_indicator_path, t.undefined]); +export type ThreatIndicatorPathOrUndefined = t.TypeOf; + +export const threat_filters = t.array(t.unknown); // Filters are not easily type-able yet +export type ThreatFilters = t.TypeOf; +export const threatFiltersOrUndefined = t.union([threat_filters, t.undefined]); +export type ThreatFiltersOrUndefined = t.TypeOf; + +export const threatMapEntry = t.exact( + t.type({ + field: NonEmptyString, + type: t.keyof({ mapping: null }), + value: NonEmptyString, + }) +); + +export type ThreatMapEntry = t.TypeOf; + +export const threatMappingEntries = t.array(threatMapEntry); +export type ThreatMappingEntries = t.TypeOf; + +export const threatMap = t.exact( + t.type({ + entries: threatMappingEntries, + }) +); +export type ThreatMap = t.TypeOf; + +export const threat_mapping = NonEmptyArray(threatMap, 'NonEmptyArray'); +export type ThreatMapping = t.TypeOf; + +export const threatMappingOrUndefined = t.union([threat_mapping, t.undefined]); +export type ThreatMappingOrUndefined = t.TypeOf; + +export const threat_index = t.array(t.string); +export type ThreatIndex = t.TypeOf; +export const threatIndexOrUndefined = t.union([threat_index, t.undefined]); +export type ThreatIndexOrUndefined = t.TypeOf; + +export const threat_language = t.union([language, t.undefined]); +export type ThreatLanguage = t.TypeOf; +export const threatLanguageOrUndefined = t.union([threat_language, t.undefined]); +export type ThreatLanguageOrUndefined = t.TypeOf; + +export const concurrent_searches = PositiveIntegerGreaterThanZero; +export type ConcurrentSearches = t.TypeOf; +export const concurrentSearchesOrUndefined = t.union([concurrent_searches, t.undefined]); +export type ConcurrentSearchesOrUndefined = t.TypeOf; + +export const items_per_search = PositiveIntegerGreaterThanZero; +export type ItemsPerSearch = t.TypeOf; +export const itemsPerSearchOrUndefined = t.union([items_per_search, t.undefined]); +export type ItemsPerSearchOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_subtechnique/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_subtechnique/index.ts new file mode 100644 index 0000000000000..b5f2d95a139b5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_subtechnique/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const threat_subtechnique_id = t.string; +export const threat_subtechnique_name = t.string; +export const threat_subtechnique_reference = t.string; + +export const threat_subtechnique = t.type({ + id: threat_subtechnique_id, + name: threat_subtechnique_name, + reference: threat_subtechnique_reference, +}); + +export const threat_subtechniques = t.array(threat_subtechnique); + +export type ThreatSubtechnique = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_tactic/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_tactic/index.ts new file mode 100644 index 0000000000000..a4c63cb632892 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_tactic/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const threat_tactic_id = t.string; +export const threat_tactic_name = t.string; +export const threat_tactic_reference = t.string; + +export const threat_tactic = t.type({ + id: threat_tactic_id, + name: threat_tactic_name, + reference: threat_tactic_reference, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_technique/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_technique/index.ts new file mode 100644 index 0000000000000..992c5b15ba655 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/threat_technique/index.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; +import { threat_subtechniques } from '../threat_subtechnique'; + +export const threat_technique_id = t.string; +export const threat_technique_name = t.string; +export const threat_technique_reference = t.string; + +export const threat_technique = t.intersection([ + t.exact( + t.type({ + id: threat_technique_id, + name: threat_technique_name, + reference: threat_technique_reference, + }) + ), + t.exact( + t.partial({ + subtechnique: threat_subtechniques, + }) + ), +]); +export const threat_techniques = t.array(threat_technique); + +export type ThreatTechnique = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/throttle/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/throttle/index.ts new file mode 100644 index 0000000000000..b4be7a4a97ff7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/throttle/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { TimeDuration } from '@kbn/securitysolution-io-ts-types'; + +export type RuleActionThrottle = t.TypeOf; +export const RuleActionThrottle = t.union([ + t.literal('no_actions'), + t.literal('rule'), + TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }), +]); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/type/index.ts new file mode 100644 index 0000000000000..92b71faf14fe8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/src/type/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const type = t.keyof({ + eql: null, + machine_learning: null, + query: null, + saved_query: null, + threshold: null, + threat_match: null, + new_terms: null, + esql: null, +}); +export type Type = t.TypeOf; + +export const typeOrUndefined = t.union([type, t.undefined]); +export type TypeOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/tsconfig.json new file mode 100644 index 0000000000000..9b61aea31d977 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "kbn_references": [ + "@kbn/securitysolution-io-ts-types", + "@kbn/securitysolution-io-ts-utils" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-io-ts-list-types/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/README.md similarity index 100% rename from packages/kbn-securitysolution-io-ts-list-types/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/index.ts new file mode 100644 index 0000000000000..90db551881094 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export * from './src/common'; +export * from './src/request'; +export * from './src/response'; +export * from './src/typescript_types'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/jest.config.js new file mode 100644 index 0000000000000..1e8525371d27c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types'], +}; diff --git a/packages/kbn-securitysolution-io-ts-list-types/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-io-ts-list-types/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/package.json new file mode 100644 index 0000000000000..da6c209015847 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/securitysolution-io-ts-list-types", + "version": "1.0.0", + "description": "io ts utilities and types to be shared with plugins from the security solution project", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.mock.ts new file mode 100644 index 0000000000000..69ad828a480ed --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.mock.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import { Comment, CommentsArray } from '.'; +import { DATE_NOW, ID, USER } from '../../constants/index.mock'; + +export const getCommentsMock = (): Comment => ({ + comment: 'some old comment', + created_at: DATE_NOW, + created_by: USER, + id: ID, +}); + +export const getCommentsArrayMock = (): CommentsArray => [getCommentsMock(), getCommentsMock()]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.test.ts new file mode 100644 index 0000000000000..32a230fcf586d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.test.ts @@ -0,0 +1,236 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getCommentsArrayMock, getCommentsMock } from './index.mock'; +import { + Comment, + comment, + CommentsArray, + commentsArray, + CommentsArrayOrUndefined, + commentsArrayOrUndefined, +} from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { DATE_NOW } from '../../constants/index.mock'; + +describe('Comment', () => { + describe('comment', () => { + test('it fails validation when "id" is undefined', () => { + const payload = { ...getCommentsMock(), id: undefined }; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it passes validation with a typical comment', () => { + const payload = getCommentsMock(); + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation with "updated_at" and "updated_by" fields included', () => { + const payload = getCommentsMock(); + payload.updated_at = DATE_NOW; + payload.updated_by = 'someone'; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when "comment" is an empty string', () => { + const payload: Omit & { comment: string } = { + ...getCommentsMock(), + comment: '', + }; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "comment"']); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when "comment" is not a string', () => { + const payload: Omit & { comment: string[] } = { + ...getCommentsMock(), + comment: ['some value'], + }; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["some value"]" supplied to "comment"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when "created_at" is not a string', () => { + const payload: Omit & { created_at: number } = { + ...getCommentsMock(), + created_at: 1, + }; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "created_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when "created_by" is not a string', () => { + const payload: Omit & { created_by: number } = { + ...getCommentsMock(), + created_by: 1, + }; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "created_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when "updated_at" is not a string', () => { + const payload: Omit & { updated_at: number } = { + ...getCommentsMock(), + updated_at: 1, + }; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "updated_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when "updated_by" is not a string', () => { + const payload: Omit & { updated_by: number } = { + ...getCommentsMock(), + updated_by: 1, + }; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "updated_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: Comment & { + extraKey?: string; + } = getCommentsMock(); + payload.extraKey = 'some value'; + const decoded = comment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getCommentsMock()); + }); + }); + + describe('commentsArray', () => { + test('it passes validation an array of Comment', () => { + const payload = getCommentsArrayMock(); + const decoded = commentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation when a Comment includes "updated_at" and "updated_by"', () => { + const commentsPayload = getCommentsMock(); + commentsPayload.updated_at = DATE_NOW; + commentsPayload.updated_by = 'someone'; + const payload = [{ ...commentsPayload }, ...getCommentsArrayMock()]; + const decoded = commentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = commentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when array includes non Comment types', () => { + const payload = [1] as unknown as CommentsArray; + const decoded = commentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('commentsArrayOrUndefined', () => { + test('it passes validation an array of Comment', () => { + const payload = getCommentsArrayMock(); + const decoded = commentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation when undefined', () => { + const payload = undefined; + const decoded = commentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when array includes non Comment types', () => { + const payload = [1] as unknown as CommentsArrayOrUndefined; + const decoded = commentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.ts new file mode 100644 index 0000000000000..48bce8fabafe7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/comment/index.ts @@ -0,0 +1,38 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { created_at } from '../created_at'; +import { created_by } from '../created_by'; +import { id } from '../id'; +import { updated_at } from '../updated_at'; +import { updated_by } from '../updated_by'; + +export const comment = t.intersection([ + t.exact( + t.type({ + comment: NonEmptyString, + created_at, + created_by, + id, + }) + ), + t.exact( + t.partial({ + updated_at, + updated_by, + }) + ), +]); + +export const commentsArray = t.array(comment); +export type CommentsArray = t.TypeOf; +export type Comment = t.TypeOf; +export const commentsArrayOrUndefined = t.union([commentsArray, t.undefined]); +export type CommentsArrayOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.mock.ts new file mode 100644 index 0000000000000..67be8d1f15da4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.mock.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import { CreateComment, CreateCommentsArray } from '.'; + +export const getCreateCommentsMock = (): CreateComment => ({ + comment: 'some comments', +}); + +export const getCreateCommentsArrayMock = (): CreateCommentsArray => [getCreateCommentsMock()]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.test.ts new file mode 100644 index 0000000000000..15fab1c35a19c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.test.ts @@ -0,0 +1,133 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getCreateCommentsArrayMock, getCreateCommentsMock } from './index.mock'; +import { + CreateComment, + createComment, + CreateCommentsArray, + createCommentsArray, + CreateCommentsArrayOrUndefined, + createCommentsArrayOrUndefined, +} from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('CreateComment', () => { + describe('createComment', () => { + test('it passes validation with a default comment', () => { + const payload = getCreateCommentsMock(); + const decoded = createComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = createComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "{| comment: NonEmptyString |}"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when "comment" is not a string', () => { + const payload: Omit & { comment: string[] } = { + ...getCreateCommentsMock(), + comment: ['some value'], + }; + const decoded = createComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["some value"]" supplied to "comment"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: CreateComment & { + extraKey?: string; + } = getCreateCommentsMock(); + payload.extraKey = 'some value'; + const decoded = createComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getCreateCommentsMock()); + }); + }); + + describe('createCommentsArray', () => { + test('it passes validation an array of comments', () => { + const payload = getCreateCommentsArrayMock(); + const decoded = createCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = createCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "Array<{| comment: NonEmptyString |}>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when array includes non comments types', () => { + const payload = [1] as unknown as CreateCommentsArray; + const decoded = createCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<{| comment: NonEmptyString |}>"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('createCommentsArrayOrUndefined', () => { + test('it passes validation an array of comments', () => { + const payload = getCreateCommentsArrayMock(); + const decoded = createCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation when undefined', () => { + const payload = undefined; + const decoded = createCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when array includes non comments types', () => { + const payload = [1] as unknown as CreateCommentsArrayOrUndefined; + const decoded = createCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<{| comment: NonEmptyString |}>"', + ]); + expect(message.schema).toEqual({}); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.ts new file mode 100644 index 0000000000000..e0942203bac66 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/create_comment/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +export const createComment = t.exact( + t.type({ + comment: NonEmptyString, + }) +); + +export type CreateComment = t.TypeOf; +export const createCommentsArray = t.array(createComment); +export type CreateCommentsArray = t.TypeOf; +export type CreateComments = t.TypeOf; +export const createCommentsArrayOrUndefined = t.union([createCommentsArray, t.undefined]); +export type CreateCommentsArrayOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/created_at/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/created_at/index.ts new file mode 100644 index 0000000000000..e962946e447e8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/created_at/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const created_at = t.string; // TODO: Make this into an ISO Date string check diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/created_by/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/created_by/index.ts new file mode 100644 index 0000000000000..ccf8d816f8e82 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/created_by/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const created_by = t.string; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/cursor/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/cursor/index.ts new file mode 100644 index 0000000000000..626b510ec8958 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/cursor/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const cursor = t.string; +export type Cursor = t.TypeOf; +export const cursorOrUndefined = t.union([cursor, t.undefined]); +export type CursorOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.test.ts new file mode 100644 index 0000000000000..af9f342c15e55 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.test.ts @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { CommentsArray } from '../comment'; +import { DefaultCommentsArray } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getCommentsArrayMock } from '../comment/index.mock'; + +describe('default_comments_array', () => { + test('it should pass validation when supplied an empty array', () => { + const payload: CommentsArray = []; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of comments', () => { + const payload: CommentsArray = getCommentsArrayMock(); + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an array of numbers', () => { + const payload = [1]; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an array of strings', () => { + const payload = ['some string']; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default array entry', () => { + const payload = null; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.ts new file mode 100644 index 0000000000000..af1576237b9ca --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_comments_array/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { comment, CommentsArray } from '../comment'; + +/** + * Types the DefaultCommentsArray as: + * - If null or undefined, then a default array of type entry will be set + */ +export const DefaultCommentsArray = new t.Type( + 'DefaultCommentsArray', + t.array(comment).is, + (input): Either => + input == null ? t.success([]) : t.array(comment).decode(input), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.test.ts new file mode 100644 index 0000000000000..9f4aba07c9bf1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.test.ts @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { CommentsArray } from '../comment'; +import { DefaultCommentsArray } from '../default_comments_array'; +import { getCommentsArrayMock } from '../comment/index.mock'; + +describe('default_comments_array', () => { + test('it should pass validation when supplied an empty array', () => { + const payload: CommentsArray = []; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of comments', () => { + const payload: CommentsArray = getCommentsArrayMock(); + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an array of numbers', () => { + const payload = [1]; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an array of strings', () => { + const payload = ['some string']; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default array entry', () => { + const payload = null; + const decoded = DefaultCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.ts new file mode 100644 index 0000000000000..5b825578191f9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_create_comments_array/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { createComment, CreateCommentsArray } from '../create_comment'; + +/** + * Types the DefaultCreateComments as: + * - If null or undefined, then a default array of type entry will be set + */ +export const DefaultCreateCommentsArray = new t.Type< + CreateCommentsArray, + CreateCommentsArray, + unknown +>( + 'DefaultCreateComments', + t.array(createComment).is, + (input): Either => + input == null ? t.success([]) : t.array(createComment).decode(input), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts new file mode 100644 index 0000000000000..ea59988dfe0c5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts @@ -0,0 +1,86 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { ImportCommentsArray } from '../import_comment'; +import { DefaultImportCommentsArray } from '.'; +import { getCommentsArrayMock } from '../comment/index.mock'; +import { getCreateCommentsArrayMock } from '../create_comment/index.mock'; + +describe('default_import_comments_array', () => { + test('it should pass validation when supplied an empty array', () => { + const payload: ImportCommentsArray = []; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of comments', () => { + const payload: ImportCommentsArray = getCommentsArrayMock(); + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of new comments', () => { + const payload: ImportCommentsArray = getCreateCommentsArrayMock(); + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of new and existing comments', () => { + const payload: ImportCommentsArray = [ + ...getCommentsArrayMock(), + ...getCreateCommentsArrayMock(), + ]; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an array of numbers', () => { + const payload = [1]; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "DefaultImportComments"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an array of strings', () => { + const payload = ['some string']; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "DefaultImportComments"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default array entry', () => { + const payload = null; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts new file mode 100644 index 0000000000000..135288c2dd3f5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { importComment, ImportCommentsArray } from '../import_comment'; + +/** + * Types the DefaultImportCommentsArray as: + * - If null or undefined, then a default array of type ImportCommentsArray will be set + */ +export const DefaultImportCommentsArray = new t.Type< + ImportCommentsArray, + ImportCommentsArray, + unknown +>( + 'DefaultImportComments', + t.array(importComment).is, + (input, context): Either => + input == null ? t.success([]) : t.array(importComment).validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.test.ts new file mode 100644 index 0000000000000..fc271855fc12e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.test.ts @@ -0,0 +1,60 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultNamespace } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_namespace', () => { + test('it should validate "single"', () => { + const payload = 'single'; + const decoded = DefaultNamespace.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate "agnostic"', () => { + const payload = 'agnostic'; + const decoded = DefaultNamespace.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it defaults to "single" if "undefined"', () => { + const payload = undefined; + const decoded = DefaultNamespace.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual('single'); + }); + + test('it defaults to "single" if "null"', () => { + const payload = null; + const decoded = DefaultNamespace.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual('single'); + }); + + test('it should FAIL validation if not "single" or "agnostic"', () => { + const payload = 'something else'; + const decoded = DefaultNamespace.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + `Invalid value "something else" supplied to "DefaultNamespace"`, + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.ts new file mode 100644 index 0000000000000..667ddbb82253d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; + +export const namespaceType = t.keyof({ agnostic: null, single: null }); +export type NamespaceType = t.TypeOf; + +/** + * Types the DefaultNamespace as: + * - If null or undefined, then a default string/enumeration of "single" will be used. + */ +export const DefaultNamespace = new t.Type( + 'DefaultNamespace', + namespaceType.is, + (input, context): Either => + input == null ? t.success('single') : namespaceType.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.test.ts new file mode 100644 index 0000000000000..cb7012503d382 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.test.ts @@ -0,0 +1,98 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultNamespaceArray, DefaultNamespaceArrayType } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('default_namespace_array', () => { + test('it should validate "null" single item as an array with a "single" value', () => { + const payload: DefaultNamespaceArrayType = null; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(['single']); + }); + + test('it should FAIL validation of numeric value', () => { + const payload = 5; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "5" supplied to "DefaultNamespaceArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should validate "undefined" item as an array with a "single" value', () => { + const payload: DefaultNamespaceArrayType = undefined; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(['single']); + }); + + test('it should validate "single" as an array of a "single" value', () => { + const payload: DefaultNamespaceArrayType = 'single'; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([payload]); + }); + + test('it should validate "agnostic" as an array of a "agnostic" value', () => { + const payload: DefaultNamespaceArrayType = 'agnostic'; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([payload]); + }); + + test('it should validate "single,agnostic" as an array of 2 values of ["single", "agnostic"] values', () => { + const payload: DefaultNamespaceArrayType = 'agnostic,single'; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(['agnostic', 'single']); + }); + + test('it should validate 3 elements of "single,agnostic,single" as an array of 3 values of ["single", "agnostic", "single"] values', () => { + const payload: DefaultNamespaceArrayType = 'single,agnostic,single'; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(['single', 'agnostic', 'single']); + }); + + test('it should validate 3 elements of "single,agnostic, single" as an array of 3 values of ["single", "agnostic", "single"] values when there are spaces', () => { + const payload: DefaultNamespaceArrayType = ' single, agnostic, single '; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(['single', 'agnostic', 'single']); + }); + + test('it should FAIL validation when given 3 elements of "single,agnostic,junk" since the 3rd value is junk', () => { + const payload: DefaultNamespaceArrayType = 'single,agnostic,junk'; + const decoded = DefaultNamespaceArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "junk" supplied to "DefaultNamespaceArray"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.ts new file mode 100644 index 0000000000000..494c6025f198e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_namespace_array/index.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { namespaceType } from '../default_namespace'; + +export const namespaceTypeArray = t.array(namespaceType); +export type NamespaceTypeArray = t.TypeOf; + +/** + * Types the DefaultNamespaceArray as: + * - If null or undefined, then a default string array of "single" will be used. + * - If it contains a string, then it is split along the commas and puts them into an array and validates it + */ +export const DefaultNamespaceArray = new t.Type< + NamespaceTypeArray, + string | undefined | null, + unknown +>( + 'DefaultNamespaceArray', + namespaceTypeArray.is, + (input, context): Either => { + if (input == null) { + return t.success(['single']); + } else if (typeof input === 'string') { + const commaSeparatedValues = input + .trim() + .split(',') + .map((value) => value.trim()); + return namespaceTypeArray.validate(commaSeparatedValues, context); + } + return t.failure(input, context); + }, + String +); + +export type DefaultNamespaceArrayType = t.OutputOf; +export type DefaultNamespaceArrayTypeDecoded = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts new file mode 100644 index 0000000000000..3cced7284425c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { UpdateCommentsArray } from '../update_comment'; +import { DefaultUpdateCommentsArray } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getUpdateCommentsArrayMock } from '../update_comment/index.mock'; + +describe('default_update_comments_array', () => { + test('it should pass validation when supplied an empty array', () => { + const payload: UpdateCommentsArray = []; + const decoded = DefaultUpdateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of comments', () => { + const payload: UpdateCommentsArray = getUpdateCommentsArrayMock(); + const decoded = DefaultUpdateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an array of numbers', () => { + const payload = [1]; + const decoded = DefaultUpdateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "DefaultUpdateComments"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an array of strings', () => { + const payload = ['some string']; + const decoded = DefaultUpdateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "DefaultUpdateComments"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default array entry', () => { + const payload = null; + const decoded = DefaultUpdateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts new file mode 100644 index 0000000000000..28edd4af353e6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { updateCommentsArray, UpdateCommentsArray } from '../update_comment'; + +/** + * Types the DefaultUpdateComments as: + * - If null or undefined, then a default array of type UpdateCommentsArray will be set + */ +export const DefaultUpdateCommentsArray = new t.Type< + UpdateCommentsArray, + UpdateCommentsArray, + unknown +>( + 'DefaultUpdateComments', + updateCommentsArray.is, + (input, context): Either => + input == null ? t.success([]) : updateCommentsArray.validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/description/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/description/index.ts new file mode 100644 index 0000000000000..adba3ae0ef4fa --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/description/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const description = t.string; +export type Description = t.TypeOf; +export const descriptionOrUndefined = t.union([description, t.undefined]); +export type DescriptionOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/deserializer/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/deserializer/index.ts new file mode 100644 index 0000000000000..4956736b5cf4e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/deserializer/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const deserializer = t.string; +export type Deserializer = t.TypeOf; +export const deserializerOrUndefined = t.union([deserializer, t.undefined]); +export type DeserializerOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.mock.ts new file mode 100644 index 0000000000000..1d46d6412e122 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.mock.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import { EndpointEntriesArray } from '.'; +import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; +import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { getEndpointEntryNestedMock } from '../entry_nested/index.mock'; +import { getEndpointEntryMatchWildcardMock } from '../entry_match_wildcard/index.mock'; + +export const getEndpointEntriesArrayMock = (): EndpointEntriesArray => [ + getEndpointEntryMatchMock(), + getEndpointEntryMatchAnyMock(), + getEndpointEntryNestedMock(), + getEndpointEntryMatchWildcardMock(), +]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.test.ts new file mode 100644 index 0000000000000..4a317d5c9152d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.test.ts @@ -0,0 +1,120 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; +import { + endpointEntriesArray, + nonEmptyEndpointEntriesArray, + NonEmptyEndpointEntriesArray, +} from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { getEndpointEntryNestedMock } from '../entry_nested/index.mock'; +import { getEndpointEntriesArrayMock } from './index.mock'; +import { getEntryListMock } from '../../entries_list/index.mock'; +import { getEntryExistsMock } from '../../entries_exist/index.mock'; +import { getEndpointEntryMatchWildcardMock } from '../entry_match_wildcard/index.mock'; + +describe('Endpoint', () => { + describe('entriesArray', () => { + test('it should validate an array with match entry', () => { + const payload = [getEndpointEntryMatchMock()]; + const decoded = endpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with match_any entry', () => { + const payload = [getEndpointEntryMatchAnyMock()]; + const decoded = endpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT validate an empty array', () => { + const payload: NonEmptyEndpointEntriesArray = []; + const decoded = nonEmptyEndpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "[]" supplied to "NonEmptyEndpointEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('type guard for nonEmptyEndpointNestedEntries should allow array of endpoint entries', () => { + const payload: NonEmptyEndpointEntriesArray = [getEndpointEntryMatchAnyMock()]; + const guarded = nonEmptyEndpointEntriesArray.is(payload); + expect(guarded).toBeTruthy(); + }); + + test('type guard for nonEmptyEndpointNestedEntries should disallow empty arrays', () => { + const payload: NonEmptyEndpointEntriesArray = []; + const guarded = nonEmptyEndpointEntriesArray.is(payload); + expect(guarded).toBeFalsy(); + }); + + test('it should NOT validate an array with exists entry', () => { + const payload = [getEntryExistsMock()]; + const decoded = endpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "exists" supplied to "type"', + 'Invalid value "undefined" supplied to "value"', + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT validate an array with list entry', () => { + const payload = [getEntryListMock()]; + const decoded = endpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "list" supplied to "type"', + 'Invalid value "undefined" supplied to "value"', + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should validate an array with nested entry', () => { + const payload = [getEndpointEntryNestedMock()]; + const decoded = endpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with wildcard entry', () => { + const payload = [getEndpointEntryMatchWildcardMock()]; + const decoded = endpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with all types of entries', () => { + const payload = getEndpointEntriesArrayMock(); + const decoded = endpointEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.ts new file mode 100644 index 0000000000000..c9a74ae525734 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entries/index.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { endpointEntryMatch } from '../entry_match'; +import { endpointEntryMatchAny } from '../entry_match_any'; +import { endpointEntryNested } from '../entry_nested'; +import { endpointEntryMatchWildcard } from '../entry_match_wildcard'; + +export const endpointEntriesArray = t.array( + t.union([ + endpointEntryMatch, + endpointEntryMatchAny, + endpointEntryMatchWildcard, + endpointEntryNested, + ]) +); +export type EndpointEntriesArray = t.TypeOf; + +/** + * Types the nonEmptyEndpointEntriesArray as: + * - An array of entries of length 1 or greater + * + */ +export const nonEmptyEndpointEntriesArray = new t.Type< + EndpointEntriesArray, + EndpointEntriesArray, + unknown +>( + 'NonEmptyEndpointEntriesArray', + (u: unknown): u is EndpointEntriesArray => endpointEntriesArray.is(u) && u.length > 0, + (input, context): Either => { + if (Array.isArray(input) && input.length === 0) { + return t.failure(input, context); + } else { + return endpointEntriesArray.validate(input, context); + } + }, + t.identity +); + +export type NonEmptyEndpointEntriesArray = t.OutputOf; +export type NonEmptyEndpointEntriesArrayDecoded = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.mock.ts new file mode 100644 index 0000000000000..ddcda0e1e2d98 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { EndpointEntryMatch } from '.'; +import { ENTRY_VALUE, FIELD, MATCH, OPERATOR } from '../../../constants/index.mock'; + +export const getEndpointEntryMatchMock = (): EndpointEntryMatch => ({ + field: FIELD, + operator: OPERATOR, + type: MATCH, + value: ENTRY_VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.test.ts new file mode 100644 index 0000000000000..561a36ab194c7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.test.ts @@ -0,0 +1,101 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEndpointEntryMatchMock } from './index.mock'; +import { EndpointEntryMatch, endpointEntryMatch } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEntryMatchMock } from '../../entry_match/index.mock'; + +describe('endpointEntryMatch', () => { + test('it should validate an entry', () => { + const payload = getEndpointEntryMatchMock(); + const decoded = endpointEntryMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT validate when "operator" is "excluded"', () => { + // Use the generic entry mock so we can test operator: excluded + const payload = getEntryMatchMock(); + payload.operator = 'excluded'; + const decoded = endpointEntryMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "excluded" supplied to "operator"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "field" is empty string', () => { + const payload: Omit & { field: string } = { + ...getEndpointEntryMatchMock(), + field: '', + }; + const decoded = endpointEntryMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is not string', () => { + const payload: Omit & { value: string[] } = { + ...getEndpointEntryMatchMock(), + value: ['some value'], + }; + const decoded = endpointEntryMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["some value"]" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is empty string', () => { + const payload: Omit & { value: string } = { + ...getEndpointEntryMatchMock(), + value: '', + }; + const decoded = endpointEntryMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "type" is not "match"', () => { + const payload: Omit & { type: string } = { + ...getEndpointEntryMatchMock(), + type: 'match_any', + }; + const decoded = endpointEntryMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "match_any" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EndpointEntryMatch & { + extraKey?: string; + } = getEndpointEntryMatchMock(); + payload.extraKey = 'some value'; + const decoded = endpointEntryMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryMatchMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.ts new file mode 100644 index 0000000000000..7cc51636cf583 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match/index.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString, operatorIncluded } from '@kbn/securitysolution-io-ts-types'; + +export const endpointEntryMatch = t.exact( + t.type({ + field: NonEmptyString, + operator: operatorIncluded, + type: t.keyof({ match: null }), + value: NonEmptyString, + }) +); +export type EndpointEntryMatch = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.mock.ts new file mode 100644 index 0000000000000..6c04a6b596d63 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { ENTRY_VALUE, FIELD, MATCH_ANY, OPERATOR } from '../../../constants/index.mock'; +import { EndpointEntryMatchAny } from '.'; + +export const getEndpointEntryMatchAnyMock = (): EndpointEntryMatchAny => ({ + field: FIELD, + operator: OPERATOR, + type: MATCH_ANY, + value: [ENTRY_VALUE], +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.test.ts new file mode 100644 index 0000000000000..feb04606adf9c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.test.ts @@ -0,0 +1,99 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEndpointEntryMatchAnyMock } from './index.mock'; +import { EndpointEntryMatchAny, endpointEntryMatchAny } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEntryMatchAnyMock } from '../../entry_match_any/index.mock'; + +describe('endpointEntryMatchAny', () => { + test('it should validate an entry', () => { + const payload = getEndpointEntryMatchAnyMock(); + const decoded = endpointEntryMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT validate when operator is "excluded"', () => { + // Use the generic entry mock so we can test operator: excluded + const payload = getEntryMatchAnyMock(); + payload.operator = 'excluded'; + const decoded = endpointEntryMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "excluded" supplied to "operator"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when field is empty string', () => { + const payload: Omit & { field: string } = { + ...getEndpointEntryMatchAnyMock(), + field: '', + }; + const decoded = endpointEntryMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when value is empty array', () => { + const payload: Omit & { value: string[] } = { + ...getEndpointEntryMatchAnyMock(), + value: [], + }; + const decoded = endpointEntryMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "[]" supplied to "value"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when value is not string array', () => { + const payload: Omit & { value: string } = { + ...getEndpointEntryMatchAnyMock(), + value: 'some string', + }; + const decoded = endpointEntryMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "type" is not "match_any"', () => { + const payload: Omit & { type: string } = { + ...getEndpointEntryMatchAnyMock(), + type: 'match', + }; + const decoded = endpointEntryMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EndpointEntryMatchAny & { + extraKey?: string; + } = getEndpointEntryMatchAnyMock(); + payload.extraKey = 'some extra key'; + const decoded = endpointEntryMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryMatchAnyMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.ts new file mode 100644 index 0000000000000..7d23e7338e71a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_any/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { + NonEmptyString, + nonEmptyOrNullableStringArray, + operatorIncluded, +} from '@kbn/securitysolution-io-ts-types'; + +export const endpointEntryMatchAny = t.exact( + t.type({ + field: NonEmptyString, + operator: operatorIncluded, + type: t.keyof({ match_any: null }), + value: nonEmptyOrNullableStringArray, + }) +); +export type EndpointEntryMatchAny = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.mock.ts new file mode 100644 index 0000000000000..ca8f01d3e30e0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { ENTRY_VALUE, FIELD, OPERATOR, WILDCARD } from '../../../constants/index.mock'; +import { EndpointEntryMatchWildcard } from '.'; + +export const getEndpointEntryMatchWildcardMock = (): EndpointEntryMatchWildcard => ({ + field: FIELD, + operator: OPERATOR, + type: WILDCARD, + value: ENTRY_VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.test.ts new file mode 100644 index 0000000000000..95ea73b2aac11 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.test.ts @@ -0,0 +1,96 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEndpointEntryMatchWildcardMock } from './index.mock'; +import { EndpointEntryMatchWildcard, endpointEntryMatchWildcard } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEntryMatchWildcardMock } from '../../entry_match_wildcard/index.mock'; + +describe('endpointEntryMatchWildcard', () => { + test('it should validate an entry', () => { + const payload = getEndpointEntryMatchWildcardMock(); + const decoded = endpointEntryMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when "operator" is "excluded"', () => { + const payload = getEntryMatchWildcardMock(); + payload.operator = 'excluded'; + const decoded = endpointEntryMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when "field" is empty string', () => { + const payload: Omit & { field: string } = { + ...getEndpointEntryMatchWildcardMock(), + field: '', + }; + const decoded = endpointEntryMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is not string', () => { + const payload: Omit & { value: string[] } = { + ...getEndpointEntryMatchWildcardMock(), + value: ['some value'], + }; + const decoded = endpointEntryMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["some value"]" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is empty string', () => { + const payload: Omit & { value: string } = { + ...getEndpointEntryMatchWildcardMock(), + value: '', + }; + const decoded = endpointEntryMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "type" is not "wildcard"', () => { + const payload: Omit & { type: string } = { + ...getEndpointEntryMatchWildcardMock(), + type: 'match', + }; + const decoded = endpointEntryMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EndpointEntryMatchWildcard & { + extraKey?: string; + } = getEndpointEntryMatchWildcardMock(); + payload.extraKey = 'some value'; + const decoded = endpointEntryMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryMatchWildcardMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.ts new file mode 100644 index 0000000000000..cfc96337b6276 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_match_wildcard/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { + NonEmptyString, + operatorExcluded, + operatorIncluded, +} from '@kbn/securitysolution-io-ts-types'; + +export const endpointEntryMatchWildcard = t.exact( + t.type({ + field: NonEmptyString, + operator: t.union([operatorIncluded, operatorExcluded]), + type: t.keyof({ wildcard: null }), + value: NonEmptyString, + }) +); +export type EndpointEntryMatchWildcard = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.mock.ts new file mode 100644 index 0000000000000..93b99e71b0bca --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.mock.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import { EndpointEntryNested } from '.'; +import { FIELD, NESTED } from '../../../constants/index.mock'; +import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; +import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; + +export const getEndpointEntryNestedMock = (): EndpointEntryNested => ({ + entries: [getEndpointEntryMatchMock(), getEndpointEntryMatchAnyMock()], + field: FIELD, + type: NESTED, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.test.ts new file mode 100644 index 0000000000000..d68a0686a4391 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.test.ts @@ -0,0 +1,136 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { EndpointEntryNested, endpointEntryNested } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEndpointEntryNestedMock } from './index.mock'; +import { getEndpointEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { + nonEmptyEndpointNestedEntriesArray, + NonEmptyEndpointNestedEntriesArray, +} from '../non_empty_nested_entries_array'; +import { getEndpointEntryMatchMock } from '../entry_match/index.mock'; +import { getEntryExistsMock } from '../../entries_exist/index.mock'; + +describe('endpointEntryNested', () => { + test('it should validate a nested entry', () => { + const payload = getEndpointEntryNestedMock(); + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when "type" is not "nested"', () => { + const payload: Omit & { type: 'match' } = { + ...getEndpointEntryNestedMock(), + type: 'match', + }; + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "field" is empty string', () => { + const payload: Omit & { + field: string; + } = { ...getEndpointEntryNestedMock(), field: '' }; + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "field" is not a string', () => { + const payload: Omit & { + field: number; + } = { ...getEndpointEntryNestedMock(), field: 1 }; + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "entries" is not an array', () => { + const payload: Omit & { + entries: string; + } = { ...getEndpointEntryNestedMock(), entries: 'im a string' }; + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "im a string" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should validate when "entries" contains an entry item that is type "match"', () => { + const payload = { ...getEndpointEntryNestedMock(), entries: [getEndpointEntryMatchAnyMock()] }; + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual({ + entries: [ + { + field: 'host.name', + operator: 'included', + type: 'match_any', + value: ['some host name'], + }, + ], + field: 'host.name', + type: 'nested', + }); + }); + + test('it should NOT validate when "entries" contains an entry item that is type "exists"', () => { + const payload = { ...getEndpointEntryNestedMock(), entries: [getEntryExistsMock()] }; + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "exists" supplied to "entries,type"', + 'Invalid value "undefined" supplied to "entries,value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EndpointEntryNested & { + extraKey?: string; + } = getEndpointEntryNestedMock(); + payload.extraKey = 'some extra key'; + const decoded = endpointEntryNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEndpointEntryNestedMock()); + }); + + test('type guard for nonEmptyEndpointNestedEntries should allow array of endpoint entries', () => { + const payload: NonEmptyEndpointNestedEntriesArray = [ + getEndpointEntryMatchMock(), + getEndpointEntryMatchAnyMock(), + ]; + const guarded = nonEmptyEndpointNestedEntriesArray.is(payload); + expect(guarded).toBeTruthy(); + }); + + test('type guard for nonEmptyEndpointNestedEntries should disallow empty arrays', () => { + const payload: NonEmptyEndpointNestedEntriesArray = []; + const guarded = nonEmptyEndpointNestedEntriesArray.is(payload); + expect(guarded).toBeFalsy(); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.ts new file mode 100644 index 0000000000000..f02570af1013e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/entry_nested/index.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { nonEmptyEndpointNestedEntriesArray } from '../non_empty_nested_entries_array'; + +export const endpointEntryNested = t.exact( + t.type({ + entries: nonEmptyEndpointNestedEntriesArray, + field: NonEmptyString, + type: t.keyof({ nested: null }), + }) +); +export type EndpointEntryNested = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/index.ts new file mode 100644 index 0000000000000..5138682f463b2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export * from './entries'; +export * from './non_empty_nested_entries_array'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/non_empty_nested_entries_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/non_empty_nested_entries_array/index.ts new file mode 100644 index 0000000000000..5085b4fdacac7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/endpoint/non_empty_nested_entries_array/index.ts @@ -0,0 +1,45 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { endpointEntryMatch } from '../entry_match'; +import { endpointEntryMatchAny } from '../entry_match_any'; + +export const endpointNestedEntriesArray = t.array( + t.union([endpointEntryMatch, endpointEntryMatchAny]) +); +export type EndpointNestedEntriesArray = t.TypeOf; + +/** + * Types the nonEmptyNestedEntriesArray as: + * - An array of entries of length 1 or greater + * + */ +export const nonEmptyEndpointNestedEntriesArray = new t.Type< + EndpointNestedEntriesArray, + EndpointNestedEntriesArray, + unknown +>( + 'NonEmptyEndpointNestedEntriesArray', + (u: unknown): u is EndpointNestedEntriesArray => endpointNestedEntriesArray.is(u) && u.length > 0, + (input, context): Either => { + if (Array.isArray(input) && input.length === 0) { + return t.failure(input, context); + } else { + return endpointNestedEntriesArray.validate(input, context); + } + }, + t.identity +); + +export type NonEmptyEndpointNestedEntriesArray = t.OutputOf< + typeof nonEmptyEndpointNestedEntriesArray +>; +export type NonEmptyEndpointNestedEntriesArrayDecoded = t.TypeOf< + typeof nonEmptyEndpointNestedEntriesArray +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.mock.ts new file mode 100644 index 0000000000000..1aeea284751b6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.mock.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import { EntriesArray } from '.'; +import { getEntryExistsMock } from '../entries_exist/index.mock'; +import { getEntryListMock } from '../entries_list/index.mock'; +import { getEntryMatchMock } from '../entry_match/index.mock'; +import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { getEntryNestedMock } from '../entry_nested/index.mock'; + +export const getListAndNonListEntriesArrayMock = (): EntriesArray => [ + getEntryMatchMock(), + getEntryMatchAnyMock(), + getEntryListMock(), + getEntryExistsMock(), + getEntryNestedMock(), +]; + +export const getListEntriesArrayMock = (): EntriesArray => [getEntryListMock(), getEntryListMock()]; + +export const getEntriesArrayMock = (): EntriesArray => [ + getEntryMatchMock(), + getEntryMatchAnyMock(), + getEntryExistsMock(), + getEntryNestedMock(), +]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.test.ts new file mode 100644 index 0000000000000..25c52b68a6f9d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.test.ts @@ -0,0 +1,147 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEntryMatchMock } from '../entry_match/index.mock'; +import { entriesArray, entriesArrayOrUndefined, entry } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { getEntryExistsMock } from '../entries_exist/index.mock'; +import { getEntryListMock } from '../entries_list/index.mock'; +import { getEntryNestedMock } from '../entry_nested/index.mock'; +import { getEntriesArrayMock } from './index.mock'; + +describe('Entries', () => { + describe('entry', () => { + test('it should validate a match entry', () => { + const payload = getEntryMatchMock(); + const decoded = entry.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate a match_any entry', () => { + const payload = getEntryMatchAnyMock(); + const decoded = entry.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate a exists entry', () => { + const payload = getEntryExistsMock(); + const decoded = entry.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate a list entry', () => { + const payload = getEntryListMock(); + const decoded = entry.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation of nested entry', () => { + const payload = getEntryNestedMock(); + const decoded = entry.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "operator"', + 'Invalid value "nested" supplied to "type"', + 'Invalid value "undefined" supplied to "value"', + 'Invalid value "undefined" supplied to "list"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('entriesArray', () => { + test('it should validate an array with match entry', () => { + const payload = [getEntryMatchMock()]; + const decoded = entriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with match_any entry', () => { + const payload = [getEntryMatchAnyMock()]; + const decoded = entriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with exists entry', () => { + const payload = [getEntryExistsMock()]; + const decoded = entriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with list entry', () => { + const payload = [getEntryListMock()]; + const decoded = entriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with nested entry', () => { + const payload = [getEntryNestedMock()]; + const decoded = entriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with all types of entries', () => { + const payload = [...getEntriesArrayMock()]; + const decoded = entriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + }); + + describe('entriesArrayOrUndefined', () => { + test('it should validate undefined', () => { + const payload = undefined; + const decoded = entriesArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array with nested entry', () => { + const payload = [getEntryNestedMock()]; + const decoded = entriesArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.ts new file mode 100644 index 0000000000000..73340d2c0af54 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries/index.ts @@ -0,0 +1,40 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { entriesExists } from '../entries_exist'; +import { entriesList } from '../entries_list'; +import { entriesMatch } from '../entry_match'; +import { entriesMatchAny } from '../entry_match_any'; +import { entriesMatchWildcard } from '../entry_match_wildcard'; +import { entriesNested } from '../entry_nested'; + +// NOTE: Type nested is not included here to denote it's non-recursive nature. +// So a nested entry is really just a collection of `Entry` types. +export const entry = t.union([ + entriesMatch, + entriesMatchAny, + entriesList, + entriesExists, + entriesMatchWildcard, +]); +export type Entry = t.TypeOf; + +export const entriesArray = t.array( + t.union([ + entriesMatch, + entriesMatchAny, + entriesList, + entriesExists, + entriesNested, + entriesMatchWildcard, + ]) +); +export type EntriesArray = t.TypeOf; + +export const entriesArrayOrUndefined = t.union([entriesArray, t.undefined]); +export type EntriesArrayOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.mock.ts new file mode 100644 index 0000000000000..e66d14c3c7af7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.mock.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import { EntryExists } from '.'; +import { EXISTS, FIELD, OPERATOR } from '../../constants/index.mock'; + +export const getEntryExistsMock = (): EntryExists => ({ + field: FIELD, + operator: OPERATOR, + type: EXISTS, +}); + +export const getEntryExistsExcludedMock = (): EntryExists => ({ + ...getEntryExistsMock(), + operator: 'excluded', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.test.ts new file mode 100644 index 0000000000000..dcc6d47a437a1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.test.ts @@ -0,0 +1,78 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEntryExistsMock } from './index.mock'; +import { entriesExists, EntryExists } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('entriesExists', () => { + test('it should validate an entry', () => { + const payload = getEntryExistsMock(); + const decoded = entriesExists.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when "operator" is "included"', () => { + const payload = getEntryExistsMock(); + const decoded = entriesExists.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when "operator" is "excluded"', () => { + const payload = getEntryExistsMock(); + payload.operator = 'excluded'; + const decoded = entriesExists.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when "field" is empty string', () => { + const payload: Omit & { field: string } = { + ...getEntryExistsMock(), + field: '', + }; + const decoded = entriesExists.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EntryExists & { + extraKey?: string; + } = getEntryExistsMock(); + payload.extraKey = 'some extra key'; + const decoded = entriesExists.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryExistsMock()); + }); + + test('it should FAIL validation when "type" is not "exists"', () => { + const payload: Omit & { type: string } = { + ...getEntryExistsMock(), + type: 'match', + }; + const decoded = entriesExists.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.ts new file mode 100644 index 0000000000000..44c83c3f5b640 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_exist/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { listOperator as operator } from '../list_operator'; + +export const entriesExists = t.exact( + t.type({ + field: NonEmptyString, + operator, + type: t.keyof({ exists: null }), + }) +); +export type EntryExists = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.mock.ts new file mode 100644 index 0000000000000..77c73d0bcfa38 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { EntryList } from '.'; +import { FIELD, LIST, LIST_ID, OPERATOR, TYPE } from '../../constants/index.mock'; + +export const getEntryListMock = (): EntryList => ({ + field: FIELD, + list: { id: LIST_ID, type: TYPE }, + operator: OPERATOR, + type: LIST, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.test.ts new file mode 100644 index 0000000000000..a9b56207d9590 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.test.ts @@ -0,0 +1,95 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEntryListMock } from './index.mock'; +import { entriesList, EntryList } from '.'; + +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('entriesList', () => { + test('it should validate an entry', () => { + const payload = getEntryListMock(); + const decoded = entriesList.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when operator is "included"', () => { + const payload = getEntryListMock(); + const decoded = entriesList.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when "operator" is "excluded"', () => { + const payload = getEntryListMock(); + payload.operator = 'excluded'; + const decoded = entriesList.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when "list" is not expected value', () => { + const payload: Omit & { list: string } = { + ...getEntryListMock(), + list: 'someListId', + }; + const decoded = entriesList.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "someListId" supplied to "list"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "list.id" is empty string', () => { + const payload: Omit & { list: { id: string; type: 'ip' } } = { + ...getEntryListMock(), + list: { id: '', type: 'ip' }, + }; + const decoded = entriesList.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "list,id"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "type" is not "lists"', () => { + const payload: Omit & { type: 'match_any' } = { + ...getEntryListMock(), + type: 'match_any', + }; + const decoded = entriesList.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "match_any" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EntryList & { + extraKey?: string; + } = getEntryListMock(); + payload.extraKey = 'some extra key'; + const decoded = entriesList.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryListMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.ts new file mode 100644 index 0000000000000..214f0c92db221 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entries_list/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +import { type } from '../type'; +import { listOperator as operator } from '../list_operator'; + +export const entriesList = t.exact( + t.type({ + field: NonEmptyString, + list: t.exact(t.type({ id: NonEmptyString, type })), + operator, + type: t.keyof({ list: null }), + }) +); +export type EntryList = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.mock.ts new file mode 100644 index 0000000000000..9af6cf08090b9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.mock.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { EntryMatch } from '.'; +import { ENTRY_VALUE, FIELD, MATCH, OPERATOR } from '../../constants/index.mock'; + +export const getEntryMatchMock = (): EntryMatch => ({ + field: FIELD, + operator: OPERATOR, + type: MATCH, + value: ENTRY_VALUE, +}); + +export const getEntryMatchExcludeMock = (): EntryMatch => ({ + ...getEntryMatchMock(), + operator: 'excluded', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.test.ts new file mode 100644 index 0000000000000..6f2fc7fd9e8d6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.test.ts @@ -0,0 +1,106 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEntryMatchMock } from './index.mock'; +import { entriesMatch, EntryMatch } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('entriesMatch', () => { + test('it should validate an entry', () => { + const payload = getEntryMatchMock(); + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when operator is "included"', () => { + const payload = getEntryMatchMock(); + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when "operator" is "excluded"', () => { + const payload = getEntryMatchMock(); + payload.operator = 'excluded'; + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when "field" is empty string', () => { + const payload: Omit & { field: string } = { + ...getEntryMatchMock(), + field: '', + }; + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is not string', () => { + const payload: Omit & { value: string[] } = { + ...getEntryMatchMock(), + value: ['some value'], + }; + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["some value"]" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is empty string', () => { + const payload: Omit & { value: string } = { + ...getEntryMatchMock(), + value: '', + }; + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "type" is not "match"', () => { + const payload: Omit & { type: string } = { + ...getEntryMatchMock(), + type: 'match_any', + }; + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "match_any" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EntryMatch & { + extraKey?: string; + } = getEntryMatchMock(); + payload.extraKey = 'some value'; + const decoded = entriesMatch.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryMatchMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.ts new file mode 100644 index 0000000000000..8e56991b977a7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { listOperator as operator } from '../list_operator'; + +export const entriesMatch = t.exact( + t.type({ + field: NonEmptyString, + operator, + type: t.keyof({ match: null }), + value: NonEmptyString, + }) +); +export type EntryMatch = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.mock.ts new file mode 100644 index 0000000000000..a564d4e8fd95b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.mock.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import { EntryMatchAny } from '.'; +import { ENTRY_VALUE, FIELD, MATCH_ANY, OPERATOR } from '../../constants/index.mock'; + +export const getEntryMatchAnyMock = (): EntryMatchAny => ({ + field: FIELD, + operator: OPERATOR, + type: MATCH_ANY, + value: [ENTRY_VALUE], +}); + +export const getEntryMatchAnyExcludeMock = (): EntryMatchAny => ({ + ...getEntryMatchAnyMock(), + operator: 'excluded', + value: [ENTRY_VALUE, 'some other host name'], +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.test.ts new file mode 100644 index 0000000000000..84844c432aa2c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.test.ts @@ -0,0 +1,104 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEntryMatchAnyMock } from './index.mock'; +import { entriesMatchAny, EntryMatchAny } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('entriesMatchAny', () => { + test('it should validate an entry', () => { + const payload = getEntryMatchAnyMock(); + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when operator is "included"', () => { + const payload = getEntryMatchAnyMock(); + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when operator is "excluded"', () => { + const payload = getEntryMatchAnyMock(); + payload.operator = 'excluded'; + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when field is empty string', () => { + const payload: Omit & { field: string } = { + ...getEntryMatchAnyMock(), + field: '', + }; + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when value is empty array', () => { + const payload: Omit & { value: string[] } = { + ...getEntryMatchAnyMock(), + value: [], + }; + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "[]" supplied to "value"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when value is not string array', () => { + const payload: Omit & { value: string } = { + ...getEntryMatchAnyMock(), + value: 'some string', + }; + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "type" is not "match_any"', () => { + const payload: Omit & { type: string } = { + ...getEntryMatchAnyMock(), + type: 'match', + }; + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EntryMatchAny & { + extraKey?: string; + } = getEntryMatchAnyMock(); + payload.extraKey = 'some extra key'; + const decoded = entriesMatchAny.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryMatchAnyMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.ts new file mode 100644 index 0000000000000..989c729f8b1b1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_any/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NonEmptyString, nonEmptyOrNullableStringArray } from '@kbn/securitysolution-io-ts-types'; +import { listOperator as operator } from '../list_operator'; + +export const entriesMatchAny = t.exact( + t.type({ + field: NonEmptyString, + operator, + type: t.keyof({ match_any: null }), + value: nonEmptyOrNullableStringArray, + }) +); +export type EntryMatchAny = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.mock.ts new file mode 100644 index 0000000000000..c279fe3ed45dd --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.mock.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { EntryMatchWildcard } from '.'; +import { ENTRY_VALUE, FIELD, OPERATOR, WILDCARD } from '../../constants/index.mock'; + +export const getEntryMatchWildcardMock = (): EntryMatchWildcard => ({ + field: FIELD, + operator: OPERATOR, + type: WILDCARD, + value: ENTRY_VALUE, +}); + +export const getEntryMatchWildcardExcludeMock = (): EntryMatchWildcard => ({ + ...getEntryMatchWildcardMock(), + operator: 'excluded', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.test.ts new file mode 100644 index 0000000000000..4bd2d146412a8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.test.ts @@ -0,0 +1,104 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEntryMatchWildcardMock } from './index.mock'; +import { entriesMatchWildcard, EntryMatchWildcard } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('entriesMatchWildcard', () => { + test('it should validate an entry', () => { + const payload = getEntryMatchWildcardMock(); + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when operator is "included"', () => { + const payload = getEntryMatchWildcardMock(); + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when "operator" is "excluded"', () => { + const payload = getEntryMatchWildcardMock(); + payload.operator = 'excluded'; + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when "field" is empty string', () => { + const payload: Omit & { field: string } = { + ...getEntryMatchWildcardMock(), + field: '', + }; + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is not string', () => { + const payload: Omit & { value: string[] } = { + ...getEntryMatchWildcardMock(), + value: ['some value'], + }; + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["some value"]" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "value" is empty string', () => { + const payload: Omit & { value: string } = { + ...getEntryMatchWildcardMock(), + value: '', + }; + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "type" is not "wildcard"', () => { + const payload: Omit & { type: string } = { + ...getEntryMatchWildcardMock(), + type: 'match', + }; + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: EntryMatchWildcard & { + extraKey?: string; + } = getEntryMatchWildcardMock(); + payload.extraKey = 'some value'; + const decoded = entriesMatchWildcard.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryMatchWildcardMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.ts new file mode 100644 index 0000000000000..af168e33fa70a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_match_wildcard/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { listOperator as operator } from '../list_operator'; + +export const entriesMatchWildcard = t.exact( + t.type({ + field: NonEmptyString, + operator, + type: t.keyof({ wildcard: null }), + value: NonEmptyString, + }) +); +export type EntryMatchWildcard = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.mock.ts new file mode 100644 index 0000000000000..890c3d379d27d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.mock.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import { EntryNested } from '.'; +import { NESTED, NESTED_FIELD } from '../../constants/index.mock'; +import { getEntryExistsMock } from '../entries_exist/index.mock'; +import { getEntryMatchExcludeMock, getEntryMatchMock } from '../entry_match/index.mock'; +import { getEntryMatchAnyExcludeMock, getEntryMatchAnyMock } from '../entry_match_any/index.mock'; + +export const getEntryNestedMock = (): EntryNested => ({ + entries: [getEntryMatchMock(), getEntryMatchAnyMock()], + field: NESTED_FIELD, + type: NESTED, +}); + +export const getEntryNestedExcludeMock = (): EntryNested => ({ + ...getEntryNestedMock(), + entries: [getEntryMatchExcludeMock(), getEntryMatchAnyExcludeMock()], +}); + +export const getEntryNestedMixedEntries = (): EntryNested => ({ + ...getEntryNestedMock(), + entries: [getEntryMatchMock(), getEntryMatchAnyExcludeMock(), getEntryExistsMock()], +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.test.ts new file mode 100644 index 0000000000000..be37a0273bce9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.test.ts @@ -0,0 +1,123 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEntryNestedMock } from './index.mock'; +import { entriesNested, EntryNested } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { getEntryExistsMock } from '../entries_exist/index.mock'; + +describe('entriesNested', () => { + test('it should validate a nested entry', () => { + const payload = getEntryNestedMock(); + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when "type" is not "nested"', () => { + const payload: Omit & { type: 'match' } = { + ...getEntryNestedMock(), + type: 'match', + }; + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "field" is empty string', () => { + const payload: Omit & { + field: string; + } = { ...getEntryNestedMock(), field: '' }; + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "field" is not a string', () => { + const payload: Omit & { + field: number; + } = { ...getEntryNestedMock(), field: 1 }; + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "field"']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when "entries" is not a an array', () => { + const payload: Omit & { + entries: string; + } = { ...getEntryNestedMock(), entries: 'im a string' }; + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "im a string" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should validate when "entries" contains an entry item that is type "match"', () => { + const payload = { ...getEntryNestedMock(), entries: [getEntryMatchAnyMock()] }; + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual({ + entries: [ + { + field: 'host.name', + operator: 'included', + type: 'match_any', + value: ['some host name'], + }, + ], + field: 'parent.field', + type: 'nested', + }); + }); + + test('it should validate when "entries" contains an entry item that is type "exists"', () => { + const payload = { ...getEntryNestedMock(), entries: [getEntryExistsMock()] }; + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual({ + entries: [ + { + field: 'host.name', + operator: 'included', + type: 'exists', + }, + ], + field: 'parent.field', + type: 'nested', + }); + }); + + test('it should strip out extra keys', () => { + const payload: EntryNested & { + extraKey?: string; + } = getEntryNestedMock(); + payload.extraKey = 'some extra key'; + const decoded = entriesNested.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getEntryNestedMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.ts new file mode 100644 index 0000000000000..dac5d6a3d5a88 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/entry_nested/index.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { nonEmptyNestedEntriesArray } from '../non_empty_nested_entries_array'; + +export const entriesNested = t.exact( + t.type({ + entries: nonEmptyNestedEntriesArray, + field: NonEmptyString, + type: t.keyof({ nested: null }), + }) +); +export type EntryNested = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.mock.ts new file mode 100644 index 0000000000000..ded6a6bfbb8ab --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.mock.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import { ExportExceptionDetails } from '.'; + +export interface ExportExceptionDetailsMock { + listCount?: number; + missingListsCount?: number; + missingLists?: Array>; + itemCount?: number; + missingItemCount?: number; + missingItems?: Array>; +} + +export const getExceptionExportDetailsMock = ( + details?: ExportExceptionDetailsMock +): ExportExceptionDetails => ({ + exported_exception_list_count: details?.listCount ?? 0, + exported_exception_list_item_count: details?.itemCount ?? 0, + missing_exception_list_item_count: details?.missingItemCount ?? 0, + missing_exception_list_items: details?.missingItems ?? [], + missing_exception_lists: details?.missingLists ?? [], + missing_exception_lists_count: details?.missingListsCount ?? 0, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.test.ts new file mode 100644 index 0000000000000..fe8150fd6f3be --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.test.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getExceptionExportDetailsMock } from './index.mock'; +import { exportExceptionDetailsSchema, ExportExceptionDetails } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('exportExceptionDetails', () => { + test('it should validate export meta', () => { + const payload = getExceptionExportDetailsMock(); + const decoded = exportExceptionDetailsSchema.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should strip out extra keys', () => { + const payload: ExportExceptionDetails & { + extraKey?: string; + } = getExceptionExportDetailsMock(); + payload.extraKey = 'some extra key'; + const decoded = exportExceptionDetailsSchema.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getExceptionExportDetailsMock()); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.ts new file mode 100644 index 0000000000000..358e987d8b178 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_export_details/index.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +export const exportExceptionDetails = { + exported_exception_list_count: t.number, + exported_exception_list_item_count: t.number, + missing_exception_list_item_count: t.number, + missing_exception_list_items: t.array( + t.exact( + t.type({ + item_id: NonEmptyString, + }) + ) + ), + missing_exception_lists: t.array( + t.exact( + t.type({ + list_id: NonEmptyString, + }) + ) + ), + missing_exception_lists_count: t.number, +}; + +export const exportExceptionDetailsSchema = t.exact(t.type(exportExceptionDetails)); + +export type ExportExceptionDetails = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.test.ts new file mode 100644 index 0000000000000..ac57828355d36 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.test.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +import { exceptionListType, ExceptionListTypeEnum } from '.'; + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('exceptionListType', () => { + test('it should validate for "detection"', () => { + const payload = 'detection'; + const decoded = exceptionListType.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate for "rule_default"', () => { + const payload = 'rule_default'; + const decoded = exceptionListType.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate for "endpoint"', () => { + const payload = 'endpoint'; + const decoded = exceptionListType.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should contain same amount of keys as enum', () => { + // Might seem like a weird test, but its meant to + // ensure that if exceptionListType is updated, you + // also update the ExceptionListTypeEnum, a workaround + // for io-ts not yet supporting enums + // https://github.com/gcanti/io-ts/issues/67 + const keys = Object.keys(exceptionListType.keys).sort().join(',').toLowerCase(); + const enumKeys = Object.keys(ExceptionListTypeEnum).sort().join(',').toLowerCase(); + + expect(keys).toEqual(enumKeys); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.ts new file mode 100644 index 0000000000000..50273a9c55a99 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list/index.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const exceptionListType = t.keyof({ + detection: null, + rule_default: null, + endpoint: null, + endpoint_trusted_apps: null, + endpoint_events: null, + endpoint_host_isolation_exceptions: null, + endpoint_blocklists: null, +}); +export const exceptionListTypeOrUndefined = t.union([exceptionListType, t.undefined]); +export type ExceptionListType = t.TypeOf; +export type ExceptionListTypeOrUndefined = t.TypeOf; +export enum ExceptionListTypeEnum { + DETECTION = 'detection', // shared exception list type + RULE_DEFAULT = 'rule_default', // rule default, cannot be shared + ENDPOINT = 'endpoint', + ENDPOINT_TRUSTED_APPS = 'endpoint', + ENDPOINT_EVENTS = 'endpoint_events', + ENDPOINT_HOST_ISOLATION_EXCEPTIONS = 'endpoint_host_isolation_exceptions', + ENDPOINT_BLOCKLISTS = 'endpoint_blocklists', +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list_item_type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list_item_type/index.ts new file mode 100644 index 0000000000000..36857aec92dfd --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/exception_list_item_type/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const exceptionListItemType = t.keyof({ simple: null }); +export const exceptionListItemTypeOrUndefined = t.union([exceptionListItemType, t.undefined]); +export type ExceptionListItemType = t.TypeOf; +export type ExceptionListItemTypeOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/expire_time/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/expire_time/index.ts new file mode 100644 index 0000000000000..9a3f4db110ed1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/expire_time/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { IsoDateString } from '@kbn/securitysolution-io-ts-types'; + +export const expireTime = IsoDateString; +export const expireTimeOrUndefined = t.union([expireTime, t.undefined]); +export type ExpireTimeOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/file/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/file/index.ts new file mode 100644 index 0000000000000..885d714de4411 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/file/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const file = t.object; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/filter/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/filter/index.ts new file mode 100644 index 0000000000000..43ac9592ed31e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/filter/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const filter = t.string; +export type Filter = t.TypeOf; +export const filterOrUndefined = t.union([filter, t.undefined]); +export type FilterOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/id/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/id/index.ts new file mode 100644 index 0000000000000..967282c158a27 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/id/index.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +export const id = NonEmptyString; +export type Id = t.TypeOf; +export const idOrUndefined = t.union([id, t.undefined]); +export type IdOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/immutable/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/immutable/index.ts new file mode 100644 index 0000000000000..afeb2de36ea1d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/immutable/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const immutable = t.boolean; +export type Immutable = t.TypeOf; +export const immutableOrUndefined = t.union([immutable, t.undefined]); +export type ImmutableOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts new file mode 100644 index 0000000000000..a447d1f535071 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts @@ -0,0 +1,134 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getCommentsArrayMock, getCommentsMock } from '../comment/index.mock'; +import { getCreateCommentsArrayMock } from '../create_comment/index.mock'; +import { + importComment, + ImportCommentsArray, + importCommentsArray, + ImportCommentsArrayOrUndefined, + importCommentsArrayOrUndefined, +} from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('ImportComment', () => { + describe('importComment', () => { + test('it passes validation with a typical comment', () => { + const payload = getCommentsMock(); + const decoded = importComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation with a new comment', () => { + const payload = { comment: 'new comment' }; + const decoded = importComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = importComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('importCommentsArray', () => { + test('it passes validation an array of Comment', () => { + const payload = getCommentsArrayMock(); + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation an array of CreateComment', () => { + const payload = getCreateCommentsArrayMock(); + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation an array of Comment and CreateComment', () => { + const payload = [...getCommentsArrayMock(), ...getCreateCommentsArrayMock()]; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when array includes non ImportComment types', () => { + const payload = [1] as unknown as ImportCommentsArray; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('importCommentsArrayOrUndefined', () => { + test('it passes validation an array of ImportComment', () => { + const payload = [...getCommentsArrayMock(), ...getCreateCommentsArrayMock()]; + const decoded = importCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation when undefined', () => { + const payload = undefined; + const decoded = importCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when array includes non ImportComment types', () => { + const payload = [1] as unknown as ImportCommentsArrayOrUndefined; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', + ]); + expect(message.schema).toEqual({}); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts new file mode 100644 index 0000000000000..c4c906117ecdb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { createComment } from '../create_comment'; +import { comment } from '../comment'; + +export const importComment = t.union([comment, createComment]); + +export type ImportComment = t.TypeOf; +export const importCommentsArray = t.array(importComment); +export type ImportCommentsArray = t.TypeOf; +export const importCommentsArrayOrUndefined = t.union([importCommentsArray, t.undefined]); +export type ImportCommentsArrayOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/include_expired_exceptions/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/include_expired_exceptions/index.ts new file mode 100644 index 0000000000000..0c3d5e4959bc4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/include_expired_exceptions/index.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const include_expired_exceptions = t.keyof({ true: null, false: null }); +export const includeExpiredExceptionsOrUndefined = t.union([ + include_expired_exceptions, + t.undefined, +]); +export type IncludeExpiredExceptionsOrUndefined = t.TypeOf< + typeof includeExpiredExceptionsOrUndefined +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts new file mode 100644 index 0000000000000..0ff54c5e5a726 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +export * from './comment'; +export * from './create_comment'; +export * from './created_at'; +export * from './created_by'; +export * from './cursor'; +export * from './default_namespace'; +export * from './default_namespace_array'; +export * from './default_create_comments_array'; +export * from './default_import_comments_array'; +export * from './description'; +export * from './deserializer'; +export * from './endpoint'; +export * from './entries'; +export * from './entries_exist'; +export * from './entries_list'; +export * from './entry_match'; +export * from './entry_match_any'; +export * from './entry_match_wildcard'; +export * from './entry_nested'; +export * from './exception_export_details'; +export * from './exception_list'; +export * from './exception_list_item_type'; +export * from './expire_time'; +export * from './filter'; +export * from './id'; +export * from './immutable'; +export * from './import_comment'; +export * from './item_id'; +export * from './list_id'; +export * from './list_operator'; +export * from './list_type'; +export * from './lists'; +export * from './lists_default_array'; +export * from './max_size'; +export * from './meta'; +export * from './name'; +export * from './namespace_type'; +export * from './non_empty_entries_array'; +export * from './non_empty_nested_entries_array'; +export * from './os_type'; +export * from './page'; +export * from './per_page'; +export * from './pit'; +export * from './search'; +export * from './search_after'; +export * from './serializer'; +export * from './sort_field'; +export * from './sort_order'; +export * from './tags'; +export * from './tie_breaker_id'; +export * from './timestamp'; +export * from './total'; +export * from './type'; +export * from './underscore_version'; +export * from './update_comment'; +export * from './updated_at'; +export * from './updated_by'; +export * from './refresh'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/item/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/item/index.ts new file mode 100644 index 0000000000000..5a71e1242d26e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/item/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const item = t.string; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/item_id/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/item_id/index.ts new file mode 100644 index 0000000000000..44ccc97d46664 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/item_id/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +export const item_id = NonEmptyString; +export type ItemId = t.TypeOf; +export const itemIdOrUndefined = t.union([item_id, t.undefined]); +export type ItemIdOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_id/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_id/index.ts new file mode 100644 index 0000000000000..c813d7170e8ad --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_id/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; + +export const list_id = NonEmptyString; +export type ListId = t.TypeOf; +export const list_idOrUndefined = t.union([list_id, t.undefined]); +export type ListIdOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.test.ts new file mode 100644 index 0000000000000..d3d67a8fd60a8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.test.ts @@ -0,0 +1,44 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { ListOperatorEnum as OperatorEnum, listOperator as operator } from '.'; + +describe('operator', () => { + test('it should validate for "included"', () => { + const payload = 'included'; + const decoded = operator.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate for "excluded"', () => { + const payload = 'excluded'; + const decoded = operator.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should contain same amount of keys as enum', () => { + // Might seem like a weird test, but its meant to + // ensure that if operator is updated, you + // also update the operatorEnum, a workaround + // for io-ts not yet supporting enums + // https://github.com/gcanti/io-ts/issues/67 + const keys = Object.keys(operator.keys).sort().join(',').toLowerCase(); + const enumKeys = Object.keys(OperatorEnum).sort().join(',').toLowerCase(); + + expect(keys).toEqual(enumKeys); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.ts new file mode 100644 index 0000000000000..096b21ec20f90 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_operator/index.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const listOperator = t.keyof({ excluded: null, included: null }); +export type ListOperator = t.TypeOf; +export enum ListOperatorEnum { + INCLUDED = 'included', + EXCLUDED = 'excluded', +} + +export const listOperatorType = t.keyof({ + nested: null, + match: null, + match_any: null, + wildcard: null, + exists: null, + list: null, +}); +export type ListOperatorType = t.TypeOf; +export enum ListOperatorTypeEnum { + NESTED = 'nested', + MATCH = 'match', + MATCH_ANY = 'match_any', + WILDCARD = 'wildcard', + EXISTS = 'exists', + LIST = 'list', +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_type/index.ts new file mode 100644 index 0000000000000..7a160486c3994 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/list_type/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const list_type = t.keyof({ item: null, list: null }); +export type ListType = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.mock.ts new file mode 100644 index 0000000000000..6ad3c6a371d18 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.mock.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +import { List, ListArray } from '.'; +import { ENDPOINT_LIST_ID } from '@kbn/securitysolution-list-constants'; + +export const getListMock = (): List => ({ + id: 'some_uuid', + list_id: 'list_id_single', + namespace_type: 'single', + type: 'detection', +}); + +export const getEndpointListMock = (): List => ({ + id: ENDPOINT_LIST_ID, + list_id: ENDPOINT_LIST_ID, + namespace_type: 'agnostic', + type: 'endpoint', +}); + +export const getListArrayMock = (): ListArray => [getListMock(), getEndpointListMock()]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.test.ts new file mode 100644 index 0000000000000..aecfe9501ac17 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.test.ts @@ -0,0 +1,125 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getEndpointListMock, getListArrayMock, getListMock } from './index.mock'; +import { List, list, ListArray, listArray, ListArrayOrUndefined, listArrayOrUndefined } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('Lists', () => { + describe('list', () => { + test('it should validate a list', () => { + const payload = getListMock(); + const decoded = list.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate a list with "namespace_type" of "agnostic"', () => { + const payload = getEndpointListMock(); + const decoded = list.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT validate a list without an "id"', () => { + const payload = getListMock(); + // @ts-expect-error + delete payload.id; + const decoded = list.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT validate a list without "namespace_type"', () => { + const payload = getListMock(); + // @ts-expect-error + delete payload.namespace_type; + const decoded = list.decode(payload); + const message = pipe(decoded, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "namespace_type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra keys', () => { + const payload: List & { + extraKey?: string; + } = getListMock(); + payload.extraKey = 'some value'; + const decoded = list.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getListMock()); + }); + }); + + describe('listArray', () => { + test('it should validate an array of lists', () => { + const payload = getListArrayMock(); + const decoded = listArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate when unexpected type found in array', () => { + const payload = [1] as unknown as ListArray; + const decoded = listArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "rule_default" | "endpoint" | "endpoint_trusted_apps" | "endpoint_events" | "endpoint_host_isolation_exceptions" | "endpoint_blocklists", namespace_type: "agnostic" | "single" |}>"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('listArrayOrUndefined', () => { + test('it should validate an array of lists', () => { + const payload = getListArrayMock(); + const decoded = listArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate when undefined', () => { + const payload = undefined; + const decoded = listArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an item that is not of type "list" in array', () => { + const payload = [1] as unknown as ListArrayOrUndefined; + const decoded = listArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "rule_default" | "endpoint" | "endpoint_trusted_apps" | "endpoint_events" | "endpoint_host_isolation_exceptions" | "endpoint_blocklists", namespace_type: "agnostic" | "single" |}> | undefined)"', + 'Invalid value "[1]" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "rule_default" | "endpoint" | "endpoint_trusted_apps" | "endpoint_events" | "endpoint_host_isolation_exceptions" | "endpoint_blocklists", namespace_type: "agnostic" | "single" |}> | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.ts new file mode 100644 index 0000000000000..bbc99142ffc7b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { exceptionListType } from '../exception_list'; +import { namespaceType } from '../default_namespace'; + +export const list = t.exact( + t.type({ + id: NonEmptyString, + list_id: NonEmptyString, + type: exceptionListType, + namespace_type: namespaceType, + }) +); + +export type List = t.TypeOf; +export const listArray = t.array(list); +export type ListArray = t.TypeOf; +export const listArrayOrUndefined = t.union([listArray, t.undefined]); +export type ListArrayOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.test.ts new file mode 100644 index 0000000000000..b702f617d17c7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.test.ts @@ -0,0 +1,62 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { DefaultListArray } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getListArrayMock } from '../lists/index.mock'; + +describe('lists_default_array', () => { + test('it should return a default array when null', () => { + const payload = null; + const decoded = DefaultListArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); + + test('it should return a default array when undefined', () => { + const payload = undefined; + const decoded = DefaultListArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); + + test('it should validate an empty array', () => { + const payload: string[] = []; + const decoded = DefaultListArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of lists', () => { + const payload = getListArrayMock(); + const decoded = DefaultListArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not validate an array of non accepted types', () => { + // Terrible casting for purpose of tests + const payload = [1] as unknown; + const decoded = DefaultListArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "DefaultListArray"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.ts new file mode 100644 index 0000000000000..33ab281a6f176 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/lists_default_array/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { list, ListArray } from '../lists'; + +/** + * Types the DefaultListArray as: + * - If null or undefined, then a default array of type list will be set + */ +export const DefaultListArray = new t.Type( + 'DefaultListArray', + t.array(list).is, + (input, context): Either => + input == null ? t.success([]) : t.array(list).validate(input, context), + t.identity +); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.test.ts new file mode 100644 index 0000000000000..2c733c93ee778 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.test.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { maxSizeOrUndefined } from '.'; + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; + +describe('maxSizeOrUndefined', () => { + test('it will validate a correct max value', () => { + const payload = 123; + const decoded = maxSizeOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will fail to validate a 0', () => { + const payload = 0; + const decoded = maxSizeOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "0" supplied to "(PositiveIntegerGreaterThanZero | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it will fail to validate a -1', () => { + const payload = -1; + const decoded = maxSizeOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "-1" supplied to "(PositiveIntegerGreaterThanZero | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it will fail to validate a string', () => { + const payload = '123'; + const decoded = maxSizeOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "123" supplied to "(PositiveIntegerGreaterThanZero | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.ts new file mode 100644 index 0000000000000..c652ae81d6c41 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/max_size/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import { PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; +import * as t from 'io-ts'; + +export const max_size = PositiveIntegerGreaterThanZero; +export type MaxSize = t.TypeOf; + +export const maxSizeOrUndefined = t.union([max_size, t.undefined]); +export type MaxSizeOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts new file mode 100644 index 0000000000000..547b45969be71 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const meta = t.object; +export type Meta = t.TypeOf; +export const metaOrUndefined = t.union([meta, t.undefined]); +export type MetaOrUndefined = t.TypeOf; + +export const nullableMetaOrUndefined = t.union([metaOrUndefined, t.null]); +export type NullableMetaOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/name/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/name/index.ts new file mode 100644 index 0000000000000..020f3642306a9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/name/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const name = t.string; +export type Name = t.TypeOf; +export const nameOrUndefined = t.union([name, t.undefined]); +export type NameOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/namespace_type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/namespace_type/index.ts new file mode 100644 index 0000000000000..ae16f8b4521ca --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/namespace_type/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import { DefaultNamespace } from '../default_namespace'; + +export const namespace_type = DefaultNamespace; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.test.ts new file mode 100644 index 0000000000000..321a57dd4feea --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.test.ts @@ -0,0 +1,130 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { EntriesArray } from '../entries'; +import { nonEmptyEntriesArray } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEntryMatchMock } from '../entry_match/index.mock'; +import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { getEntryExistsMock } from '../entries_exist/index.mock'; +import { + getEntriesArrayMock, + getListAndNonListEntriesArrayMock, + getListEntriesArrayMock, +} from '../entries/index.mock'; +import { getEntryNestedMock } from '../entry_nested/index.mock'; + +describe('non_empty_entries_array', () => { + test('it should FAIL validation when given an empty array', () => { + const payload: EntriesArray = []; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "[]" supplied to "NonEmptyEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when given "undefined"', () => { + const payload = undefined; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "NonEmptyEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when given "null"', () => { + const payload = null; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "null" supplied to "NonEmptyEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should validate an array of "match" entries', () => { + const payload: EntriesArray = [getEntryMatchMock(), getEntryMatchMock()]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of "match_any" entries', () => { + const payload: EntriesArray = [getEntryMatchAnyMock(), getEntryMatchAnyMock()]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of "exists" entries', () => { + const payload: EntriesArray = [getEntryExistsMock(), getEntryExistsMock()]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of "list" entries', () => { + const payload: EntriesArray = [...getListEntriesArrayMock()]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of "nested" entries', () => { + const payload: EntriesArray = [getEntryNestedMock(), getEntryNestedMock()]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of entries', () => { + const payload: EntriesArray = [...getEntriesArrayMock()]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when given an array of entries of value list and non-value list entries', () => { + const payload: EntriesArray = [...getListAndNonListEntriesArrayMock()]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Cannot have entry of type list and other']); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when given an array of non entries', () => { + const payload = [1]; + const decoded = nonEmptyEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "NonEmptyEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.ts new file mode 100644 index 0000000000000..8d6812077d4e2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_entries_array/index.ts @@ -0,0 +1,40 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { entriesArray, EntriesArray } from '../entries'; +import { entriesList } from '../entries_list'; + +/** + * Types the nonEmptyEntriesArray as: + * - An array of entries of length 1 or greater + * + */ +export const nonEmptyEntriesArray = new t.Type( + 'NonEmptyEntriesArray', + entriesArray.is, + (input, context): Either => { + if (Array.isArray(input) && input.length === 0) { + return t.failure(input, context); + } else { + if ( + Array.isArray(input) && + input.some((entry) => entriesList.is(entry)) && + input.some((entry) => !entriesList.is(entry)) + ) { + // fail when an exception item contains both a value list entry and a non-value list entry + return t.failure(input, context, 'Cannot have entry of type list and other'); + } + return entriesArray.validate(input, context); + } + }, + t.identity +); + +export type NonEmptyEntriesArray = t.OutputOf; +export type NonEmptyEntriesArrayDecoded = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.test.ts new file mode 100644 index 0000000000000..1d1d659f028c4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.test.ts @@ -0,0 +1,115 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { EntriesArray } from '../entries'; +import { nonEmptyNestedEntriesArray } from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getEntryMatchMock } from '../entry_match/index.mock'; +import { getEntryMatchAnyMock } from '../entry_match_any/index.mock'; +import { getEntryExistsMock } from '../entries_exist/index.mock'; +import { getEntryNestedMock } from '../entry_nested/index.mock'; + +describe('non_empty_nested_entries_array', () => { + test('it should FAIL validation when given an empty array', () => { + const payload: EntriesArray = []; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "[]" supplied to "NonEmptyNestedEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when given "undefined"', () => { + const payload = undefined; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "NonEmptyNestedEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should FAIL validation when given "null"', () => { + const payload = null; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "null" supplied to "NonEmptyNestedEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should validate an array of "match" entries', () => { + const payload: EntriesArray = [getEntryMatchMock(), getEntryMatchMock()]; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of "match_any" entries', () => { + const payload: EntriesArray = [getEntryMatchAnyMock(), getEntryMatchAnyMock()]; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate an array of "exists" entries', () => { + const payload: EntriesArray = [getEntryExistsMock(), getEntryExistsMock()]; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when given an array of "nested" entries', () => { + const payload: EntriesArray = [getEntryNestedMock(), getEntryNestedMock()]; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "operator"', + 'Invalid value "nested" supplied to "type"', + 'Invalid value "undefined" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should validate an array of entries', () => { + const payload: EntriesArray = [ + getEntryExistsMock(), + getEntryMatchAnyMock(), + getEntryMatchMock(), + ]; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should FAIL validation when given an array of non entries', () => { + const payload = [1]; + const decoded = nonEmptyNestedEntriesArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "NonEmptyNestedEntriesArray"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.ts new file mode 100644 index 0000000000000..eb2d1074b9f44 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/non_empty_nested_entries_array/index.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { entriesMatch } from '../entry_match'; +import { entriesMatchAny } from '../entry_match_any'; +import { entriesExists } from '../entries_exist'; + +export const nestedEntryItem = t.union([entriesMatch, entriesMatchAny, entriesExists]); +export const nestedEntriesArray = t.array(nestedEntryItem); +export type NestedEntriesArray = t.TypeOf; + +/** + * Types the nonEmptyNestedEntriesArray as: + * - An array of entries of length 1 or greater + * + */ +export const nonEmptyNestedEntriesArray = new t.Type< + NestedEntriesArray, + NestedEntriesArray, + unknown +>( + 'NonEmptyNestedEntriesArray', + nestedEntriesArray.is, + (input, context): Either => { + if (Array.isArray(input) && input.length === 0) { + return t.failure(input, context); + } else { + return nestedEntriesArray.validate(input, context); + } + }, + t.identity +); + +export type NonEmptyNestedEntriesArray = t.OutputOf; +export type NonEmptyNestedEntriesArrayDecoded = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.test.ts new file mode 100644 index 0000000000000..3b8ca29afa4e9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.test.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { osType, osTypeArrayOrUndefined } from '.'; + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; + +describe('osType', () => { + test('it will validate a correct osType', () => { + const payload = 'windows'; + const decoded = osType.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will fail to validate an incorrect osType', () => { + const payload = 'foo'; + const decoded = osType.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "foo" supplied to ""linux" | "macos" | "windows""', + ]); + expect(message.schema).toEqual({}); + }); + + test('it will default to an empty array when osTypeArrayOrUndefined is used', () => { + const payload = undefined; + const decoded = osTypeArrayOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.ts new file mode 100644 index 0000000000000..6e8cbb85b6312 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/os_type/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { DefaultArray } from '@kbn/securitysolution-io-ts-types'; + +export const osType = t.keyof({ + linux: null, + macos: null, + windows: null, +}); +export type OsType = t.TypeOf; + +export const osTypeArray = DefaultArray(osType); +export type OsTypeArray = t.TypeOf; + +export const osTypeArrayOrUndefined = t.union([osTypeArray, t.undefined]); +export type OsTypeArrayOrUndefined = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/page/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/page/index.ts new file mode 100644 index 0000000000000..36faf8e7e5e24 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/page/index.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const page = t.number; // TODO: Change this out for PositiveNumber from siem +export type Page = t.TypeOf; + +export const pageOrUndefined = t.union([page, t.undefined]); +export type PageOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/per_page/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/per_page/index.ts new file mode 100644 index 0000000000000..669e0699b366c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/per_page/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const per_page = t.number; // TODO: Change this out for PositiveNumber from siem +export type PerPage = t.TypeOf; + +export const perPageOrUndefined = t.union([per_page, t.undefined]); +export type PerPageOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.test.ts new file mode 100644 index 0000000000000..9cafd8ed5ec0f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.test.ts @@ -0,0 +1,62 @@ +/* + * 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. + */ + +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { pitOrUndefined } from '.'; + +import * as t from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; + +describe('pitOrUndefined', () => { + test('it will validate a correct pit', () => { + const payload = { id: '123', keepAlive: '1m' }; + const decoded = pitOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will validate with the value of "undefined"', () => { + const obj = t.exact( + t.type({ + pit_id: pitOrUndefined, + }) + ); + const payload: t.TypeOf = { + pit_id: undefined, + }; + const decoded = obj.decode({ + pit_id: undefined, + }); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will validate a correct pit without having a "keepAlive"', () => { + const payload = { id: '123' }; + const decoded = pitOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will fail to validate an incorrect pit', () => { + const payload = 'foo'; + const decoded = pitOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "foo" supplied to "({| id: string, keepAlive: (string | undefined) |} | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.ts new file mode 100644 index 0000000000000..97b6957e07e53 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/pit/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const pitId = t.string; +export const pit = t.exact( + t.type({ + id: pitId, + keepAlive: t.union([t.string, t.undefined]), + }) +); +export const pitOrUndefined = t.union([pit, t.undefined]); + +export type Pit = t.TypeOf; +export type PitId = t.TypeOf; +export type PitOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/refresh/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/refresh/index.ts new file mode 100644 index 0000000000000..d1a7fe34fc704 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/refresh/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const refresh = t.union([t.literal('true'), t.literal('false')]); +export const refreshWithWaitFor = t.union([ + t.literal('true'), + t.literal('false'), + t.literal('wait_for'), +]); +export type Refresh = t.TypeOf; +export type RefreshWithWaitFor = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/required_keep_undefined/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/required_keep_undefined/index.ts new file mode 100644 index 0000000000000..5854fc42a3a78 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/required_keep_undefined/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * This makes any optional property the same as Required would but also has the + * added benefit of keeping your undefined. + * + * For example: + * type A = RequiredKeepUndefined<{ a?: undefined; b: number }>; + * + * will yield a type of: + * type A = { a: undefined; b: number; } + * @deprecated This has no replacement. We should stop using/relying on this and just remove it. + */ +export type RequiredKeepUndefined = { [K in keyof T]-?: [T[K]] } extends infer U + ? U extends Record + ? { [K in keyof U]: U[K][0] } + : never + : never; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts new file mode 100644 index 0000000000000..6c45f50c9c894 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { searchOrUndefined } from '.'; + +import * as t from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; + +describe('search', () => { + test('it will validate a correct search', () => { + const payload = 'name:foo'; + const decoded = searchOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will validate with the value of "undefined"', () => { + const obj = t.exact( + t.type({ + search: searchOrUndefined, + }) + ); + const payload: t.TypeOf = { + search: undefined, + }; + const decoded = obj.decode({ + pit_id: undefined, + }); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will fail to validate an incorrect search', () => { + const payload = ['foo']; + const decoded = searchOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["foo"]" supplied to "(string | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts new file mode 100644 index 0000000000000..b93c4631cd223 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const search = t.string; +export type Search = t.TypeOf; + +export const searchOrUndefined = t.union([search, t.undefined]); +export type SearchOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.test.ts new file mode 100644 index 0000000000000..bc176af4fa307 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.test.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { searchAfterOrUndefined } from '.'; + +import * as t from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; + +describe('searchAfter', () => { + test('it will validate a correct search_after', () => { + const payload = ['test-1', 'test-2']; + const decoded = searchAfterOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will validate with the value of "undefined"', () => { + const obj = t.exact( + t.type({ + search_after: searchAfterOrUndefined, + }) + ); + const payload: t.TypeOf = { + search_after: undefined, + }; + const decoded = obj.decode({ + pit_id: undefined, + }); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will fail to validate an incorrect search_after', () => { + const payload = 'foo'; + const decoded = searchAfterOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "foo" supplied to "(Array | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.ts new file mode 100644 index 0000000000000..17735728d3418 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/search_after/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const search_after = t.array(t.string); +export type SearchAfter = t.TypeOf; + +export const searchAfterOrUndefined = t.union([search_after, t.undefined]); +export type SearchAfterOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/serializer/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/serializer/index.ts new file mode 100644 index 0000000000000..28322ff2e9910 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/serializer/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const serializer = t.string; +export type Serializer = t.TypeOf; +export const serializerOrUndefined = t.union([serializer, t.undefined]); +export type SerializerOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_field/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_field/index.ts new file mode 100644 index 0000000000000..762fdf80c227d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_field/index.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const sort_field = t.string; +export const sortFieldOrUndefined = t.union([sort_field, t.undefined]); +export type SortFieldOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_order/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_order/index.ts new file mode 100644 index 0000000000000..a849e45c316ea --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/sort_order/index.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const sort_order = t.keyof({ asc: null, desc: null }); +export const sortOrderOrUndefined = t.union([sort_order, t.undefined]); +export type SortOrderOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/tags/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/tags/index.ts new file mode 100644 index 0000000000000..0ad756f057718 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/tags/index.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { DefaultStringArray } from '@kbn/securitysolution-io-ts-types'; + +export const tags = DefaultStringArray; +export type Tags = t.TypeOf; +export const tagsOrUndefined = t.union([tags, t.undefined]); +export type TagsOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/tie_breaker_id/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/tie_breaker_id/index.ts new file mode 100644 index 0000000000000..362e500890818 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/tie_breaker_id/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const tie_breaker_id = t.string; // TODO: Use UUID for this instead of a string for validation diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts new file mode 100644 index 0000000000000..30472bcd101f9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { IsoDateString } from '@kbn/securitysolution-io-ts-types'; + +export const timestamp = IsoDateString; +export const timestampOrUndefined = t.union([IsoDateString, t.undefined]); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/total/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/total/index.ts new file mode 100644 index 0000000000000..f67ca0f2fc5e5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/total/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const total = t.number; // TODO: Change this out for PositiveNumber from siem +export const totalUndefined = t.union([total, t.undefined]); +export type TotalOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.test.ts new file mode 100644 index 0000000000000..d87ea94728b13 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.test.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { Type, type } from '.'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('type', () => { + test('it will work with a given expected type', () => { + const payload: Type = 'keyword'; + const decoded = type.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will give an error if given a type that does not exist', () => { + const payload: Type | 'madeup' = 'madeup'; + const decoded = type.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "madeup" supplied to ""binary" | "boolean" | "byte" | "date" | "date_nanos" | "date_range" | "double" | "double_range" | "float" | "float_range" | "geo_point" | "geo_shape" | "half_float" | "integer" | "integer_range" | "ip" | "ip_range" | "keyword" | "long" | "long_range" | "shape" | "short" | "text""', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.ts new file mode 100644 index 0000000000000..5a1d234d5f2fc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/type/index.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +/** + * Types of all the regular single value list items but not exception list + * or exception list types. Those types are in the list_types folder. + */ +export const type = t.keyof({ + binary: null, + boolean: null, + byte: null, + date: null, + date_nanos: null, + date_range: null, + double: null, + double_range: null, + float: null, + float_range: null, + geo_point: null, + geo_shape: null, + half_float: null, + integer: null, + integer_range: null, + ip: null, + ip_range: null, + keyword: null, + long: null, + long_range: null, + shape: null, + short: null, + text: null, +}); + +export const typeOrUndefined = t.union([type, t.undefined]); +export type Type = t.TypeOf; +export type TypeOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/underscore_version/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/underscore_version/index.ts new file mode 100644 index 0000000000000..6e47b89af8163 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/underscore_version/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const _version = t.string; +export const _versionOrUndefined = t.union([_version, t.undefined]); +export type _VersionOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.mock.ts new file mode 100644 index 0000000000000..c0cbfe5e3019c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.mock.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import { UpdateComment, UpdateCommentsArray } from '.'; +import { ID } from '../../constants/index.mock'; + +export const getUpdateCommentMock = (): UpdateComment => ({ + comment: 'some comment', + id: ID, +}); + +export const getUpdateCommentsArrayMock = (): UpdateCommentsArray => [ + getUpdateCommentMock(), + getUpdateCommentMock(), +]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts new file mode 100644 index 0000000000000..c1f1be8be9c1c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts @@ -0,0 +1,148 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getUpdateCommentMock, getUpdateCommentsArrayMock } from './index.mock'; +import { + UpdateComment, + updateComment, + UpdateCommentsArray, + updateCommentsArray, + UpdateCommentsArrayOrUndefined, + updateCommentsArrayOrUndefined, +} from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('UpdateComment', () => { + describe('updateComment', () => { + test('it should pass validation when supplied typical comment update', () => { + const payload = getUpdateCommentMock(); + const decoded = updateComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an undefined for "comment"', () => { + const payload = getUpdateCommentMock(); + // @ts-expect-error + delete payload.comment; + const decoded = updateComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "comment"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an empty string for "comment"', () => { + const payload = { ...getUpdateCommentMock(), comment: '' }; + const decoded = updateComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "comment"']); + expect(message.schema).toEqual({}); + }); + + test('it should pass validation when supplied an undefined for "id"', () => { + const payload = getUpdateCommentMock(); + delete payload.id; + const decoded = updateComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an empty string for "id"', () => { + const payload = { ...getUpdateCommentMock(), id: '' }; + const decoded = updateComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should strip out extra key passed in', () => { + const payload: UpdateComment & { + extraKey?: string; + } = { ...getUpdateCommentMock(), extraKey: 'some new value' }; + const decoded = updateComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getUpdateCommentMock()); + }); + }); + + describe('updateCommentsArray', () => { + test('it should pass validation when supplied an array of comments', () => { + const payload = getUpdateCommentsArrayMock(); + const decoded = updateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when undefined', () => { + const payload = undefined; + const decoded = updateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when array includes non comments types', () => { + const payload = [1] as unknown as UpdateCommentsArray; + const decoded = updateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('updateCommentsArrayOrUndefined', () => { + test('it should pass validation when supplied an array of comments', () => { + const payload = getUpdateCommentsArrayMock(); + const decoded = updateCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied when undefined', () => { + const payload = undefined; + const decoded = updateCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when array includes non comments types', () => { + const payload = [1] as unknown as UpdateCommentsArrayOrUndefined; + const decoded = updateCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', + ]); + expect(message.schema).toEqual({}); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts new file mode 100644 index 0000000000000..6a0b4b08c7722 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; +import { id } from '../id'; + +export const updateComment = t.intersection([ + t.exact( + t.type({ + comment: NonEmptyString, + }) + ), + t.exact( + t.partial({ + id, + }) + ), +]); + +export type UpdateComment = t.TypeOf; +export const updateCommentsArray = t.array(updateComment); +export type UpdateCommentsArray = t.TypeOf; +export const updateCommentsArrayOrUndefined = t.union([updateCommentsArray, t.undefined]); +export type UpdateCommentsArrayOrUndefined = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_at/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_at/index.ts new file mode 100644 index 0000000000000..bafbadcd8f09b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_at/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const updated_at = t.string; // TODO: Make this into an ISO Date string check diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_by/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_by/index.ts new file mode 100644 index 0000000000000..58c5b2d666bd8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/updated_by/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import * as t from 'io-ts'; + +export const updated_by = t.string; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/value/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/value/index.ts new file mode 100644 index 0000000000000..38530a942275c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/common/value/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const value = t.string; +export const valueOrUndefined = t.union([value, t.undefined]); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/constants/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/constants/index.mock.ts new file mode 100644 index 0000000000000..ae91d63d6b7e3 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/constants/index.mock.ts @@ -0,0 +1,113 @@ +/* + * 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. + */ + +import { EndpointEntriesArray } from '../common/endpoint/entries'; +import { EntriesArray, Entry } from '../common/entries'; +import { EntryMatch } from '../common/entry_match'; +import { EntryNested } from '../common/entry_nested'; +import { OsTypeArray } from '../common/os_type'; + +export const DATE_NOW = '2020-04-20T15:25:31.830Z'; +export const OLD_DATE_RELATIVE_TO_DATE_NOW = '2020-04-19T15:25:31.830Z'; +export const USER = 'some user'; +export const ELASTIC_USER = 'elastic'; +export const LIST_INDEX = '.lists'; +export const LIST_ITEM_INDEX = '.items'; +export const NAME = 'some name'; +export const DESCRIPTION = 'some description'; +export const LIST_ID = 'some-list-id'; +export const LIST_ITEM_ID = 'some-list-item-id'; +export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; +export const TIE_BREAKERS = [ + '21530991-4051-46ec-bc35-2afa09a1b0b5', + '3c662054-ae37-4aa9-9936-3e8e2ea26775', + '60e49a20-3a23-48b6-8bf9-ed5e3b70f7a0', + '38814080-a40f-4358-992a-3b875f9b7dec', + '29fa61be-aaaf-411c-a78a-7059e3f723f1', + '9c19c959-cb9d-4cd2-99e4-1ea2baf0ef0e', + 'd409308c-f94b-4b3a-8234-bbd7a80c9140', + '87824c99-cd83-45c4-8aa6-4ad95dfea62c', + '7b940c17-9355-479f-b882-f3e575718f79', + '5983ad0c-4ef4-4fa0-8308-80ab9ecc4f74', +]; +export const META = {}; +export const TYPE = 'ip'; +export const VALUE = '127.0.0.1'; +export const VALUE_2 = '255.255.255'; +export const NAMESPACE_TYPE = 'single'; +export const NESTED_FIELD = 'parent.field'; + +// Exception List specific +export const ID = 'uuid_here'; +export const ITEM_ID = 'some-list-item-id'; +export const DETECTION_TYPE = 'detection'; +export const ENDPOINT_TYPE = 'endpoint'; +export const FIELD = 'host.name'; +export const OPERATOR = 'included'; +export const OPERATOR_EXCLUDED = 'excluded'; +export const ENTRY_VALUE = 'some host name'; +export const MATCH = 'match'; +export const MATCH_ANY = 'match_any'; +export const WILDCARD = 'wildcard'; +export const MAX_IMPORT_PAYLOAD_BYTES = 9000000; +export const IMPORT_BUFFER_SIZE = 1000; +export const LIST = 'list'; +export const EXISTS = 'exists'; +export const NESTED = 'nested'; +export const ENTRIES: EntriesArray = [ + { + entries: [{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }], + field: 'some.parentField', + type: 'nested', + }, + { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, +]; +export const ENDPOINT_ENTRIES: EndpointEntriesArray = [ + { + entries: [{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }], + field: 'some.parentField', + type: 'nested', + }, + { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, +]; +// ENTRIES_WITH_IDS should only be used to mock out functionality of a collection of transforms +// that are UI specific and useful for UI concerns that are inserted between the +// API and the actual user interface. In some ways these might be viewed as +// technical debt or to compensate for the differences and preferences +// of how ReactJS might prefer data vs. how we want to model data. +export const ENTRIES_WITH_IDS: EntriesArray = [ + { + entries: [ + { + field: 'nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as EntryMatch & { id: string }, + ], + field: 'some.parentField', + id: '123', + type: 'nested', + } as EntryNested & { id: string }, + { + field: 'some.not.nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as Entry & { id: string }, +]; +export const ITEM_TYPE = 'simple'; +export const OS_TYPES: OsTypeArray = ['windows']; +export const TAGS = []; +export const COMMENTS = []; +export const FILTER = 'name:Nicolas Bourbaki'; +export const CURSOR = 'c29tZXN0cmluZ2ZvcnlvdQ=='; +export const _VERSION = 'WzI5NywxXQ=='; +export const VERSION = 1; +export const IMMUTABLE = false; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..0efac9d4de7f5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.mock.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import { CreateEndpointListItemSchema } from '.'; +import { + COMMENTS, + DESCRIPTION, + ENDPOINT_ENTRIES, + ITEM_TYPE, + META, + NAME, + OS_TYPES, + TAGS, +} from '../../constants/index.mock'; + +export const getCreateEndpointListItemSchemaMock = (): CreateEndpointListItemSchema => ({ + comments: COMMENTS, + description: DESCRIPTION, + entries: ENDPOINT_ENTRIES, + item_id: undefined, + meta: META, + name: NAME, + os_types: OS_TYPES, + tags: TAGS, + type: ITEM_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..78d578dd5d475 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.test.ts @@ -0,0 +1,205 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { getCreateEndpointListItemSchemaMock } from './index.mock'; +import { CreateEndpointListItemSchema, createEndpointListItemSchema } from '.'; +import { getCreateCommentsArrayMock } from '../../common/create_comment/index.mock'; +import { getCommentsMock } from '../../common/comment/index.mock'; +import { CommentsArray } from '../../common/comment'; + +describe('create_endpoint_list_item_schema', () => { + test('it should pass validation when supplied a typical list item request not counting the auto generated uuid', () => { + const payload = getCreateEndpointListItemSchemaMock(); + const decoded = createEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateEndpointListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an undefined for "description"', () => { + const payload = getCreateEndpointListItemSchemaMock(); + // @ts-expect-error + delete payload.description; + const decoded = createEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an undefined for "name"', () => { + const payload = getCreateEndpointListItemSchemaMock(); + // @ts-expect-error + delete payload.name; + const decoded = createEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an undefined for "type"', () => { + const payload = getCreateEndpointListItemSchemaMock(); + // @ts-expect-error + delete payload.type; + const decoded = createEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied a "list_id" since it does not required one', () => { + const inputPayload: CreateEndpointListItemSchema & { list_id: string } = { + ...getCreateEndpointListItemSchemaMock(), + list_id: 'list-123', + }; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "list_id"']); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied a "namespace_type" since it does not required one', () => { + const inputPayload: CreateEndpointListItemSchema & { namespace_type: string } = { + ...getCreateEndpointListItemSchemaMock(), + namespace_type: 'single', + }; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "namespace_type"']); + expect(message.schema).toEqual({}); + }); + + test('it should pass validation when supplied an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => { + const payload = getCreateEndpointListItemSchemaMock(); + const outputPayload = getCreateEndpointListItemSchemaMock(); + delete payload.meta; + delete outputPayload.meta; + const decoded = createEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateEndpointListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should pass validation when supplied an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => { + const inputPayload = getCreateEndpointListItemSchemaMock(); + const outputPayload = getCreateEndpointListItemSchemaMock(); + delete inputPayload.comments; + outputPayload.comments = []; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateEndpointListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should pass validation when supplied "comments" array', () => { + const inputPayload = { + ...getCreateEndpointListItemSchemaMock(), + comments: getCreateCommentsArrayMock(), + }; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateEndpointListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(inputPayload); + }); + + test('it should fail validation when supplied "comments" with "created_at", "created_by", or "id" values', () => { + const inputPayload: Omit & { + comments?: CommentsArray; + } = { + ...getCreateEndpointListItemSchemaMock(), + comments: [getCommentsMock()], + }; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by,id"']); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an undefined for "entries"', () => { + const inputPayload = getCreateEndpointListItemSchemaMock(); + const outputPayload = getCreateEndpointListItemSchemaMock(); + // @ts-expect-error + delete inputPayload.entries; + outputPayload.entries = []; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateEndpointListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should pass validation when supplied an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => { + const inputPayload = getCreateEndpointListItemSchemaMock(); + const outputPayload = getCreateEndpointListItemSchemaMock(); + delete inputPayload.tags; + outputPayload.tags = []; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateEndpointListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should pass validation when supplied an undefined for "item_id" and auto generate a uuid', () => { + const inputPayload = getCreateEndpointListItemSchemaMock(); + delete inputPayload.item_id; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect((message.schema as CreateEndpointListItemSchema).item_id).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i + ); + }); + + test('it should pass validation when supplied an undefined for "item_id" and generate a correct body not counting the uuid', () => { + const inputPayload = getCreateEndpointListItemSchemaMock(); + delete inputPayload.item_id; + const decoded = createEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateEndpointListItemSchema).item_id; + expect(message.schema).toEqual(inputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: CreateEndpointListItemSchema & { + extraKey: string; + } = { ...getCreateEndpointListItemSchemaMock(), extraKey: 'some new value' }; + const decoded = createEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.ts new file mode 100644 index 0000000000000..08fd5e339ade9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_endpoint_list_item_schema/index.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { DefaultUuid } from '@kbn/securitysolution-io-ts-types'; +import { nonEmptyEndpointEntriesArray } from '../../common/endpoint/entries'; +import { exceptionListItemType } from '../../common/exception_list_item_type'; +import { DefaultCreateCommentsArray } from '../../common/default_create_comments_array'; +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { CreateCommentsArray } from '../../common/create_comment'; +import { Tags, tags } from '../../common/tags'; +import { ItemId } from '../../common/item_id'; +import { EntriesArray } from '../../common/entries'; +import { description } from '../../common/description'; +import { name } from '../../common/name'; +import { meta } from '../../common/meta'; + +export const createEndpointListItemSchema = t.intersection([ + t.exact( + t.type({ + description, + entries: nonEmptyEndpointEntriesArray, + name, + type: exceptionListItemType, + }) + ), + t.exact( + t.partial({ + comments: DefaultCreateCommentsArray, // defaults to empty array if not set during decode + item_id: DefaultUuid, // defaults to GUID (uuid v4) if not set during decode + meta, // defaults to undefined if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + }) + ), +]); + +export type CreateEndpointListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type CreateEndpointListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'tags' | 'item_id' | 'entries' | 'comments' | 'os_types' +> & { + comments: CreateCommentsArray; + tags: Tags; + item_id: ItemId; + entries: EntriesArray; + os_types: OsTypeArray; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..4ccc82bf2af05 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.mock.ts @@ -0,0 +1,61 @@ +/* + * 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. + */ + +import { CreateExceptionListItemSchema } from '.'; +import { + COMMENTS, + DESCRIPTION, + ENTRIES, + ITEM_ID, + ITEM_TYPE, + LIST_ID, + META, + NAME, + NAMESPACE_TYPE, + OS_TYPES, + TAGS, +} from '../../constants/index.mock'; + +export const getCreateExceptionListItemSchemaMock = (): CreateExceptionListItemSchema => ({ + comments: COMMENTS, + description: DESCRIPTION, + entries: ENTRIES, + item_id: undefined, + list_id: LIST_ID, + meta: META, + name: NAME, + namespace_type: NAMESPACE_TYPE, + os_types: OS_TYPES, + tags: TAGS, + type: ITEM_TYPE, +}); + +/** + * Useful for end to end testing + */ +export const getCreateExceptionListItemMinimalSchemaMock = (): CreateExceptionListItemSchema => ({ + description: DESCRIPTION, + entries: ENTRIES, + item_id: ITEM_ID, + list_id: LIST_ID, + name: NAME, + os_types: OS_TYPES, + type: ITEM_TYPE, +}); + +/** + * Useful for end to end testing + */ +export const getCreateExceptionListItemMinimalSchemaMockWithoutId = + (): CreateExceptionListItemSchema => ({ + description: DESCRIPTION, + entries: ENTRIES, + list_id: LIST_ID, + name: NAME, + os_types: OS_TYPES, + type: ITEM_TYPE, + }); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..4d03b83112a3f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.test.ts @@ -0,0 +1,209 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getCreateExceptionListItemSchemaMock } from './index.mock'; +import { CreateExceptionListItemSchema, createExceptionListItemSchema } from '.'; +import { getCreateCommentsArrayMock } from '../../common/create_comment/index.mock'; +import { getCommentsMock } from '../../common/comment/index.mock'; +import { CommentsArray } from '../../common/comment'; + +describe('create_exception_list_item_schema', () => { + test('it should pass validation when supplied a typical exception list item request not counting the auto generated uuid', () => { + const payload = getCreateExceptionListItemSchemaMock(); + const decoded = createExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an undefined for "description"', () => { + const payload = getCreateExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.description; + const decoded = createExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an undefined for "name"', () => { + const payload = getCreateExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.name; + const decoded = createExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an undefined for "type"', () => { + const payload = getCreateExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.type; + const decoded = createExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an undefined for "list_id"', () => { + const inputPayload = getCreateExceptionListItemSchemaMock(); + // @ts-expect-error + delete inputPayload.list_id; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should pass validation when supplied an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => { + const payload = getCreateExceptionListItemSchemaMock(); + const outputPayload = getCreateExceptionListItemSchemaMock(); + delete payload.meta; + delete outputPayload.meta; + const decoded = createExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should pass validation when supplied an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => { + const inputPayload = getCreateExceptionListItemSchemaMock(); + const outputPayload = getCreateExceptionListItemSchemaMock(); + delete inputPayload.comments; + outputPayload.comments = []; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should pass validation when supplied "comments" array', () => { + const inputPayload = { + ...getCreateExceptionListItemSchemaMock(), + comments: getCreateCommentsArrayMock(), + }; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(inputPayload); + }); + + test('it should fail validation when supplied "comments" with "created_at" or "created_by" values', () => { + const inputPayload: Omit & { + comments?: CommentsArray; + } = { + ...getCreateExceptionListItemSchemaMock(), + comments: [getCommentsMock()], + }; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by,id"']); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an undefined for "entries"', () => { + const inputPayload = getCreateExceptionListItemSchemaMock(); + const outputPayload = getCreateExceptionListItemSchemaMock(); + // @ts-expect-error + delete inputPayload.entries; + outputPayload.entries = []; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should pass validation when supplied an undefined for "namespace_type" but return enum "single" and generate a correct body not counting the auto generated uuid', () => { + const inputPayload = getCreateExceptionListItemSchemaMock(); + const outputPayload = getCreateExceptionListItemSchemaMock(); + delete inputPayload.namespace_type; + outputPayload.namespace_type = 'single'; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should pass validation when supplied an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => { + const inputPayload = getCreateExceptionListItemSchemaMock(); + const outputPayload = getCreateExceptionListItemSchemaMock(); + delete inputPayload.tags; + outputPayload.tags = []; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should pass validation when supplied an undefined for "item_id" and auto generate a uuid', () => { + const inputPayload = getCreateExceptionListItemSchemaMock(); + delete inputPayload.item_id; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect((message.schema as CreateExceptionListItemSchema).item_id).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i + ); + }); + + test('it should pass validation when supplied an undefined for "item_id" and generate a correct body not counting the uuid', () => { + const inputPayload = getCreateExceptionListItemSchemaMock(); + delete inputPayload.item_id; + const decoded = createExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListItemSchema).item_id; + expect(message.schema).toEqual(inputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: CreateExceptionListItemSchema & { + extraKey?: string; + } = getCreateExceptionListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = createExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.ts new file mode 100644 index 0000000000000..9276a0dafa8b5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_item_schema/index.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { DefaultUuid } from '@kbn/securitysolution-io-ts-types'; + +import { DefaultCreateCommentsArray } from '../../common/default_create_comments_array'; +import { CreateCommentsArray } from '../../common/create_comment'; +import { Tags, tags } from '../../common/tags'; +import { ItemId } from '../../common/item_id'; +import { EntriesArray } from '../../common/entries'; +import { NamespaceType } from '../../common/default_namespace'; +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { description } from '../../common/description'; +import { list_id } from '../../common/list_id'; +import { name } from '../../common/name'; +import { exceptionListItemType } from '../../common/exception_list_item_type'; +import { meta } from '../../common/meta'; +import { namespace_type } from '../../common/namespace_type'; +import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; +import { ExpireTimeOrUndefined, expireTimeOrUndefined } from '../../common'; + +export const createExceptionListItemSchema = t.intersection([ + t.exact( + t.type({ + description, + entries: nonEmptyEntriesArray, + list_id, + name, + type: exceptionListItemType, + }) + ), + t.exact( + t.partial({ + comments: DefaultCreateCommentsArray, // defaults to empty array if not set during decode + expire_time: expireTimeOrUndefined, + item_id: DefaultUuid, // defaults to GUID (uuid v4) if not set during decode + meta, // defaults to undefined if not set during decode + namespace_type, // defaults to 'single' if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + }) + ), +]); + +export type CreateExceptionListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type CreateExceptionListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments' | 'expire_time' +> & { + comments: CreateCommentsArray; + expire_time: ExpireTimeOrUndefined; + tags: Tags; + item_id: ItemId; + entries: EntriesArray; + namespace_type: NamespaceType; + os_types: OsTypeArray; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..2110a0056f0c4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.mock.ts @@ -0,0 +1,59 @@ +/* + * 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. + */ + +import { + DESCRIPTION, + ENDPOINT_TYPE, + LIST_ID, + META, + NAME, + NAMESPACE_TYPE, + VERSION, +} from '../../constants/index.mock'; + +import { CreateExceptionListSchema } from '.'; + +export const getCreateExceptionListSchemaMock = (): CreateExceptionListSchema => ({ + description: DESCRIPTION, + list_id: undefined, + meta: META, + name: NAME, + namespace_type: NAMESPACE_TYPE, + os_types: [], + tags: [], + type: ENDPOINT_TYPE, + version: VERSION, +}); + +/** + * Useful for end to end testing + */ +export const getCreateExceptionListMinimalSchemaMock = (): CreateExceptionListSchema => ({ + description: DESCRIPTION, + list_id: LIST_ID, + name: NAME, + type: ENDPOINT_TYPE, +}); + +/** + * Useful for end to end testing + */ +export const getCreateExceptionListMinimalSchemaMockWithoutId = (): CreateExceptionListSchema => ({ + description: DESCRIPTION, + name: NAME, + type: ENDPOINT_TYPE, +}); + +/** + * Useful for end to end testing with detections + */ +export const getCreateExceptionListDetectionSchemaMock = (): CreateExceptionListSchema => ({ + description: DESCRIPTION, + list_id: LIST_ID, + name: NAME, + type: 'detection', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..26399804591e2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.test.ts @@ -0,0 +1,83 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { CreateExceptionListSchema, createExceptionListSchema } from '.'; +import { getCreateExceptionListSchemaMock } from './index.mock'; + +describe('create_exception_list_schema', () => { + test('it should validate a typical exception lists request and generate a correct body not counting the uuid', () => { + const payload = getCreateExceptionListSchemaMock(); + const decoded = createExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListSchema).list_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "meta" and generate a correct body not counting the uuid', () => { + const payload = getCreateExceptionListSchemaMock(); + delete payload.meta; + const decoded = createExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListSchema).list_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "tags" but return an array and generate a correct body not counting the uuid', () => { + const inputPayload = getCreateExceptionListSchemaMock(); + const outputPayload = getCreateExceptionListSchemaMock(); + delete inputPayload.tags; + outputPayload.tags = []; + const decoded = createExceptionListSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListSchema).list_id; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "list_id" and auto generate a uuid', () => { + const inputPayload = getCreateExceptionListSchemaMock(); + delete inputPayload.list_id; + const decoded = createExceptionListSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect((message.schema as CreateExceptionListSchema).list_id).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i + ); + }); + + test('it should accept an undefined for "list_id" and generate a correct body not counting the uuid', () => { + const inputPayload = getCreateExceptionListSchemaMock(); + delete inputPayload.list_id; + const decoded = createExceptionListSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as CreateExceptionListSchema).list_id; + expect(message.schema).toEqual(inputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: CreateExceptionListSchema & { + extraKey?: string; + } = getCreateExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = createExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.ts new file mode 100644 index 0000000000000..000b4c65a01f4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_exception_list_schema/index.ts @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { + DefaultUuid, + DefaultVersionNumber, + DefaultVersionNumberDecoded, +} from '@kbn/securitysolution-io-ts-types'; + +import { exceptionListType } from '../../common/exception_list'; +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { Tags, tags } from '../../common/tags'; +import { ListId } from '../../common/list_id'; +import { NamespaceType } from '../../common/default_namespace'; +import { name } from '../../common/name'; +import { description } from '../../common/description'; +import { namespace_type } from '../../common/namespace_type'; +import { meta } from '../../common/meta'; + +export const createExceptionListSchema = t.intersection([ + t.exact( + t.type({ + description, + name, + type: exceptionListType, + }) + ), + t.exact( + t.partial({ + list_id: DefaultUuid, // defaults to a GUID (UUID v4) string if not set during decode + meta, // defaults to undefined if not set during decode + namespace_type, // defaults to 'single' if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + version: DefaultVersionNumber, // defaults to numerical 1 if not set during decode + }) + ), +]); + +export type CreateExceptionListSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type CreateExceptionListSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'tags' | 'list_id' | 'namespace_type' | 'os_types' +> & { + tags: Tags; + list_id: ListId; + namespace_type: NamespaceType; + os_types: OsTypeArray; + version: DefaultVersionNumberDecoded; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..03085b3cfa8e7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.mock.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import { LIST_ID, LIST_ITEM_ID, META, VALUE } from '../../constants/index.mock'; + +import { CreateListItemSchema } from '.'; + +export const getCreateListItemSchemaMock = (): CreateListItemSchema => ({ + id: LIST_ITEM_ID, + list_id: LIST_ID, + meta: META, + value: VALUE, +}); + +/** + * Useful for end to end testing + */ +export const getCreateMinimalListItemSchemaMock = (): CreateListItemSchema => ({ + id: LIST_ITEM_ID, + list_id: LIST_ID, + value: VALUE, +}); + +/** + * Useful for end to end testing + */ +export const getCreateMinimalListItemSchemaMockWithoutId = (): CreateListItemSchema => ({ + list_id: LIST_ID, + value: VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..509cbdbf0465a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.test.ts @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getCreateListItemSchemaMock } from './index.mock'; +import { CreateListItemSchema, createListItemSchema } from '.'; + +describe('create_list_item_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getCreateListItemSchemaMock(); + const decoded = createListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for an id', () => { + const payload = getCreateListItemSchemaMock(); + delete payload.id; + const decoded = createListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for meta', () => { + const payload = getCreateListItemSchemaMock(); + delete payload.meta; + const decoded = createListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: CreateListItemSchema & { extraKey?: string } = getCreateListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = createListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.ts new file mode 100644 index 0000000000000..d18e7930c3eec --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_item_schema/index.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { list_id } from '../../common/list_id'; +import { value } from '../../common/value'; +import { id } from '../../common/id'; +import { meta } from '../../common/meta'; +import { refreshWithWaitFor } from '../../common/refresh'; + +export const createListItemSchema = t.intersection([ + t.exact( + t.type({ + list_id, + value, + }) + ), + t.exact(t.partial({ id, meta, refresh: refreshWithWaitFor })), +]); + +export type CreateListItemSchema = t.OutputOf; +export type CreateListItemSchemaDecoded = RequiredKeepUndefined< + t.TypeOf +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.mock.ts new file mode 100644 index 0000000000000..aa4f45d74f4ad --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.mock.ts @@ -0,0 +1,40 @@ +/* + * 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. + */ + +import { DESCRIPTION, LIST_ID, META, NAME, TYPE, VERSION } from '../../constants/index.mock'; + +import { CreateListSchema } from '.'; + +export const getCreateListSchemaMock = (): CreateListSchema => ({ + description: DESCRIPTION, + deserializer: undefined, + id: LIST_ID, + meta: META, + name: NAME, + serializer: undefined, + type: TYPE, + version: VERSION, +}); + +/** + * Useful for end to end tests and other mechanisms which want to fill in the values + */ +export const getCreateMinimalListSchemaMock = (): CreateListSchema => ({ + description: DESCRIPTION, + id: LIST_ID, + name: NAME, + type: TYPE, +}); + +/** + * Useful for end to end tests and other mechanisms which want to fill in the values + */ +export const getCreateMinimalListSchemaMockWithoutId = (): CreateListSchema => ({ + description: DESCRIPTION, + name: NAME, + type: TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.test.ts new file mode 100644 index 0000000000000..a6043addd72a1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.test.ts @@ -0,0 +1,75 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { CreateListSchema, createListSchema } from '.'; +import { getCreateListSchemaMock } from './index.mock'; + +describe('create_list_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getCreateListSchemaMock(); + const decoded = createListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for an id', () => { + const payload = getCreateListSchemaMock(); + delete payload.id; + const decoded = createListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for meta', () => { + const payload = getCreateListSchemaMock(); + delete payload.meta; + const decoded = createListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for serializer', () => { + const payload = getCreateListSchemaMock(); + delete payload.serializer; + const decoded = createListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for deserializer', () => { + const payload = getCreateListSchemaMock(); + delete payload.deserializer; + const decoded = createListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: CreateListSchema & { extraKey?: string } = getCreateListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = createListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.ts new file mode 100644 index 0000000000000..fd771d40a501c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_list_schema/index.ts @@ -0,0 +1,45 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { + DefaultVersionNumber, + DefaultVersionNumberDecoded, +} from '@kbn/securitysolution-io-ts-types'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { name } from '../../common/name'; +import { description } from '../../common/description'; +import { type } from '../../common/type'; +import { deserializer } from '../../common/deserializer'; +import { id } from '../../common/id'; +import { meta } from '../../common/meta'; +import { serializer } from '../../common/serializer'; + +export const createListSchema = t.intersection([ + t.exact( + t.type({ + description, + name, + type, + }) + ), + t.exact( + t.partial({ + deserializer, // defaults to undefined if not set during decode + id, // defaults to undefined if not set during decode + meta, // defaults to undefined if not set during decode + serializer, // defaults to undefined if not set during decode + version: DefaultVersionNumber, // defaults to a numerical 1 if not set during decode + }) + ), +]); + +export type CreateListSchema = t.OutputOf; +export type CreateListSchemaDecoded = RequiredKeepUndefined< + Omit, 'version'> +> & { version: DefaultVersionNumberDecoded }; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.test.ts new file mode 100644 index 0000000000000..bd95fdd0e0866 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.test.ts @@ -0,0 +1,125 @@ +/* + * 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. + */ + +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { CreateRuleExceptionListItemSchema, createRuleExceptionListItemSchema } from '.'; +import { CreateExceptionListItemSchema } from '../create_exception_list_item_schema'; + +const getCreateExceptionListItemSchemaMock = (): CreateExceptionListItemSchema => ({ + comments: [], + description: 'some description', + entries: [ + { + field: 'host.name', + operator: 'included', + type: 'match_any', + value: ['foo', 'bar'], + }, + ], + item_id: undefined, + list_id: 'some-list-id', + name: 'some name', + namespace_type: 'single', + os_types: [], + tags: [], + type: 'simple', +}); + +describe('createRuleExceptionListItemSchema', () => { + test('empty objects do not validate', () => { + const payload = {} as CreateRuleExceptionListItemSchema; + + const decoded = createRuleExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + 'Invalid value "undefined" supplied to "entries"', + 'Invalid value "undefined" supplied to "name"', + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('items without list_id validate', () => { + const payload: CreateRuleExceptionListItemSchema = { + description: 'Exception item for rule default exception list', + entries: [ + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + name: 'Sample exception item', + type: 'simple', + }; + + const decoded = createRuleExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual( + expect.objectContaining({ + comments: [], + description: 'Exception item for rule default exception list', + entries: [ + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + name: 'Sample exception item', + os_types: [], + tags: [], + type: 'simple', + }) + ); + }); + + test('items with list_id do not validate', () => { + const payload = + getCreateExceptionListItemSchemaMock() as unknown as CreateRuleExceptionListItemSchema; + + const decoded = createRuleExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some-list-id" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('made up parameters do not validate', () => { + const payload: Partial & { madeUp: string } = { + description: 'Exception item for rule default exception list', + entries: [ + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + name: 'Sample exception item', + type: 'simple', + madeUp: 'invalid value', + }; + + const decoded = createRuleExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "madeUp"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.ts new file mode 100644 index 0000000000000..ef0446d9207a7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/create_rule_exception_item_schema/index.ts @@ -0,0 +1,71 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { DefaultUuid } from '@kbn/securitysolution-io-ts-types'; + +import { + CreateCommentsArray, + DefaultCreateCommentsArray, + description, + EntriesArray, + exceptionListItemType, + ItemId, + meta, + NamespaceType, + namespaceType, + nonEmptyEntriesArray, + OsTypeArray, + osTypeArrayOrUndefined, + Tags, + tags, + name, + ExpireTimeOrUndefined, + expireTimeOrUndefined, +} from '../../common'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; + +export const createRuleExceptionListItemSchema = t.intersection([ + t.exact( + t.type({ + description, + entries: nonEmptyEntriesArray, + name, + type: exceptionListItemType, + }) + ), + t.exact( + t.partial({ + comments: DefaultCreateCommentsArray, // defaults to empty array if not set during decode + item_id: DefaultUuid, // defaults to GUID (uuid v4) if not set during decode + list_id: t.undefined, + meta, // defaults to undefined if not set during decode + namespace_type: namespaceType, // defaults to 'single' if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + expire_time: expireTimeOrUndefined, + }) + ), +]); + +export type CreateRuleExceptionListItemSchema = t.OutputOf< + typeof createRuleExceptionListItemSchema +>; + +// This type is used after a decode since some things are defaults after a decode. +export type CreateRuleExceptionListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments' | 'expire_time' +> & { + comments: CreateCommentsArray; + tags: Tags; + item_id: ItemId; + entries: EntriesArray; + namespace_type: NamespaceType; + os_types: OsTypeArray; + expire_time: ExpireTimeOrUndefined; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..2547180e114f7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.mock.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import { ID } from '../../constants/index.mock'; + +import { DeleteEndpointListItemSchema } from '.'; + +export const getDeleteEndpointListItemSchemaMock = (): DeleteEndpointListItemSchema => ({ + id: ID, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..09697db0c5f42 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.test.ts @@ -0,0 +1,49 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { DeleteEndpointListItemSchema, deleteEndpointListItemSchema } from '.'; +import { getDeleteEndpointListItemSchemaMock } from './index.mock'; + +describe('delete_endpoint_list_item_schema', () => { + test('it should validate a typical endpoint list item request', () => { + const payload = getDeleteEndpointListItemSchemaMock(); + const decoded = deleteEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept a value for "namespace_type" since it does not require one', () => { + const payload: DeleteEndpointListItemSchema & { + namespace_type: string; + } = { ...getDeleteEndpointListItemSchemaMock(), namespace_type: 'single' }; + // @ts-expect-error + delete payload.namespace_type; + const decoded = deleteEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getDeleteEndpointListItemSchemaMock()); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: DeleteEndpointListItemSchema & { + extraKey?: string; + } = { ...getDeleteEndpointListItemSchemaMock(), extraKey: 'some new value' }; + const decoded = deleteEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.ts new file mode 100644 index 0000000000000..9825b74142382 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_endpoint_list_item_schema/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { id } from '../../common/id'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { item_id } from '../../common/item_id'; + +export const deleteEndpointListItemSchema = t.exact( + t.partial({ + id, + item_id, + }) +); + +export type DeleteEndpointListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type DeleteEndpointListItemSchemaDecoded = RequiredKeepUndefined< + t.TypeOf +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..98404e189beb7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.mock.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +import { ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { DeleteExceptionListItemSchema } from '.'; + +export const getDeleteExceptionListItemSchemaMock = (): DeleteExceptionListItemSchema => ({ + id: ID, + namespace_type: NAMESPACE_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..7131a969a795b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.test.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { DeleteExceptionListItemSchema, deleteExceptionListItemSchema } from '.'; +import { getDeleteExceptionListItemSchemaMock } from './index.mock'; + +describe('delete_exception_list_item_schema', () => { + test('it should validate a typical exception list item request', () => { + const payload = getDeleteExceptionListItemSchemaMock(); + const decoded = deleteExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "namespace_type" but default to "single"', () => { + const payload = getDeleteExceptionListItemSchemaMock(); + delete payload.namespace_type; + const decoded = deleteExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getDeleteExceptionListItemSchemaMock()); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: DeleteExceptionListItemSchema & { + extraKey?: string; + } = getDeleteExceptionListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = deleteExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.ts new file mode 100644 index 0000000000000..02bcd800712ea --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_item_schema/index.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NamespaceType } from '../../common/default_namespace'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { item_id } from '../../common/item_id'; +import { namespace_type } from '../../common/namespace_type'; + +export const deleteExceptionListItemSchema = t.exact( + t.partial({ + id, + item_id, + namespace_type, // defaults to 'single' if not set during decode + }) +); + +export type DeleteExceptionListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type DeleteExceptionListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'namespace_type' +> & { + namespace_type: NamespaceType; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..7eca83a9d7135 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.mock.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +import { ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { DeleteExceptionListSchema } from '.'; + +export const getDeleteExceptionListSchemaMock = (): DeleteExceptionListSchema => ({ + id: ID, + namespace_type: NAMESPACE_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..a439ac0403225 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.test.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { DeleteExceptionListSchema, deleteExceptionListSchema } from '.'; +import { getDeleteExceptionListSchemaMock } from './index.mock'; + +describe('delete_exception_list_schema', () => { + test('it should validate a typical exception list request', () => { + const payload = getDeleteExceptionListSchemaMock(); + const decoded = deleteExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "namespace_type" but default to "single"', () => { + const payload = getDeleteExceptionListSchemaMock(); + delete payload.namespace_type; + const decoded = deleteExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getDeleteExceptionListSchemaMock()); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: DeleteExceptionListSchema & { + extraKey?: string; + } = getDeleteExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = deleteExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.ts new file mode 100644 index 0000000000000..1c04c0fdc17aa --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_exception_list_schema/index.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NamespaceType } from '../../common/default_namespace'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { list_id } from '../../common/list_id'; +import { namespace_type } from '../../common/namespace_type'; + +export const deleteExceptionListSchema = t.exact( + t.partial({ + id, + list_id, + namespace_type, // defaults to 'single' if not set during decode + }) +); + +export type DeleteExceptionListSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type DeleteExceptionListSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'namespace_type' +> & { + namespace_type: NamespaceType; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..ef4ff721119a6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { ID, LIST_ID, VALUE } from '../../constants/index.mock'; + +import { DeleteListItemSchema } from '.'; + +export const getDeleteListItemSchemaMock = (): DeleteListItemSchema => ({ + id: ID, + list_id: LIST_ID, + value: VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..07db295d3ef2d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.test.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { DeleteListItemSchema, deleteListItemSchema } from '.'; +import { getDeleteListItemSchemaMock } from './index.mock'; + +describe('delete_list_item_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getDeleteListItemSchemaMock(); + const decoded = deleteListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: DeleteListItemSchema & { + extraKey?: string; + } = { ...getDeleteListItemSchemaMock(), extraKey: 'some new value' }; + const decoded = deleteListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.ts new file mode 100644 index 0000000000000..4b9ef67630142 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_item_schema/index.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { list_id } from '../../common/list_id'; +import { valueOrUndefined } from '../../common/value'; +import { refresh } from '../../common/refresh'; + +export const deleteListItemSchema = t.intersection([ + t.exact( + t.type({ + value: valueOrUndefined, + }) + ), + t.exact(t.partial({ id, list_id, refresh })), +]); + +export type DeleteListItemSchema = t.OutputOf; +export type DeleteListItemSchemaDecoded = RequiredKeepUndefined< + t.TypeOf +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.mock.ts new file mode 100644 index 0000000000000..19b7a2aa15b94 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { LIST_ID } from '../../constants/index.mock'; + +import { DeleteListSchema } from '.'; + +export const getDeleteListSchemaMock = (): DeleteListSchema => ({ + deleteReferences: false, + id: LIST_ID, + ignoreReferences: true, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.test.ts new file mode 100644 index 0000000000000..5077c0795df34 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.test.ts @@ -0,0 +1,46 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { DeleteListSchema, deleteListSchema } from '.'; +import { getDeleteListSchemaMock } from './index.mock'; + +describe('delete_list_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getDeleteListSchemaMock(); + const decoded = deleteListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for an id', () => { + const payload = getDeleteListSchemaMock(); + // @ts-expect-error + delete payload.id; + const decoded = deleteListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: DeleteListSchema & { extraKey?: string } = getDeleteListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = deleteListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.ts new file mode 100644 index 0000000000000..da1d252d9e368 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/delete_list_schema/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { DefaultStringBooleanFalse } from '@kbn/securitysolution-io-ts-types'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; + +export const deleteListSchema = t.intersection([ + t.exact( + t.type({ + id, + }) + ), + t.exact( + t.partial({ + deleteReferences: DefaultStringBooleanFalse, + ignoreReferences: DefaultStringBooleanFalse, + }) + ), +]); + +export type DeleteListSchema = RequiredKeepUndefined>; +export type DeleteListSchemaEncoded = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.mock.ts new file mode 100644 index 0000000000000..d3f9b59d5cf0e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { DuplicateExceptionListQuerySchema } from '.'; + +export const getDuplicateExceptionListQuerySchemaMock = (): DuplicateExceptionListQuerySchema => ({ + list_id: LIST_ID, + namespace_type: NAMESPACE_TYPE, + include_expired_exceptions: 'true', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.test.ts new file mode 100644 index 0000000000000..73762793e3d2f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.test.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { DuplicateExceptionListQuerySchema, duplicateExceptionListQuerySchema } from '.'; +import { getDuplicateExceptionListQuerySchemaMock } from './index.mock'; + +describe('duplicate_exceptionList_query_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getDuplicateExceptionListQuerySchemaMock(); + const decoded = duplicateExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should default namespace_type to "single" if an undefined given for namespacetype', () => { + const payload = getDuplicateExceptionListQuerySchemaMock(); + delete payload.namespace_type; + const decoded = duplicateExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(message.schema).toEqual({ + include_expired_exceptions: 'true', + list_id: 'some-list-id', + namespace_type: 'single', + }); + }); + + test('it should NOT accept an undefined for an list_id', () => { + const payload = getDuplicateExceptionListQuerySchemaMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = duplicateExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: DuplicateExceptionListQuerySchema & { + extraKey?: string; + } = getDuplicateExceptionListQuerySchemaMock(); + payload.extraKey = 'some new value'; + const decoded = duplicateExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.ts new file mode 100644 index 0000000000000..2a90eb4aeb05a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/duplicate_exception_list_query_schema/index.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { NamespaceType } from '../../common'; + +import { includeExpiredExceptionsOrUndefined } from '../../common/include_expired_exceptions'; +import { list_id } from '../../common/list_id'; +import { namespace_type } from '../../common/namespace_type'; + +export const duplicateExceptionListQuerySchema = t.exact( + t.type({ + list_id, + namespace_type, + include_expired_exceptions: includeExpiredExceptionsOrUndefined, + }) +); + +export type DuplicateExceptionListQuerySchema = t.OutputOf< + typeof duplicateExceptionListQuerySchema +>; + +// This type is used after a decode since some things are defaults after a decode. +export type DuplicateExceptionListQuerySchemaDecoded = Omit< + t.TypeOf, + 'namespace_type' +> & { + namespace_type: NamespaceType; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.mock.ts new file mode 100644 index 0000000000000..2b1d6a439064e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.mock.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import { ID, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { ExportExceptionListQuerySchema } from '.'; + +export const getExportExceptionListQuerySchemaMock = (): ExportExceptionListQuerySchema => ({ + id: ID, + list_id: LIST_ID, + namespace_type: NAMESPACE_TYPE, + include_expired_exceptions: 'true', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.test.ts new file mode 100644 index 0000000000000..dea087dca36d8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.test.ts @@ -0,0 +1,78 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { ExportExceptionListQuerySchema, exportExceptionListQuerySchema } from '.'; +import { getExportExceptionListQuerySchemaMock } from './index.mock'; + +describe('export_exception_list_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getExportExceptionListQuerySchemaMock(); + const decoded = exportExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for an id', () => { + const payload = getExportExceptionListQuerySchemaMock(); + // @ts-expect-error + delete payload.id; + const decoded = exportExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should default namespace_type to "single" if an undefined given for namespacetype', () => { + const payload = getExportExceptionListQuerySchemaMock(); + delete payload.namespace_type; + const decoded = exportExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(message.schema).toEqual({ + id: 'uuid_here', + include_expired_exceptions: 'true', + list_id: 'some-list-id', + namespace_type: 'single', + }); + }); + + test('it should NOT accept an undefined for an list_id', () => { + const payload = getExportExceptionListQuerySchemaMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = exportExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ExportExceptionListQuerySchema & { + extraKey?: string; + } = getExportExceptionListQuerySchemaMock(); + payload.extraKey = 'some new value'; + const decoded = exportExceptionListQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.ts new file mode 100644 index 0000000000000..8967e45c5a61e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_exception_list_query_schema/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { id } from '../../common/id'; +import { includeExpiredExceptionsOrUndefined } from '../../common/include_expired_exceptions'; +import { list_id } from '../../common/list_id'; +import { namespace_type } from '../../common/namespace_type'; + +export const exportExceptionListQuerySchema = t.exact( + t.type({ + id, + list_id, + namespace_type, + include_expired_exceptions: includeExpiredExceptionsOrUndefined, + // TODO: Add file_name here with a default value + }) +); + +export type ExportExceptionListQuerySchema = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.mock.ts new file mode 100644 index 0000000000000..85076f592d16e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.mock.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import { LIST_ID } from '../../constants/index.mock'; + +import { ExportListItemQuerySchema } from '.'; + +export const getExportListItemQuerySchemaMock = (): ExportListItemQuerySchema => ({ + list_id: LIST_ID, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.test.ts new file mode 100644 index 0000000000000..f05e530cbb415 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.test.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { ExportListItemQuerySchema, exportListItemQuerySchema } from '.'; +import { getExportListItemQuerySchemaMock } from './index.mock'; + +describe('export_list_item_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getExportListItemQuerySchemaMock(); + const decoded = exportListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for an id', () => { + const payload = getExportListItemQuerySchemaMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = exportListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ExportListItemQuerySchema & { + extraKey?: string; + } = getExportListItemQuerySchemaMock(); + payload.extraKey = 'some new value'; + const decoded = exportListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.ts new file mode 100644 index 0000000000000..a07e6c73434e5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/export_list_item_query_schema/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { list_id } from '../../common/list_id'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; + +export const exportListItemQuerySchema = t.exact( + t.type({ + list_id, + // TODO: Add file_name here with a default value + }) +); + +export type ExportListItemQuerySchema = RequiredKeepUndefined< + t.TypeOf +>; +export type ExportListItemQuerySchemaEncoded = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..5df0322cc803f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.mock.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import { FILTER } from '../../constants/index.mock'; + +import { FindEndpointListItemSchema, FindEndpointListItemSchemaDecoded } from '.'; + +export const getFindEndpointListItemSchemaMock = (): FindEndpointListItemSchema => ({ + filter: FILTER, + page: '1', + per_page: '25', + sort_field: undefined, + sort_order: undefined, +}); + +export const getFindEndpointListItemSchemaDecodedMock = (): FindEndpointListItemSchemaDecoded => ({ + filter: FILTER, + page: 1, + per_page: 25, + sort_field: undefined, + sort_order: undefined, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..1ce9618781c46 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.test.ts @@ -0,0 +1,107 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { + getFindEndpointListItemSchemaDecodedMock, + getFindEndpointListItemSchemaMock, +} from './index.mock'; +import { FindEndpointListItemSchema, findEndpointListItemSchema } from '.'; + +describe('find_endpoint_list_item_schema', () => { + test('it should validate a typical find item request', () => { + const payload = getFindEndpointListItemSchemaMock(); + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getFindEndpointListItemSchemaDecodedMock()); + }); + + test('it should validate and empty object since everything is optional and has defaults', () => { + const payload: FindEndpointListItemSchema = {}; + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate with page missing', () => { + const payload = getFindEndpointListItemSchemaMock(); + delete payload.page; + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindEndpointListItemSchemaDecodedMock(); + delete expected.page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with pre_page missing', () => { + const payload = getFindEndpointListItemSchemaMock(); + delete payload.per_page; + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindEndpointListItemSchemaDecodedMock(); + delete expected.per_page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with filter missing', () => { + const payload = getFindEndpointListItemSchemaMock(); + delete payload.filter; + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindEndpointListItemSchemaDecodedMock(); + delete expected.filter; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_field missing', () => { + const payload = getFindEndpointListItemSchemaMock(); + delete payload.sort_field; + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindEndpointListItemSchemaDecodedMock(); + delete expected.sort_field; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_order missing', () => { + const payload = getFindEndpointListItemSchemaMock(); + delete payload.sort_order; + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindEndpointListItemSchemaDecodedMock(); + delete expected.sort_order; + expect(message.schema).toEqual(expected); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: FindEndpointListItemSchema & { + extraKey: string; + } = { ...getFindEndpointListItemSchemaMock(), extraKey: 'some new value' }; + const decoded = findEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.ts new file mode 100644 index 0000000000000..05f32f452f5d9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_endpoint_list_item_schema/index.ts @@ -0,0 +1,31 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { filter } from '../../common/filter'; +import { sort_field } from '../../common/sort_field'; +import { sort_order } from '../../common/sort_order'; + +export const findEndpointListItemSchema = t.exact( + t.partial({ + filter, // defaults to undefined if not set during decode + page: StringToPositiveNumber, // defaults to undefined if not set during decode + per_page: StringToPositiveNumber, // defaults to undefined if not set during decode + sort_field, // defaults to undefined if not set during decode + sort_order, // defaults to undefined if not set during decode + }) +); + +export type FindEndpointListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type FindEndpointListItemSchemaDecoded = RequiredKeepUndefined< + t.TypeOf +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..16b2ee7a8a370 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import { FILTER, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { FindExceptionListItemSchema, FindExceptionListItemSchemaDecoded } from '.'; + +export const getFindExceptionListItemSchemaMock = (): FindExceptionListItemSchema => ({ + filter: FILTER, + list_id: LIST_ID, + namespace_type: NAMESPACE_TYPE, + page: '1', + per_page: '25', + search: undefined, + sort_field: undefined, + sort_order: undefined, +}); + +export const getFindExceptionListItemSchemaMultipleMock = (): FindExceptionListItemSchema => ({ + filter: 'name:Sofia Kovalevskaya,name:Hypatia,name:Sophie Germain', + list_id: 'list-1,list-2,list-3', + namespace_type: 'single,single,agnostic', + page: '1', + per_page: '25', + search: undefined, + sort_field: undefined, + sort_order: undefined, +}); + +export const getFindExceptionListItemSchemaDecodedMock = + (): FindExceptionListItemSchemaDecoded => ({ + filter: [FILTER], + list_id: [LIST_ID], + namespace_type: [NAMESPACE_TYPE], + page: 1, + per_page: 25, + search: undefined, + sort_field: undefined, + sort_order: undefined, + }); + +export const getFindExceptionListItemSchemaDecodedMultipleMock = + (): FindExceptionListItemSchemaDecoded => ({ + filter: ['name:Sofia Kovalevskaya', 'name:Hypatia', 'name:Sophie Germain'], + list_id: ['list-1', 'list-2', 'list-3'], + namespace_type: ['single', 'single', 'agnostic'], + page: 1, + per_page: 25, + search: undefined, + sort_field: undefined, + sort_order: undefined, + }); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..1d66969333212 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts @@ -0,0 +1,148 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { LIST_ID } from '../../constants/index.mock'; + +import { + getFindExceptionListItemSchemaDecodedMock, + getFindExceptionListItemSchemaDecodedMultipleMock, + getFindExceptionListItemSchemaMock, + getFindExceptionListItemSchemaMultipleMock, +} from './index.mock'; +import { + FindExceptionListItemSchema, + FindExceptionListItemSchemaDecoded, + findExceptionListItemSchema, +} from '.'; + +describe('find_list_item_schema', () => { + test('it should validate a typical find item request', () => { + const payload = getFindExceptionListItemSchemaMock(); + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getFindExceptionListItemSchemaDecodedMock()); + }); + + test('it should validate a typical find item request with multiple input strings turned into array elements', () => { + const payload = getFindExceptionListItemSchemaMultipleMock(); + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getFindExceptionListItemSchemaDecodedMultipleMock()); + }); + + test('it should validate just a list_id where it decodes into an array for list_id and adds a namespace_type of "single" as an array', () => { + const payload: FindExceptionListItemSchema = { list_id: LIST_ID }; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected: FindExceptionListItemSchemaDecoded = { + filter: [], + list_id: [LIST_ID], + namespace_type: ['single'], + page: undefined, + per_page: undefined, + search: undefined, + sort_field: undefined, + sort_order: undefined, + }; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with page missing', () => { + const payload = getFindExceptionListItemSchemaMock(); + delete payload.page; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListItemSchemaDecodedMock(); + delete expected.page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with per_page missing', () => { + const payload = getFindExceptionListItemSchemaMock(); + delete payload.per_page; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListItemSchemaDecodedMock(); + delete expected.per_page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with filter missing and add filter as an empty array', () => { + const payload = getFindExceptionListItemSchemaMock(); + delete payload.filter; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected: FindExceptionListItemSchemaDecoded = { + ...getFindExceptionListItemSchemaDecodedMock(), + filter: [], + }; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_field missing', () => { + const payload = getFindExceptionListItemSchemaMock(); + delete payload.sort_field; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListItemSchemaDecodedMock(); + delete expected.sort_field; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_order missing', () => { + const payload = getFindExceptionListItemSchemaMock(); + delete payload.sort_order; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListItemSchemaDecodedMock(); + delete expected.sort_order; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with search missing', () => { + const payload = getFindExceptionListItemSchemaMock(); + delete payload.search; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListItemSchemaDecodedMock(); + delete expected.search; + expect(message.schema).toEqual(expected); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: FindExceptionListItemSchema & { + extraKey: string; + } = { ...getFindExceptionListItemSchemaMock(), extraKey: 'some new value' }; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts new file mode 100644 index 0000000000000..7177a7144c7fb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { + EmptyStringArray, + EmptyStringArrayDecoded, + NonEmptyStringArray, + StringToPositiveNumber, +} from '@kbn/securitysolution-io-ts-types'; + +import { + DefaultNamespaceArray, + DefaultNamespaceArrayTypeDecoded, +} from '../../common/default_namespace_array'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { sort_field } from '../../common/sort_field'; +import { sort_order } from '../../common/sort_order'; +import { search } from '../../common/search'; + +export const findExceptionListItemSchema = t.intersection([ + t.exact( + t.type({ + list_id: NonEmptyStringArray, + }) + ), + t.exact( + t.partial({ + filter: EmptyStringArray, // defaults to an empty array [] if not set during decode + namespace_type: DefaultNamespaceArray, // defaults to ['single'] if not set during decode + page: StringToPositiveNumber, // defaults to undefined if not set during decode + per_page: StringToPositiveNumber, // defaults to undefined if not set during decode + search, + sort_field, // defaults to undefined if not set during decode + sort_order, // defaults to undefined if not set during decode + }) + ), +]); + +export type FindExceptionListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type FindExceptionListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'namespace_type' | 'filter' +> & { + filter: EmptyStringArrayDecoded; + namespace_type: DefaultNamespaceArrayTypeDecoded; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..f963c6650cf29 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.mock.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import { FILTER, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { FindExceptionListSchema, FindExceptionListSchemaDecoded } from '.'; + +export const getFindExceptionListSchemaMock = (): FindExceptionListSchema => ({ + filter: FILTER, + namespace_type: NAMESPACE_TYPE, + page: '1', + per_page: '25', + sort_field: undefined, + sort_order: undefined, +}); + +export const getFindExceptionListSchemaDecodedMock = (): FindExceptionListSchemaDecoded => ({ + filter: FILTER, + namespace_type: [NAMESPACE_TYPE], + page: 1, + per_page: 25, + sort_field: undefined, + sort_order: undefined, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..8669a3657f025 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.test.ts @@ -0,0 +1,119 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { + getFindExceptionListSchemaDecodedMock, + getFindExceptionListSchemaMock, +} from './index.mock'; +import { + FindExceptionListSchema, + FindExceptionListSchemaDecoded, + findExceptionListSchema, +} from '.'; + +describe('find_exception_list_schema', () => { + test('it should validate a typical find item request', () => { + const payload = getFindExceptionListSchemaMock(); + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getFindExceptionListSchemaDecodedMock()); + }); + + test('it should validate and empty object since everything is optional and will respond only with namespace_type filled out to be "single"', () => { + const payload: FindExceptionListSchema = {}; + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected: FindExceptionListSchemaDecoded = { + filter: undefined, + namespace_type: ['single'], + page: undefined, + per_page: undefined, + sort_field: undefined, + sort_order: undefined, + }; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with page missing', () => { + const payload = getFindExceptionListSchemaMock(); + delete payload.page; + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListSchemaDecodedMock(); + delete expected.page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with pre_page missing', () => { + const payload = getFindExceptionListSchemaMock(); + delete payload.per_page; + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListSchemaDecodedMock(); + delete expected.per_page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with filter missing', () => { + const payload = getFindExceptionListSchemaMock(); + delete payload.filter; + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListSchemaDecodedMock(); + delete expected.filter; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_field missing', () => { + const payload = getFindExceptionListSchemaMock(); + delete payload.sort_field; + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListSchemaDecodedMock(); + delete expected.sort_field; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_order missing', () => { + const payload = getFindExceptionListSchemaMock(); + delete payload.sort_order; + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListSchemaDecodedMock(); + delete expected.sort_order; + expect(message.schema).toEqual(expected); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: FindExceptionListSchema & { + extraKey: string; + } = { ...getFindExceptionListSchemaMock(), extraKey: 'some new value' }; + const decoded = findExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.ts new file mode 100644 index 0000000000000..dc9acdefd7a97 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_schema/index.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; + +import { DefaultNamespaceArray, NamespaceTypeArray } from '../../common/default_namespace_array'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { filter } from '../../common/filter'; +import { sort_field } from '../../common/sort_field'; +import { sort_order } from '../../common/sort_order'; + +export const findExceptionListSchema = t.exact( + t.partial({ + filter, // defaults to undefined if not set during decode + namespace_type: DefaultNamespaceArray, // defaults to 'single' if not set during decode + page: StringToPositiveNumber, // defaults to undefined if not set during decode + per_page: StringToPositiveNumber, // defaults to undefined if not set during decode + sort_field, // defaults to undefined if not set during decode + sort_order, // defaults to undefined if not set during decode + }) +); + +export type FindExceptionListSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type FindExceptionListSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'namespace_type' +> & { + namespace_type: NamespaceTypeArray; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..44c952a9a3827 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.mock.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import { CURSOR, FILTER, LIST_ID } from '../../constants/index.mock'; + +import { FindListItemSchema, FindListItemSchemaDecoded } from '.'; + +export const getFindListItemSchemaMock = (): FindListItemSchema => ({ + cursor: CURSOR, + filter: FILTER, + list_id: LIST_ID, + page: '1', + per_page: '25', + sort_field: undefined, + sort_order: undefined, +}); + +export const getFindListItemSchemaDecodedMock = (): FindListItemSchemaDecoded => ({ + cursor: CURSOR, + filter: FILTER, + list_id: LIST_ID, + page: 1, + per_page: 25, + sort_field: undefined, + sort_order: undefined, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..589a40f641c67 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.test.ts @@ -0,0 +1,103 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { LIST_ID } from '../../constants/index.mock'; + +import { FindListItemSchema, FindListItemSchemaDecoded, findListItemSchema } from '.'; +import { getFindListItemSchemaDecodedMock, getFindListItemSchemaMock } from './index.mock'; + +describe('find_list_item_schema', () => { + test('it should validate a typical find item request', () => { + const payload = getFindListItemSchemaMock(); + const decoded = findListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getFindListItemSchemaDecodedMock()); + }); + + test('it should validate just a list_id where it decodes into an array for list_id and adds a namespace_type of "single"', () => { + const payload: FindListItemSchema = { list_id: LIST_ID }; + const decoded = findListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected: FindListItemSchemaDecoded = { + cursor: undefined, + filter: undefined, + list_id: LIST_ID, + page: undefined, + per_page: undefined, + sort_field: undefined, + sort_order: undefined, + }; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with page missing', () => { + const payload = getFindListItemSchemaMock(); + delete payload.page; + const decoded = findListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListItemSchemaDecodedMock(); + delete expected.page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with pre_page missing', () => { + const payload = getFindListItemSchemaMock(); + delete payload.per_page; + const decoded = findListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListItemSchemaDecodedMock(); + delete expected.per_page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_field missing', () => { + const payload = getFindListItemSchemaMock(); + delete payload.sort_field; + const decoded = findListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListItemSchemaDecodedMock(); + delete expected.sort_field; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_order missing', () => { + const payload = getFindListItemSchemaMock(); + delete payload.sort_order; + const decoded = findListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListItemSchemaDecodedMock(); + delete expected.sort_order; + expect(message.schema).toEqual(expected); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: FindListItemSchema & { + extraKey: string; + } = { ...getFindListItemSchemaMock(), extraKey: 'some new value' }; + const decoded = findListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.ts new file mode 100644 index 0000000000000..4279d5ef4a07f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_item_schema/index.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; +import { filter } from '../../common/filter'; +import { cursor } from '../../common/cursor'; +import { sort_field } from '../../common/sort_field'; +import { sort_order } from '../../common/sort_order'; +import { list_id } from '../../common/list_id'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; + +export const findListItemSchema = t.intersection([ + t.exact(t.type({ list_id })), + t.exact( + t.partial({ + cursor, // defaults to undefined if not set during decode + filter, // defaults to undefined if not set during decode + page: StringToPositiveNumber, // defaults to undefined if not set during decode + per_page: StringToPositiveNumber, // defaults to undefined if not set during decode + sort_field, // defaults to undefined if not set during decode + sort_order, // defaults to undefined if not set during decode + }) + ), +]); + +export type FindListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type FindListItemSchemaDecoded = RequiredKeepUndefined>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.mock.ts new file mode 100644 index 0000000000000..b80369fb6b432 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.mock.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +import { FILTER } from '../../constants/index.mock'; + +import { FindListSchema, FindListSchemaEncoded } from '.'; + +export const getFindListSchemaMock = (): FindListSchemaEncoded => ({ + filter: FILTER, + page: '1', + per_page: '25', + sort_field: undefined, + sort_order: undefined, +}); + +export const getFindListSchemaDecodedMock = (): FindListSchema => ({ + cursor: undefined, + filter: FILTER, + page: 1, + per_page: 25, + sort_field: undefined, + sort_order: undefined, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.test.ts new file mode 100644 index 0000000000000..06b37bacf8452 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.test.ts @@ -0,0 +1,104 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getFindListSchemaDecodedMock, getFindListSchemaMock } from './index.mock'; +import { FindListSchemaEncoded, findListSchema } from '.'; + +describe('find_list_schema', () => { + test('it should validate a typical find item request', () => { + const payload = getFindListSchemaMock(); + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getFindListSchemaDecodedMock()); + }); + + test('it should validate and empty object since everything is optional and will respond with an empty object', () => { + const payload: FindListSchemaEncoded = {}; + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should validate with page missing', () => { + const payload = getFindListSchemaMock(); + delete payload.page; + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListSchemaDecodedMock(); + delete expected.page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with pre_page missing', () => { + const payload = getFindListSchemaMock(); + delete payload.per_page; + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListSchemaDecodedMock(); + delete expected.per_page; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with filter missing', () => { + const payload = getFindListSchemaMock(); + delete payload.filter; + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListSchemaDecodedMock(); + delete expected.filter; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_field missing', () => { + const payload = getFindListSchemaMock(); + delete payload.sort_field; + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListSchemaDecodedMock(); + delete expected.sort_field; + expect(message.schema).toEqual(expected); + }); + + test('it should validate with sort_order missing', () => { + const payload = getFindListSchemaMock(); + delete payload.sort_order; + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindListSchemaDecodedMock(); + delete expected.sort_order; + expect(message.schema).toEqual(expected); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: FindListSchemaEncoded & { + extraKey: string; + } = { ...getFindListSchemaMock(), extraKey: 'some new value' }; + const decoded = findListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.ts new file mode 100644 index 0000000000000..8f1520d0caf13 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/find_list_schema/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { StringToPositiveNumber } from '@kbn/securitysolution-io-ts-types'; +import { cursor } from '../../common/cursor'; +import { filter } from '../../common/filter'; +import { sort_field } from '../../common/sort_field'; +import { sort_order } from '../../common/sort_order'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; + +export const findListSchema = t.exact( + t.partial({ + cursor, // defaults to undefined if not set during decode + filter, // defaults to undefined if not set during decode + page: StringToPositiveNumber, // defaults to undefined if not set during decode + per_page: StringToPositiveNumber, // defaults to undefined if not set during decode + sort_field, // defaults to undefined if not set during decode + sort_order, // defaults to undefined if not set during decode + }) +); + +export type FindListSchema = RequiredKeepUndefined>; +export type FindListSchemaEncoded = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/get_exception_filter_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/get_exception_filter_schema/index.ts new file mode 100644 index 0000000000000..656d6cea6164e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/get_exception_filter_schema/index.ts @@ -0,0 +1,38 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { namespaceType } from '../../common/default_namespace'; +import { exceptionListItemSchema } from '../../response'; +import { createExceptionListItemSchema } from '../create_exception_list_item_schema'; + +const exceptionListId = t.type({ + exception_list_id: t.string, + namespace_type: namespaceType, +}); + +export const exceptionListIds = t.type({ + exception_list_ids: t.array(exceptionListId), + type: t.literal('exception_list_ids'), +}); + +export const exceptions = t.type({ + exceptions: t.array(t.union([exceptionListItemSchema, createExceptionListItemSchema])), + type: t.literal('exception_items'), +}); + +const optionalExceptionParams = t.exact( + t.partial({ alias: t.string, chunk_size: t.number, exclude_exceptions: t.boolean }) +); + +export const getExceptionFilterSchema = t.intersection([ + t.union([exceptions, exceptionListIds]), + optionalExceptionParams, +]); + +export type GetExceptionFilterSchema = t.TypeOf; +export type ExceptionListId = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.mock.ts new file mode 100644 index 0000000000000..a50c455a9d60f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.mock.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import { ENTRIES } from '../../constants/index.mock'; +import { ImportExceptionListItemSchema, ImportExceptionListItemSchemaDecoded } from '.'; + +export const getImportExceptionsListItemSchemaMock = ( + itemId = 'item_id_1', + listId = 'detection_list_id' +): ImportExceptionListItemSchema => ({ + description: 'some description', + entries: ENTRIES, + item_id: itemId, + list_id: listId, + name: 'Query with a rule id', + type: 'simple', +}); + +export const getImportExceptionsListItemSchemaDecodedMock = ( + itemId = 'item_id_1', + listId = 'detection_list_id' +): ImportExceptionListItemSchemaDecoded => ({ + ...getImportExceptionsListItemSchemaMock(itemId, listId), + comments: [], + meta: undefined, + namespace_type: 'single', + os_types: [], + tags: [], + expire_time: undefined, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts new file mode 100644 index 0000000000000..61e135bfd59a6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts @@ -0,0 +1,172 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { importExceptionListItemSchema, ImportExceptionListItemSchema } from '.'; +import { + getImportExceptionsListItemSchemaDecodedMock, + getImportExceptionsListItemSchemaMock, +} from './index.mock'; +import { getCommentsArrayMock } from '../../common/comment/index.mock'; + +describe('import_list_item_schema', () => { + test('it should validate a typical item request', () => { + const payload = getImportExceptionsListItemSchemaMock(); + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getImportExceptionsListItemSchemaDecodedMock()); + }); + + test('it should validate a typical item request with comments', () => { + const payload = { + ...getImportExceptionsListItemSchemaMock(), + comments: getCommentsArrayMock(), + }; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual({ + ...getImportExceptionsListItemSchemaDecodedMock(), + comments: [ + { + comment: 'some old comment', + created_at: '2020-04-20T15:25:31.830Z', + created_by: 'some user', + id: 'uuid_here', + }, + { + comment: 'some old comment', + created_at: '2020-04-20T15:25:31.830Z', + created_by: 'some user', + id: 'uuid_here', + }, + ], + }); + }); + + test('it should NOT accept an undefined for "item_id"', () => { + const payload: Partial> = + getImportExceptionsListItemSchemaMock(); + delete payload.item_id; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "item_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "list_id"', () => { + const payload: Partial> = + getImportExceptionsListItemSchemaMock(); + delete payload.list_id; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "description"', () => { + const payload: Partial> = + getImportExceptionsListItemSchemaMock(); + delete payload.description; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "name"', () => { + const payload: Partial> = + getImportExceptionsListItemSchemaMock(); + delete payload.name; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "type"', () => { + const payload: Partial> = + getImportExceptionsListItemSchemaMock(); + delete payload.type; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "entries"', () => { + const payload: Partial> = + getImportExceptionsListItemSchemaMock(); + delete payload.entries; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept any partial fields', () => { + const payload: ImportExceptionListItemSchema = { + ...getImportExceptionsListItemSchemaMock(), + id: '123', + namespace_type: 'single', + comments: [], + os_types: [], + tags: ['123'], + created_at: '2018-08-24T17:49:30.145142000', + created_by: 'elastic', + updated_at: '2018-08-24T17:49:30.145142000', + updated_by: 'elastic', + tie_breaker_id: '123', + _version: '3', + meta: undefined, + }; + + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ImportExceptionListItemSchema & { + extraKey?: string; + } = getImportExceptionsListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts new file mode 100644 index 0000000000000..a2d60e292aff5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts @@ -0,0 +1,86 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { Tags, tags } from '../../common/tags'; +import { NamespaceType } from '../../common/default_namespace'; +import { name } from '../../common/name'; +import { description } from '../../common/description'; +import { namespace_type } from '../../common/namespace_type'; +import { meta } from '../../common/meta'; +import { list_id } from '../../common/list_id'; +import { item_id, ItemId } from '../../common/item_id'; +import { id } from '../../common/id'; +import { created_at } from '../../common/created_at'; +import { created_by } from '../../common/created_by'; +import { updated_at } from '../../common/updated_at'; +import { updated_by } from '../../common/updated_by'; +import { _version } from '../../common/underscore_version'; +import { tie_breaker_id } from '../../common/tie_breaker_id'; +import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; +import { exceptionListItemType } from '../../common/exception_list_item_type'; +import { EntriesArray } from '../../common/entries'; +import { DefaultImportCommentsArray } from '../../common/default_import_comments_array'; +import { ExpireTimeOrUndefined, expireTimeOrUndefined, ImportCommentsArray } from '../../common'; + +/** + * Differences from this and the createExceptionsListItemSchema are + * - item_id is required + * - id is optional (but ignored in the import code - item_id is exclusively used for imports) + * - immutable is optional but if it is any value other than false it will be rejected + * - created_at is optional (but ignored in the import code) + * - updated_at is optional (but ignored in the import code) + * - created_by is optional (but ignored in the import code) + * - updated_by is optional (but ignored in the import code) + */ +export const importExceptionListItemSchema = t.intersection([ + t.exact( + t.type({ + description, + entries: nonEmptyEntriesArray, + item_id, + list_id, + name, + type: exceptionListItemType, + }) + ), + t.exact( + t.partial({ + id, // defaults to undefined if not set during decode + comments: DefaultImportCommentsArray, // defaults to empty array if not set during decode + created_at, // defaults undefined if not set during decode + updated_at, // defaults undefined if not set during decode + created_by, // defaults undefined if not set during decode + updated_by, // defaults undefined if not set during decode + _version, // defaults to undefined if not set during decode + tie_breaker_id, + meta, // defaults to undefined if not set during decode + namespace_type, // defaults to 'single' if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + expire_time: expireTimeOrUndefined, + }) + ), +]); + +export type ImportExceptionListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type ImportExceptionListItemSchemaDecoded = Omit< + ImportExceptionListItemSchema, + 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments' | 'expire_time' +> & { + comments: ImportCommentsArray; + tags: Tags; + item_id: ItemId; + entries: EntriesArray; + namespace_type: NamespaceType; + os_types: OsTypeArray; + expire_time: ExpireTimeOrUndefined; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..438b0cd54fb09 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.mock.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import { ImportExceptionListSchemaDecoded, ImportExceptionsListSchema } from '.'; + +export const getImportExceptionsListSchemaMock = ( + listId = 'detection_list_id' +): ImportExceptionsListSchema => ({ + description: 'some description', + list_id: listId, + name: 'Query with a rule id', + type: 'detection', +}); + +export const getImportExceptionsListSchemaDecodedMock = ( + listId = 'detection_list_id' +): ImportExceptionListSchemaDecoded => ({ + ...getImportExceptionsListSchemaMock(listId), + immutable: false, + meta: undefined, + namespace_type: 'single', + os_types: [], + tags: [], + version: 1, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..e1d0a55a17704 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.test.ts @@ -0,0 +1,131 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { importExceptionsListSchema, ImportExceptionsListSchema } from '.'; +import { + getImportExceptionsListSchemaMock, + getImportExceptionsListSchemaDecodedMock, +} from './index.mock'; + +describe('import_list_item_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getImportExceptionsListSchemaMock(); + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getImportExceptionsListSchemaDecodedMock()); + }); + + test('it should NOT accept an undefined for "list_id"', () => { + const payload: Partial> = + getImportExceptionsListSchemaMock(); + delete payload.list_id; + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "description"', () => { + const payload: Partial> = + getImportExceptionsListSchemaMock(); + delete payload.description; + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "name"', () => { + const payload: Partial> = + getImportExceptionsListSchemaMock(); + delete payload.name; + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "type"', () => { + const payload: Partial> = + getImportExceptionsListSchemaMock(); + delete payload.type; + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept value of "true" for "immutable"', () => { + const payload: ImportExceptionsListSchema = { + ...getImportExceptionsListSchemaMock(), + immutable: true, + }; + + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "true" supplied to "immutable"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept any partial fields', () => { + const payload: ImportExceptionsListSchema = { + ...getImportExceptionsListSchemaMock(), + namespace_type: 'single', + immutable: false, + os_types: [], + tags: ['123'], + created_at: '2018-08-24T17:49:30.145142000', + created_by: 'elastic', + updated_at: '2018-08-24T17:49:30.145142000', + updated_by: 'elastic', + version: 3, + tie_breaker_id: '123', + _version: '3', + meta: undefined, + }; + + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ImportExceptionsListSchema & { + extraKey?: string; + } = getImportExceptionsListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = importExceptionsListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.ts new file mode 100644 index 0000000000000..98f5988daf1cc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_list_schema/index.ts @@ -0,0 +1,84 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { + DefaultVersionNumber, + DefaultVersionNumberDecoded, + OnlyFalseAllowed, +} from '@kbn/securitysolution-io-ts-types'; + +import { exceptionListType } from '../../common/exception_list'; +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { Tags, tags } from '../../common/tags'; +import { ListId, list_id } from '../../common/list_id'; +import { NamespaceType } from '../../common/default_namespace'; +import { name } from '../../common/name'; +import { description } from '../../common/description'; +import { namespace_type } from '../../common/namespace_type'; +import { meta } from '../../common/meta'; +import { id } from '../../common/id'; +import { created_at } from '../../common/created_at'; +import { created_by } from '../../common/created_by'; +import { updated_at } from '../../common/updated_at'; +import { updated_by } from '../../common/updated_by'; +import { _version } from '../../common/underscore_version'; +import { tie_breaker_id } from '../../common/tie_breaker_id'; + +/** + * Differences from this and the createExceptionsSchema are + * - list_id is required + * - id is optional (but ignored in the import code - list_id is exclusively used for imports) + * - immutable is optional but if it is any value other than false it will be rejected + * - created_at is optional (but ignored in the import code) + * - updated_at is optional (but ignored in the import code) + * - created_by is optional (but ignored in the import code) + * - updated_by is optional (but ignored in the import code) + */ +export const importExceptionsListSchema = t.intersection([ + t.exact( + t.type({ + description, + name, + type: exceptionListType, + list_id, + }) + ), + t.exact( + t.partial({ + id, // defaults to undefined if not set during decode + immutable: OnlyFalseAllowed, + meta, // defaults to undefined if not set during decode + namespace_type, // defaults to 'single' if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + created_at, // defaults "undefined" if not set during decode + updated_at, // defaults "undefined" if not set during decode + created_by, // defaults "undefined" if not set during decode + updated_by, // defaults "undefined" if not set during decode + _version, // defaults to undefined if not set during decode + tie_breaker_id, + version: DefaultVersionNumber, // defaults to numerical 1 if not set during decode + }) + ), +]); + +export type ImportExceptionsListSchema = t.TypeOf; + +// This type is used after a decode since some things are defaults after a decode. +export type ImportExceptionListSchemaDecoded = Omit< + ImportExceptionsListSchema, + 'tags' | 'list_id' | 'namespace_type' | 'os_types' | 'immutable' +> & { + immutable: false; + tags: Tags; + list_id: ListId; + namespace_type: NamespaceType; + os_types: OsTypeArray; + version: DefaultVersionNumberDecoded; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.mock.ts new file mode 100644 index 0000000000000..fc5fc0ca703b0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.mock.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import { LIST_ID, TYPE } from '../../constants/index.mock'; + +import { ImportListItemQuerySchema } from '.'; + +export const getImportListItemQuerySchemaMock = (): ImportListItemQuerySchema => ({ + deserializer: undefined, + list_id: LIST_ID, + serializer: undefined, + type: TYPE, + refresh: 'false', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.test.ts new file mode 100644 index 0000000000000..26d1ba486468f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.test.ts @@ -0,0 +1,88 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { ImportListItemQuerySchema, importListItemQuerySchema } from '.'; +import { getImportListItemQuerySchemaMock } from './index.mock'; + +describe('import_list_item_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getImportListItemQuerySchemaMock(); + const decoded = importListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "list_id"', () => { + const payload = getImportListItemQuerySchemaMock(); + delete payload.list_id; + const decoded = importListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "type"', () => { + const payload = getImportListItemQuerySchemaMock(); + delete payload.type; + const decoded = importListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "type" and "list_id', () => { + const payload = getImportListItemQuerySchemaMock(); + delete payload.type; + delete payload.list_id; + const decoded = importListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "serializer"', () => { + const payload = getImportListItemQuerySchemaMock(); + delete payload.serializer; + const decoded = importListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "deserializer"', () => { + const payload = getImportListItemQuerySchemaMock(); + delete payload.deserializer; + const decoded = importListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ImportListItemQuerySchema & { + extraKey?: string; + } = getImportListItemQuerySchemaMock(); + payload.extraKey = 'some new value'; + const decoded = importListItemQuerySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.ts new file mode 100644 index 0000000000000..19cd873825d2d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_query_schema/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { deserializer } from '../../common/deserializer'; +import { list_id } from '../../common/list_id'; +import { type } from '../../common/type'; +import { serializer } from '../../common/serializer'; +import { refreshWithWaitFor } from '../../common/refresh'; + +export const importListItemQuerySchema = t.exact( + t.partial({ deserializer, list_id, serializer, type, refresh: refreshWithWaitFor }) +); + +export type ImportListItemQuerySchema = RequiredKeepUndefined< + t.TypeOf +>; +export type ImportListItemQuerySchemaEncoded = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..32fee251c0781 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.mock.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { ImportListItemSchema } from '.'; + +export const getImportListItemSchemaMock = (): ImportListItemSchema => ({ + file: {}, +}); + +/** + * This is useful for end to end tests, it will return a buffer given a string array + * of things to import. + * @param input Array of strings of things to import + */ +export const getImportListItemAsBuffer = (input: string[]): Buffer => { + return Buffer.from(input.join('\r\n')); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..0e572255b5741 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.test.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { ImportListItemSchema, importListItemSchema } from '.'; +import { getImportListItemSchemaMock } from './index.mock'; + +describe('import_list_item_schema', () => { + test('it should validate a typical lists request', () => { + const payload = getImportListItemSchemaMock(); + const decoded = importListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for a file', () => { + const payload = getImportListItemSchemaMock(); + // @ts-expect-error + delete payload.file; + const decoded = importListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "file"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ImportListItemSchema & { + extraKey?: string; + } = getImportListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = importListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.ts new file mode 100644 index 0000000000000..4072cf029bae9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/import_list_item_schema/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { file } from '../../common/file'; + +export const importListItemSchema = t.exact( + t.type({ + file, + }) +); + +export type ImportListItemSchema = RequiredKeepUndefined>; +export type ImportListItemSchemaEncoded = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/index.ts new file mode 100644 index 0000000000000..a6a3099ddde8c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/index.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +export * from './create_endpoint_list_item_schema'; +export * from './create_exception_list_item_schema'; +export * from './create_exception_list_schema'; +export * from './create_rule_exception_item_schema'; +export * from './create_list_item_schema'; +export * from './create_list_schema'; +export * from './delete_endpoint_list_item_schema'; +export * from './delete_exception_list_schema'; +export * from './delete_exception_list_item_schema'; +export * from './delete_list_item_schema'; +export * from './delete_list_schema'; +export * from './duplicate_exception_list_query_schema'; +export * from './export_exception_list_query_schema'; +export * from './export_list_item_query_schema'; +export * from './find_endpoint_list_item_schema'; +export * from './find_exception_list_schema'; +export * from './find_exception_list_item_schema'; +export * from './find_list_item_schema'; +export * from './find_list_schema'; +export * from './get_exception_filter_schema'; +export * from './import_list_item_query_schema'; +export * from './import_exception_list_schema'; +export * from './import_exception_item_schema'; +export * from './import_list_item_schema'; +export * from './patch_list_item_schema'; +export * from './patch_list_schema'; +export * from './read_endpoint_list_item_schema'; +export * from './read_exception_list_item_schema'; +export * from './read_exception_list_schema'; +export * from './read_list_item_schema'; +export * from './read_list_schema'; +export * from './summary_exception_list_schema'; +export * from './update_endpoint_list_item_schema'; +export * from './update_exception_list_item_schema'; +export * from './update_exception_list_schema'; +export * from './update_list_item_schema'; +export * from './update_list_schema'; + +// Internal routes +export * from './internal/create_exception_list_schema'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..8ab58a7b0bdd4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.test.ts @@ -0,0 +1,68 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; + +import { ExceptionListTypeEnum } from '../../../common/exception_list'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { internalCreateExceptionListSchema } from '.'; +import { getCreateExceptionListSchemaMock } from '../../create_exception_list_schema/index.mock'; + +describe('create_exception_list_schema', () => { + test('it should accept artifact list_id', () => { + const payload = { + ...getCreateExceptionListSchemaMock(), + list_id: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, + }; + const decoded = internalCreateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + test('it should fail when invalid list_id', () => { + const payload = { + ...getCreateExceptionListSchemaMock(), + list_id: ExceptionListTypeEnum.DETECTION, + }; + const decoded = internalCreateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "detection" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + test('it should accept artifact type', () => { + const payload = { + ...getCreateExceptionListSchemaMock(), + list_id: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, + type: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, + }; + const decoded = internalCreateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + test('it should fail when invalid type', () => { + const payload = { + ...getCreateExceptionListSchemaMock(), + list_id: ExceptionListTypeEnum.ENDPOINT_BLOCKLISTS, + type: ExceptionListTypeEnum.DETECTION, + }; + const decoded = internalCreateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "detection" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts new file mode 100644 index 0000000000000..ff8f9670a4e03 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts @@ -0,0 +1,46 @@ +/* + * 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. + */ + +import { ENDPOINT_ARTIFACT_LIST_IDS } from '@kbn/securitysolution-list-constants'; +import * as t from 'io-ts'; + +import { + createExceptionListSchema, + CreateExceptionListSchemaDecoded, +} from '../../create_exception_list_schema'; + +export const internalCreateExceptionListSchema = t.intersection([ + t.exact( + t.type({ + type: t.keyof({ + endpoint: null, + endpoint_events: null, + endpoint_host_isolation_exceptions: null, + endpoint_blocklists: null, + }), + }) + ), + t.exact( + t.partial({ + list_id: t.keyof( + ENDPOINT_ARTIFACT_LIST_IDS.reduce>((mapOfListIds, listId) => { + mapOfListIds[listId] = null; + + return mapOfListIds; + }, {}) + ), + }) + ), + createExceptionListSchema, +]); + +export type InternalCreateExceptionListSchema = t.OutputOf< + typeof internalCreateExceptionListSchema +>; + +// This type is used after a decode since some things are defaults after a decode. +export type InternalCreateExceptionListSchemaDecoded = CreateExceptionListSchemaDecoded; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..fd30cba204398 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { LIST_ITEM_ID, META, VALUE } from '../../constants/index.mock'; + +import { PatchListItemSchema } from '.'; + +export const getPathListItemSchemaMock = (): PatchListItemSchema => ({ + id: LIST_ITEM_ID, + meta: META, + value: VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..55050ea6eab86 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.test.ts @@ -0,0 +1,81 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getPathListItemSchemaMock } from './index.mock'; +import { PatchListItemSchema, patchListItemSchema } from '.'; + +describe('patch_list_item_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getPathListItemSchemaMock(); + const decoded = patchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "id"', () => { + const payload = getPathListItemSchemaMock(); + // @ts-expect-error + delete payload.id; + const decoded = patchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta"', () => { + const payload = getPathListItemSchemaMock(); + delete payload.meta; + const decoded = patchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "value"', () => { + const payload = getPathListItemSchemaMock(); + delete payload.value; + const decoded = patchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "meta" and "value"', () => { + const payload = getPathListItemSchemaMock(); + delete payload.meta; + delete payload.value; + const decoded = patchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: PatchListItemSchema & { extraKey?: string } = getPathListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = patchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.ts new file mode 100644 index 0000000000000..caa0d62f003f1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_item_schema/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { _version } from '../../common/underscore_version'; +import { id } from '../../common/id'; +import { meta } from '../../common/meta'; +import { value } from '../../common/value'; +import { refresh } from '../../common/refresh'; + +export const patchListItemSchema = t.intersection([ + t.exact( + t.type({ + id, + }) + ), + t.exact(t.partial({ _version, meta, value, refresh })), +]); + +export type PatchListItemSchema = t.OutputOf; +export type PatchListItemSchemaDecoded = RequiredKeepUndefined< + t.TypeOf +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.mock.ts new file mode 100644 index 0000000000000..2b71a46c46659 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.mock.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import { DESCRIPTION, LIST_ITEM_ID, META, NAME } from '../../constants/index.mock'; + +import { PatchListSchema } from '.'; + +export const getPathListSchemaMock = (): PatchListSchema => ({ + description: DESCRIPTION, + id: LIST_ITEM_ID, + meta: META, + name: NAME, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.test.ts new file mode 100644 index 0000000000000..be0dd3b2f6eaa --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.test.ts @@ -0,0 +1,129 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getPathListSchemaMock } from './index.mock'; +import { PatchListSchema, patchListSchema } from '.'; + +describe('patch_list_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getPathListSchemaMock(); + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "id"', () => { + const payload = getPathListSchemaMock(); + // @ts-expect-error + delete payload.id; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta"', () => { + const payload = getPathListSchemaMock(); + delete payload.meta; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "name"', () => { + const payload = getPathListSchemaMock(); + delete payload.name; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "description"', () => { + const payload = getPathListSchemaMock(); + delete payload.description; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "description", "meta", "name', () => { + const payload = getPathListSchemaMock(); + delete payload.description; + delete payload.name; + delete payload.meta; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "description", "meta"', () => { + const payload = getPathListSchemaMock(); + delete payload.description; + delete payload.meta; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "description", "name"', () => { + const payload = getPathListSchemaMock(); + delete payload.description; + delete payload.name; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "meta", "name"', () => { + const payload = getPathListSchemaMock(); + delete payload.meta; + delete payload.name; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: PatchListSchema & { extraKey?: string } = getPathListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = patchListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.ts new file mode 100644 index 0000000000000..cb72d902f1896 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/patch_list_schema/index.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { version } from '@kbn/securitysolution-io-ts-types'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { _version } from '../../common/underscore_version'; +import { meta } from '../../common/meta'; +import { name } from '../../common/name'; +import { description } from '../../common/description'; + +export const patchListSchema = t.intersection([ + t.exact( + t.type({ + id, + }) + ), + t.exact( + t.partial({ + _version, // is undefined if not set during decode + description, // is undefined if not set during decode + meta, // is undefined if not set during decode + name, // is undefined if not set during decode + version, // is undefined if not set during decode + }) + ), +]); + +export type PatchListSchema = t.OutputOf; +export type PatchListSchemaDecoded = RequiredKeepUndefined>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..7b83368ad73e4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.mock.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +import { ID, ITEM_ID } from '../../constants/index.mock'; + +import { ReadEndpointListItemSchema } from '.'; + +export const getReadEndpointListItemSchemaMock = (): ReadEndpointListItemSchema => ({ + id: ID, + item_id: ITEM_ID, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..dc8a14b2ef101 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.test.ts @@ -0,0 +1,85 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getReadEndpointListItemSchemaMock } from './index.mock'; +import { ReadEndpointListItemSchema, readEndpointListItemSchema } from '.'; + +describe('read_endpoint_list_item_schema', () => { + test('it should validate a typical list request', () => { + const payload = getReadEndpointListItemSchemaMock(); + const decoded = readEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id"', () => { + const payload = getReadEndpointListItemSchemaMock(); + delete payload.id; + const decoded = readEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "item_id"', () => { + const payload = getReadEndpointListItemSchemaMock(); + delete payload.item_id; + const decoded = readEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept "namespace_type" since endpoint list items do not need it', () => { + const payload: ReadEndpointListItemSchema & { + namespace_type: string; + } = { ...getReadEndpointListItemSchemaMock(), namespace_type: 'single' }; + // @ts-expect-error + delete payload.namespace_type; + const decoded = readEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getReadEndpointListItemSchemaMock()); + }); + + test('it should accept an undefined for "id", "item_id"', () => { + const payload = getReadEndpointListItemSchemaMock(); + delete payload.id; + delete payload.item_id; + const decoded = readEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ReadEndpointListItemSchema & { + extraKey?: string; + } = getReadEndpointListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = readEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.ts new file mode 100644 index 0000000000000..6e32b1fe5186c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_endpoint_list_item_schema/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { item_id } from '../../common/item_id'; + +export const readEndpointListItemSchema = t.exact( + t.partial({ + id, + item_id, + }) +); + +export type ReadEndpointListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type ReadEndpointListItemSchemaDecoded = RequiredKeepUndefined< + t.TypeOf +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..6ce6e68ec6e0a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { ID, ITEM_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { ReadExceptionListItemSchema } from '.'; + +export const getReadExceptionListItemSchemaMock = (): ReadExceptionListItemSchema => ({ + id: ID, + item_id: ITEM_ID, + namespace_type: NAMESPACE_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..68f636ccb8705 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.test.ts @@ -0,0 +1,126 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getReadExceptionListItemSchemaMock } from './index.mock'; +import { ReadExceptionListItemSchema, readExceptionListItemSchema } from '.'; + +describe('read_exception_list_item_schema', () => { + test('it should validate a typical exception list request', () => { + const payload = getReadExceptionListItemSchemaMock(); + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id"', () => { + const payload = getReadExceptionListItemSchemaMock(); + delete payload.id; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "item_id"', () => { + const payload = getReadExceptionListItemSchemaMock(); + delete payload.item_id; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "namespace_type" but default to "single"', () => { + const payload = getReadExceptionListItemSchemaMock(); + delete payload.namespace_type; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getReadExceptionListItemSchemaMock()); + }); + + test('it should accept an undefined for "id", "item_id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getReadExceptionListItemSchemaMock(); + delete payload.id; + delete payload.namespace_type; + delete payload.item_id; + const output = getReadExceptionListItemSchemaMock(); + delete output.id; + delete output.item_id; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should accept an undefined for "id", "item_id"', () => { + const payload = getReadExceptionListItemSchemaMock(); + delete payload.id; + delete payload.item_id; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getReadExceptionListItemSchemaMock(); + delete payload.id; + delete payload.namespace_type; + const output = getReadExceptionListItemSchemaMock(); + delete output.id; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should accept an undefined for "item_id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getReadExceptionListItemSchemaMock(); + delete payload.namespace_type; + delete payload.item_id; + const output = getReadExceptionListItemSchemaMock(); + delete output.item_id; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ReadExceptionListItemSchema & { + extraKey?: string; + } = getReadExceptionListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = readExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.ts new file mode 100644 index 0000000000000..9111587af7e93 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_item_schema/index.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NamespaceType } from '../../common/default_namespace'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { item_id } from '../../common/item_id'; +import { namespace_type } from '../../common/namespace_type'; + +export const readExceptionListItemSchema = t.exact( + t.partial({ + id, + item_id, + namespace_type, // defaults to 'single' if not set during decode + }) +); + +export type ReadExceptionListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type ReadExceptionListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'namespace_type' +> & { + namespace_type: NamespaceType; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..f122f1d20339e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { ID, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { ReadExceptionListSchema } from '.'; + +export const getReadExceptionListSchemaMock = (): ReadExceptionListSchema => ({ + id: ID, + list_id: LIST_ID, + namespace_type: NAMESPACE_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..89cd869bd17c1 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.test.ts @@ -0,0 +1,126 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getReadExceptionListSchemaMock } from './index.mock'; +import { ReadExceptionListSchema, readExceptionListSchema } from '.'; + +describe('read_exception_list_schema', () => { + test('it should validate a typical exception list request', () => { + const payload = getReadExceptionListSchemaMock(); + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id"', () => { + const payload = getReadExceptionListSchemaMock(); + delete payload.id; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "list_id"', () => { + const payload = getReadExceptionListSchemaMock(); + delete payload.list_id; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "namespace_type" but default to "single"', () => { + const payload = getReadExceptionListSchemaMock(); + delete payload.namespace_type; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getReadExceptionListSchemaMock()); + }); + + test('it should accept an undefined for "id", "list_id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getReadExceptionListSchemaMock(); + delete payload.id; + delete payload.namespace_type; + delete payload.list_id; + const output = getReadExceptionListSchemaMock(); + delete output.id; + delete output.list_id; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should accept an undefined for "id", "list_id"', () => { + const payload = getReadExceptionListSchemaMock(); + delete payload.id; + delete payload.list_id; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getReadExceptionListSchemaMock(); + delete payload.id; + delete payload.namespace_type; + const output = getReadExceptionListSchemaMock(); + delete output.id; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should accept an undefined for "list_id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getReadExceptionListSchemaMock(); + delete payload.namespace_type; + delete payload.list_id; + const output = getReadExceptionListSchemaMock(); + delete output.list_id; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ReadExceptionListSchema & { + extraKey?: string; + } = getReadExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = readExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.ts new file mode 100644 index 0000000000000..b4d9b7309fb5f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_exception_list_schema/index.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NamespaceType } from '../../common/default_namespace'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { list_id } from '../../common/list_id'; +import { namespace_type } from '../../common/namespace_type'; + +export const readExceptionListSchema = t.exact( + t.partial({ + id, + list_id, + namespace_type, // defaults to 'single' if not set during decode + }) +); + +export type ReadExceptionListSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type ReadExceptionListSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'namespace_type' +> & { + namespace_type: NamespaceType; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..a239111231404 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { LIST_ID, LIST_ITEM_ID, VALUE } from '../../constants/index.mock'; + +import { ReadListItemSchema } from '.'; + +export const getReadListItemSchemaMock = (): ReadListItemSchema => ({ + id: LIST_ITEM_ID, + list_id: LIST_ID, + value: VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..9370aa5e3d459 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.test.ts @@ -0,0 +1,117 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getReadListItemSchemaMock } from './index.mock'; +import { ReadListItemSchema, readListItemSchema } from '.'; + +describe('read_list_item_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getReadListItemSchemaMock(); + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id"', () => { + const payload = getReadListItemSchemaMock(); + delete payload.id; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "list_id"', () => { + const payload = getReadListItemSchemaMock(); + delete payload.list_id; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "value"', () => { + const payload = getReadListItemSchemaMock(); + delete payload.value; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id", "list_id", "value"', () => { + const payload = getReadListItemSchemaMock(); + delete payload.id; + delete payload.value; + delete payload.list_id; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id", "list_id"', () => { + const payload = getReadListItemSchemaMock(); + delete payload.id; + delete payload.list_id; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id", "value"', () => { + const payload = getReadListItemSchemaMock(); + delete payload.id; + delete payload.value; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "list_id", "value"', () => { + const payload = getReadListItemSchemaMock(); + delete payload.value; + delete payload.list_id; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ReadListItemSchema & { extraKey?: string } = getReadListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = readListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.ts new file mode 100644 index 0000000000000..571f37ff403e0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_item_schema/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { list_id } from '../../common/list_id'; +import { value } from '../../common/value'; + +export const readListItemSchema = t.exact(t.partial({ id, list_id, value })); + +export type ReadListItemSchema = t.OutputOf; +export type ReadListItemSchemaDecoded = RequiredKeepUndefined>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.mock.ts new file mode 100644 index 0000000000000..c82b343815540 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.mock.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import { LIST_ID } from '../../constants/index.mock'; + +import { ReadListSchema } from '.'; + +export const getReadListSchemaMock = (): ReadListSchema => ({ + id: LIST_ID, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.test.ts new file mode 100644 index 0000000000000..1953341d2be41 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.test.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getReadListSchemaMock } from './index.mock'; +import { ReadListSchema, readListSchema } from '.'; + +describe('read_list_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getReadListSchemaMock(); + const decoded = readListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "id"', () => { + const payload = getReadListSchemaMock(); + // @ts-expect-error + delete payload.id; + const decoded = readListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ReadListSchema & { extraKey?: string } = getReadListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = readListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.ts new file mode 100644 index 0000000000000..6382a7c0ad975 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/read_list_schema/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { id } from '../../common/id'; + +export const readListSchema = t.exact( + t.type({ + id, + }) +); + +export type ReadListSchema = t.OutputOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..af6dc55b61da7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.mock.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import { FILTER, ID, LIST_ID, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { SummaryExceptionListSchema } from '.'; + +export const getSummaryExceptionListSchemaMock = (): SummaryExceptionListSchema => ({ + filter: FILTER, + id: ID, + list_id: LIST_ID, + namespace_type: NAMESPACE_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..53a734ed034e7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.test.ts @@ -0,0 +1,136 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getSummaryExceptionListSchemaMock } from './index.mock'; +import { SummaryExceptionListSchema, summaryExceptionListSchema } from '.'; + +describe('summary_exception_list_schema', () => { + test('it should validate a typical exception list request', () => { + const payload = getSummaryExceptionListSchemaMock(); + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "filter"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.filter; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.id; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "list_id"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.list_id; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "namespace_type" but default to "single"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.namespace_type; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(getSummaryExceptionListSchemaMock()); + }); + + test('it should accept an undefined for "id", "list_id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.id; + delete payload.namespace_type; + delete payload.list_id; + const output = getSummaryExceptionListSchemaMock(); + delete output.id; + delete output.list_id; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should accept an undefined for "id", "list_id"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.id; + delete payload.list_id; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.id; + delete payload.namespace_type; + const output = getSummaryExceptionListSchemaMock(); + delete output.id; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should accept an undefined for "list_id", "namespace_type" but default "namespace_type" to "single"', () => { + const payload = getSummaryExceptionListSchemaMock(); + delete payload.namespace_type; + delete payload.list_id; + const output = getSummaryExceptionListSchemaMock(); + delete output.list_id; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(output); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: SummaryExceptionListSchema & { + extraKey?: string; + } = getSummaryExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = summaryExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = foldLeftRight(checked); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts new file mode 100644 index 0000000000000..6be4f0c57b086 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { NamespaceType } from '../../common/default_namespace'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { filter, Filter } from '../../common/filter'; +import { list_id } from '../../common/list_id'; +import { namespace_type } from '../../common/namespace_type'; + +export const summaryExceptionListSchema = t.exact( + t.partial({ + filter, + id, + list_id, + namespace_type, // defaults to 'single' if not set during decode + }) +); + +export type SummaryExceptionListSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type SummaryExceptionListSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'namespace_type' +> & { + namespace_type: NamespaceType; + filter: Filter; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..57244aac0426f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.mock.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import { + COMMENTS, + DESCRIPTION, + ENTRIES, + ID, + ITEM_TYPE, + LIST_ITEM_ID, + META, + NAME, + OS_TYPES, + TAGS, +} from '../../constants/index.mock'; + +import { UpdateEndpointListItemSchema } from '.'; + +export const getUpdateEndpointListItemSchemaMock = (): UpdateEndpointListItemSchema => ({ + _version: undefined, + comments: COMMENTS, + description: DESCRIPTION, + entries: ENTRIES, + id: ID, + item_id: LIST_ITEM_ID, + meta: META, + name: NAME, + os_types: OS_TYPES, + tags: TAGS, + type: ITEM_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..1def91ca1a8e2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.test.ts @@ -0,0 +1,138 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { UpdateEndpointListItemSchema, updateEndpointListItemSchema } from '.'; +import { getUpdateEndpointListItemSchemaMock } from './index.mock'; + +describe('update_endpoint_list_item_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getUpdateEndpointListItemSchemaMock(); + const decoded = updateEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not accept an undefined for "description"', () => { + const payload = getUpdateEndpointListItemSchemaMock(); + // @ts-expect-error + delete payload.description; + const decoded = updateEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept an undefined for "name"', () => { + const payload = getUpdateEndpointListItemSchemaMock(); + // @ts-expect-error + delete payload.name; + const decoded = updateEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept an undefined for "type"', () => { + const payload = getUpdateEndpointListItemSchemaMock(); + // @ts-expect-error + delete payload.type; + const decoded = updateEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept a value for "list_id"', () => { + const payload: UpdateEndpointListItemSchema & { + list_id?: string; + } = getUpdateEndpointListItemSchemaMock(); + payload.list_id = 'some new list_id'; + const decoded = updateEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "list_id"']); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta" but strip it out', () => { + const payload = getUpdateEndpointListItemSchemaMock(); + const outputPayload = getUpdateEndpointListItemSchemaMock(); + delete payload.meta; + const decoded = updateEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete outputPayload.meta; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "comments" but return an array', () => { + const inputPayload = getUpdateEndpointListItemSchemaMock(); + const outputPayload = getUpdateEndpointListItemSchemaMock(); + delete inputPayload.comments; + outputPayload.comments = []; + const decoded = updateEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should NOT accept an undefined for "entries"', () => { + const inputPayload = getUpdateEndpointListItemSchemaMock(); + const outputPayload = getUpdateEndpointListItemSchemaMock(); + // @ts-expect-error + delete inputPayload.entries; + outputPayload.entries = []; + const decoded = updateEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "tags" but return an array', () => { + const inputPayload = getUpdateEndpointListItemSchemaMock(); + const outputPayload = getUpdateEndpointListItemSchemaMock(); + delete inputPayload.tags; + outputPayload.tags = []; + const decoded = updateEndpointListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: UpdateEndpointListItemSchema & { + extraKey?: string; + } = getUpdateEndpointListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = updateEndpointListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.ts new file mode 100644 index 0000000000000..e301137058afc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_endpoint_list_item_schema/index.ts @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { DefaultUpdateCommentsArray } from '../../common/default_update_comments_array'; +import { exceptionListItemType } from '../../common/exception_list_item_type'; +import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { description } from '../../common/description'; +import { name } from '../../common/name'; +import { _version } from '../../common/underscore_version'; +import { id } from '../../common/id'; +import { meta } from '../../common/meta'; +import { Tags, tags } from '../../common/tags'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { UpdateCommentsArray } from '../../common/update_comment'; +import { EntriesArray } from '../../common/entries'; + +export const updateEndpointListItemSchema = t.intersection([ + t.exact( + t.type({ + description, + entries: nonEmptyEntriesArray, + name, + type: exceptionListItemType, + }) + ), + t.exact( + t.partial({ + _version, // defaults to undefined if not set during decode + comments: DefaultUpdateCommentsArray, // defaults to empty array if not set during decode + id, // defaults to undefined if not set during decode + item_id: t.union([t.string, t.undefined]), + meta, // defaults to undefined if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + }) + ), +]); + +export type UpdateEndpointListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type UpdateEndpointListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'tags' | 'entries' | 'comments' +> & { + comments: UpdateCommentsArray; + tags: Tags; + entries: EntriesArray; + os_types: OsTypeArray; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..c7560348179dc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.mock.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ + +import { + COMMENTS, + DESCRIPTION, + ENTRIES, + ID, + ITEM_ID, + ITEM_TYPE, + LIST_ITEM_ID, + META, + NAME, + NAMESPACE_TYPE, + OS_TYPES, + TAGS, +} from '../../constants/index.mock'; + +import { UpdateExceptionListItemSchema } from '.'; + +export const getUpdateExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ + _version: undefined, + comments: COMMENTS, + description: DESCRIPTION, + entries: ENTRIES, + id: ID, + item_id: LIST_ITEM_ID, + meta: META, + name: NAME, + namespace_type: NAMESPACE_TYPE, + os_types: ['linux'], + tags: TAGS, + type: ITEM_TYPE, +}); + +/** + * Useful for end to end tests and other mechanisms which want to fill in the values + * after doing a get of the structure. + */ +export const getUpdateMinimalExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ + description: DESCRIPTION, + entries: ENTRIES, + item_id: ITEM_ID, + name: NAME, + os_types: OS_TYPES, + type: ITEM_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..0adbf1224d720 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.test.ts @@ -0,0 +1,160 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { UpdateExceptionListItemSchema, updateExceptionListItemSchema } from '.'; +import { getUpdateExceptionListItemSchemaMock } from './index.mock'; + +describe('update_exception_list_item_schema', () => { + test('it should validate a typical exception list item request', () => { + const payload = getUpdateExceptionListItemSchemaMock(); + const decoded = updateExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not accept an undefined for "description"', () => { + const payload = getUpdateExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.description; + const decoded = updateExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept an undefined for "name"', () => { + const payload = getUpdateExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.name; + const decoded = updateExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept an undefined for "type"', () => { + const payload = getUpdateExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.type; + const decoded = updateExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept a value for "list_id"', () => { + const payload: UpdateExceptionListItemSchema & { + list_id?: string; + } = getUpdateExceptionListItemSchemaMock(); + payload.list_id = 'some new list_id'; + const decoded = updateExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "list_id"']); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta" but strip it out', () => { + const payload = getUpdateExceptionListItemSchemaMock(); + const outputPayload = getUpdateExceptionListItemSchemaMock(); + delete payload.meta; + const decoded = updateExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete outputPayload.meta; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "comments" but return an array', () => { + const inputPayload = getUpdateExceptionListItemSchemaMock(); + const outputPayload = getUpdateExceptionListItemSchemaMock(); + delete inputPayload.comments; + outputPayload.comments = []; + const decoded = updateExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should NOT accept an undefined for "entries"', () => { + const inputPayload = getUpdateExceptionListItemSchemaMock(); + const outputPayload = getUpdateExceptionListItemSchemaMock(); + // @ts-expect-error + delete inputPayload.entries; + outputPayload.entries = []; + const decoded = updateExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "namespace_type" but return enum "single"', () => { + const inputPayload = getUpdateExceptionListItemSchemaMock(); + const outputPayload = getUpdateExceptionListItemSchemaMock(); + delete inputPayload.namespace_type; + outputPayload.namespace_type = 'single'; + const decoded = updateExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "tags" but return an array', () => { + const inputPayload = getUpdateExceptionListItemSchemaMock(); + const outputPayload = getUpdateExceptionListItemSchemaMock(); + delete inputPayload.tags; + outputPayload.tags = []; + const decoded = updateExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "item_id" and generate a correct body not counting the uuid', () => { + const inputPayload = getUpdateExceptionListItemSchemaMock(); + delete inputPayload.item_id; + const decoded = updateExceptionListItemSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as UpdateExceptionListItemSchema).item_id; + expect(message.schema).toEqual(inputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: UpdateExceptionListItemSchema & { + extraKey?: string; + } = getUpdateExceptionListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = updateExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.ts new file mode 100644 index 0000000000000..910acbe2c942f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_item_schema/index.ts @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { ExceptionListItemEntryArray } from '@kbn/securitysolution-exceptions-common/api'; +import { NamespaceType } from '../../common/default_namespace'; +import { DefaultUpdateCommentsArray } from '../../common/default_update_comments_array'; +import { exceptionListItemType } from '../../common/exception_list_item_type'; +import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { Tags, tags } from '../../common/tags'; +import { UpdateCommentsArray } from '../../common/update_comment'; +import { description } from '../../common/description'; +import { name } from '../../common/name'; +import { _version } from '../../common/underscore_version'; +import { id } from '../../common/id'; +import { item_id } from '../../common/item_id'; +import { meta } from '../../common/meta'; +import { namespace_type } from '../../common/namespace_type'; +import { ExpireTimeOrUndefined, expireTimeOrUndefined } from '../../common'; + +export const updateExceptionListItemSchema = t.intersection([ + t.exact( + t.type({ + description, + entries: nonEmptyEntriesArray, + name, + type: exceptionListItemType, + }) + ), + t.exact( + t.partial({ + _version, // defaults to undefined if not set during decode + comments: DefaultUpdateCommentsArray, // defaults to empty array if not set during decode + expire_time: expireTimeOrUndefined, + id, // defaults to undefined if not set during decode + item_id, + meta, // defaults to undefined if not set during decode + namespace_type, // defaults to 'single' if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + }) + ), +]); + +export type UpdateExceptionListItemSchema = t.OutputOf; + +// This type is used after a decode since some things are defaults after a decode. +export type UpdateExceptionListItemSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'tags' | 'entries' | 'namespace_type' | 'comments' | 'os_types' | 'expire_time' +> & { + comments: UpdateCommentsArray; + tags: Tags; + entries: ExceptionListItemEntryArray; + namespace_type: NamespaceType; + os_types: OsTypeArray; + expire_time: ExpireTimeOrUndefined; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..9aac2453a7beb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.mock.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import { DESCRIPTION, ID, LIST_ID, META, NAME, NAMESPACE_TYPE } from '../../constants/index.mock'; + +import { UpdateExceptionListSchema } from '.'; + +export const getUpdateExceptionListSchemaMock = (): UpdateExceptionListSchema => ({ + _version: undefined, + description: DESCRIPTION, + id: ID, + list_id: LIST_ID, + meta: META, + name: NAME, + namespace_type: NAMESPACE_TYPE, + os_types: [], + tags: ['malware'], + type: 'endpoint', +}); + +/** + * Useful for end to end tests and other mechanisms which want to fill in the values + * after doing a get of the structure. + */ +export const getUpdateMinimalExceptionListSchemaMock = (): UpdateExceptionListSchema => ({ + description: DESCRIPTION, + list_id: LIST_ID, + name: NAME, + type: 'endpoint', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..029751ac4d144 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.test.ts @@ -0,0 +1,121 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { UpdateExceptionListSchema, updateExceptionListSchema } from '.'; +import { getUpdateExceptionListSchemaMock } from './index.mock'; + +describe('update_exception_list_schema', () => { + test('it should validate a typical exception list request', () => { + const payload = getUpdateExceptionListSchemaMock(); + const decoded = updateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should not accept an undefined for "description"', () => { + const payload = getUpdateExceptionListSchemaMock(); + // @ts-expect-error + delete payload.description; + const decoded = updateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept an undefined for "name"', () => { + const payload = getUpdateExceptionListSchemaMock(); + // @ts-expect-error + delete payload.name; + const decoded = updateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not accept an undefined for "type"', () => { + const payload = getUpdateExceptionListSchemaMock(); + // @ts-expect-error + delete payload.type; + const decoded = updateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta" but strip it out', () => { + const payload = getUpdateExceptionListSchemaMock(); + const outputPayload = getUpdateExceptionListSchemaMock(); + delete payload.meta; + const decoded = updateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete outputPayload.meta; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "namespace_type" but return enum "single"', () => { + const inputPayload = getUpdateExceptionListSchemaMock(); + const outputPayload = getUpdateExceptionListSchemaMock(); + delete inputPayload.namespace_type; + outputPayload.namespace_type = 'single'; + const decoded = updateExceptionListSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "tags" but return an array', () => { + const inputPayload = getUpdateExceptionListSchemaMock(); + const outputPayload = getUpdateExceptionListSchemaMock(); + delete inputPayload.tags; + outputPayload.tags = []; + const decoded = updateExceptionListSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should accept an undefined for "list_id" and generate a correct body not counting the uuid', () => { + const inputPayload = getUpdateExceptionListSchemaMock(); + delete inputPayload.list_id; + const decoded = updateExceptionListSchema.decode(inputPayload); + const checked = exactCheck(inputPayload, decoded); + const message = pipe(checked, foldLeftRight); + delete (message.schema as UpdateExceptionListSchema).list_id; + expect(message.schema).toEqual(inputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: UpdateExceptionListSchema & { + extraKey?: string; + } = getUpdateExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = updateExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.ts new file mode 100644 index 0000000000000..be4006c3efa18 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_exception_list_schema/index.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { version } from '@kbn/securitysolution-io-ts-types'; +import { OsTypeArray, osTypeArrayOrUndefined } from '../../common/os_type'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { Tags, tags } from '../../common/tags'; +import { NamespaceType } from '../../common/default_namespace'; +import { description } from '../../common/description'; +import { name } from '../../common/name'; +import { _version } from '../../common/underscore_version'; +import { exceptionListType } from '../../common/exception_list'; +import { id } from '../../common/id'; +import { list_id } from '../../common/list_id'; +import { meta } from '../../common/meta'; +import { namespace_type } from '../../common/namespace_type'; + +export const updateExceptionListSchema = t.intersection([ + t.exact( + t.type({ + description, + name, + type: exceptionListType, + }) + ), + t.exact( + t.partial({ + _version, // defaults to undefined if not set during decode + id, // defaults to undefined if not set during decode + list_id, // defaults to undefined if not set during decode + meta, // defaults to undefined if not set during decode + namespace_type, // defaults to 'single' if not set during decode + os_types: osTypeArrayOrUndefined, // defaults to empty array if not set during decode + tags, // defaults to empty array if not set during decode + version, // defaults to undefined if not set during decode + }) + ), +]); + +export type UpdateExceptionListSchema = t.OutputOf; + +// This type is used after a decode since the arrays turn into defaults of empty arrays. +export type UpdateExceptionListSchemaDecoded = Omit< + RequiredKeepUndefined>, + 'tags | namespace_type' | 'os_types' +> & { + tags: Tags; + namespace_type: NamespaceType; + os_types: OsTypeArray; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..7d65f59aa8cda --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.mock.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { ID, LIST_ITEM_ID, META, VALUE } from '../../constants/index.mock'; + +import { UpdateListItemSchema } from '.'; + +export const getUpdateListItemSchemaMock = (): UpdateListItemSchema => ({ + id: ID, + meta: META, + value: VALUE, +}); + +/** + * Useful for end to end testing + */ +export const getUpdateMinimalListItemSchemaMock = (): UpdateListItemSchema => ({ + id: LIST_ITEM_ID, + value: VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..ca6402455aabe --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.test.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { UpdateListItemSchema, updateListItemSchema } from '.'; +import { getUpdateListItemSchemaMock } from './index.mock'; + +describe('update_list_item_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getUpdateListItemSchemaMock(); + const decoded = updateListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "meta" but strip it out', () => { + const payload = getUpdateListItemSchemaMock(); + const outputPayload = getUpdateListItemSchemaMock(); + delete payload.meta; + const decoded = updateListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete outputPayload.meta; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: UpdateListItemSchema & { + extraKey?: string; + } = getUpdateListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = updateListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.ts new file mode 100644 index 0000000000000..2df22b5c57b74 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_item_schema/index.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { _version } from '../../common/underscore_version'; +import { id } from '../../common/id'; +import { value } from '../../common/value'; +import { meta } from '../../common/meta'; + +export const updateListItemSchema = t.intersection([ + t.exact( + t.type({ + id, + value, + }) + ), + t.exact( + t.partial({ + _version, // defaults to undefined if not set during decode + meta, // defaults to undefined if not set during decode + }) + ), +]); + +export type UpdateListItemSchema = t.OutputOf; +export type UpdateListItemSchemaDecoded = RequiredKeepUndefined< + t.TypeOf +>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.mock.ts new file mode 100644 index 0000000000000..99362d8ef8a7e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.mock.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import { DESCRIPTION, LIST_ID, META, NAME, _VERSION } from '../../constants/index.mock'; + +import { UpdateListSchema } from '.'; + +export const getUpdateListSchemaMock = (): UpdateListSchema => ({ + _version: _VERSION, + description: DESCRIPTION, + id: LIST_ID, + meta: META, + name: NAME, +}); + +/** + * Useful for end to end tests and other mechanisms which want to fill in the values + * after doing a get of the structure. + */ +export const getUpdateMinimalListSchemaMock = (): UpdateListSchema => ({ + description: DESCRIPTION, + id: LIST_ID, + name: NAME, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.test.ts new file mode 100644 index 0000000000000..c35861f66e910 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.test.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { UpdateListSchema, updateListSchema } from '.'; +import { getUpdateListSchemaMock } from './index.mock'; + +describe('update_list_schema', () => { + test('it should validate a typical list request', () => { + const payload = getUpdateListSchemaMock(); + const decoded = updateListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "meta" but strip it out', () => { + const payload = getUpdateListSchemaMock(); + const outputPayload = getUpdateListSchemaMock(); + delete payload.meta; + const decoded = updateListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + delete outputPayload.meta; + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(outputPayload); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: UpdateListSchema & { + extraKey?: string; + } = getUpdateListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = updateListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.ts new file mode 100644 index 0000000000000..c6182af2f23fa --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/request/update_list_schema/index.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { version } from '@kbn/securitysolution-io-ts-types'; +import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; +import { id } from '../../common/id'; +import { name } from '../../common/name'; +import { description } from '../../common/description'; +import { _version } from '../../common/underscore_version'; +import { meta } from '../../common/meta'; + +export const updateListSchema = t.intersection([ + t.exact( + t.type({ + description, + id, + name, + }) + ), + t.exact( + t.partial({ + _version, // defaults to undefined if not set during decode + meta, // defaults to undefined if not set during decode + version, // defaults to undefined if not set during decode + }) + ), +]); + +export type UpdateListSchema = t.OutputOf; +export type UpdateListSchemaDecoded = RequiredKeepUndefined>; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.mock.ts new file mode 100644 index 0000000000000..2c4ac68f46132 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.mock.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +import { AcknowledgeSchema } from '.'; + +export const getAcknowledgeSchemaResponseMock = (): AcknowledgeSchema => ({ + acknowledged: true, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.test.ts new file mode 100644 index 0000000000000..4fd4adf861bbd --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.test.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getAcknowledgeSchemaResponseMock } from './index.mock'; +import { AcknowledgeSchema, acknowledgeSchema } from '.'; + +describe('acknowledge_schema', () => { + test('it should validate a typical response', () => { + const payload = getAcknowledgeSchemaResponseMock(); + const decoded = acknowledgeSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + test('it should NOT accept an undefined for "ok"', () => { + const payload = getAcknowledgeSchemaResponseMock(); + // @ts-expect-error + delete payload.acknowledged; + const decoded = acknowledgeSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "acknowledged"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: AcknowledgeSchema & { extraKey?: string } = getAcknowledgeSchemaResponseMock(); + payload.extraKey = 'some new value'; + const decoded = acknowledgeSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.ts new file mode 100644 index 0000000000000..97a0dc23682c4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/acknowledge_schema/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const acknowledgeSchema = t.exact(t.type({ acknowledged: t.boolean })); + +export type AcknowledgeSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.test.ts new file mode 100644 index 0000000000000..2ac63d9719e29 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.test.ts @@ -0,0 +1,73 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { CreateEndpointListSchema, createEndpointListSchema } from '.'; +import { getExceptionListSchemaMock } from '../exception_list_schema/index.mock'; + +describe('create_endpoint_list_schema', () => { + test('it should validate a typical endpoint list response', () => { + const payload = getExceptionListSchemaMock(); + const decoded = createEndpointListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an empty object when an endpoint list already exists', () => { + const payload: CreateEndpointListSchema = {}; + const decoded = createEndpointListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "list_id"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = createEndpointListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'invalid keys "_version,created_at,created_by,description,id,immutable,meta,{},name,namespace_type,os_types,["linux"],tags,["user added string for a tag","malware"],tie_breaker_id,type,updated_at,updated_by,version"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT allow missing fields', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = createEndpointListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors)).length).toEqual(1); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: CreateEndpointListSchema & { + extraKey?: string; + } = getExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = createEndpointListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.ts new file mode 100644 index 0000000000000..44f3629973a06 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/create_endpoint_list_schema/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { exceptionListSchema } from '../exception_list_schema'; + +export const createEndpointListSchema = t.union([exceptionListSchema, t.exact(t.type({}))]); + +export type CreateEndpointListSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..fad9dc5990a85 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.mock.ts @@ -0,0 +1,70 @@ +/* + * 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. + */ + +import { + COMMENTS, + DATE_NOW, + DESCRIPTION, + ELASTIC_USER, + ENTRIES, + ITEM_ID, + ITEM_TYPE, + LIST_ID, + META, + NAME, + NAMESPACE_TYPE, + OS_TYPES, + TIE_BREAKER, + USER, +} from '../../constants/index.mock'; + +import { ExceptionListItemSchema } from '.'; + +export const getExceptionListItemSchemaMock = ( + overrides?: Partial +): ExceptionListItemSchema => ({ + _version: undefined, + comments: COMMENTS, + created_at: DATE_NOW, + created_by: USER, + description: DESCRIPTION, + entries: ENTRIES, + expire_time: undefined, + id: '1', + item_id: 'endpoint_list_item', + list_id: 'endpoint_list_id', + meta: META, + name: NAME, + namespace_type: NAMESPACE_TYPE, + os_types: ['linux'], + tags: ['user added string for a tag', 'malware'], + tie_breaker_id: TIE_BREAKER, + type: ITEM_TYPE, + updated_at: DATE_NOW, + updated_by: USER, + ...(overrides || {}), +}); + +/** + * This is useful for end to end tests where we remove the auto generated parts for comparisons + * such as created_at, updated_at, and id. + */ +export const getExceptionListItemResponseMockWithoutAutoGeneratedValues = + (): Partial => ({ + comments: [], + created_by: ELASTIC_USER, + description: DESCRIPTION, + entries: ENTRIES, + item_id: ITEM_ID, + list_id: LIST_ID, + name: NAME, + namespace_type: 'single', + os_types: OS_TYPES, + tags: [], + type: ITEM_TYPE, + updated_by: ELASTIC_USER, + }); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..1231764ae7f52 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.test.ts @@ -0,0 +1,240 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getExceptionListItemSchemaMock } from './index.mock'; +import { ExceptionListItemSchema, exceptionListItemSchema } from '.'; + +describe('exception_list_item_schema', () => { + test('it should validate a typical exception list item response', () => { + const payload = getExceptionListItemSchemaMock(); + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "id"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.id; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "list_id"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "item_id"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.item_id; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "item_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "comments"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.comments; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "comments"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "entries"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.entries; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "name"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.name; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "namespace_type" and return "single" as a default value for "namespace_type"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.namespace_type; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect((message.schema as ExceptionListItemSchema).namespace_type).toEqual('single'); + }); + + test('it should NOT accept an undefined for "description"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.description; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta"', () => { + const payload = getExceptionListItemSchemaMock(); + delete payload.meta; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "created_at"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.created_at; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "created_by"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.created_by; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "tie_breaker_id"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.tie_breaker_id; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "tie_breaker_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "type"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.type; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_at"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.updated_at; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_by"', () => { + const payload = getExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.updated_by; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ExceptionListItemSchema & { + extraKey?: string; + } = getExceptionListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = exceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.ts new file mode 100644 index 0000000000000..f3f3986c4ea37 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_item_schema/index.ts @@ -0,0 +1,54 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { namespace_type } from '../../common/namespace_type'; +import { metaOrUndefined } from '../../common/meta'; +import { name } from '../../common/name'; +import { created_at } from '../../common/created_at'; +import { created_by } from '../../common/created_by'; +import { id } from '../../common/id'; +import { tie_breaker_id } from '../../common/tie_breaker_id'; +import { updated_at } from '../../common/updated_at'; +import { updated_by } from '../../common/updated_by'; +import { list_id } from '../../common/list_id'; +import { description } from '../../common/description'; +import { osTypeArray } from '../../common/os_type'; +import { tags } from '../../common/tags'; +import { _versionOrUndefined } from '../../common/underscore_version'; +import { commentsArray } from '../../common/comment'; +import { entriesArray } from '../../common/entries'; +import { item_id } from '../../common/item_id'; +import { exceptionListItemType } from '../../common/exception_list_item_type'; +import { expireTimeOrUndefined } from '../../common/expire_time'; + +export const exceptionListItemSchema = t.exact( + t.type({ + _version: _versionOrUndefined, + comments: commentsArray, + created_at, + created_by, + description, + entries: entriesArray, + expire_time: expireTimeOrUndefined, + id, + item_id, + list_id, + meta: metaOrUndefined, + name, + namespace_type, + os_types: osTypeArray, + tags, + tie_breaker_id, + type: exceptionListItemType, + updated_at, + updated_by, + }) +); + +export type ExceptionListItemSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..07b47f91fead8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.mock.ts @@ -0,0 +1,77 @@ +/* + * 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. + */ + +import { + DATE_NOW, + DESCRIPTION, + ELASTIC_USER, + ENDPOINT_TYPE, + IMMUTABLE, + LIST_ID, + META, + NAME, + TIE_BREAKER, + USER, + VERSION, + _VERSION, +} from '../../constants/index.mock'; +import { + ENDPOINT_LIST_ID, + ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION, + ENDPOINT_TRUSTED_APPS_LIST_ID, + ENDPOINT_TRUSTED_APPS_LIST_NAME, +} from '@kbn/securitysolution-list-constants'; + +import { ExceptionListSchema } from '.'; + +export const getExceptionListSchemaMock = (): ExceptionListSchema => ({ + _version: _VERSION, + created_at: DATE_NOW, + created_by: USER, + description: DESCRIPTION, + id: '1', + immutable: IMMUTABLE, + list_id: ENDPOINT_LIST_ID, + meta: META, + name: 'Sample Endpoint Exception List', + namespace_type: 'agnostic', + os_types: ['linux'], + tags: ['user added string for a tag', 'malware'], + tie_breaker_id: TIE_BREAKER, + type: ENDPOINT_TYPE, + updated_at: DATE_NOW, + updated_by: 'user_name', + version: VERSION, +}); + +export const getTrustedAppsListSchemaMock = (): ExceptionListSchema => { + return { + ...getExceptionListSchemaMock(), + description: ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION, + list_id: ENDPOINT_TRUSTED_APPS_LIST_ID, + name: ENDPOINT_TRUSTED_APPS_LIST_NAME, + }; +}; + +/** + * This is useful for end to end tests where we remove the auto generated parts for comparisons + * such as created_at, updated_at, and id. + */ +export const getExceptionResponseMockWithoutAutoGeneratedValues = + (): Partial => ({ + created_by: ELASTIC_USER, + description: DESCRIPTION, + immutable: IMMUTABLE, + list_id: LIST_ID, + name: NAME, + namespace_type: 'single', + os_types: [], + tags: [], + type: ENDPOINT_TYPE, + updated_by: ELASTIC_USER, + version: VERSION, + }); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..b043cde4c3f0d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.test.ts @@ -0,0 +1,198 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getExceptionListSchemaMock } from './index.mock'; +import { ExceptionListSchema, exceptionListSchema } from '.'; + +describe('exception_list_schema', () => { + test('it should validate a typical exception list response', () => { + const payload = getExceptionListSchemaMock(); + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "id"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.id; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "list_id"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "name"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.name; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "namespace_type" and make "namespace_type" that of "single"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.namespace_type; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect((message.schema as ExceptionListSchema).namespace_type).toEqual('single'); + }); + + test('it should NOT accept an undefined for "description"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.description; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta"', () => { + const payload = getExceptionListSchemaMock(); + delete payload.meta; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "created_at"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.created_at; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "created_by"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.created_by; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "tie_breaker_id"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.tie_breaker_id; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "tie_breaker_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "type"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.type; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_at"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.updated_at; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_by"', () => { + const payload = getExceptionListSchemaMock(); + // @ts-expect-error + delete payload.updated_by; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ExceptionListSchema & { + extraKey?: string; + } = getExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = exceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.ts new file mode 100644 index 0000000000000..e04eadb707657 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { version } from '@kbn/securitysolution-io-ts-types'; +import { _versionOrUndefined } from '../../common/underscore_version'; +import { namespace_type } from '../../common/namespace_type'; +import { metaOrUndefined } from '../../common/meta'; +import { name } from '../../common/name'; +import { created_at } from '../../common/created_at'; +import { created_by } from '../../common/created_by'; +import { id } from '../../common/id'; +import { tie_breaker_id } from '../../common/tie_breaker_id'; +import { immutable } from '../../common/immutable'; +import { updated_at } from '../../common/updated_at'; +import { updated_by } from '../../common/updated_by'; +import { list_id } from '../../common/list_id'; +import { description } from '../../common/description'; +import { osTypeArray } from '../../common/os_type'; +import { exceptionListType } from '../../common/exception_list'; +import { tags } from '../../common/tags'; + +export const exceptionListSchema = t.exact( + t.type({ + _version: _versionOrUndefined, + created_at, + created_by, + description, + id, + immutable, + list_id, + meta: metaOrUndefined, + name, + namespace_type, + os_types: osTypeArray, + tags, + tie_breaker_id, + type: exceptionListType, + updated_at, + updated_by, + version, + }) +); + +export type ExceptionListSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.mock.ts new file mode 100644 index 0000000000000..0acac1da648d5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.mock.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +import { ExceptionListSummarySchema } from '.'; + +export const getListSummaryResponseMock = (): ExceptionListSummarySchema => ({ + windows: 0, + linux: 1, + macos: 2, + total: 3, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.test.ts new file mode 100644 index 0000000000000..b4b6de2e25d1e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.test.ts @@ -0,0 +1,93 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getListSummaryResponseMock } from './index.mock'; +import { ExceptionListSummarySchema, exceptionListSummarySchema } from '.'; + +describe('list_summary_schema', () => { + test('it should validate a typical list summary response', () => { + const payload = getListSummaryResponseMock(); + const decoded = exceptionListSummarySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "windows"', () => { + const payload = getListSummaryResponseMock(); + // @ts-expect-error + delete payload.windows; + const decoded = exceptionListSummarySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "windows"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "linux"', () => { + const payload = getListSummaryResponseMock(); + // @ts-expect-error + delete payload.linux; + const decoded = exceptionListSummarySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "linux"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "macos"', () => { + const payload = getListSummaryResponseMock(); + // @ts-expect-error + delete payload.macos; + const decoded = exceptionListSummarySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "macos"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "total"', () => { + const payload = getListSummaryResponseMock(); + // @ts-expect-error + delete payload.total; + const decoded = exceptionListSummarySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "total"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ExceptionListSummarySchema & { + extraKey?: string; + } = getListSummaryResponseMock(); + payload.extraKey = 'some new value'; + const decoded = exceptionListSummarySchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.ts new file mode 100644 index 0000000000000..7414ca257fbd2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_summary_schema/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import { PositiveInteger } from '@kbn/securitysolution-io-ts-types'; +import * as t from 'io-ts'; + +export const exceptionListSummarySchema = t.exact( + t.type({ + windows: PositiveInteger, + linux: PositiveInteger, + macos: PositiveInteger, + total: PositiveInteger, + }) +); + +export type ExceptionListSummarySchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.mock.ts new file mode 100644 index 0000000000000..75330f4937432 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.mock.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import { FoundAllListItemsSchema } from '.'; +import { getListItemResponseMock } from '../list_item_schema/index.mock'; + +export const getFoundAllListItemsSchemaMock = (): FoundAllListItemsSchema => ({ + data: [getListItemResponseMock()], + total: 1, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.ts new file mode 100644 index 0000000000000..c5812499b3e77 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { listItemSchema } from '../list_item_schema'; +import { total } from '../../common/total'; + +export const foundAllListItemsSchema = t.exact( + t.type({ + data: t.array(listItemSchema), + total, + }) +); + +export type FoundAllListItemsSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..6f8592320895d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { FoundExceptionListItemSchema } from '.'; +import { getExceptionListItemSchemaMock } from '../exception_list_item_schema/index.mock'; + +export const getFoundExceptionListItemSchemaMock = (): FoundExceptionListItemSchema => ({ + data: [getExceptionListItemSchemaMock()], + page: 1, + per_page: 1, + total: 1, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..33d26ca32a5bc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.test.ts @@ -0,0 +1,152 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getFoundExceptionListItemSchemaMock } from './index.mock'; +import { FoundExceptionListItemSchema, foundExceptionListItemSchema } from '.'; +import { ExceptionListItemSchema } from '../exception_list_item_schema'; +import { getExceptionListItemSchemaMock } from '../exception_list_item_schema/index.mock'; + +describe('found_exception_list_item_schema', () => { + test('it should validate a typical exception list response', () => { + const payload = getFoundExceptionListItemSchemaMock(); + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept a malformed exception list item within "data"', () => { + const item: Omit & { + entries?: string; + } = { ...getExceptionListItemSchemaMock(), entries: 'I should be an array' }; + const payload: Omit & { + data?: Array< + Omit & { + entries?: string; + } + >; + } = { ...getFoundExceptionListItemSchemaMock(), data: [item] }; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "I should be an array" supplied to "data,entries"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept a string for "page"', () => { + const payload: Omit & { + page?: string; + } = { ...getFoundExceptionListItemSchemaMock(), page: '1' }; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "page"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept a string for "per_page"', () => { + const payload: Omit & { + per_page?: string; + } = { ...getFoundExceptionListItemSchemaMock(), per_page: '20' }; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "20" supplied to "per_page"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept a string for "total"', () => { + const payload: Omit & { + total?: string; + } = { ...getFoundExceptionListItemSchemaMock(), total: '1' }; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "total"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "page"', () => { + const payload = getFoundExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.page; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "page"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "per_page"', () => { + const payload = getFoundExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.per_page; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "per_page"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "total"', () => { + const payload = getFoundExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.total; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "total"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "data"', () => { + const payload = getFoundExceptionListItemSchemaMock(); + // @ts-expect-error + delete payload.data; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "data"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: FoundExceptionListItemSchema & { + extraKey?: string; + } = getFoundExceptionListItemSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = foundExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.ts new file mode 100644 index 0000000000000..50f57bf424593 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_item_schema/index.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { page } from '../../common/page'; +import { per_page } from '../../common/per_page'; +import { pitId } from '../../common/pit'; +import { total } from '../../common/total'; +import { exceptionListItemSchema } from '../exception_list_item_schema'; + +export const foundExceptionListItemSchema = t.intersection([ + t.exact( + t.type({ + data: t.array(exceptionListItemSchema), + page, + per_page, + total, + }) + ), + t.exact( + t.partial({ + pit: pitId, + }) + ), +]); + +export type FoundExceptionListItemSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.mock.ts new file mode 100644 index 0000000000000..8a6d9fe2d2a79 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.mock.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +import { FoundExceptionListSchema } from '.'; +import { getExceptionListSchemaMock } from '../exception_list_schema/index.mock'; + +export const getFoundExceptionListSchemaMock = (): FoundExceptionListSchema => ({ + data: [getExceptionListSchemaMock()], + page: 1, + per_page: 1, + total: 1, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.test.ts new file mode 100644 index 0000000000000..18d96785ad2eb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.test.ts @@ -0,0 +1,152 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getFoundExceptionListSchemaMock } from './index.mock'; +import { FoundExceptionListSchema, foundExceptionListSchema } from '.'; +import { getExceptionListSchemaMock } from '../exception_list_schema/index.mock'; +import { ExceptionListSchema } from '../exception_list_schema'; + +describe('exception_list_schema', () => { + test('it should validate a typical exception list response', () => { + const payload = getFoundExceptionListSchemaMock(); + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept a malformed exception list item within "data"', () => { + const item: Omit & { + entries?: string[]; + } = { ...getExceptionListSchemaMock(), entries: ['I should not be here'] }; + const payload: Omit & { + data?: Array< + Omit & { + entries?: string[]; + } + >; + } = { ...getFoundExceptionListSchemaMock(), data: [item] }; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'invalid keys "entries,["I should not be here"]"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept a string for "page"', () => { + const payload: Omit & { + page?: string; + } = { ...getFoundExceptionListSchemaMock(), page: '1' }; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "page"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept a string for "per_page"', () => { + const payload: Omit & { + per_page?: string; + } = { ...getFoundExceptionListSchemaMock(), per_page: '20' }; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "20" supplied to "per_page"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept a string for "total"', () => { + const payload: Omit & { + total?: string; + } = { ...getFoundExceptionListSchemaMock(), total: '1' }; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "1" supplied to "total"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "page"', () => { + const payload = getFoundExceptionListSchemaMock(); + // @ts-expect-error + delete payload.page; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "page"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "per_page"', () => { + const payload = getFoundExceptionListSchemaMock(); + // @ts-expect-error + delete payload.per_page; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "per_page"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "total"', () => { + const payload = getFoundExceptionListSchemaMock(); + // @ts-expect-error + delete payload.total; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "total"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "data"', () => { + const payload = getFoundExceptionListSchemaMock(); + // @ts-expect-error + delete payload.data; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "data"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: FoundExceptionListSchema & { + extraKey?: string; + } = getFoundExceptionListSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = foundExceptionListSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.ts new file mode 100644 index 0000000000000..cb7867db7f295 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_exception_list_schema/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { page } from '../../common/page'; +import { per_page } from '../../common/per_page'; +import { pitId } from '../../common/pit'; +import { total } from '../../common/total'; + +import { exceptionListSchema } from '../exception_list_schema'; + +export const foundExceptionListSchema = t.intersection([ + t.exact( + t.type({ + data: t.array(exceptionListSchema), + page, + per_page, + total, + }) + ), + t.exact(t.partial({ pit: pitId })), +]); + +export type FoundExceptionListSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..bc6c6b63dbea5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.mock.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import { FoundListItemSchema } from '.'; +import { getListItemResponseMock } from '../list_item_schema/index.mock'; + +export const getFoundListItemSchemaMock = (): FoundListItemSchema => ({ + cursor: 'WzI1LFsiNmE3NmI2OWQtODBkZi00YWIyLThjM2UtODVmNDY2YjA2YTBlIl1d', + data: [getListItemResponseMock()], + page: 1, + per_page: 25, + total: 1, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.ts new file mode 100644 index 0000000000000..86801ed60bca9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { listItemSchema } from '../list_item_schema'; +import { cursor } from '../../common/cursor'; +import { page } from '../../common/page'; +import { per_page } from '../../common/per_page'; +import { total } from '../../common/total'; + +export const foundListItemSchema = t.exact( + t.type({ + cursor, + data: t.array(listItemSchema), + page, + per_page, + total, + }) +); + +export type FoundListItemSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.mock.ts new file mode 100644 index 0000000000000..07cbb1d03000f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.mock.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import { FoundListSchema } from '.'; +import { getListResponseMock } from '../list_schema/index.mock'; + +export const getFoundListSchemaMock = (): FoundListSchema => ({ + cursor: '123', + data: [getListResponseMock()], + page: 1, + per_page: 1, + total: 1, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.ts new file mode 100644 index 0000000000000..16922174e7496 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { listSchema } from '../list_schema'; +import { cursor } from '../../common/cursor'; +import { page } from '../../common/page'; +import { per_page } from '../../common/per_page'; +import { total } from '../../common/total'; + +export const foundListSchema = t.exact( + t.type({ + cursor, + data: t.array(listSchema), + page, + per_page, + total, + }) +); + +export type FoundListSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.mock.ts new file mode 100644 index 0000000000000..8d1a421acef2e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.mock.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +import { FoundListsBySizeSchema } from '.'; +import { getListResponseMock } from '../list_schema/index.mock'; + +export const getFoundListsBySizeSchemaMock = (): FoundListsBySizeSchema => ({ + smallLists: [getListResponseMock()], + largeLists: [getListResponseMock()], +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.ts new file mode 100644 index 0000000000000..0271416b5f3cf --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { listSchema } from '../list_schema'; + +export const foundListsBySizeSchema = t.exact( + t.type({ + largeLists: t.array(listSchema), + smallLists: t.array(listSchema), + }) +); + +export type FoundListsBySizeSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.mock.ts new file mode 100644 index 0000000000000..9e8293b382cc5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.mock.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import { ImportExceptionsResponseSchema } from '.'; + +export const getImportExceptionsResponseSchemaMock = ( + success = 0, + lists = 0, + items = 0 +): ImportExceptionsResponseSchema => ({ + errors: [], + success: true, + success_count: success, + success_exception_lists: true, + success_count_exception_lists: lists, + success_exception_list_items: true, + success_count_exception_list_items: items, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.test.ts new file mode 100644 index 0000000000000..d5d481fe87bed --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.test.ts @@ -0,0 +1,128 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { importExceptionsResponseSchema, ImportExceptionsResponseSchema } from '.'; +import { getImportExceptionsResponseSchemaMock } from './index.mock'; + +describe('importExceptionsResponseSchema', () => { + test('it should validate a typical exceptions import response', () => { + const payload = getImportExceptionsResponseSchemaMock(); + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "errors"', () => { + const payload: Partial> = + getImportExceptionsResponseSchemaMock(); + delete payload.errors; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "errors"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "success"', () => { + const payload: Partial> = + getImportExceptionsResponseSchemaMock(); + delete payload.success; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "success"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "success_count"', () => { + const payload: Partial> = + getImportExceptionsResponseSchemaMock(); + delete payload.success_count; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "success_count"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "success_exception_lists"', () => { + const payload: Partial> = + getImportExceptionsResponseSchemaMock(); + delete payload.success_exception_lists; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "success_exception_lists"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "success_count_exception_lists"', () => { + const payload: Partial> = + getImportExceptionsResponseSchemaMock(); + delete payload.success_count_exception_lists; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "success_count_exception_lists"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "success_exception_list_items"', () => { + const payload: Partial> = + getImportExceptionsResponseSchemaMock(); + delete payload.success_exception_list_items; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "success_exception_list_items"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "success_count_exception_list_items"', () => { + const payload: Partial> = + getImportExceptionsResponseSchemaMock(); + delete payload.success_count_exception_list_items; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "success_count_exception_list_items"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ImportExceptionsResponseSchema & { + extraKey?: string; + } = getImportExceptionsResponseSchemaMock(); + payload.extraKey = 'some new value'; + const decoded = importExceptionsResponseSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.ts new file mode 100644 index 0000000000000..4a172d2ec10a7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/import_exceptions_schema/index.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { PositiveInteger } from '@kbn/securitysolution-io-ts-types'; + +import { id } from '../../common/id'; +import { list_id } from '../../common/list_id'; +import { item_id } from '../../common/item_id'; + +export const bulkErrorErrorSchema = t.exact( + t.type({ + status_code: t.number, + message: t.string, + }) +); + +export const bulkErrorSchema = t.intersection([ + t.exact( + t.type({ + error: bulkErrorErrorSchema, + }) + ), + t.partial({ + id, + list_id, + item_id, + }), +]); + +export type BulkErrorSchema = t.TypeOf; + +export const importExceptionsResponseSchema = t.exact( + t.type({ + errors: t.array(bulkErrorSchema), + success: t.boolean, + success_count: PositiveInteger, + success_exception_lists: t.boolean, + success_count_exception_lists: PositiveInteger, + success_exception_list_items: t.boolean, + success_count_exception_list_items: PositiveInteger, + }) +); + +export type ImportExceptionsResponseSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/index.ts new file mode 100644 index 0000000000000..04b00f43c7029 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +export * from './acknowledge_schema'; +export * from './create_endpoint_list_schema'; +export * from './exception_list_schema'; +export * from './exception_list_item_schema'; +export * from './found_exception_list_item_schema'; +export * from './found_exception_list_schema'; +export * from './found_all_list_items_schema'; +export * from './found_lists_by_size_schema'; +export * from './found_list_item_schema'; +export * from './found_list_schema'; +export * from './import_exceptions_schema'; +export * from './list_item_schema'; +export * from './list_schema'; +export * from './exception_list_summary_schema'; +export * from './list_item_index_exist_schema'; +export * from './search_list_item_schema'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.mock.ts new file mode 100644 index 0000000000000..b3416ab76852e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.mock.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import { ListItemIndexExistSchema } from '.'; + +export const getListItemIndexExistSchemaResponseMock = (): ListItemIndexExistSchema => ({ + list_index: true, + list_item_index: true, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.test.ts new file mode 100644 index 0000000000000..0c8812795935e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.test.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getListItemIndexExistSchemaResponseMock } from './index.mock'; +import { ListItemIndexExistSchema, listItemIndexExistSchema } from '.'; + +describe('list_item_index_exist_schema', () => { + test('it should validate a typical list item request', () => { + const payload = getListItemIndexExistSchemaResponseMock(); + const decoded = listItemIndexExistSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "list_index"', () => { + const payload = getListItemIndexExistSchemaResponseMock(); + // @ts-expect-error + delete payload.list_index; + const decoded = listItemIndexExistSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_index"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "list_item_index"', () => { + const payload = getListItemIndexExistSchemaResponseMock(); + // @ts-expect-error + delete payload.list_item_index; + const decoded = listItemIndexExistSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_item_index"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ListItemIndexExistSchema & { + extraKey?: string; + } = getListItemIndexExistSchemaResponseMock(); + payload.extraKey = 'some new value'; + const decoded = listItemIndexExistSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.ts new file mode 100644 index 0000000000000..fb1070f72daea --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_index_exist_schema/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +export const listItemIndexExistSchema = t.exact( + t.type({ + list_index: t.boolean, + list_item_index: t.boolean, + }) +); + +export type ListItemIndexExistSchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..10283965276d2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import { ListItemSchema } from '.'; +import { + DATE_NOW, + ELASTIC_USER, + LIST_ID, + LIST_ITEM_ID, + META, + TIE_BREAKER, + TYPE, + USER, + VALUE, +} from '../../constants/index.mock'; + +export const getListItemResponseMock = (): ListItemSchema => ({ + _version: undefined, + '@timestamp': DATE_NOW, + created_at: DATE_NOW, + created_by: USER, + deserializer: undefined, + id: LIST_ITEM_ID, + list_id: LIST_ID, + meta: META, + serializer: undefined, + tie_breaker_id: TIE_BREAKER, + type: TYPE, + updated_at: DATE_NOW, + updated_by: USER, + value: VALUE, +}); + +/** + * This is useful for end to end tests where we remove the auto generated parts for comparisons + * such as created_at, updated_at, and id. + */ +export const getListItemResponseMockWithoutAutoGeneratedValues = (): Partial => ({ + created_by: ELASTIC_USER, + list_id: LIST_ID, + type: TYPE, + updated_by: ELASTIC_USER, + value: VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.test.ts new file mode 100644 index 0000000000000..f855448ff26ef --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.test.ts @@ -0,0 +1,192 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getListItemResponseMock } from './index.mock'; +import { ListItemSchema, listItemSchema } from '.'; + +describe('list_item_schema', () => { + test('it should validate a typical list item response', () => { + const payload = getListItemResponseMock(); + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "id"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.id; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "list_id"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.list_id; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "list_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta"', () => { + const payload = getListItemResponseMock(); + delete payload.meta; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "serializer"', () => { + const payload = getListItemResponseMock(); + delete payload.serializer; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "deserializer"', () => { + const payload = getListItemResponseMock(); + delete payload.deserializer; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "created_at"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.created_at; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "created_by"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.created_by; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "tie_breaker_id"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.tie_breaker_id; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "tie_breaker_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "type"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.type; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_at"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.updated_at; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_by"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.updated_by; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "value"', () => { + const payload = getListItemResponseMock(); + // @ts-expect-error + delete payload.value; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "value"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ListItemSchema & { extraKey?: string } = getListItemResponseMock(); + payload.extraKey = 'some new value'; + const decoded = listItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts new file mode 100644 index 0000000000000..0e7af6ab27267 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; + +import { _versionOrUndefined } from '../../common/underscore_version'; +import { deserializerOrUndefined } from '../../common/deserializer'; +import { metaOrUndefined } from '../../common/meta'; +import { timestampOrUndefined } from '../../common/timestamp'; +import { serializerOrUndefined } from '../../common/serializer'; +import { created_at } from '../../common/created_at'; +import { created_by } from '../../common/created_by'; +import { id } from '../../common/id'; +import { tie_breaker_id } from '../../common/tie_breaker_id'; +import { type } from '../../common/type'; +import { updated_at } from '../../common/updated_at'; +import { updated_by } from '../../common/updated_by'; +import { list_id } from '../../common/list_id'; +import { value } from '../../common/value'; + +export const listItemSchema = t.exact( + t.type({ + _version: _versionOrUndefined, + '@timestamp': timestampOrUndefined, + created_at, + created_by, + deserializer: deserializerOrUndefined, + id, + list_id, + meta: metaOrUndefined, + serializer: serializerOrUndefined, + tie_breaker_id, + type, + updated_at, + updated_by, + value, + }) +); + +export type ListItemSchema = t.TypeOf; + +export const listItemArraySchema = t.array(listItemSchema); +export type ListItemArraySchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts new file mode 100644 index 0000000000000..3b6ff22ceb155 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts @@ -0,0 +1,54 @@ +/* + * 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. + */ + +import { ListSchema } from '.'; +import { + DATE_NOW, + DESCRIPTION, + ELASTIC_USER, + IMMUTABLE, + LIST_ID, + META, + NAME, + TIE_BREAKER, + TYPE, + USER, + VERSION, +} from '../../constants/index.mock'; + +export const getListResponseMock = (): ListSchema => ({ + _version: undefined, + '@timestamp': DATE_NOW, + created_at: DATE_NOW, + created_by: USER, + description: DESCRIPTION, + deserializer: undefined, + id: LIST_ID, + immutable: IMMUTABLE, + meta: META, + name: NAME, + serializer: undefined, + tie_breaker_id: TIE_BREAKER, + type: TYPE, + updated_at: DATE_NOW, + updated_by: USER, + version: VERSION, +}); + +/** + * This is useful for end to end tests where we remove the auto generated parts for comparisons + * such as created_at, updated_at, and id. + */ +export const getListResponseMockWithoutAutoGeneratedValues = (): Partial => ({ + created_by: ELASTIC_USER, + description: DESCRIPTION, + immutable: IMMUTABLE, + name: NAME, + type: TYPE, + updated_by: ELASTIC_USER, + version: VERSION, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.test.ts new file mode 100644 index 0000000000000..920941a2135a8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.test.ts @@ -0,0 +1,192 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getListResponseMock } from './index.mock'; +import { ListSchema, listSchema } from '.'; + +describe('list_schema', () => { + test('it should validate a typical list response', () => { + const payload = getListResponseMock(); + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "id"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.id; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual(['Invalid value "undefined" supplied to "id"']); + expect(message.schema).toEqual({}); + }); + + test('it should accept an undefined for "meta"', () => { + const payload = getListResponseMock(); + delete payload.meta; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "serializer"', () => { + const payload = getListResponseMock(); + delete payload.serializer; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should accept an undefined for "deserializer"', () => { + const payload = getListResponseMock(); + delete payload.deserializer; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT accept an undefined for "created_at"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.created_at; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "created_by"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.created_by; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "created_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "tie_breaker_id"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.tie_breaker_id; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "tie_breaker_id"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "type"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.type; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "type"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_at"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.updated_at; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_at"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "updated_by"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.updated_by; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "updated_by"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "name"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.name; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "name"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should NOT accept an undefined for "description"', () => { + const payload = getListResponseMock(); + // @ts-expect-error + delete payload.description; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "description"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: ListSchema & { extraKey?: string } = getListResponseMock(); + payload.extraKey = 'some new value'; + const decoded = listSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts new file mode 100644 index 0000000000000..687c93ad6f6d0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { version } from '@kbn/securitysolution-io-ts-types'; +import { _versionOrUndefined } from '../../common/underscore_version'; +import { deserializerOrUndefined } from '../../common/deserializer'; +import { metaOrUndefined } from '../../common/meta'; +import { serializerOrUndefined } from '../../common/serializer'; +import { created_at } from '../../common/created_at'; +import { timestampOrUndefined } from '../../common/timestamp'; +import { created_by } from '../../common/created_by'; +import { description } from '../../common/description'; +import { id } from '../../common/id'; +import { immutable } from '../../common/immutable'; +import { name } from '../../common/name'; +import { tie_breaker_id } from '../../common/tie_breaker_id'; +import { type } from '../../common/type'; +import { updated_at } from '../../common/updated_at'; +import { updated_by } from '../../common/updated_by'; + +export const listSchema = t.exact( + t.type({ + _version: _versionOrUndefined, + '@timestamp': timestampOrUndefined, + created_at, + created_by, + description, + deserializer: deserializerOrUndefined, + id, + immutable, + meta: metaOrUndefined, + name, + serializer: serializerOrUndefined, + tie_breaker_id, + type, + updated_at, + updated_by, + version, + }) +); + +export type ListSchema = t.TypeOf; + +export const listArraySchema = t.array(listSchema); +export type ListArraySchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.mock.ts new file mode 100644 index 0000000000000..1ce8e23d4af5b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.mock.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +import { SearchListItemSchema } from '.'; +import { VALUE } from '../../constants/index.mock'; +import { getListItemResponseMock } from '../list_item_schema/index.mock'; + +export const getSearchListItemResponseMock = (): SearchListItemSchema => ({ + items: [getListItemResponseMock()], + value: VALUE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.test.ts new file mode 100644 index 0000000000000..6f89a58e0bc3d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.test.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import { left } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +import { getSearchListItemResponseMock } from './index.mock'; +import { SearchListItemSchema, searchListItemSchema } from '.'; + +describe('search_list_item_schema', () => { + test('it should validate a typical search list item response', () => { + const payload = getSearchListItemResponseMock(); + const decoded = searchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should NOT validate with an "undefined" for "items"', () => { + const { items, ...noItems } = getSearchListItemResponseMock(); + const decoded = searchListItemSchema.decode(noItems); + const checked = exactCheck(noItems, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "items"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should not allow an extra key to be sent in', () => { + const payload: SearchListItemSchema & { extraKey?: string } = getSearchListItemResponseMock(); + payload.extraKey = 'some new value'; + const decoded = searchListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); + expect(message.schema).toEqual({}); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts new file mode 100644 index 0000000000000..8c17db0765005 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import * as t from 'io-ts'; +import { listItemArraySchema } from '../list_item_schema'; + +/** + * NOTE: Although this is defined within "response" this does not expose a REST API + * endpoint right now for this particular response. Instead this is only used internally + * for the plugins at this moment. If this changes, please remove this message. + */ +export const searchListItemSchema = t.exact( + t.type({ + items: listItemArraySchema, + value: t.unknown, + }) +); + +export type SearchListItemSchema = t.TypeOf; + +export const searchListItemArraySchema = t.array(searchListItemSchema); +export type SearchListItemArraySchema = t.TypeOf; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts new file mode 100644 index 0000000000000..8b172753bbc5b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts @@ -0,0 +1,242 @@ +/* + * 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. + */ + +import type { HttpStart } from '@kbn/core-http-browser'; +import type { NotificationsStart } from '@kbn/core-notifications-browser'; +import type { Filter } from '@kbn/es-query'; +import { NamespaceType } from '../common/default_namespace'; +import { ExceptionListType, ExceptionListTypeEnum } from '../common/exception_list'; +import { Page } from '../common/page'; +import { PerPage } from '../common/per_page'; +import { TotalOrUndefined } from '../common/total'; +import { CreateExceptionListItemSchema } from '../request/create_exception_list_item_schema'; +import { CreateExceptionListSchema } from '../request/create_exception_list_schema'; +import { ExceptionListId } from '../request/get_exception_filter_schema'; +import { UpdateExceptionListItemSchema } from '../request/update_exception_list_item_schema'; +import { UpdateExceptionListSchema } from '../request/update_exception_list_schema'; +import { ExceptionListItemSchema } from '../response/exception_list_item_schema'; +import { ExceptionListSchema } from '../response/exception_list_schema'; + +interface BaseParams { + http: HttpStart; + signal: AbortSignal; +} + +export interface DuplicateExceptionListProps extends BaseParams { + listId: string; + namespaceType: NamespaceType; + includeExpiredExceptions: boolean; +} + +export interface ApiListDuplicateProps + extends Omit { + onError: (err: Error) => void; + onSuccess: (newList: ExceptionListSchema) => void; +} + +export interface ExceptionListFilter { + name?: string | null; + list_id?: string | null; + created_by?: string | null; + types?: ExceptionListTypeEnum[] | null; + tags?: string | null; +} + +export interface UseExceptionListsProps { + errorMessage: string; + filterOptions?: ExceptionListFilter; + http: HttpStart; + namespaceTypes: NamespaceType[]; + notifications: NotificationsStart; + initialPagination?: Pagination; + hideLists?: readonly string[]; + initialSort?: Sort; +} + +export interface UseExceptionListProps { + http: HttpStart; + lists: ExceptionListIdentifiers[]; + onError?: (arg: string[]) => void; + filterOptions: FilterExceptionsOptions[]; + pagination?: Pagination; + showDetectionsListsOnly: boolean; + showEndpointListsOnly: boolean; + matchFilters: boolean; + onSuccess?: (arg: UseExceptionListItemsSuccess) => void; + sort?: Sort; +} + +export interface FilterExceptionsOptions { + filter: string; + tags: string[]; +} + +export interface ApiCallMemoProps { + id: string; + namespaceType: NamespaceType; + onError: (arg: Error) => void; + onSuccess: () => void; +} + +// TODO: Switch to use ApiCallMemoProps +// after cleaning up exceptions/api file to +// remove unnecessary validation checks +export interface ApiListExportProps { + id: string; + includeExpiredExceptions: boolean; + listId: string; + namespaceType: NamespaceType; + onError: (err: Error) => void; + onSuccess: (blob: Blob) => void; +} + +export interface Sort { + field: string; + order: string; +} +export interface Pagination { + page: Page; + perPage: PerPage; + total: TotalOrUndefined; +} + +export interface UseExceptionListItemsSuccess { + exceptions: ExceptionListItemSchema[]; + pagination: Pagination; +} + +export interface ExceptionListIdentifiers { + id: string; + listId: string; + namespaceType: NamespaceType; + type: ExceptionListType; +} + +export interface ApiCallFindListsItemsMemoProps { + lists: ExceptionListIdentifiers[]; + pagination: Partial; + showDetectionsListsOnly: boolean; + showEndpointListsOnly: boolean; + filter?: string; + onError: (arg: string[]) => void; + onSuccess: (arg: UseExceptionListItemsSuccess) => void; +} + +export interface ApiCallGetExceptionFilterFromIdsMemoProps extends GetExceptionFilterOptionalProps { + exceptionListIds: ExceptionListId[]; + onError: (arg: string[]) => void; + onSuccess: (arg: Filter) => void; +} + +export interface ApiCallGetExceptionFilterFromExceptionsMemoProps + extends GetExceptionFilterOptionalProps { + exceptions: Array; + onError: (arg: string[]) => void; + onSuccess: (arg: Filter) => void; +} + +export interface ExportExceptionListProps { + http: HttpStart; + id: string; + listId: string; + namespaceType: NamespaceType; + includeExpiredExceptions: boolean; + signal: AbortSignal; +} + +export interface AddEndpointExceptionListProps { + http: HttpStart; + signal: AbortSignal; +} + +export interface UpdateExceptionListItemProps { + http: HttpStart; + listItem: UpdateExceptionListItemSchema; + signal: AbortSignal; +} + +export interface UpdateExceptionListProps { + http: HttpStart; + list: UpdateExceptionListSchema; + signal: AbortSignal; +} + +export interface AddExceptionListItemProps { + http: HttpStart; + listItem: CreateExceptionListItemSchema; + signal: AbortSignal; +} + +export interface AddExceptionListProps { + http: HttpStart; + list: CreateExceptionListSchema; + signal: AbortSignal; +} + +export interface UseExceptionListsSuccess { + exceptions: ExceptionListSchema[]; + pagination: Pagination; +} + +export interface ApiCallFetchExceptionListsProps { + http: HttpStart; + namespaceTypes: string; + pagination: Partial; + sort?: Sort; + filters: string; + signal: AbortSignal; +} + +export interface ApiCallByIdProps { + http: HttpStart; + id: string; + namespaceType: NamespaceType; + signal: AbortSignal; +} + +export interface ApiCallByListIdProps { + http: HttpStart; + listIds: string[]; + namespaceTypes: NamespaceType[]; + pagination: Partial; + search?: string; + filter?: string; + signal: AbortSignal; +} + +export type AddExceptionList = UpdateExceptionListSchema | CreateExceptionListSchema; + +export interface PersistHookProps { + http: HttpStart; + onError: (arg: Error) => void; +} + +export interface ExceptionList extends ExceptionListSchema { + totalItems: number; +} + +export interface GetExceptionFilterOptionalProps { + signal?: AbortSignal; + chunkSize?: number; + alias?: string; + excludeExceptions?: boolean; +} + +export interface GetExceptionFilterFromExceptionListIdsProps + extends GetExceptionFilterOptionalProps { + http: HttpStart; + exceptionListIds: ExceptionListId[]; +} + +export interface GetExceptionFilterFromExceptionsProps extends GetExceptionFilterOptionalProps { + http: HttpStart; + exceptions: Array; +} + +export interface ExceptionFilterResponse { + filter: Filter; +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/tsconfig.json new file mode 100644 index 0000000000000..b8097b0b7b12d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "include": ["**/*.ts"], + "kbn_references": [ + "@kbn/securitysolution-io-ts-types", + "@kbn/securitysolution-io-ts-utils", + "@kbn/securitysolution-list-constants", + "@kbn/es-query", + "@kbn/core-http-browser", + "@kbn/core-notifications-browser", + "@kbn/securitysolution-exceptions-common" + ], + "exclude": ["target/**/*"] +} diff --git a/packages/kbn-securitysolution-list-api/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/README.md similarity index 100% rename from packages/kbn-securitysolution-list-api/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-list-api/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/index.ts new file mode 100644 index 0000000000000..afe1280b9b856 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +export * from './src/api'; +export * from './src/fp_utils'; +export * from './src/list_api'; +export * from './src/list_item_api'; +export * from './src/types'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/jest.config.js new file mode 100644 index 0000000000000..9e9844e5cbd01 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-list-api'], +}; diff --git a/packages/kbn-securitysolution-list-api/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-list-api/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-list-api/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/package.json new file mode 100644 index 0000000000000..5159b04f62049 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/securitysolution-list-api", + "version": "1.0.0", + "description": "security solution list REST API", + "license": "Elastic License 2.0", + "private": true +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/api/index.ts new file mode 100644 index 0000000000000..c8fe4143d1bdb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/api/index.ts @@ -0,0 +1,664 @@ +/* + * 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. + */ + +import { chain, fromEither, tryCatch } from 'fp-ts/lib/TaskEither'; +import { flow } from 'fp-ts/lib/function'; +import { validateEither } from '@kbn/securitysolution-io-ts-utils'; +import { + CreateEndpointListSchema, + ExceptionListItemSchema, + ExceptionListSchema, + FoundExceptionListItemSchema, + FoundExceptionListSchema, + createEndpointListSchema, + exceptionListItemSchema, + exceptionListSchema, + foundExceptionListItemSchema, + foundExceptionListSchema, + AddEndpointExceptionListProps, + AddExceptionListItemProps, + AddExceptionListProps, + ApiCallByIdProps, + ApiCallByListIdProps, + ApiCallFetchExceptionListsProps, + ExportExceptionListProps, + UpdateExceptionListItemProps, + UpdateExceptionListProps, + GetExceptionFilterFromExceptionListIdsProps, + GetExceptionFilterFromExceptionsProps, + ExceptionFilterResponse, + DuplicateExceptionListProps, +} from '@kbn/securitysolution-io-ts-list-types'; + +import { + ENDPOINT_LIST_URL, + INTERNAL_EXCEPTION_FILTER, + EXCEPTION_LIST_ITEM_URL, + EXCEPTION_LIST_URL, +} from '@kbn/securitysolution-list-constants'; +import { toError, toPromise } from '../fp_utils'; + +const version = '2023-10-31'; + +/** + * Add new ExceptionList + * + * @param http Kibana http service + * @param list exception list to add + * @param signal to cancel request + * + * @throws An error if response is not OK + * + */ +const addExceptionList = async ({ + http, + list, + signal, +}: AddExceptionListProps): Promise => + http.fetch(EXCEPTION_LIST_URL, { + body: JSON.stringify(list), + method: 'POST', + signal, + version, + }); + +const addExceptionListWithValidation = async ({ + http, + list, + signal, +}: AddExceptionListProps): Promise => + flow( + () => + tryCatch( + () => + addExceptionList({ + http, + list, + signal, + }), + toError + ), + chain((response) => fromEither(validateEither(exceptionListSchema, response))), + flow(toPromise) + )(); + +export { addExceptionListWithValidation as addExceptionList }; + +/** + * Add new ExceptionListItem + * + * @param http Kibana http service + * @param listItem exception list item to add + * @param signal to cancel request + * + * @throws An error if response is not OK + * + */ +const addExceptionListItem = async ({ + http, + listItem, + signal, +}: AddExceptionListItemProps): Promise => + http.fetch(EXCEPTION_LIST_ITEM_URL, { + body: JSON.stringify(listItem), + method: 'POST', + signal, + version, + }); + +const addExceptionListItemWithValidation = async ({ + http, + listItem, + signal, +}: AddExceptionListItemProps): Promise => + flow( + () => + tryCatch( + () => + addExceptionListItem({ + http, + listItem, + signal, + }), + toError + ), + chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), + flow(toPromise) + )(); + +export { addExceptionListItemWithValidation as addExceptionListItem }; + +/** + * Update existing ExceptionList + * + * @param http Kibana http service + * @param list exception list to add + * @param signal to cancel request + * + * @throws An error if response is not OK + * + */ +const updateExceptionList = async ({ + http, + list, + signal, +}: UpdateExceptionListProps): Promise => + http.fetch(EXCEPTION_LIST_URL, { + body: JSON.stringify(list), + method: 'PUT', + signal, + version, + }); + +const updateExceptionListWithValidation = async ({ + http, + list, + signal, +}: UpdateExceptionListProps): Promise => + flow( + () => + tryCatch( + () => + updateExceptionList({ + http, + list, + signal, + }), + toError + ), + chain((response) => fromEither(validateEither(exceptionListSchema, response))), + flow(toPromise) + )(); + +export { updateExceptionListWithValidation as updateExceptionList }; + +/** + * Update existing ExceptionListItem + * + * @param http Kibana http service + * @param listItem exception list item to add + * @param signal to cancel request + * + * @throws An error if response is not OK + * + */ +const updateExceptionListItem = async ({ + http, + listItem, + signal, +}: UpdateExceptionListItemProps): Promise => + http.fetch(EXCEPTION_LIST_ITEM_URL, { + body: JSON.stringify(listItem), + method: 'PUT', + signal, + version, + }); + +const updateExceptionListItemWithValidation = async ({ + http, + listItem, + signal, +}: UpdateExceptionListItemProps): Promise => + flow( + () => + tryCatch( + () => + updateExceptionListItem({ + http, + listItem, + signal, + }), + toError + ), + chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), + flow(toPromise) + )(); + +export { updateExceptionListItemWithValidation as updateExceptionListItem }; + +/** + * Fetch all ExceptionLists (optionally by namespaceType) + * + * @param http Kibana http service + * @param namespaceTypes ExceptionList namespace_types of lists to find + * @param filters search bar filters + * @param pagination optional + * @param signal to cancel request + * + * @throws An error if request params or response is not OK + */ +const fetchExceptionLists = async ({ + http, + filters, + namespaceTypes, + pagination, + signal, + sort, +}: ApiCallFetchExceptionListsProps): Promise => { + const query = { + filter: filters || undefined, + namespace_type: namespaceTypes, + page: pagination.page ? `${pagination.page}` : '1', + per_page: pagination.perPage ? `${pagination.perPage}` : '20', + sort_field: sort?.field ? sort?.field : 'exception-list.created_at', + sort_order: sort?.order ? sort?.order : 'desc', + }; + + return http.fetch(`${EXCEPTION_LIST_URL}/_find`, { + method: 'GET', + query, + signal, + version, + }); +}; + +const fetchExceptionListsWithValidation = async ({ + filters, + http, + namespaceTypes, + pagination, + signal, + sort, +}: ApiCallFetchExceptionListsProps): Promise => + flow( + () => + tryCatch( + () => + fetchExceptionLists({ + filters, + http, + namespaceTypes, + pagination, + signal, + sort, + }), + toError + ), + chain((response) => fromEither(validateEither(foundExceptionListSchema, response))), + flow(toPromise) + )(); + +export { fetchExceptionListsWithValidation as fetchExceptionLists }; + +/** + * Fetch an ExceptionList by providing a ExceptionList ID + * + * @param http Kibana http service + * @param id ExceptionList ID (not list_id) + * @param namespaceType ExceptionList namespace_type + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +const fetchExceptionListById = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + http.fetch(EXCEPTION_LIST_URL, { + method: 'GET', + query: { id, namespace_type: namespaceType }, + signal, + version, + }); + +const fetchExceptionListByIdWithValidation = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + flow( + () => + tryCatch( + () => + fetchExceptionListById({ + http, + id, + namespaceType, + signal, + }), + toError + ), + chain((response) => fromEither(validateEither(exceptionListSchema, response))), + flow(toPromise) + )(); + +export { fetchExceptionListByIdWithValidation as fetchExceptionListById }; + +/** + * Fetch an ExceptionList's ExceptionItems by providing a ExceptionList list_id + * + * @param http Kibana http service + * @param listIds ExceptionList list_ids (not ID) + * @param namespaceTypes ExceptionList namespace_types + * @param search optional - simple search string + * @param filter optional + * @param pagination optional + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +const fetchExceptionListsItemsByListIds = async ({ + http, + listIds, + namespaceTypes, + filter, + pagination, + search, + signal, +}: ApiCallByListIdProps): Promise => { + const query = { + list_id: listIds.join(','), + namespace_type: namespaceTypes.join(','), + page: pagination.page ? `${pagination.page}` : '1', + per_page: pagination.perPage ? `${pagination.perPage}` : '20', + search, + sort_field: 'exception-list.created_at', + sort_order: 'desc', + filter, + }; + + return http.fetch(`${EXCEPTION_LIST_ITEM_URL}/_find`, { + method: 'GET', + query, + signal, + version, + }); +}; + +const fetchExceptionListsItemsByListIdsWithValidation = async ({ + filter, + http, + listIds, + namespaceTypes, + pagination, + search, + signal, +}: ApiCallByListIdProps): Promise => + flow( + () => + tryCatch( + () => + fetchExceptionListsItemsByListIds({ + filter, + http, + listIds, + namespaceTypes, + pagination, + search, + signal, + }), + toError + ), + chain((response) => fromEither(validateEither(foundExceptionListItemSchema, response))), + flow(toPromise) + )(); + +export { fetchExceptionListsItemsByListIdsWithValidation as fetchExceptionListsItemsByListIds }; + +/** + * Fetch an ExceptionListItem by providing a ExceptionListItem ID + * + * @param http Kibana http service + * @param id ExceptionListItem ID (not item_id) + * @param namespaceType ExceptionList namespace_type + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +const fetchExceptionListItemById = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + http.fetch(EXCEPTION_LIST_ITEM_URL, { + method: 'GET', + query: { id, namespace_type: namespaceType }, + signal, + version, + }); + +const fetchExceptionListItemByIdWithValidation = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + flow( + () => tryCatch(() => fetchExceptionListItemById({ http, id, namespaceType, signal }), toError), + chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), + flow(toPromise) + )(); + +export { fetchExceptionListItemByIdWithValidation as fetchExceptionListItemById }; + +/** + * Delete an ExceptionList by providing a ExceptionList ID + * + * @param http Kibana http service + * @param id ExceptionList ID (not list_id) + * @param namespaceType ExceptionList namespace_type + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +const deleteExceptionListById = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + http.fetch(EXCEPTION_LIST_URL, { + method: 'DELETE', + query: { id, namespace_type: namespaceType }, + signal, + version, + }); + +const deleteExceptionListByIdWithValidation = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + flow( + () => tryCatch(() => deleteExceptionListById({ http, id, namespaceType, signal }), toError), + chain((response) => fromEither(validateEither(exceptionListSchema, response))), + flow(toPromise) + )(); + +export { deleteExceptionListByIdWithValidation as deleteExceptionListById }; + +/** + * Delete an ExceptionListItem by providing a ExceptionListItem ID + * + * @param http Kibana http service + * @param id ExceptionListItem ID (not item_id) + * @param namespaceType ExceptionList namespace_type + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +const deleteExceptionListItemById = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + http.fetch(EXCEPTION_LIST_ITEM_URL, { + method: 'DELETE', + query: { id, namespace_type: namespaceType }, + signal, + version, + }); + +const deleteExceptionListItemByIdWithValidation = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + flow( + () => tryCatch(() => deleteExceptionListItemById({ http, id, namespaceType, signal }), toError), + chain((response) => fromEither(validateEither(exceptionListItemSchema, response))), + flow(toPromise) + )(); + +export { deleteExceptionListItemByIdWithValidation as deleteExceptionListItemById }; + +/** + * Add new Endpoint ExceptionList + * + * @param http Kibana http service + * @param signal to cancel request + * + * @throws An error if response is not OK + * + */ +const addEndpointExceptionList = async ({ + http, + signal, +}: AddEndpointExceptionListProps): Promise => + http.fetch(ENDPOINT_LIST_URL, { + method: 'POST', + signal, + version, + }); + +const addEndpointExceptionListWithValidation = async ({ + http, + signal, +}: AddEndpointExceptionListProps): Promise => + flow( + () => tryCatch(() => addEndpointExceptionList({ http, signal }), toError), + chain((response) => fromEither(validateEither(createEndpointListSchema, response))), + flow(toPromise) + )(); + +export { addEndpointExceptionListWithValidation as addEndpointExceptionList }; + +/** + * Export an ExceptionList by providing a ExceptionList ID + * + * @param http Kibana http service + * @param id ExceptionList ID (not list_id) + * @param includeExpiredExceptions boolean for including expired exceptions + * @param listId ExceptionList LIST_ID (not id) + * @param namespaceType ExceptionList namespace_type + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +export const exportExceptionList = async ({ + http, + id, + includeExpiredExceptions, + listId, + namespaceType, + signal, +}: ExportExceptionListProps): Promise => + http.fetch(`${EXCEPTION_LIST_URL}/_export`, { + method: 'POST', + query: { + id, + list_id: listId, + namespace_type: namespaceType, + include_expired_exceptions: includeExpiredExceptions, + }, + signal, + version, + }); + +/** + * Create a Filter query from an exception list id + * + * @param exceptionListId The id of the exception list from which create a Filter query + * @param signal AbortSignal for cancelling request + * + * @throws An error if response is not OK + */ +export const getExceptionFilterFromExceptionListIds = async ({ + alias, + chunkSize, + exceptionListIds, + excludeExceptions, + http, + signal, +}: GetExceptionFilterFromExceptionListIdsProps): Promise => + http.fetch(INTERNAL_EXCEPTION_FILTER, { + method: 'POST', + version: '1', + body: JSON.stringify({ + exception_list_ids: exceptionListIds, + type: 'exception_list_ids', + alias, + exclude_exceptions: excludeExceptions, + chunk_size: chunkSize, + }), + signal, + }); + +/** + * Create a Filter query from a list of exceptions + * + * @param exceptions Exception items to be made into a `Filter` query + * @param signal AbortSignal for cancelling request + * + * @throws An error if response is not OK + */ +export const getExceptionFilterFromExceptions = async ({ + exceptions, + alias, + excludeExceptions, + http, + chunkSize, + signal, +}: GetExceptionFilterFromExceptionsProps): Promise => + http.fetch(INTERNAL_EXCEPTION_FILTER, { + method: 'POST', + version: '1', + body: JSON.stringify({ + exceptions, + type: 'exception_items', + alias, + exclude_exceptions: excludeExceptions, + chunk_size: chunkSize, + }), + signal, + }); + +/** + * Duplicate an ExceptionList and its items by providing a ExceptionList list_id + * + * @param http Kibana http service + * @param includeExpiredExceptions boolean for including exception items with expired TTL + * @param listId ExceptionList LIST_ID (not id) + * @param namespaceType ExceptionList namespace_type + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +export const duplicateExceptionList = async ({ + http, + includeExpiredExceptions, + listId, + namespaceType, + signal, +}: DuplicateExceptionListProps): Promise => + http.fetch(`${EXCEPTION_LIST_URL}/_duplicate`, { + method: 'POST', + query: { + list_id: listId, + namespace_type: namespaceType, + include_expired_exceptions: includeExpiredExceptions, + }, + signal, + version, + }); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/fp_utils/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/fp_utils/index.test.ts new file mode 100644 index 0000000000000..574c0f97292ef --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/fp_utils/index.test.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { tryCatch } from 'fp-ts/lib/TaskEither'; + +import { toPromise } from '.'; + +describe('toPromise', () => { + it('rejects with left if TaskEither is left', async () => { + const task = tryCatch(() => Promise.reject(new Error('whoops')), String); + + await expect(toPromise(task)).rejects.toEqual('Error: whoops'); + }); + + it('resolves with right if TaskEither is right', async () => { + const task = tryCatch(() => Promise.resolve('success'), String); + + await expect(toPromise(task)).resolves.toEqual('success'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/fp_utils/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/fp_utils/index.ts new file mode 100644 index 0000000000000..1360c78db59ef --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/fp_utils/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { TaskEither } from 'fp-ts/lib/TaskEither'; +import { fold } from 'fp-ts/lib/Either'; + +// TODO: This is copied in a few other spots and probably should live within its own kbn package +// rather than living here. A package such as kbn-security-solution-fp-utils +export const toPromise = async (taskEither: TaskEither): Promise => + pipe( + await taskEither(), + fold( + (e) => Promise.reject(e), + (a) => Promise.resolve(a) + ) + ); + +export const toError = (e: unknown): Error => (e instanceof Error ? e : new Error(String(e))); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/index.test.ts new file mode 100644 index 0000000000000..1168b4e491951 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/index.test.ts @@ -0,0 +1,443 @@ +/* + * 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. + */ + +import { createListIndex, deleteList, exportList, findLists, importList, readListIndex } from '.'; +import { + ApiPayload, + DeleteListParams, + ExportListParams, + FindListsParams, + ImportListParams, +} from '../types'; + +import { HttpFetchOptions } from '@kbn/core-http-browser'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; + +import { getFoundListSchemaMock } from './mocks/response/found_list_schema.mock'; +import { getListResponseMock } from './mocks/response/list_schema.mock'; +import { getListItemIndexExistSchemaResponseMock } from './mocks/response/list_item_index_exist_schema.mock'; +import { getAcknowledgeSchemaResponseMock } from './mocks/response/acknowledge_schema.mock'; + +describe('Value Lists API', () => { + let httpMock: ReturnType; + + beforeEach(() => { + httpMock = httpServiceMock.createStartContract(); + }); + describe('deleteList', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getListResponseMock()); + }); + + it('DELETEs specifying the id as a query parameter', async () => { + const abortCtrl = new AbortController(); + const payload: ApiPayload = { + deleteReferences: false, + id: 'list-id', + ignoreReferences: true, + }; + await deleteList({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists', + expect.objectContaining({ + method: 'DELETE', + query: { deleteReferences: false, id: 'list-id', ignoreReferences: true }, + }) + ); + }); + + it('rejects with an error if request payload is invalid (and does not make API call)', async () => { + const abortCtrl = new AbortController(); + const payload: Omit, 'id'> & { + id: number; + } = { id: 23 }; + + await expect( + deleteList({ + http: httpMock, + ...(payload as unknown as ApiPayload), + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "23" supplied to "id"')); + expect(httpMock.fetch).not.toHaveBeenCalled(); + }); + + it('rejects with an error if response payload is invalid', async () => { + const abortCtrl = new AbortController(); + const payload: ApiPayload = { id: 'list-id' }; + const badResponse = { ...getListResponseMock(), id: undefined }; + httpMock.fetch.mockResolvedValue(badResponse); + + await expect( + deleteList({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "id"')); + }); + }); + describe('findLists', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getFoundListSchemaMock()); + }); + + it('GETs from the lists endpoint', async () => { + const abortCtrl = new AbortController(); + await findLists({ + http: httpMock, + pageIndex: 1, + pageSize: 10, + signal: abortCtrl.signal, + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/_find', + expect.objectContaining({ + method: 'GET', + }) + ); + }); + + it('sends pagination as query parameters', async () => { + const abortCtrl = new AbortController(); + await findLists({ + cursor: 'cursor', + http: httpMock, + pageIndex: 1, + pageSize: 10, + signal: abortCtrl.signal, + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/_find', + expect.objectContaining({ + query: { + cursor: 'cursor', + page: 1, + per_page: 10, + }, + }) + ); + }); + + it('sends sort_field and sort_order as query parameters', async () => { + const abortCtrl = new AbortController(); + await findLists({ + cursor: 'cursor', + http: httpMock, + pageIndex: 1, + pageSize: 10, + signal: abortCtrl.signal, + sortField: 'created_at', + sortOrder: 'desc', + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/_find', + expect.objectContaining({ + query: { + cursor: 'cursor', + page: 1, + per_page: 10, + sort_field: 'created_at', + sort_order: 'desc', + }, + }) + ); + }); + + it('rejects with an error if request payload is invalid (and does not make API call)', async () => { + const abortCtrl = new AbortController(); + const payload: ApiPayload = { + pageIndex: 10, + pageSize: 0, + }; + + await expect( + findLists({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "0" supplied to "per_page"')); + expect(httpMock.fetch).not.toHaveBeenCalled(); + }); + + it('rejects with an error if response payload is invalid', async () => { + const abortCtrl = new AbortController(); + const payload: ApiPayload = { + pageIndex: 1, + pageSize: 10, + }; + const badResponse = { ...getFoundListSchemaMock(), cursor: undefined }; + httpMock.fetch.mockResolvedValue(badResponse); + + await expect( + findLists({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "cursor"')); + }); + }); + describe('importList', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getListResponseMock()); + }); + + it('POSTs the file', async () => { + const abortCtrl = new AbortController(); + const file = new File([], 'name'); + + await importList({ + file, + http: httpMock, + listId: 'my_list', + signal: abortCtrl.signal, + type: 'keyword', + }); + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items/_import', + expect.objectContaining({ + method: 'POST', + }) + ); + + // httpmock's fetch signature is inferred incorrectly + const [[, { body }]] = httpMock.fetch.mock.calls as unknown as Array< + [unknown, HttpFetchOptions] + >; + const actualFile = (body as FormData).get('file'); + expect(actualFile).toEqual(file); + }); + + it('sends type and id as query parameters', async () => { + const abortCtrl = new AbortController(); + const file = new File([], 'name'); + + await importList({ + file, + http: httpMock, + listId: 'my_list', + signal: abortCtrl.signal, + type: 'keyword', + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items/_import', + expect.objectContaining({ + query: { list_id: 'my_list', type: 'keyword' }, + }) + ); + }); + + it('rejects with an error if request body is invalid (and does not make API call)', async () => { + const abortCtrl = new AbortController(); + const payload: ApiPayload = { + file: undefined as unknown as File, + listId: 'list-id', + type: 'ip', + }; + + await expect( + importList({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "file"')); + expect(httpMock.fetch).not.toHaveBeenCalled(); + }); + + it('rejects with an error if request params are invalid (and does not make API call)', async () => { + const abortCtrl = new AbortController(); + const file = new File([], 'name'); + const payload: ApiPayload = { + file, + listId: 'list-id', + type: 'other' as 'ip', + }; + + await expect( + importList({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "other" supplied to "type"')); + expect(httpMock.fetch).not.toHaveBeenCalled(); + }); + + it('rejects with an error if response payload is invalid', async () => { + const abortCtrl = new AbortController(); + const file = new File([], 'name'); + const payload: ApiPayload = { + file, + listId: 'list-id', + type: 'ip', + }; + const badResponse = { ...getListResponseMock(), id: undefined }; + httpMock.fetch.mockResolvedValue(badResponse); + + await expect( + importList({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "id"')); + }); + }); + describe('exportList', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue({}); + }); + + it('POSTs to the export endpoint', async () => { + const abortCtrl = new AbortController(); + + await exportList({ + http: httpMock, + listId: 'my_list', + signal: abortCtrl.signal, + }); + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items/_export', + expect.objectContaining({ + method: 'POST', + }) + ); + }); + + it('sends type and id as query parameters', async () => { + const abortCtrl = new AbortController(); + + await exportList({ + http: httpMock, + listId: 'my_list', + signal: abortCtrl.signal, + }); + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items/_export', + expect.objectContaining({ + query: { list_id: 'my_list' }, + }) + ); + }); + + it('rejects with an error if request params are invalid (and does not make API call)', async () => { + const abortCtrl = new AbortController(); + const payload: ApiPayload = { + listId: 23 as unknown as string, + }; + + await expect( + exportList({ + http: httpMock, + ...payload, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "23" supplied to "list_id"')); + expect(httpMock.fetch).not.toHaveBeenCalled(); + }); + }); + + describe('readListIndex', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getListItemIndexExistSchemaResponseMock()); + }); + + it('GETs the list index', async () => { + const abortCtrl = new AbortController(); + await readListIndex({ + http: httpMock, + signal: abortCtrl.signal, + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/index', + expect.objectContaining({ + method: 'GET', + }) + ); + }); + + it('returns the response when valid', async () => { + const abortCtrl = new AbortController(); + const result = await readListIndex({ + http: httpMock, + signal: abortCtrl.signal, + }); + + expect(result).toEqual(getListItemIndexExistSchemaResponseMock()); + }); + + it('rejects with an error if response payload is invalid', async () => { + const abortCtrl = new AbortController(); + const badResponse = { ...getListItemIndexExistSchemaResponseMock(), list_index: undefined }; + httpMock.fetch.mockResolvedValue(badResponse); + + await expect( + readListIndex({ + http: httpMock, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "list_index"')); + }); + }); + + describe('createListIndex', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getAcknowledgeSchemaResponseMock()); + }); + + it('GETs the list index', async () => { + const abortCtrl = new AbortController(); + await createListIndex({ + http: httpMock, + signal: abortCtrl.signal, + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/index', + expect.objectContaining({ + method: 'POST', + }) + ); + }); + + it('returns the response when valid', async () => { + const abortCtrl = new AbortController(); + const result = await createListIndex({ + http: httpMock, + signal: abortCtrl.signal, + }); + + expect(result).toEqual(getAcknowledgeSchemaResponseMock()); + }); + + it('rejects with an error if response payload is invalid', async () => { + const abortCtrl = new AbortController(); + const badResponse = { acknowledged: undefined }; + httpMock.fetch.mockResolvedValue(badResponse); + + await expect( + createListIndex({ + http: httpMock, + signal: abortCtrl.signal, + }) + ).rejects.toEqual(new Error('Invalid value "undefined" supplied to "acknowledged"')); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/index.ts new file mode 100644 index 0000000000000..93160ca739e2e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/index.ts @@ -0,0 +1,342 @@ +/* + * 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. + */ + +import { chain, fromEither, map, tryCatch } from 'fp-ts/lib/TaskEither'; +import { flow } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { validateEither } from '@kbn/securitysolution-io-ts-utils'; +import { + AcknowledgeSchema, + DeleteListSchemaEncoded, + ExportListItemQuerySchemaEncoded, + FindListSchemaEncoded, + FoundListSchema, + ImportListItemQuerySchemaEncoded, + ImportListItemSchemaEncoded, + ListItemIndexExistSchema, + ListSchema, + ReadListSchema, + acknowledgeSchema, + deleteListSchema, + readListSchema, + exportListItemQuerySchema, + findListSchema, + foundListSchema, + importListItemQuerySchema, + importListItemSchema, + listItemIndexExistSchema, + listSchema, + foundListsBySizeSchema, + FoundListsBySizeSchema, +} from '@kbn/securitysolution-io-ts-list-types'; +import { + LIST_INDEX, + LIST_ITEM_URL, + LIST_PRIVILEGES_URL, + LIST_URL, + INTERNAL_FIND_LISTS_BY_SIZE, +} from '@kbn/securitysolution-list-constants'; +import { toError, toPromise } from '../fp_utils'; + +import { + ApiParams, + DeleteListParams, + ExportListParams, + FindListsParams, + ImportListParams, + GetListByIdParams, +} from '../types'; + +export type { + ApiParams, + DeleteListParams, + ExportListParams, + FindListsParams, + ImportListParams, +} from '../types'; + +const version = '2023-10-31'; + +const findLists = async ({ + http, + cursor, + page, + // eslint-disable-next-line @typescript-eslint/naming-convention + per_page, + signal, + // eslint-disable-next-line @typescript-eslint/naming-convention + sort_field, + // eslint-disable-next-line @typescript-eslint/naming-convention + sort_order, +}: ApiParams & FindListSchemaEncoded): Promise => { + return http.fetch(`${LIST_URL}/_find`, { + method: 'GET', + query: { + cursor, + page, + per_page, + sort_field, + sort_order, + }, + signal, + version, + }); +}; + +const findListsWithValidation = async ({ + cursor, + http, + pageIndex, + pageSize, + signal, + sortField, + sortOrder, +}: FindListsParams): Promise => + pipe( + { + cursor: cursor != null ? cursor.toString() : undefined, + page: pageIndex != null ? pageIndex.toString() : undefined, + per_page: pageSize != null ? pageSize.toString() : undefined, + sort_field: sortField != null ? sortField.toString() : undefined, + sort_order: sortOrder, + }, + (payload) => fromEither(validateEither(findListSchema, payload)), + chain((payload) => tryCatch(() => findLists({ http, signal, ...payload }), toError)), + chain((response) => fromEither(validateEither(foundListSchema, response))), + flow(toPromise) + ); + +export { findListsWithValidation as findLists }; + +const findListsBySize = async ({ + http, + cursor, + page, + // eslint-disable-next-line @typescript-eslint/naming-convention + per_page, + signal, +}: ApiParams & FindListSchemaEncoded): Promise => { + return http.fetch(`${INTERNAL_FIND_LISTS_BY_SIZE}`, { + method: 'GET', + version: '1', + query: { + cursor, + page, + per_page, + }, + signal, + }); +}; + +const findListsBySizeWithValidation = async ({ + cursor, + http, + pageIndex, + pageSize, + signal, +}: FindListsParams): Promise => + pipe( + { + cursor: cursor != null ? cursor.toString() : undefined, + page: pageIndex != null ? pageIndex.toString() : undefined, + per_page: pageSize != null ? pageSize.toString() : undefined, + }, + (payload) => fromEither(validateEither(findListSchema, payload)), + chain((payload) => tryCatch(() => findListsBySize({ http, signal, ...payload }), toError)), + chain((response) => fromEither(validateEither(foundListsBySizeSchema, response))), + flow(toPromise) + ); + +export { findListsBySizeWithValidation as findListsBySize }; + +const importList = async ({ + file, + http, + // eslint-disable-next-line @typescript-eslint/naming-convention + list_id, + type, + signal, + refresh, +}: ApiParams & + ImportListItemSchemaEncoded & + ImportListItemQuerySchemaEncoded): Promise => { + const formData = new FormData(); + formData.append('file', file as Blob); + + return http.fetch(`${LIST_ITEM_URL}/_import`, { + body: formData, + headers: { 'Content-Type': undefined }, + method: 'POST', + query: { list_id, type, refresh }, + signal, + version, + }); +}; + +const importListWithValidation = async ({ + file, + http, + listId, + type, + signal, + refresh, +}: ImportListParams): Promise => + pipe( + { + list_id: listId, + type, + refresh, + }, + (query) => fromEither(validateEither(importListItemQuerySchema, query)), + chain((query) => + pipe( + fromEither(validateEither(importListItemSchema, { file })), + map((body) => ({ ...body, ...query })) + ) + ), + chain((payload) => tryCatch(() => importList({ http, signal, ...payload }), toError)), + chain((response) => fromEither(validateEither(listSchema, response))), + toPromise + ); + +export { importListWithValidation as importList }; + +const deleteList = async ({ + deleteReferences = false, + http, + id, + ignoreReferences = false, + signal, +}: ApiParams & DeleteListSchemaEncoded): Promise => + http.fetch(LIST_URL, { + method: 'DELETE', + query: { deleteReferences, id, ignoreReferences }, + signal, + version, + }); + +const deleteListWithValidation = async ({ + deleteReferences, + http, + id, + ignoreReferences, + signal, +}: DeleteListParams): Promise => + pipe( + { deleteReferences, id, ignoreReferences }, + (payload) => fromEither(validateEither(deleteListSchema, payload)), + chain((payload) => tryCatch(() => deleteList({ http, signal, ...payload }), toError)), + chain((response) => fromEither(validateEither(listSchema, response))), + flow(toPromise) + ); + +export { deleteListWithValidation as deleteList }; + +const exportList = async ({ + http, + // eslint-disable-next-line @typescript-eslint/naming-convention + list_id, + signal, +}: ApiParams & ExportListItemQuerySchemaEncoded): Promise => + http.fetch(`${LIST_ITEM_URL}/_export`, { + method: 'POST', + query: { list_id }, + signal, + version, + }); + +const exportListWithValidation = async ({ + http, + listId, + signal, +}: ExportListParams): Promise => + pipe( + { list_id: listId }, + (payload) => fromEither(validateEither(exportListItemQuerySchema, payload)), + chain((payload) => tryCatch(() => exportList({ http, signal, ...payload }), toError)), + flow(toPromise) + ); + +export { exportListWithValidation as exportList }; + +const readListIndex = async ({ http, signal }: ApiParams): Promise => + http.fetch(LIST_INDEX, { + method: 'GET', + signal, + version, + }); + +const readListIndexWithValidation = async ({ + http, + signal, +}: ApiParams): Promise => + flow( + () => tryCatch(() => readListIndex({ http, signal }), toError), + chain((response) => fromEither(validateEither(listItemIndexExistSchema, response))), + flow(toPromise) + )(); + +export { readListIndexWithValidation as readListIndex }; + +// TODO add types and validation +export const readListPrivileges = async ({ http, signal }: ApiParams): Promise => + http.fetch(LIST_PRIVILEGES_URL, { + method: 'GET', + signal, + version, + }); + +const createListIndex = async ({ http, signal }: ApiParams): Promise => + http.fetch(LIST_INDEX, { + method: 'POST', + signal, + version, + }); + +const createListIndexWithValidation = async ({ + http, + signal, +}: ApiParams): Promise => + flow( + () => tryCatch(() => createListIndex({ http, signal }), toError), + chain((response) => fromEither(validateEither(acknowledgeSchema, response))), + flow(toPromise) + )(); + +export { createListIndexWithValidation as createListIndex }; + +const getListById = async ({ + http, + signal, + id, +}: ApiParams & ReadListSchema): Promise => { + return http.fetch(`${LIST_URL}`, { + method: 'GET', + query: { + id, + }, + signal, + version, + }); +}; + +const getListByIdWithValidation = async ({ + http, + signal, + id, +}: GetListByIdParams): Promise => + pipe( + { + id, + }, + (payload) => fromEither(validateEither(readListSchema, payload)), + chain((payload) => tryCatch(() => getListById({ http, signal, ...payload }), toError)), + chain((response) => fromEither(validateEither(listSchema, response))), + flow(toPromise) + ); + +export { getListByIdWithValidation as getListById }; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/constants.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/constants.mock.ts new file mode 100644 index 0000000000000..b3ce62d03f486 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/constants.mock.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +export const DATE_NOW = '2020-04-20T15:25:31.830Z'; +export const USER = 'some user'; +export const ELASTIC_USER = 'elastic'; +export const NAME = 'some name'; +export const DESCRIPTION = 'some description'; +export const LIST_ID = 'some-list-id'; +export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; + +export const META = {}; +export const TYPE = 'ip'; + +export const VERSION = 1; +export const IMMUTABLE = false; diff --git a/x-pack/plugins/lists/common/schemas/response/acknowledge_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/acknowledge_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/acknowledge_schema.mock.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/acknowledge_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/found_list_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/found_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/found_list_schema.mock.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/found_list_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/list_item_index_exist_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_item_index_exist_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/list_item_index_exist_schema.mock.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_item_index_exist_schema.mock.ts diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts new file mode 100644 index 0000000000000..b2b66ad4636c2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts @@ -0,0 +1,55 @@ +/* + * 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. + */ + +import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { + DATE_NOW, + DESCRIPTION, + ELASTIC_USER, + IMMUTABLE, + LIST_ID, + META, + NAME, + TIE_BREAKER, + TYPE, + USER, + VERSION, +} from '../constants.mock'; + +export const getListResponseMock = (): ListSchema => ({ + '@timestamp': DATE_NOW, + _version: undefined, + created_at: DATE_NOW, + created_by: USER, + description: DESCRIPTION, + deserializer: undefined, + id: LIST_ID, + immutable: IMMUTABLE, + meta: META, + name: NAME, + serializer: undefined, + tie_breaker_id: TIE_BREAKER, + type: TYPE, + updated_at: DATE_NOW, + updated_by: USER, + version: VERSION, +}); + +/** + * This is useful for end to end tests where we remove the auto generated parts for comparisons + * such as created_at, updated_at, and id. + */ +export const getListResponseMockWithoutAutoGeneratedValues = (): Partial => ({ + created_by: ELASTIC_USER, + description: DESCRIPTION, + immutable: IMMUTABLE, + name: NAME, + type: TYPE, + updated_by: ELASTIC_USER, + version: VERSION, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/index.test.ts new file mode 100644 index 0000000000000..651edfe25cb18 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/index.test.ts @@ -0,0 +1,171 @@ +/* + * 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. + */ + +import { createListItem, deleteListItem, findListItems, patchListItem } from '.'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; +import { + getFoundListSchemaMock, + getCreateListItemResponseMock, + getUpdatedListItemResponseMock, + getDeletedListItemResponseMock, +} from './mocks/response'; + +describe('Value list item API', () => { + let httpMock: ReturnType; + beforeEach(() => { + httpMock = httpServiceMock.createStartContract(); + }); + + describe('findListItems', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getFoundListSchemaMock()); + }); + + it('GETs from the lists endpoint with query params', async () => { + const abortCtrl = new AbortController(); + await findListItems({ + http: httpMock, + pageIndex: 1, + pageSize: 10, + signal: abortCtrl.signal, + filter: '*:*', + listId: 'list_id', + sortField: 'updated_at', + sortOrder: 'asc', + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items/_find', + expect.objectContaining({ + method: 'GET', + query: { + cursor: undefined, + filter: '*:*', + list_id: 'list_id', + page: 1, + per_page: 10, + sort_field: 'updated_at', + sort_order: 'asc', + }, + }) + ); + }); + }); + + describe('createListItem', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getCreateListItemResponseMock()); + }); + + it('POSTs to the lists endpoint with the list item', async () => { + const abortCtrl = new AbortController(); + await createListItem({ + http: httpMock, + signal: abortCtrl.signal, + value: '123', + listId: 'list_id', + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items', + expect.objectContaining({ + method: 'POST', + body: JSON.stringify({ + value: '123', + list_id: 'list_id', + }), + }) + ); + }); + + it('returns the created list item', async () => { + const abortCtrl = new AbortController(); + const result = await createListItem({ + http: httpMock, + signal: abortCtrl.signal, + value: '123', + listId: 'list_id', + }); + + expect(result).toEqual(getCreateListItemResponseMock()); + }); + }); + + describe('patchListItem', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getUpdatedListItemResponseMock()); + }); + + it('PATCH to the lists endpoint with the list item', async () => { + const abortCtrl = new AbortController(); + await patchListItem({ + http: httpMock, + signal: abortCtrl.signal, + id: 'item_id', + value: '123', + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items', + expect.objectContaining({ + method: 'PATCH', + body: JSON.stringify({ + id: 'item_id', + value: '123', + }), + }) + ); + }); + + it('returns the updated list item', async () => { + const abortCtrl = new AbortController(); + const result = await patchListItem({ + http: httpMock, + signal: abortCtrl.signal, + id: 'item_id', + value: '123', + }); + + expect(result).toEqual(getUpdatedListItemResponseMock()); + }); + }); + + describe('deleteListItem', () => { + beforeEach(() => { + httpMock.fetch.mockResolvedValue(getCreateListItemResponseMock()); + }); + + it('DELETE to the lists endpoint with the list item', async () => { + const abortCtrl = new AbortController(); + await deleteListItem({ + http: httpMock, + signal: abortCtrl.signal, + id: 'item_id', + refresh: 'true', + }); + + expect(httpMock.fetch).toHaveBeenCalledWith( + '/api/lists/items', + expect.objectContaining({ + method: 'DELETE', + query: { id: 'item_id', refresh: 'true' }, + }) + ); + }); + + it('returns the deleted list item', async () => { + const abortCtrl = new AbortController(); + const result = await deleteListItem({ + http: httpMock, + signal: abortCtrl.signal, + id: 'item_id', + }); + + expect(result).toEqual(getDeletedListItemResponseMock()); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/index.ts new file mode 100644 index 0000000000000..1605b68ee04cd --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/index.ts @@ -0,0 +1,225 @@ +/* + * 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. + */ + +import { + FindListItemSchema, + ListItemSchema, + deleteListItemSchema, + patchListItemSchema, + createListItemSchema, + findListItemSchema, + foundListItemSchema, + listItemSchema, + FoundListItemSchema, + DeleteListItemSchema, + PatchListItemSchema, + CreateListItemSchema, +} from '@kbn/securitysolution-io-ts-list-types'; +import { chain, fromEither, tryCatch } from 'fp-ts/lib/TaskEither'; +import { flow } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { validateEither } from '@kbn/securitysolution-io-ts-utils'; + +import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { + ApiParams, + FindListItemsParams, + DeleteListItemParams, + PatchListItemParams, + CreateListItemParams, +} from '../types'; +import { toError, toPromise } from '../fp_utils'; + +const version = '2023-10-31'; + +/** + * Fetch list items + */ +const findListItems = async ({ + http, + cursor, + page, + // eslint-disable-next-line @typescript-eslint/naming-convention + list_id, + // eslint-disable-next-line @typescript-eslint/naming-convention + per_page, + signal, + // eslint-disable-next-line @typescript-eslint/naming-convention + sort_field, + // eslint-disable-next-line @typescript-eslint/naming-convention + sort_order, + filter, +}: ApiParams & FindListItemSchema): Promise => { + return http.fetch(`${LIST_ITEM_URL}/_find`, { + method: 'GET', + query: { + cursor, + page, + per_page, + sort_field, + sort_order, + list_id, + filter, + }, + signal, + version, + }); +}; + +const findListItemsWithValidation = async ({ + cursor, + http, + pageIndex, + pageSize, + signal, + sortField, + sortOrder, + filter, + listId, +}: FindListItemsParams): Promise => + pipe( + { + cursor: cursor != null ? cursor.toString() : undefined, + page: pageIndex != null ? pageIndex.toString() : undefined, + per_page: pageSize != null ? pageSize.toString() : undefined, + sort_field: sortField != null ? sortField.toString() : undefined, + filter: filter != null ? filter.toString() : undefined, + sort_order: sortOrder, + list_id: listId, + }, + (payload) => fromEither(validateEither(findListItemSchema, payload)), + chain((payload) => tryCatch(() => findListItems({ http, signal, ...payload }), toError)), + chain((response) => fromEither(validateEither(foundListItemSchema, response))), + flow(toPromise) + ); + +export { findListItemsWithValidation as findListItems }; + +const deleteListItem = async ({ + http, + id, + signal, + refresh, +}: ApiParams & DeleteListItemSchema): Promise => + http.fetch(LIST_ITEM_URL, { + method: 'DELETE', + query: { id, refresh }, + signal, + version, + }); + +const deleteListItemWithValidation = async ({ + http, + id, + signal, + refresh, +}: DeleteListItemParams): Promise => + pipe( + { id, refresh }, + (payload) => fromEither(validateEither(deleteListItemSchema, payload)), + chain((payload) => + tryCatch( + () => + deleteListItem({ + http, + signal, + ...payload, + value: undefined, + list_id: undefined, + }), + toError + ) + ), + chain((response) => fromEither(validateEither(listItemSchema, response))), + flow(toPromise) + ); + +export { deleteListItemWithValidation as deleteListItem }; + +const patchListItem = async ({ + http, + id, + signal, + value, + _version, +}: ApiParams & PatchListItemSchema): Promise => + http.fetch(LIST_ITEM_URL, { + method: 'PATCH', + body: JSON.stringify({ id, value, _version }), + signal, + version, + }); + +const patchListItemWithValidation = async ({ + http, + id, + signal, + value, + refresh, + _version, +}: PatchListItemParams): Promise => + pipe( + { id, value, _version, refresh }, + (payload) => fromEither(validateEither(patchListItemSchema, payload)), + chain((payload) => + tryCatch( + () => + patchListItem({ + http, + signal, + ...payload, + }), + toError + ) + ), + chain((response) => fromEither(validateEither(listItemSchema, response))), + flow(toPromise) + ); + +export { patchListItemWithValidation as patchListItem }; + +const createListItem = async ({ + http, + signal, + value, + // eslint-disable-next-line @typescript-eslint/naming-convention + list_id, + refresh, +}: ApiParams & CreateListItemSchema): Promise => + http.fetch(LIST_ITEM_URL, { + method: 'POST', + body: JSON.stringify({ value, list_id, refresh }), + signal, + version, + }); + +const createListItemWithValidation = async ({ + http, + signal, + value, + refresh, + listId, +}: CreateListItemParams): Promise => + pipe( + { list_id: listId, value, refresh }, + (payload) => fromEither(validateEither(createListItemSchema, payload)), + chain((payload) => + tryCatch( + () => + createListItem({ + http, + signal, + ...payload, + }), + toError + ) + ), + chain((response) => fromEither(validateEither(listItemSchema, response))), + flow(toPromise) + ); + +export { createListItemWithValidation as createListItem }; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/index.ts new file mode 100644 index 0000000000000..2dddd844c5f23 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import type { FoundListItemSchema, ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { getListItemResponseMock } from './list_item_schema.mock'; + +export const getFoundListSchemaMock = (): FoundListItemSchema => ({ + cursor: '123', + data: [getListItemResponseMock()], + page: 1, + per_page: 1, + total: 1, +}); + +export const getCreateListItemResponseMock = (): ListItemSchema => getListItemResponseMock(); +export const getUpdatedListItemResponseMock = (): ListItemSchema => getListItemResponseMock(); +export const getDeletedListItemResponseMock = (): ListItemSchema => getListItemResponseMock(); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/list_item_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/list_item_schema.mock.ts new file mode 100644 index 0000000000000..726f49e9d0d3f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/list_item_api/mocks/response/list_item_schema.mock.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; + +export const getListItemResponseMock = (): ListItemSchema => ({ + _version: '1', + '@timestamp': '2020-08-11T11:22:13.670Z', + created_at: '2020-08-11T11:22:13.670Z', + created_by: 'elastic', + deserializer: 'some deserializer', + id: 'bpdB3XMBx7pemMHopQ6M', + list_id: 'list_id', + meta: {}, + serializer: 'some serializer', + tie_breaker_id: '17d3befb-dc22-4b3c-a286-b5504c4fbeeb', + type: 'keyword', + updated_at: '2020-08-11T11:22:13.670Z', + updated_by: 'elastic', + value: 'some keyword', +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/types.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/types.ts new file mode 100644 index 0000000000000..54aa89936d73c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/src/types.ts @@ -0,0 +1,85 @@ +/* + * 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. + */ + +import type { + SortFieldOrUndefined, + SortOrderOrUndefined, + Type, + Refresh, + RefreshWithWaitFor, +} from '@kbn/securitysolution-io-ts-list-types'; + +// TODO: Replace these with kbn packaged versions once we have those available to us +// These originally came from this location below before moving them to this hacked "any" types: +// import { HttpStart, NotificationsStart } from '../../../../../../../../src/core/public'; +interface HttpStart { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + fetch: (...args: any) => any; +} + +export interface ApiParams { + http: HttpStart; + signal: AbortSignal; +} +export type ApiPayload = Omit; + +export interface FindListsParams extends ApiParams { + cursor?: string | undefined; + pageSize: number | undefined; + pageIndex: number | undefined; + sortOrder?: SortOrderOrUndefined; + sortField?: SortFieldOrUndefined; +} + +export interface FindListItemsParams extends ApiParams { + cursor?: string | undefined; + pageSize: number | undefined; + pageIndex: number | undefined; + sortOrder?: SortOrderOrUndefined; + sortField?: SortFieldOrUndefined; + filter: string | undefined; + listId: string; +} + +export interface ImportListParams extends ApiParams { + file: File; + listId: string | undefined; + type: Type | undefined; + refresh?: RefreshWithWaitFor; +} + +export interface DeleteListParams extends ApiParams { + deleteReferences?: boolean; + id: string; + ignoreReferences?: boolean; +} + +export interface DeleteListItemParams extends ApiParams { + refresh?: Refresh; + id: string; +} + +export interface PatchListItemParams extends ApiParams { + refresh?: Refresh; + id: string; + value: string; + _version?: string; +} + +export interface CreateListItemParams extends ApiParams { + refresh?: RefreshWithWaitFor; + value: string; + listId: string; +} + +export interface ExportListParams extends ApiParams { + listId: string; +} + +export interface GetListByIdParams extends ApiParams { + id: string; +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-api/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/tsconfig.json new file mode 100644 index 0000000000000..10dbca8030001 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-api/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "kbn_references": [ + "@kbn/securitysolution-io-ts-list-types", + "@kbn/securitysolution-io-ts-utils", + "@kbn/securitysolution-list-constants", + "@kbn/core-http-browser", + "@kbn/core-http-browser-mocks", + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-list-constants/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/README.md similarity index 100% rename from packages/kbn-securitysolution-list-constants/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-list-constants/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/index.ts new file mode 100644 index 0000000000000..746294c8908fe --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/index.ts @@ -0,0 +1,146 @@ +/* + * 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. + */ + +import { deepFreeze } from '@kbn/std'; + +/** + * Value list routes + */ +export const LIST_URL = '/api/lists'; +export const LIST_INDEX = `${LIST_URL}/index`; +export const LIST_ITEM_URL = `${LIST_URL}/items`; +export const LIST_PRIVILEGES_URL = `${LIST_URL}/privileges`; + +/** + * Internal value list routes + */ +export const INTERNAL_LIST_URL = '/internal/lists'; +export const INTERNAL_FIND_LISTS_BY_SIZE = `${INTERNAL_LIST_URL}/_find_lists_by_size` as const; +export const INTERNAL_EXCEPTION_FILTER = `${INTERNAL_LIST_URL}/_create_filter` as const; + +/** + * Exception list routes + */ +export const EXCEPTION_LIST_URL = '/api/exception_lists'; +export const EXCEPTION_LIST_ITEM_URL = '/api/exception_lists/items'; + +/** + * Internal exception list routes + */ +export const INTERNAL_EXCEPTION_LIST_URL = `/internal${EXCEPTION_LIST_URL}`; +export const INTERNAL_EXCEPTIONS_LIST_ENSURE_CREATED_URL = `${INTERNAL_EXCEPTION_LIST_URL}/_create`; + +/** + * Exception list spaces + */ +export const EXCEPTION_LIST_NAMESPACE_AGNOSTIC = 'exception-list-agnostic'; +export const EXCEPTION_LIST_NAMESPACE = 'exception-list'; + +/** + * Specific routes for the single global space agnostic endpoint list + */ +export const ENDPOINT_LIST_URL = '/api/endpoint_list'; + +/** + * Specific routes for the single global space agnostic endpoint list. These are convenience + * routes where they are going to try and create the global space agnostic endpoint list if it + * does not exist yet or if it was deleted at some point and re-create it before adding items to + * the list + */ +export const ENDPOINT_LIST_ITEM_URL = '/api/endpoint_list/items'; + +/** + * This ID is used for _both_ the Saved Object ID and for the list_id + * for the single global space agnostic endpoint list + */ +export const ENDPOINT_LIST_ID = 'endpoint_list'; + +/** The name of the single global space agnostic endpoint list */ +export const ENDPOINT_LIST_NAME = 'Endpoint Security Exception List'; + +/** The description of the single global space agnostic endpoint list */ +export const ENDPOINT_LIST_DESCRIPTION = 'Endpoint Security Exception List'; + +export const MAX_EXCEPTION_LIST_SIZE = 10000; + +export const MAXIMUM_SMALL_VALUE_LIST_SIZE = 65536; + +export const MAXIMUM_SMALL_IP_RANGE_VALUE_LIST_DASH_SIZE = 200; + +/** + * List definitions for Endpoint Artifact + */ +export const ENDPOINT_ARTIFACT_LISTS = deepFreeze({ + trustedApps: { + id: 'endpoint_trusted_apps', + name: 'Endpoint Security Trusted Apps List', + description: 'Endpoint Security Trusted Apps List', + }, + eventFilters: { + id: 'endpoint_event_filters', + name: 'Endpoint Security Event Filters List', + description: 'Endpoint Security Event Filters List', + }, + hostIsolationExceptions: { + id: 'endpoint_host_isolation_exceptions', + name: 'Endpoint Security Host isolation exceptions List', + description: 'Endpoint Security Host isolation exceptions List', + }, + blocklists: { + id: 'endpoint_blocklists', + name: 'Endpoint Security Blocklists List', + description: 'Endpoint Security Blocklists List', + }, +}); + +/** + * The IDs of all Endpoint artifact lists + */ +export const ENDPOINT_ARTIFACT_LIST_IDS = Object.freeze( + Object.values(ENDPOINT_ARTIFACT_LISTS).map(({ id }) => id) +); + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_TRUSTED_APPS_LIST_ID = ENDPOINT_ARTIFACT_LISTS.trustedApps.id; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_TRUSTED_APPS_LIST_NAME = ENDPOINT_ARTIFACT_LISTS.trustedApps.name; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION = + ENDPOINT_ARTIFACT_LISTS.trustedApps.description; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_EVENT_FILTERS_LIST_ID = ENDPOINT_ARTIFACT_LISTS.eventFilters.id; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_EVENT_FILTERS_LIST_NAME = ENDPOINT_ARTIFACT_LISTS.eventFilters.name; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION = + ENDPOINT_ARTIFACT_LISTS.eventFilters.description; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID = + ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.id; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_NAME = + ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.name; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_DESCRIPTION = + ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.description; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_BLOCKLISTS_LIST_ID = ENDPOINT_ARTIFACT_LISTS.blocklists.id; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_BLOCKLISTS_LIST_NAME = ENDPOINT_ARTIFACT_LISTS.blocklists.name; + +/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */ +export const ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION = ENDPOINT_ARTIFACT_LISTS.blocklists.description; diff --git a/packages/kbn-securitysolution-list-constants/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-list-constants/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-list-constants/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/package.json new file mode 100644 index 0000000000000..f57bdd68a2cc5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/securitysolution-list-constants", + "version": "1.0.0", + "description": "security solution list constants to use across plugins such lists, security_solution, cases, etc...", + "license": "Elastic License 2.0", + "private": true +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/tsconfig.json new file mode 100644 index 0000000000000..0d3f96d6a17b5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-constants/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "kbn_references": [ + "@kbn/std" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-list-hooks/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/README.md similarity index 100% rename from packages/kbn-securitysolution-list-hooks/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/index.ts new file mode 100644 index 0000000000000..8e5fdecab1863 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +export * from './src/transforms'; +export * from './src/use_api'; +export * from './src/use_create_list_index'; +export * from './src/use_cursor'; +export * from './src/use_delete_list'; +export * from './src/use_exception_lists'; +export * from './src/use_export_list'; +export * from './src/use_find_lists'; +export * from './src/use_find_lists_by_size'; +export * from './src/use_import_list'; +export * from './src/use_persist_exception_item'; +export * from './src/use_persist_exception_list'; +export * from './src/use_read_list_index'; +export * from './src/use_read_list_privileges'; +export * from './src/use_find_list_items'; +export * from './src/use_create_list_item'; +export * from './src/use_delete_list_item'; +export * from './src/use_patch_list_item'; +export * from './src/use_get_list_by_id'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/jest.config.js new file mode 100644 index 0000000000000..7b0430c9bf092 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks'], +}; diff --git a/packages/kbn-securitysolution-list-hooks/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-list-hooks/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/package.json new file mode 100644 index 0000000000000..8a2ead4291bd3 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/securitysolution-list-hooks", + "version": "1.0.0", + "description": "Security solution list ReactJS hooks", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/constants.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/constants.ts new file mode 100644 index 0000000000000..377c980531a4e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/constants.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export const READ_INDEX_QUERY_KEY = ['detectionEngine', 'listIndex']; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/index.ts new file mode 100644 index 0000000000000..dd0e180eba269 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +export * from './transforms'; +export * from './use_api'; +export * from './use_create_list_index'; +export * from './use_cursor'; +export * from './use_delete_list'; +export * from './use_exception_lists'; +export * from './use_export_list'; +export * from './use_find_lists'; +export * from './use_import_list'; +export * from './use_persist_exception_item'; +export * from './use_persist_exception_list'; +export * from './use_read_list_index'; +export * from './use_read_list_privileges'; +export * from './use_find_list_items'; +export * from './use_create_list_item'; +export * from './use_delete_list_item'; +export * from './use_patch_list_item'; +export * from './use_get_list_by_id'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/constants.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/constants.mock.ts new file mode 100644 index 0000000000000..762d1eb243cf7 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/constants.mock.ts @@ -0,0 +1,99 @@ +/* + * 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. + */ + +import { + CommentsArray, + EntriesArray, + Entry, + EntryMatch, + EntryNested, + OsTypeArray, +} from '@kbn/securitysolution-io-ts-list-types'; + +export const DATE_NOW = '2020-04-20T15:25:31.830Z'; +export const USER = 'some user'; +export const ELASTIC_USER = 'elastic'; +export const NAME = 'some name'; +export const DESCRIPTION = 'some description'; +export const LIST_ID = 'some-list-id'; +export const TIE_BREAKER = '6a76b69d-80df-4ab2-8c3e-85f466b06a0e'; + +export const META = {}; +export const TYPE = 'ip'; + +export const VERSION = 1; +export const IMMUTABLE = false; +// Exception List specific +export const ID = 'uuid_here'; +export const NAMESPACE_TYPE = 'single'; +export const OS_TYPES: OsTypeArray = ['windows']; +export const TAGS = []; +export const UPDATED_COMMENTS = [ + { + comment: 'old comment', + id: 'old_created_id', + }, + { + comment: 'new comment', + id: 'new_id', + }, +]; +export const COMMENTS = []; +export const ENTRIES: EntriesArray = [ + { + entries: [{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }], + field: 'some.parentField', + type: 'nested', + }, + { field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' }, +]; +export const ITEM_ID = 'some-list-item-id'; +export const ITEM_TYPE = 'simple'; +export const LIST_ITEM_ID = 'some-list-item-id'; +// ENTRIES_WITH_IDS should only be used to mock out functionality of a collection of transforms +// that are UI specific and useful for UI concerns that are inserted between the +// API and the actual user interface. In some ways these might be viewed as +// technical debt or to compensate for the differences and preferences +// of how ReactJS might prefer data vs. how we want to model data. +export const ENTRIES_WITH_IDS: EntriesArray = [ + { + entries: [ + { + field: 'nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as EntryMatch & { id: string }, + ], + field: 'some.parentField', + id: '123', + type: 'nested', + } as EntryNested & { id: string }, + { + field: 'some.not.nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as Entry & { id: string }, +]; + +export const COMMENTS_WITH_CREATEDAT_CREATEDBY: CommentsArray = [ + { + comment: 'old comment', + id: 'old_created_id', + created_at: '2022-01-08T15:25:31.830Z', + created_by: 'elastic', + }, + { + comment: 'new comment', + id: 'new_id', + created_at: '2022-05-14T15:25:31.830Z', + created_by: 'elastic', + }, +]; diff --git a/packages/kbn-securitysolution-list-hooks/src/mocks/request/create_exception_list_item_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/request/create_exception_list_item_schema.mock.ts similarity index 76% rename from packages/kbn-securitysolution-list-hooks/src/mocks/request/create_exception_list_item_schema.mock.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/request/create_exception_list_item_schema.mock.ts index 5727a271a9bf8..ff9789a7995b9 100644 --- a/packages/kbn-securitysolution-list-hooks/src/mocks/request/create_exception_list_item_schema.mock.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/request/create_exception_list_item_schema.mock.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/request/update_exception_list_item_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/request/update_exception_list_item_schema.mock.ts new file mode 100644 index 0000000000000..47b0030c316aa --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/request/update_exception_list_item_schema.mock.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ + +import type { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { + DESCRIPTION, + ENTRIES, + ID, + ITEM_ID, + ITEM_TYPE, + LIST_ITEM_ID, + META, + NAME, + NAMESPACE_TYPE, + OS_TYPES, + TAGS, + UPDATED_COMMENTS, +} from '../constants.mock'; + +export const getUpdateExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ + _version: undefined, + comments: UPDATED_COMMENTS, + description: DESCRIPTION, + entries: ENTRIES, + id: ID, + item_id: LIST_ITEM_ID, + meta: META, + name: NAME, + namespace_type: NAMESPACE_TYPE, + os_types: ['linux'], + tags: TAGS, + type: ITEM_TYPE, +}); + +/** + * Useful for end to end tests and other mechanisms which want to fill in the values + * after doing a get of the structure. + */ +export const getUpdateMinimalExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({ + description: DESCRIPTION, + entries: ENTRIES, + item_id: ITEM_ID, + name: NAME, + os_types: OS_TYPES, + type: ITEM_TYPE, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/exception_list_item_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/exception_list_item_schema.mock.ts new file mode 100644 index 0000000000000..acb7204da9b76 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/exception_list_item_schema.mock.ts @@ -0,0 +1,70 @@ +/* + * 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. + */ + +import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { + COMMENTS, + DATE_NOW, + DESCRIPTION, + ELASTIC_USER, + ENTRIES, + ITEM_ID, + ITEM_TYPE, + LIST_ID, + META, + NAME, + NAMESPACE_TYPE, + OS_TYPES, + TIE_BREAKER, + USER, +} from '../constants.mock'; + +export const getExceptionListItemSchemaMock = ( + overrides?: Partial +): ExceptionListItemSchema => ({ + _version: undefined, + comments: COMMENTS, + created_at: DATE_NOW, + created_by: USER, + description: DESCRIPTION, + entries: ENTRIES, + expire_time: undefined, + id: '1', + item_id: 'endpoint_list_item', + list_id: 'endpoint_list_id', + meta: META, + name: NAME, + namespace_type: NAMESPACE_TYPE, + os_types: [], + tags: ['user added string for a tag', 'malware'], + tie_breaker_id: TIE_BREAKER, + type: ITEM_TYPE, + updated_at: DATE_NOW, + updated_by: USER, + ...(overrides || {}), +}); + +/** + * This is useful for end to end tests where we remove the auto generated parts for comparisons + * such as created_at, updated_at, and id. + */ +export const getExceptionListItemResponseMockWithoutAutoGeneratedValues = + (): Partial => ({ + comments: [], + created_by: ELASTIC_USER, + description: DESCRIPTION, + entries: ENTRIES, + item_id: ITEM_ID, + list_id: LIST_ID, + name: NAME, + namespace_type: 'single', + os_types: OS_TYPES, + tags: [], + type: ITEM_TYPE, + updated_by: ELASTIC_USER, + }); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/found_list_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/found_list_schema.mock.ts new file mode 100644 index 0000000000000..1691221842d39 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/found_list_schema.mock.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import type { FoundListSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { getListResponseMock } from './list_schema.mock'; + +export const getFoundListSchemaMock = (): FoundListSchema => ({ + cursor: '123', + data: [getListResponseMock()], + page: 1, + per_page: 1, + total: 1, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts new file mode 100644 index 0000000000000..b2b66ad4636c2 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts @@ -0,0 +1,55 @@ +/* + * 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. + */ + +import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { + DATE_NOW, + DESCRIPTION, + ELASTIC_USER, + IMMUTABLE, + LIST_ID, + META, + NAME, + TIE_BREAKER, + TYPE, + USER, + VERSION, +} from '../constants.mock'; + +export const getListResponseMock = (): ListSchema => ({ + '@timestamp': DATE_NOW, + _version: undefined, + created_at: DATE_NOW, + created_by: USER, + description: DESCRIPTION, + deserializer: undefined, + id: LIST_ID, + immutable: IMMUTABLE, + meta: META, + name: NAME, + serializer: undefined, + tie_breaker_id: TIE_BREAKER, + type: TYPE, + updated_at: DATE_NOW, + updated_by: USER, + version: VERSION, +}); + +/** + * This is useful for end to end tests where we remove the auto generated parts for comparisons + * such as created_at, updated_at, and id. + */ +export const getListResponseMockWithoutAutoGeneratedValues = (): Partial => ({ + created_by: ELASTIC_USER, + description: DESCRIPTION, + immutable: IMMUTABLE, + name: NAME, + type: TYPE, + updated_by: ELASTIC_USER, + version: VERSION, +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/transforms/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/transforms/index.test.ts new file mode 100644 index 0000000000000..dc94fcddd8498 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/transforms/index.test.ts @@ -0,0 +1,297 @@ +/* + * 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. + */ + +import type { + CreateExceptionListItemSchema, + Entry, + EntryMatch, + EntryNested, + ExceptionListItemSchema, + UpdateExceptionListItemSchema, +} from '@kbn/securitysolution-io-ts-list-types'; +import { + addIdToExceptionItemEntries, + removeIdFromExceptionItemsEntries, + transformInput, + transformOutput, +} from '../..'; + +import { getCreateExceptionListItemSchemaMock } from '../mocks/request/create_exception_list_item_schema.mock'; +import { getUpdateExceptionListItemSchemaMock } from '../mocks/request/update_exception_list_item_schema.mock'; +import { getExceptionListItemSchemaMock } from '../mocks/response/exception_list_item_schema.mock'; +import { COMMENTS_WITH_CREATEDAT_CREATEDBY, ENTRIES_WITH_IDS } from '../mocks/constants.mock'; + +jest.mock('uuid', () => ({ + v4: jest.fn().mockReturnValue('123'), +})); + +describe('Exceptions transforms', () => { + describe('transformOutput', () => { + it('should return same output as input with stripped ids per entry - CreateExceptionListItemSchema', () => { + const mockCreateExceptionItem = { + ...getCreateExceptionListItemSchemaMock(), + entries: ENTRIES_WITH_IDS, + }; + const output = transformOutput(mockCreateExceptionItem); + const expectedOutput: CreateExceptionListItemSchema = getCreateExceptionListItemSchemaMock(); + + expect(output).toEqual(expectedOutput); + }); + + it('should return same output as input with stripped ids per entry - UpdateExceptionListItemSchema', () => { + const mockUpdateExceptionItem = { + ...getUpdateExceptionListItemSchemaMock(), + entries: ENTRIES_WITH_IDS, + }; + const output = transformOutput(mockUpdateExceptionItem); + const expectedOutput: UpdateExceptionListItemSchema = getUpdateExceptionListItemSchemaMock(); + + expect(output).toEqual(expectedOutput); + }); + it('should return output as input with stripped createdAt and createdBy per entry - UpdateExceptionListItemSchema', () => { + const mockUpdateExceptionItem = { + ...getUpdateExceptionListItemSchemaMock(), + entries: ENTRIES_WITH_IDS, + comments: COMMENTS_WITH_CREATEDAT_CREATEDBY, + }; + const output = transformOutput(mockUpdateExceptionItem); + const expectedOutput: UpdateExceptionListItemSchema = getUpdateExceptionListItemSchemaMock(); + + expect(output).toEqual(expectedOutput); + }); + }); + + describe('transformInput', () => { + it('should return same output as input with added ids per entry', () => { + const mockExceptionItem = getExceptionListItemSchemaMock(); + const output = transformInput(mockExceptionItem); + const expectedOutput: ExceptionListItemSchema = { + ...getExceptionListItemSchemaMock(), + entries: ENTRIES_WITH_IDS, + }; + + expect(output).toEqual(expectedOutput); + }); + }); + + describe('addIdToExceptionItemEntries', () => { + it('should return same output as input with added ids per entry', () => { + const mockExceptionItem: ExceptionListItemSchema = { + ...getExceptionListItemSchemaMock(), + entries: [ + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + }; + const output = addIdToExceptionItemEntries(mockExceptionItem); + const expectedOutput: ExceptionListItemSchema = { + ...getExceptionListItemSchemaMock(), + entries: [ + { + field: 'some.not.nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as Entry & { id: string }, + ], + }; + + expect(output).toEqual(expectedOutput); + }); + + it('should return same output as input with added ids per nested entry', () => { + const mockExceptionItem: ExceptionListItemSchema = { + ...getExceptionListItemSchemaMock(), + entries: [ + { + entries: [ + { + field: 'nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + field: 'some.parentField', + type: 'nested', + }, + ], + }; + const output = addIdToExceptionItemEntries(mockExceptionItem); + const expectedOutput: ExceptionListItemSchema = { + ...getExceptionListItemSchemaMock(), + entries: [ + { + entries: [ + { + field: 'nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as EntryMatch & { id: string }, + ], + field: 'some.parentField', + id: '123', + type: 'nested', + } as EntryNested & { id: string }, + ], + }; + + expect(output).toEqual(expectedOutput); + }); + }); + + describe('removeIdFromExceptionItemsEntries', () => { + it('should return same output as input with stripped ids per entry - CreateExceptionListItemSchema', () => { + const mockCreateExceptionItem = { + ...getCreateExceptionListItemSchemaMock(), + entries: [ + { + field: 'some.not.nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as Entry & { id: string }, + ], + }; + const output = removeIdFromExceptionItemsEntries(mockCreateExceptionItem); + const expectedOutput: CreateExceptionListItemSchema = { + ...getCreateExceptionListItemSchemaMock(), + entries: [ + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + }; + + expect(output).toEqual(expectedOutput); + }); + + it('should return same output as input with stripped ids per nested entry - CreateExceptionListItemSchema', () => { + const mockCreateExceptionItem = { + ...getCreateExceptionListItemSchemaMock(), + entries: [ + { + entries: [ + { + field: 'nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as EntryMatch & { id: string }, + ], + field: 'some.parentField', + id: '123', + type: 'nested', + } as EntryNested & { id: string }, + ], + }; + const output = removeIdFromExceptionItemsEntries(mockCreateExceptionItem); + const expectedOutput: CreateExceptionListItemSchema = { + ...getCreateExceptionListItemSchemaMock(), + entries: [ + { + entries: [ + { + field: 'nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + field: 'some.parentField', + type: 'nested', + }, + ], + }; + + expect(output).toEqual(expectedOutput); + }); + + it('should return same output as input with stripped ids per entry - UpdateExceptionListItemSchema', () => { + const mockUpdateExceptionItem = { + ...getUpdateExceptionListItemSchemaMock(), + entries: [ + { + field: 'some.not.nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as Entry & { id: string }, + ], + }; + const output = removeIdFromExceptionItemsEntries(mockUpdateExceptionItem); + const expectedOutput: UpdateExceptionListItemSchema = { + ...getUpdateExceptionListItemSchemaMock(), + entries: [ + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + }; + + expect(output).toEqual(expectedOutput); + }); + + it('should return same output as input with stripped ids per nested entry - UpdateExceptionListItemSchema', () => { + const mockUpdateExceptionItem = { + ...getUpdateExceptionListItemSchemaMock(), + entries: [ + { + entries: [ + { + field: 'nested.field', + id: '123', + operator: 'included', + type: 'match', + value: 'some value', + } as EntryMatch & { id: string }, + ], + field: 'some.parentField', + id: '123', + type: 'nested', + } as EntryNested & { id: string }, + ], + }; + const output = removeIdFromExceptionItemsEntries(mockUpdateExceptionItem); + const expectedOutput: UpdateExceptionListItemSchema = { + ...getUpdateExceptionListItemSchemaMock(), + entries: [ + { + entries: [ + { + field: 'nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + field: 'some.parentField', + type: 'nested', + }, + ], + }; + + expect(output).toEqual(expectedOutput); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/transforms/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/transforms/index.ts new file mode 100644 index 0000000000000..276c52b000af9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/transforms/index.ts @@ -0,0 +1,136 @@ +/* + * 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. + */ + +import { flow } from 'fp-ts/lib/function'; +import { addIdToItem, removeIdFromItem } from '@kbn/securitysolution-utils'; +import type { + CreateExceptionListItemSchema, + EntriesArray, + Entry, + ExceptionListItemSchema, + UpdateExceptionListItemSchema, +} from '@kbn/securitysolution-io-ts-list-types'; + +// These are a collection of transforms that are UI specific and useful for UI concerns +// that are inserted between the API and the actual user interface. In some ways these +// might be viewed as technical debt or to compensate for the differences and preferences +// of how ReactJS might prefer data vs. how we want to model data. Each function should have +// a description giving context around the transform. + +/** + * Transforms the output of exception items to compensate for technical debt or UI concerns such as + * ReactJS preferences for having ids within arrays if the data is not modeled that way. + * + * If you add a new transform of the output called "myNewTransform" do it + * in the form of: + * flow(removeIdFromExceptionItemsEntries, myNewTransform)(exceptionItem) + * + * @param exceptionItem The exceptionItem to transform the output of + * @returns The exceptionItem transformed from the output + */ +export const transformOutput = ( + exceptionItem: UpdateExceptionListItemSchema | ExceptionListItemSchema +): UpdateExceptionListItemSchema | ExceptionListItemSchema => + flow( + removeCreatedAtCreatedByFromCommentsOnUpdate, + removeIdFromExceptionItemsEntries + )(exceptionItem); + +export const transformNewItemOutput = ( + exceptionItem: CreateExceptionListItemSchema +): CreateExceptionListItemSchema => flow(removeIdFromExceptionItemsEntries)(exceptionItem); + +/** + * Transforms the output of rules to compensate for technical debt or UI concerns such as + * ReactJS preferences for having ids within arrays if the data is not modeled that way. + * + * If you add a new transform of the input called "myNewTransform" do it + * in the form of: + * flow(addIdToExceptionItemEntries, myNewTransform)(exceptionItem) + * + * @param exceptionItem The exceptionItem to transform the output of + * @returns The exceptionItem transformed from the output + */ +export const transformInput = (exceptionItem: ExceptionListItemSchema): ExceptionListItemSchema => + flow(addIdToExceptionItemEntries)(exceptionItem); + +/** + * This adds an id to the incoming exception item entries as ReactJS prefers to have + * an id added to them for use as a stable id. Later if we decide to change the data + * model to have id's within the array then this code should be removed. If not, then + * this code should stay as an adapter for ReactJS. + * + * This does break the type system slightly as we are lying a bit to the type system as we return + * the same exceptionItem as we have previously but are augmenting the arrays with an id which TypeScript + * doesn't mind us doing here. However, downstream you will notice that you have an id when the type + * does not indicate it. In that case use (ExceptionItem & { id: string }) temporarily if you're using the id. If you're not, + * you can ignore the id and just use the normal TypeScript with ReactJS. + * + * @param exceptionItem The exceptionItem to add an id to the threat matches. + * @returns exceptionItem The exceptionItem but with id added to the exception item entries + */ +export const addIdToExceptionItemEntries = ( + exceptionItem: ExceptionListItemSchema +): ExceptionListItemSchema => { + const entries = exceptionItem.entries.map((entry) => { + if (entry.type === 'nested') { + return addIdToItem({ + ...entry, + entries: entry.entries.map((nestedEntry) => addIdToItem(nestedEntry)), + }); + } else { + return addIdToItem(entry); + } + }); + return { ...exceptionItem, entries }; +}; + +/** + * This removes an id from the exceptionItem entries as ReactJS prefers to have + * an id added to them for use as a stable id. Later if we decide to change the data + * model to have id's within the array then this code should be removed. If not, then + * this code should stay as an adapter for ReactJS. + * + * @param exceptionItem The exceptionItem to remove an id from the entries. + * @returns exceptionItem The exceptionItem but with id removed from the entries + */ +export const removeIdFromExceptionItemsEntries = ( + exceptionItem: T +): T => { + const { entries } = exceptionItem; + const entriesNoId = entries.map((entry) => { + if (entry.type === 'nested') { + return removeIdFromItem({ + ...entry, + entries: entry.entries.map((nestedEntry) => removeIdFromItem(nestedEntry)), + }); + } else { + return removeIdFromItem(entry); + } + }); + return { ...exceptionItem, entries: entriesNoId }; +}; + +/** + * This removes createdAt, createdBy from the exceptionItem if a comment was added to + * the Exception item, and return the comment message with id to prevent creating the commet + * twice + * @param exceptionItem The exceptionItem to remove createdAt, createdBy from the comments array. + * @returns exceptionItem The exceptionItem with comments do not have createdAt, createdBy. + */ +export const removeCreatedAtCreatedByFromCommentsOnUpdate = ( + exceptionItem: UpdateExceptionListItemSchema | ExceptionListItemSchema +) => { + const { comments } = exceptionItem; + if (!comments || !comments.length) return exceptionItem; + + const entriesNoCreatedAtAndBy = comments.map(({ comment, id }) => ({ + comment, + id, + })); + return { ...exceptionItem, comments: entriesNoCreatedAtAndBy }; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts new file mode 100644 index 0000000000000..673eaff90b1af --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts @@ -0,0 +1,315 @@ +/* + * 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. + */ + +import { useMemo } from 'react'; +import type { + CreateExceptionListItemSchema, + ExceptionListItemSchema, + ExceptionListSchema, + UpdateExceptionListItemSchema, + ApiCallFindListsItemsMemoProps, + ApiCallMemoProps, + ApiListExportProps, + ApiCallGetExceptionFilterFromIdsMemoProps, + ApiCallGetExceptionFilterFromExceptionsMemoProps, + ApiListDuplicateProps, +} from '@kbn/securitysolution-io-ts-list-types'; +import * as Api from '@kbn/securitysolution-list-api'; +import { getIdsAndNamespaces } from '@kbn/securitysolution-list-utils'; +import type { HttpStart } from '@kbn/core-http-browser'; + +import { transformInput, transformNewItemOutput, transformOutput } from '../transforms'; + +export interface ExceptionsApi { + addExceptionListItem: (arg: { + listItem: CreateExceptionListItemSchema; + }) => Promise; + updateExceptionListItem: (arg: { + listItem: UpdateExceptionListItemSchema; + }) => Promise; + deleteExceptionItem: (arg: ApiCallMemoProps) => Promise; + deleteExceptionList: (arg: ApiCallMemoProps) => Promise; + duplicateExceptionList: (arg: ApiListDuplicateProps) => Promise; + getExceptionItem: ( + arg: ApiCallMemoProps & { onSuccess: (arg: ExceptionListItemSchema) => void } + ) => Promise; + getExceptionList: ( + arg: ApiCallMemoProps & { onSuccess: (arg: ExceptionListSchema) => void } + ) => Promise; + getExceptionListsItems: (arg: ApiCallFindListsItemsMemoProps) => Promise; + getExceptionFilterFromIds: (arg: ApiCallGetExceptionFilterFromIdsMemoProps) => Promise; + getExceptionFilterFromExceptions: ( + arg: ApiCallGetExceptionFilterFromExceptionsMemoProps + ) => Promise; + exportExceptionList: (arg: ApiListExportProps) => Promise; +} + +export const useApi = (http: HttpStart): ExceptionsApi => { + return useMemo( + (): ExceptionsApi => ({ + async addExceptionListItem({ + listItem, + }: { + listItem: CreateExceptionListItemSchema; + }): Promise { + const abortCtrl = new AbortController(); + const sanitizedItem: CreateExceptionListItemSchema = transformNewItemOutput(listItem); + + return Api.addExceptionListItem({ + http, + listItem: sanitizedItem, + signal: abortCtrl.signal, + }); + }, + async deleteExceptionItem({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps): Promise { + const abortCtrl = new AbortController(); + + try { + await Api.deleteExceptionListItemById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(); + } catch (error) { + onError(error); + } + }, + async deleteExceptionList({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps): Promise { + const abortCtrl = new AbortController(); + + try { + await Api.deleteExceptionListById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(); + } catch (error) { + onError(error); + } + }, + async duplicateExceptionList({ + includeExpiredExceptions, + listId, + namespaceType, + onError, + onSuccess, + }: ApiListDuplicateProps): Promise { + const abortCtrl = new AbortController(); + + try { + const newList = await Api.duplicateExceptionList({ + http, + includeExpiredExceptions, + listId, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(newList); + } catch (error) { + onError(error); + } + }, + async exportExceptionList({ + id, + includeExpiredExceptions, + listId, + namespaceType, + onError, + onSuccess, + }: ApiListExportProps): Promise { + const abortCtrl = new AbortController(); + + try { + const blob = await Api.exportExceptionList({ + http, + id, + includeExpiredExceptions, + listId, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(blob); + } catch (error) { + onError(error); + } + }, + async getExceptionItem({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps & { onSuccess: (arg: ExceptionListItemSchema) => void }): Promise { + const abortCtrl = new AbortController(); + + try { + const item = transformInput( + await Api.fetchExceptionListItemById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }) + ); + onSuccess(item); + } catch (error) { + onError(error); + } + }, + async getExceptionList({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps & { onSuccess: (arg: ExceptionListSchema) => void }): Promise { + const abortCtrl = new AbortController(); + + try { + const list = await Api.fetchExceptionListById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(list); + } catch (error) { + onError(error); + } + }, + async getExceptionListsItems({ + lists, + filter, + pagination, + showDetectionsListsOnly, + showEndpointListsOnly, + onSuccess, + onError, + }: ApiCallFindListsItemsMemoProps): Promise { + const abortCtrl = new AbortController(); + const { ids, namespaces } = getIdsAndNamespaces({ + lists, + showDetection: showDetectionsListsOnly, + showEndpoint: showEndpointListsOnly, + }); + + try { + if (ids.length > 0 && namespaces.length > 0) { + const { + data, + page, + per_page: perPage, + total, + } = await Api.fetchExceptionListsItemsByListIds({ + filter, + http, + listIds: ids, + namespaceTypes: namespaces, + pagination, + signal: abortCtrl.signal, + }); + onSuccess({ + // This data transform is UI specific and useful for UI concerns + // to compensate for the differences and preferences of how ReactJS might prefer + // data vs. how we want to model data. View `transformInput` for more details + exceptions: data.map((item) => transformInput(item)), + pagination: { + page, + perPage, + total, + }, + }); + } else { + onSuccess({ + exceptions: [], + pagination: { + page: 0, + perPage: pagination.perPage != null ? pagination.perPage : 0, + total: 0, + }, + }); + } + } catch (error) { + onError(error); + } + }, + async getExceptionFilterFromIds({ + exceptionListIds, + chunkSize, + alias, + excludeExceptions, + onSuccess, + onError, + }: ApiCallGetExceptionFilterFromIdsMemoProps): Promise { + const abortCtrl = new AbortController(); + try { + const { filter } = await Api.getExceptionFilterFromExceptionListIds({ + http, + exceptionListIds, + signal: abortCtrl.signal, + chunkSize, + alias, + excludeExceptions, + }); + onSuccess(filter); + } catch (error) { + onError(error); + } + }, + async getExceptionFilterFromExceptions({ + exceptions, + chunkSize, + alias, + excludeExceptions, + onSuccess, + onError, + }: ApiCallGetExceptionFilterFromExceptionsMemoProps): Promise { + const abortCtrl = new AbortController(); + try { + const { filter } = await Api.getExceptionFilterFromExceptions({ + http, + exceptions, + signal: abortCtrl.signal, + chunkSize, + alias, + excludeExceptions, + }); + onSuccess(filter); + } catch (error) { + onError(error); + } + }, + async updateExceptionListItem({ + listItem, + }: { + listItem: UpdateExceptionListItemSchema; + }): Promise { + const abortCtrl = new AbortController(); + const sanitizedItem: UpdateExceptionListItemSchema = transformOutput(listItem); + + return Api.updateExceptionListItem({ + http, + listItem: sanitizedItem, + signal: abortCtrl.signal, + }); + }, + }), + [http] + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts new file mode 100644 index 0000000000000..9cfaf30a9e2a4 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { createListIndex, ApiParams } from '@kbn/securitysolution-list-api'; +import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +import { READ_INDEX_QUERY_KEY } from '../constants'; + +const createListIndexWithOptionalSignal = withOptionalSignal(createListIndex); + +export const useCreateListIndex = ({ + http, + onError, +}: { + http: ApiParams['http']; + onError?: (err: unknown) => void; +}) => { + const queryClient = useQueryClient(); + + const { mutate, isLoading, error } = useMutation( + () => createListIndexWithOptionalSignal({ http }), + { + onSuccess: () => { + queryClient.invalidateQueries(READ_INDEX_QUERY_KEY); + }, + onError, + } + ); + + return { + start: mutate, + loading: isLoading, + error, + }; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_create_list_item/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_create_list_item/index.ts new file mode 100644 index 0000000000000..eaafc36d87334 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_create_list_item/index.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import type { UseMutationOptions } from '@tanstack/react-query'; +import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import type { IHttpFetchError } from '@kbn/core-http-browser'; +import { useMutation } from '@tanstack/react-query'; +import { createListItem } from '@kbn/securitysolution-list-api'; +import type { CreateListItemParams } from '@kbn/securitysolution-list-api'; +import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +import { useInvalidateListItemQuery } from '../use_find_list_items'; + +const createListItemWithOptionalSignal = withOptionalSignal(createListItem); + +export const CREATE_LIST_ITEM_MUTATION_KEY = ['POST', 'LIST_ITEM_CREATE']; +type CreateListMutationParams = Omit; + +export const useCreateListItemMutation = ( + options?: UseMutationOptions, CreateListMutationParams> +) => { + const invalidateListItemQuery = useInvalidateListItemQuery(); + return useMutation, CreateListMutationParams>( + ({ listId, value, http }) => + createListItemWithOptionalSignal({ listId, value, http, refresh: 'wait_for' }), + { + ...options, + mutationKey: CREATE_LIST_ITEM_MUTATION_KEY, + onSettled: (...args) => { + invalidateListItemQuery(); + if (options?.onSettled) { + options.onSettled(...args); + } + }, + } + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.test.ts new file mode 100644 index 0000000000000..714c310f6d5ea --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.test.ts @@ -0,0 +1,119 @@ +/* + * 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. + */ + +import { renderHook, act } from '@testing-library/react'; + +import { UseCursorProps, useCursor } from '.'; + +describe('useCursor', () => { + it('returns undefined cursor if no values have been set', () => { + const { result } = renderHook((props: UseCursorProps) => useCursor(props), { + initialProps: { pageIndex: 0, pageSize: 0 }, + }); + + expect(result.current[0]).toBeUndefined(); + }); + + it('retrieves a cursor for the next page of a given page size', () => { + const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { + initialProps: { pageIndex: 0, pageSize: 0 }, + }); + rerender({ pageIndex: 1, pageSize: 1 }); + act(() => { + result.current[1]('new_cursor'); + }); + + expect(result.current[0]).toBeUndefined(); + + rerender({ pageIndex: 2, pageSize: 1 }); + expect(result.current[0]).toEqual('new_cursor'); + }); + + it('returns undefined cursor for an unknown search', () => { + const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { + initialProps: { pageIndex: 0, pageSize: 0 }, + }); + act(() => { + result.current[1]('new_cursor'); + }); + + rerender({ pageIndex: 1, pageSize: 2 }); + expect(result.current[0]).toBeUndefined(); + }); + + it('remembers cursor through rerenders', () => { + const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { + initialProps: { pageIndex: 0, pageSize: 0 }, + }); + + rerender({ pageIndex: 1, pageSize: 1 }); + act(() => { + result.current[1]('new_cursor'); + }); + + rerender({ pageIndex: 2, pageSize: 1 }); + expect(result.current[0]).toEqual('new_cursor'); + + rerender({ pageIndex: 0, pageSize: 0 }); + expect(result.current[0]).toBeUndefined(); + + rerender({ pageIndex: 2, pageSize: 1 }); + expect(result.current[0]).toEqual('new_cursor'); + }); + + it('remembers multiple cursors', () => { + const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { + initialProps: { pageIndex: 0, pageSize: 0 }, + }); + + rerender({ pageIndex: 1, pageSize: 1 }); + act(() => { + result.current[1]('new_cursor'); + }); + rerender({ pageIndex: 2, pageSize: 2 }); + act(() => { + result.current[1]('another_cursor'); + }); + + rerender({ pageIndex: 2, pageSize: 1 }); + expect(result.current[0]).toEqual('new_cursor'); + + rerender({ pageIndex: 3, pageSize: 2 }); + expect(result.current[0]).toEqual('another_cursor'); + }); + + it('returns the "nearest" cursor for the given page size', () => { + const { rerender, result } = renderHook((props: UseCursorProps) => useCursor(props), { + initialProps: { pageIndex: 0, pageSize: 0 }, + }); + + rerender({ pageIndex: 1, pageSize: 2 }); + act(() => { + result.current[1]('cursor1'); + }); + rerender({ pageIndex: 2, pageSize: 2 }); + act(() => { + result.current[1]('cursor2'); + }); + rerender({ pageIndex: 3, pageSize: 2 }); + act(() => { + result.current[1]('cursor3'); + }); + + rerender({ pageIndex: 2, pageSize: 2 }); + expect(result.current[0]).toEqual('cursor1'); + + rerender({ pageIndex: 3, pageSize: 2 }); + expect(result.current[0]).toEqual('cursor2'); + + rerender({ pageIndex: 4, pageSize: 2 }); + expect(result.current[0]).toEqual('cursor3'); + + rerender({ pageIndex: 6, pageSize: 2 }); + expect(result.current[0]).toEqual('cursor3'); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.ts new file mode 100644 index 0000000000000..1bc85c63363c8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_cursor/index.ts @@ -0,0 +1,44 @@ +/* + * 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. + */ + +import { useCallback, useState } from 'react'; + +export interface UseCursorProps { + pageIndex: number; + pageSize: number; +} +type Cursor = string | undefined; +type SetCursor = (cursor: Cursor) => void; +type UseCursor = (props: UseCursorProps) => [Cursor, SetCursor]; + +const hash = (props: UseCursorProps): string => JSON.stringify(props); + +export const useCursor: UseCursor = ({ pageIndex, pageSize }) => { + const [cache, setCache] = useState>({}); + + const setCursor = useCallback( + (cursor) => { + setCache({ + ...cache, + [hash({ pageIndex: pageIndex + 1, pageSize })]: cursor, + }); + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [pageIndex, pageSize] + ); + + let cursor: Cursor; + for (let i = pageIndex; i >= 0; i--) { + const currentProps = { pageIndex: i, pageSize }; + cursor = cache[hash(currentProps)]; + if (cursor) { + break; + } + } + + return [cursor, setCursor]; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts new file mode 100644 index 0000000000000..ae427947ab66c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import { deleteList } from '@kbn/securitysolution-list-api'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +const deleteListWithOptionalSignal = withOptionalSignal(deleteList); + +export const useDeleteList = () => useAsync(deleteListWithOptionalSignal); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_delete_list_item/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_delete_list_item/index.ts new file mode 100644 index 0000000000000..04c608f9c841f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_delete_list_item/index.ts @@ -0,0 +1,39 @@ +/* + * 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. + */ + +import type { UseMutationOptions } from '@tanstack/react-query'; +import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { useMutation } from '@tanstack/react-query'; +import { deleteListItem } from '@kbn/securitysolution-list-api'; +import type { IHttpFetchError } from '@kbn/core-http-browser'; +import type { DeleteListItemParams } from '@kbn/securitysolution-list-api'; +import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; +import { useInvalidateListItemQuery } from '../use_find_list_items'; + +const deleteListItemWithOptionalSignal = withOptionalSignal(deleteListItem); + +export const DELETE_LIST_ITEM_MUTATION_KEY = ['POST', ' DELETE_LIST_ITEM_MUTATION']; +type DeleteListMutationParams = Omit; + +export const useDeleteListItemMutation = ( + options?: UseMutationOptions, DeleteListMutationParams> +) => { + const invalidateListItemQuery = useInvalidateListItemQuery(); + return useMutation, DeleteListMutationParams>( + ({ id, http }) => deleteListItemWithOptionalSignal({ id, http }), + { + ...options, + mutationKey: DELETE_LIST_ITEM_MUTATION_KEY, + onSettled: (...args) => { + invalidateListItemQuery(); + if (options?.onSettled) { + options.onSettled(...args); + } + }, + } + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.ts new file mode 100644 index 0000000000000..8a8e2aadf258c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.ts @@ -0,0 +1,140 @@ +/* + * 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. + */ + +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import type { + ExceptionListSchema, + UseExceptionListsProps, + Pagination, + Sort, +} from '@kbn/securitysolution-io-ts-list-types'; +import { fetchExceptionLists } from '@kbn/securitysolution-list-api'; + +import { getFilters } from '@kbn/securitysolution-list-utils'; + +export type Func = () => void; +export type ReturnExceptionLists = [ + loading: boolean, + exceptionLists: ExceptionListSchema[], + pagination: Pagination, + setPagination: React.Dispatch>, + fetchLists: Func | null, + sort: Sort, + setSort: React.Dispatch> +]; + +const DEFAULT_PAGINATION = { + page: 1, + perPage: 20, + total: 0, +}; + +const DEFAULT_SORT = { + field: 'created_at', + order: 'desc', +}; + +/** + * Hook for fetching ExceptionLists + * + * @param http Kibana http service + * @param errorMessage message shown to user if error occurs + * @param filterOptions filter by certain fields + * @param namespaceTypes spaces to be searched + * @param notifications kibana service for displaying toasters + * @param hideLists a list of listIds we don't want to query + * @param initialPagination + * + */ +export const useExceptionLists = ({ + errorMessage, + http, + initialPagination = DEFAULT_PAGINATION, + filterOptions = {}, + namespaceTypes, + notifications, + hideLists = [], + initialSort = DEFAULT_SORT, +}: UseExceptionListsProps): ReturnExceptionLists => { + const [exceptionLists, setExceptionLists] = useState([]); + const [pagination, setPagination] = useState(initialPagination); + const [sort, setSort] = useState(initialSort); + const [loading, setLoading] = useState(true); + const abortCtrlRef = useRef(); + + const namespaceTypesAsString = useMemo(() => namespaceTypes.join(','), [namespaceTypes]); + const filters = useMemo( + (): string => + getFilters({ + filters: filterOptions, + namespaceTypes, + hideLists, + }), + [namespaceTypes, filterOptions, hideLists] + ); + + const fetchData = useCallback(async (): Promise => { + try { + setLoading(true); + + abortCtrlRef.current = new AbortController(); + + const { + page, + per_page: perPage, + total, + data, + } = await fetchExceptionLists({ + filters, + http, + namespaceTypes: namespaceTypesAsString, + pagination: { + page: pagination.page, + perPage: pagination.perPage, + }, + sort, + signal: abortCtrlRef.current.signal, + }); + + setPagination({ + page, + perPage, + total, + }); + setExceptionLists(data); + setLoading(false); + } catch (error) { + if (error.name !== 'AbortError') { + notifications.toasts.addError(error, { + title: errorMessage, + }); + setExceptionLists([]); + setPagination(DEFAULT_PAGINATION); + setLoading(false); + } + } + }, [ + errorMessage, + filters, + http, + namespaceTypesAsString, + notifications.toasts, + pagination.page, + pagination.perPage, + sort, + ]); + + useEffect(() => { + fetchData(); + + return (): void => { + abortCtrlRef.current?.abort(); + }; + }, [fetchData]); + + return [loading, exceptionLists, pagination, setPagination, fetchData, sort, setSort]; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts new file mode 100644 index 0000000000000..bdaec5e503615 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import { exportList } from '@kbn/securitysolution-list-api'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +const exportListWithOptionalSignal = withOptionalSignal(exportList); + +export const useExportList = () => useAsync(exportListWithOptionalSignal); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_list_items/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_list_items/index.ts new file mode 100644 index 0000000000000..86ed9892fa95e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_list_items/index.ts @@ -0,0 +1,73 @@ +/* + * 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. + */ + +import { useCallback } from 'react'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { findListItems, ApiParams } from '@kbn/securitysolution-list-api'; +import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; +import { useCursor } from '../use_cursor'; + +const findListItemsWithOptionalSignal = withOptionalSignal(findListItems); + +const FIND_LIST_ITEMS_QUERY_KEY = 'FIND_LIST_ITEMS'; + +export const useInvalidateListItemQuery = () => { + const queryClient = useQueryClient(); + + return useCallback(() => { + queryClient.invalidateQueries([FIND_LIST_ITEMS_QUERY_KEY], { + refetchType: 'active', + }); + }, [queryClient]); +}; + +export const useFindListItems = ({ + pageIndex, + pageSize, + sortField, + sortOrder, + listId, + filter, + http, +}: { + pageIndex: number; + pageSize: number; + sortField: string; + sortOrder: 'asc' | 'desc'; + listId: string; + filter: string; + http: ApiParams['http']; +}) => { + const [cursor, setCursor] = useCursor({ pageIndex, pageSize }); + return useQuery( + [FIND_LIST_ITEMS_QUERY_KEY, pageIndex, pageSize, sortField, sortOrder, listId, filter], + async ({ signal }) => { + const response = await findListItemsWithOptionalSignal({ + http, + signal, + pageIndex, + pageSize, + sortField, + sortOrder, + listId, + cursor, + filter, + }); + return response; + }, + { + keepPreviousData: true, + refetchOnWindowFocus: false, + retry: false, + onSuccess: (data) => { + if (data?.cursor) { + setCursor(data?.cursor); + } + }, + } + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts new file mode 100644 index 0000000000000..0c60b3ebebb3e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts @@ -0,0 +1,37 @@ +/* + * 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. + */ + +import { waitFor, renderHook, act } from '@testing-library/react'; + +import { useFindLists } from '.'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; +import * as Api from '@kbn/securitysolution-list-api'; + +import { getFoundListSchemaMock } from '../mocks/response/found_list_schema.mock'; + +jest.mock('@kbn/securitysolution-list-api'); + +describe('useFindLists', () => { + let httpMock: ReturnType; + + beforeEach(() => { + httpMock = httpServiceMock.createStartContract(); + (Api.findLists as jest.Mock).mockResolvedValue(getFoundListSchemaMock()); + }); + + it('invokes Api.findLists', async () => { + const { result } = renderHook(() => useFindLists()); + act(() => { + result.current.start({ http: httpMock, pageIndex: 1, pageSize: 10 }); + }); + await waitFor(() => + expect(Api.findLists).toHaveBeenCalledWith( + expect.objectContaining({ http: httpMock, pageIndex: 1, pageSize: 10 }) + ) + ); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts new file mode 100644 index 0000000000000..0ad30728be4a8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import { findLists } from '@kbn/securitysolution-list-api'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +const findListsWithOptionalSignal = withOptionalSignal(findLists); + +export const useFindLists = () => useAsync(findListsWithOptionalSignal); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists_by_size/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists_by_size/index.ts new file mode 100644 index 0000000000000..e1132bdaab293 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_find_lists_by_size/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import { findListsBySize } from '@kbn/securitysolution-list-api'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +const findListsBySizeWithOptionalSignal = withOptionalSignal(findListsBySize); + +export const useFindListsBySize = () => useAsync(findListsBySizeWithOptionalSignal); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_get_list_by_id/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_get_list_by_id/index.ts new file mode 100644 index 0000000000000..394b48352a32b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_get_list_by_id/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import { useQuery } from '@tanstack/react-query'; +import { getListById, ApiParams } from '@kbn/securitysolution-list-api'; +import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +const getListByIdWithOptionalSignal = withOptionalSignal(getListById); + +const GET_LIST_BY_ID_QUERY_KEY = 'GET_LIST_BY_ID'; +export const useGetListById = ({ http, id }: { http: ApiParams['http']; id: string }) => { + return useQuery( + [GET_LIST_BY_ID_QUERY_KEY, id], + async ({ signal }) => { + const respone = await getListByIdWithOptionalSignal({ http, signal, id }); + return respone; + }, + { + refetchOnWindowFocus: false, + } + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts new file mode 100644 index 0000000000000..4499b7220128e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import { importList } from '@kbn/securitysolution-list-api'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +const importListWithOptionalSignal = withOptionalSignal(importList); + +export const useImportList = () => useAsync(importListWithOptionalSignal); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_patch_list_item/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_patch_list_item/index.ts new file mode 100644 index 0000000000000..e321006a0b687 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_patch_list_item/index.ts @@ -0,0 +1,40 @@ +/* + * 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. + */ + +import type { UseMutationOptions } from '@tanstack/react-query'; +import type { ListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { useMutation } from '@tanstack/react-query'; +import type { PatchListItemParams } from '@kbn/securitysolution-list-api'; +import { patchListItem } from '@kbn/securitysolution-list-api'; +import type { IHttpFetchError } from '@kbn/core-http-browser'; +import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; +import { useInvalidateListItemQuery } from '../use_find_list_items'; + +const patchListItemWithOptionalSignal = withOptionalSignal(patchListItem); + +export const PATCH_LIST_ITEM_MUTATION_KEY = ['PATCH', 'LIST_ITEM_MUTATION']; +type PatchListMutationParams = Omit; + +export const usePatchListItemMutation = ( + options?: UseMutationOptions, PatchListMutationParams> +) => { + const invalidateListItemQuery = useInvalidateListItemQuery(); + return useMutation, PatchListMutationParams>( + ({ id, value, _version, http }: PatchListMutationParams) => + patchListItemWithOptionalSignal({ id, value, http, refresh: 'true', _version }), + { + ...options, + mutationKey: PATCH_LIST_ITEM_MUTATION_KEY, + onSettled: (...args) => { + invalidateListItemQuery(); + if (options?.onSettled) { + options.onSettled(...args); + } + }, + } + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.ts new file mode 100644 index 0000000000000..ad239016ed054 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.ts @@ -0,0 +1,109 @@ +/* + * 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. + */ + +import { Dispatch, useEffect, useRef, useState } from 'react'; +import type { + CreateExceptionListItemSchema, + PersistHookProps, + UpdateExceptionListItemSchema, +} from '@kbn/securitysolution-io-ts-list-types'; +import { addExceptionListItem, updateExceptionListItem } from '@kbn/securitysolution-list-api'; + +import { transformNewItemOutput, transformOutput } from '../transforms'; + +interface PersistReturnExceptionItem { + isLoading: boolean; + isSaved: boolean; +} + +export type ReturnPersistExceptionItem = [ + PersistReturnExceptionItem, + Dispatch +]; + +// TODO: Add this to @kbn/securitysolution-list-hooks + +/** + * Hook for creating or updating ExceptionListItem + * + * @param http Kibana http service + * @param onError error callback + * + */ +export const usePersistExceptionItem = ({ + http, + onError, +}: PersistHookProps): ReturnPersistExceptionItem => { + const [exceptionListItem, setExceptionItem] = useState< + CreateExceptionListItemSchema | UpdateExceptionListItemSchema | null + >(null); + const [isSaved, setIsSaved] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const isUpdateExceptionItem = (item: unknown): item is UpdateExceptionListItemSchema => + Boolean(item && (item as UpdateExceptionListItemSchema).id != null); + const isSubscribed = useRef(false); + + useEffect(() => { + let abortCtrl: AbortController | null = null; + isSubscribed.current = true; + setIsSaved(false); + + const saveExceptionItem = async (): Promise => { + if (exceptionListItem === null) { + return; + } + + try { + abortCtrl = new AbortController(); + setIsLoading(true); + + if (isUpdateExceptionItem(exceptionListItem)) { + // Please see `x-pack/solutions/security/plugins/lists/public/exceptions/transforms.ts` doc notes + // for context around the temporary `id` + const transformedList = transformOutput(exceptionListItem); + + await updateExceptionListItem({ + http, + listItem: transformedList, + signal: abortCtrl.signal, + }); + } else { + // Please see `x-pack/solutions/security/plugins/lists/public/exceptions/transforms.ts` doc notes + // for context around the temporary `id` + const transformedList = transformNewItemOutput(exceptionListItem); + + await addExceptionListItem({ + http, + listItem: transformedList, + signal: abortCtrl.signal, + }); + } + + if (isSubscribed.current) { + setIsSaved(true); + } + } catch (error) { + if (isSubscribed.current) { + onError(error); + } + } finally { + if (isSubscribed.current) { + setIsLoading(false); + } + } + }; + + saveExceptionItem(); + + return (): void => { + isSubscribed.current = false; + abortCtrl?.abort(); + }; + }, [http, exceptionListItem, onError]); + + return [{ isLoading, isSaved }, setExceptionItem]; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.ts new file mode 100644 index 0000000000000..6814a19679c57 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.ts @@ -0,0 +1,79 @@ +/* + * 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. + */ + +import { Dispatch, useEffect, useState } from 'react'; +import type { + AddExceptionList, + PersistHookProps, + UpdateExceptionListSchema, +} from '@kbn/securitysolution-io-ts-list-types'; +import { addExceptionList, updateExceptionList } from '@kbn/securitysolution-list-api'; + +interface PersistReturnExceptionList { + isLoading: boolean; + isSaved: boolean; +} + +export type ReturnPersistExceptionList = [ + PersistReturnExceptionList, + Dispatch +]; + +/** + * Hook for creating or updating ExceptionList + * + * @param http Kibana http service + * @param onError error callback + * + */ +export const usePersistExceptionList = ({ + http, + onError, +}: PersistHookProps): ReturnPersistExceptionList => { + const [exceptionList, setExceptionList] = useState(null); + const [isSaved, setIsSaved] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const isUpdateExceptionList = (item: unknown): item is UpdateExceptionListSchema => + Boolean(item && (item as UpdateExceptionListSchema).id != null); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + setIsSaved(false); + + const saveExceptionList = async (): Promise => { + if (exceptionList != null) { + try { + setIsLoading(true); + if (isUpdateExceptionList(exceptionList)) { + await updateExceptionList({ http, list: exceptionList, signal: abortCtrl.signal }); + } else { + await addExceptionList({ http, list: exceptionList, signal: abortCtrl.signal }); + } + if (isSubscribed) { + setIsSaved(true); + } + } catch (error) { + if (isSubscribed) { + onError(error); + } + } + if (isSubscribed) { + setIsLoading(false); + } + } + }; + + saveExceptionList(); + return (): void => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, [http, exceptionList, onError]); + + return [{ isLoading, isSaved }, setExceptionList]; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts new file mode 100644 index 0000000000000..2bb2a7018857d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts @@ -0,0 +1,49 @@ +/* + * 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. + */ + +import { useQuery } from '@tanstack/react-query'; + +import { readListIndex, ApiParams } from '@kbn/securitysolution-list-api'; +import { withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +import { READ_INDEX_QUERY_KEY } from '../constants'; + +const readListIndexWithOptionalSignal = withOptionalSignal(readListIndex); + +export const useReadListIndex = ({ + http, + isEnabled, + onError, +}: { + isEnabled: boolean; + http: ApiParams['http']; + onError?: (err: unknown) => void; +}) => { + const query = useQuery( + READ_INDEX_QUERY_KEY, + async ({ signal }) => { + if (!isEnabled) { + return null; + } + + return readListIndexWithOptionalSignal({ http, signal }); + }, + { + onError, + retry: false, + refetchOnWindowFocus: false, + enabled: isEnabled, + staleTime: Infinity, + } + ); + + return { + result: query.data, + loading: query.isFetching, + error: query.error, + }; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts new file mode 100644 index 0000000000000..1e96118228b5d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import { readListPrivileges } from '@kbn/securitysolution-list-api'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; + +const readListPrivilegesWithOptionalSignal = withOptionalSignal(readListPrivileges); + +export const useReadListPrivileges = () => useAsync(readListPrivilegesWithOptionalSignal); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/tsconfig.json new file mode 100644 index 0000000000000..f2583861bced6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "kbn_references": [ + "@kbn/securitysolution-hook-utils", + "@kbn/securitysolution-io-ts-list-types", + "@kbn/securitysolution-list-api", + "@kbn/securitysolution-list-utils", + "@kbn/securitysolution-utils", + "@kbn/core-http-browser-mocks", + "@kbn/core-http-browser", + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-list-utils/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/README.md similarity index 100% rename from packages/kbn-securitysolution-list-utils/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-list-utils/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/index.ts new file mode 100644 index 0000000000000..cd6928dd89e34 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export * from './src/autocomplete_operators'; +export * from './src/get_exception_list_type'; +export * from './src/get_filters'; +export * from './src/get_general_filters'; +export * from './src/get_ids_and_namespaces'; +export * from './src/get_saved_object_type'; +export * from './src/get_saved_object_types'; +export * from './src/has_large_value_list'; +export * from './src/helpers'; +export * from './src/types'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/jest.config.js new file mode 100644 index 0000000000000..e3fc2abb342ab --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-list-utils'], +}; diff --git a/packages/kbn-securitysolution-list-utils/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-list-utils/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-list-utils/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/package.json new file mode 100644 index 0000000000000..585acd8e3d70c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/securitysolution-list-utils", + "version": "1.0.0", + "description": "security solution list utilities", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts new file mode 100644 index 0000000000000..430a0dbc3a1d8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts @@ -0,0 +1,158 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; +import { + ListOperatorEnum as OperatorEnum, + ListOperatorTypeEnum as OperatorTypeEnum, +} from '@kbn/securitysolution-io-ts-list-types'; +import { OperatorOption } from '../types'; + +export const isOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.isOperatorLabel', { + defaultMessage: 'is', + }), + operator: OperatorEnum.INCLUDED, + type: OperatorTypeEnum.MATCH, + value: 'is', +}; + +export const isNotOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.isNotOperatorLabel', { + defaultMessage: 'is not', + }), + operator: OperatorEnum.EXCLUDED, + type: OperatorTypeEnum.MATCH, + value: 'is_not', +}; + +export const isOneOfOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.isOneOfOperatorLabel', { + defaultMessage: 'is one of', + }), + operator: OperatorEnum.INCLUDED, + type: OperatorTypeEnum.MATCH_ANY, + value: 'is_one_of', +}; + +export const isNotOneOfOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.isNotOneOfOperatorLabel', { + defaultMessage: 'is not one of', + }), + operator: OperatorEnum.EXCLUDED, + type: OperatorTypeEnum.MATCH_ANY, + value: 'is_not_one_of', +}; + +export const existsOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.existsOperatorLabel', { + defaultMessage: 'exists', + }), + operator: OperatorEnum.INCLUDED, + type: OperatorTypeEnum.EXISTS, + value: 'exists', +}; + +export const doesNotExistOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.doesNotExistOperatorLabel', { + defaultMessage: 'does not exist', + }), + operator: OperatorEnum.EXCLUDED, + type: OperatorTypeEnum.EXISTS, + value: 'does_not_exist', +}; + +export const isInListOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.isInListOperatorLabel', { + defaultMessage: 'is in list', + }), + operator: OperatorEnum.INCLUDED, + type: OperatorTypeEnum.LIST, + value: 'is_in_list', +}; + +export const isNotInListOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.isNotInListOperatorLabel', { + defaultMessage: 'is not in list', + }), + operator: OperatorEnum.EXCLUDED, + type: OperatorTypeEnum.LIST, + value: 'is_not_in_list', +}; + +export const matchesOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.matchesOperatorLabel', { + defaultMessage: 'matches', + }), + operator: OperatorEnum.INCLUDED, + type: OperatorTypeEnum.WILDCARD, + value: 'matches', +}; + +export const doesNotMatchOperator: OperatorOption = { + message: i18n.translate('lists.exceptions.doesNotMatchOperatorLabel', { + defaultMessage: 'does not match', + }), + operator: OperatorEnum.EXCLUDED, + type: OperatorTypeEnum.WILDCARD, + value: 'does_not_match', +}; + +export const EVENT_FILTERS_OPERATORS: OperatorOption[] = [ + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + matchesOperator, + doesNotMatchOperator, +]; + +/* + * !IMPORTANT! - Please only add to this list if it is an operator + * supported by the detection engine. + */ +export const DETECTION_ENGINE_EXCEPTION_OPERATORS: OperatorOption[] = [ + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + existsOperator, + doesNotExistOperator, + isInListOperator, + isNotInListOperator, + matchesOperator, + doesNotMatchOperator, +]; + +export const ALL_OPERATORS: OperatorOption[] = [ + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + existsOperator, + doesNotExistOperator, + isInListOperator, + isNotInListOperator, + matchesOperator, + doesNotMatchOperator, +]; + +export const EXCEPTION_OPERATORS_SANS_LISTS: OperatorOption[] = [ + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + existsOperator, + doesNotExistOperator, + matchesOperator, + doesNotMatchOperator, +]; + +export const EXCEPTION_OPERATORS_ONLY_LISTS: OperatorOption[] = [ + isInListOperator, + isNotInListOperator, +]; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_exception_list_type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_exception_list_type/index.ts new file mode 100644 index 0000000000000..29dba94f76761 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_exception_list_type/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import type { NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; + +import { exceptionListAgnosticSavedObjectType } from '../types'; + +export const getExceptionListType = ({ + savedObjectType, +}: { + savedObjectType: string; +}): NamespaceType => { + if (savedObjectType === exceptionListAgnosticSavedObjectType) { + return 'agnostic'; + } else { + return 'single'; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_filters/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_filters/index.test.ts new file mode 100644 index 0000000000000..a88a78479cf54 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_filters/index.test.ts @@ -0,0 +1,207 @@ +/* + * 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. + */ + +import { getFilters } from '.'; + +describe('getFilters', () => { + describe('single', () => { + test('it properly formats when no filters and hide lists contains few list ids', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['single'], + hideLists: ['listId-1', 'listId-2', 'listId-3'], + }); + + expect(filter).toEqual( + '(not exception-list.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3*)' + ); + }); + test('it properly formats when no filters and hide lists contains one list id', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['single'], + hideLists: ['listId-1'], + }); + + expect(filter).toEqual('(not exception-list.attributes.list_id: listId-1*)'); + }); + test('it properly formats when no filters and no hide lists', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['single'], + hideLists: [], + }); + + expect(filter).toEqual(''); + }); + test('it properly formats when filters passed and hide lists contains few list ids', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['single'], + hideLists: ['listId-1', 'listId-2', 'listId-3'], + }); + + expect(filter).toEqual( + '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3*)' + ); + }); + test('it properly formats when filters passed and hide lists contains one list id', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['single'], + hideLists: ['listId-1'], + }); + + expect(filter).toEqual( + '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1*)' + ); + }); + test('it properly formats when filters passed and no hide lists', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['single'], + hideLists: [], + }); + + expect(filter).toEqual( + '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample)' + ); + }); + }); + + describe('agnostic', () => { + test('it properly formats when no filters and hide lists contains few list ids', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['agnostic'], + hideLists: ['listId-1', 'listId-2', 'listId-3'], + }); + + expect(filter).toEqual( + '(not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list-agnostic.attributes.list_id: listId-3*)' + ); + }); + test('it properly formats when no filters and hide lists contains one list id', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['agnostic'], + hideLists: ['listId-1'], + }); + + expect(filter).toEqual('(not exception-list-agnostic.attributes.list_id: listId-1*)'); + }); + test('it properly formats when no filters and no hide lists', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['agnostic'], + hideLists: [], + }); + + expect(filter).toEqual(''); + }); + test('it properly formats when filters passed and hide lists contains few list ids', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['agnostic'], + hideLists: ['listId-1', 'listId-2', 'listId-3'], + }); + + expect(filter).toEqual( + '(exception-list-agnostic.attributes.created_by:moi) AND (exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list-agnostic.attributes.list_id: listId-3*)' + ); + }); + test('it properly formats when filters passed and hide lists contains one list id', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['agnostic'], + hideLists: ['listId-1'], + }); + + expect(filter).toEqual( + '(exception-list-agnostic.attributes.created_by:moi) AND (exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list-agnostic.attributes.list_id: listId-1*)' + ); + }); + test('it properly formats when filters passed and no hide lists', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['agnostic'], + hideLists: [], + }); + + expect(filter).toEqual( + '(exception-list-agnostic.attributes.created_by:moi) AND (exception-list-agnostic.attributes.name.text:Sample)' + ); + }); + }); + + describe('single, agnostic', () => { + test('it properly formats when no filters and hide lists contains few list ids', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['single', 'agnostic'], + hideLists: ['listId-1', 'listId-2', 'listId-3'], + }); + + expect(filter).toEqual( + '(not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2* AND not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3* AND not exception-list-agnostic.attributes.list_id: listId-3*)' + ); + }); + test('it properly formats when no filters and hide lists contains one list id', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['single', 'agnostic'], + hideLists: ['listId-1'], + }); + + expect(filter).toEqual( + '(not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)' + ); + }); + test('it properly formats when no filters and no hide lists', () => { + const filter = getFilters({ + filters: {}, + namespaceTypes: ['single', 'agnostic'], + hideLists: [], + }); + + expect(filter).toEqual(''); + }); + test('it properly formats when filters passed and hide lists contains few list ids', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['single', 'agnostic'], + hideLists: ['listId-1', 'listId-2', 'listId-3'], + }); + + expect(filter).toEqual( + '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*) AND (not exception-list.attributes.list_id: listId-2* AND not exception-list-agnostic.attributes.list_id: listId-2*) AND (not exception-list.attributes.list_id: listId-3* AND not exception-list-agnostic.attributes.list_id: listId-3*)' + ); + }); + test('it properly formats when filters passed and hide lists contains one list id', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['single', 'agnostic'], + hideLists: ['listId-1'], + }); + + expect(filter).toEqual( + '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample) AND (not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)' + ); + }); + test('it properly formats when filters passed and no hide lists', () => { + const filter = getFilters({ + filters: { created_by: 'moi', name: 'Sample' }, + namespaceTypes: ['single', 'agnostic'], + hideLists: [], + }); + + expect(filter).toEqual( + '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample)' + ); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_filters/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_filters/index.ts new file mode 100644 index 0000000000000..2bc7960de7927 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_filters/index.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import { ExceptionListFilter, NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; +import { getGeneralFilters } from '../get_general_filters'; +import { getSavedObjectTypes } from '../get_saved_object_types'; +export interface GetFiltersParams { + filters: ExceptionListFilter; + namespaceTypes: NamespaceType[]; + hideLists: readonly string[]; +} + +export const getFilters = ({ filters, namespaceTypes, hideLists }: GetFiltersParams): string => { + const namespaces = getSavedObjectTypes({ namespaceType: namespaceTypes }); + const generalFilters = getGeneralFilters(filters, namespaces); + const hideListsFilters = hideLists.map((listId) => { + const filtersByNamespace = namespaces.map((namespace) => { + return `not ${namespace}.attributes.list_id: ${listId}*`; + }); + return `(${filtersByNamespace.join(' AND ')})`; + }); + + return [generalFilters, ...hideListsFilters] + .filter((filter) => filter.trim() !== '') + .join(' AND '); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.test.ts new file mode 100644 index 0000000000000..0262023497634 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.test.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ + +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { getGeneralFilters } from '.'; + +describe('getGeneralFilters', () => { + test('it returns empty string if no filters', () => { + const filters = getGeneralFilters({}, ['exception-list']); + + expect(filters).toEqual(''); + }); + + test('it properly formats filters when one namespace type passed in', () => { + const filters = getGeneralFilters({ created_by: 'moi', name: 'Sample' }, ['exception-list']); + + expect(filters).toEqual( + '(exception-list.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample)' + ); + }); + + test('it properly formats filters when two namespace types passed in', () => { + const filters = getGeneralFilters({ created_by: 'moi', name: 'Sample' }, [ + 'exception-list', + 'exception-list-agnostic', + ]); + + expect(filters).toEqual( + '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample)' + ); + }); + + test('it properly formats filters when two types are passed in', () => { + const filters = getGeneralFilters( + { + created_by: 'moi', + name: 'Sample', + types: [ExceptionListTypeEnum.DETECTION, ExceptionListTypeEnum.RULE_DEFAULT], + }, + ['exception-list', 'exception-list-agnostic'] + ); + + expect(filters).toEqual( + '(exception-list.attributes.created_by:moi OR exception-list-agnostic.attributes.created_by:moi) AND (exception-list.attributes.name.text:Sample OR exception-list-agnostic.attributes.name.text:Sample) AND (exception-list.attributes.type:detection OR exception-list.attributes.type:rule_default OR exception-list-agnostic.attributes.type:detection OR exception-list-agnostic.attributes.type:rule_default)' + ); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.ts new file mode 100644 index 0000000000000..7960617fad485 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_general_filters/index.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import { ExceptionListFilter } from '@kbn/securitysolution-io-ts-list-types'; +import { isArray } from 'lodash'; +import { get } from 'lodash/fp'; +import { SavedObjectType } from '../types'; + +export const getGeneralFilters = ( + filters: ExceptionListFilter, + namespaceTypes: SavedObjectType[] +): string => { + return Object.keys(filters) + .map((filterKey) => { + const value = get(filterKey, filters); + if (isArray(value) || (value != null && value.trim() !== '')) { + const filtersByNamespace = namespaceTypes + .map((namespace) => { + const fieldToSearch = + filterKey === 'name' ? 'name.text' : filterKey === 'types' ? 'type' : filterKey; + return isArray(value) + ? value.map((val) => `${namespace}.attributes.${fieldToSearch}:${val}`).join(' OR ') + : `${namespace}.attributes.${fieldToSearch}:${value}`; + }) + .join(' OR '); + return `(${filtersByNamespace})`; + } else return null; + }) + .filter((item) => item != null) + .join(' AND '); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.test.ts new file mode 100644 index 0000000000000..b76bc2df94ff8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.test.ts @@ -0,0 +1,104 @@ +/* + * 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. + */ + +import { getIdsAndNamespaces } from '.'; + +describe('getIdsAndNamespaces', () => { + test('it returns empty arrays if no lists found', async () => { + const output = getIdsAndNamespaces({ + lists: [], + showDetection: false, + showEndpoint: false, + }); + + expect(output).toEqual({ ids: [], namespaces: [] }); + }); + + test('it returns all lists if "showDetection" and "showEndpoint" are "false"', async () => { + const output = getIdsAndNamespaces({ + lists: [ + { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, + { + id: 'myListIdEndpoint', + listId: 'list_id_endpoint', + namespaceType: 'agnostic', + type: 'endpoint', + }, + ], + showDetection: false, + showEndpoint: false, + }); + + expect(output).toEqual({ + ids: ['list_id', 'list_id_endpoint'], + namespaces: ['single', 'agnostic'], + }); + }); + + test('it returns only detections lists if "showDetection" is "true"', async () => { + const output = getIdsAndNamespaces({ + lists: [ + { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, + { + id: 'myListIdEndpoint', + listId: 'list_id_endpoint', + namespaceType: 'agnostic', + type: 'endpoint', + }, + ], + showDetection: true, + showEndpoint: false, + }); + + expect(output).toEqual({ + ids: ['list_id'], + namespaces: ['single'], + }); + }); + + test('it returns only endpoint lists if "showEndpoint" is "true"', async () => { + const output = getIdsAndNamespaces({ + lists: [ + { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, + { + id: 'myListIdEndpoint', + listId: 'list_id_endpoint', + namespaceType: 'agnostic', + type: 'endpoint', + }, + ], + showDetection: false, + showEndpoint: true, + }); + + expect(output).toEqual({ + ids: ['list_id_endpoint'], + namespaces: ['agnostic'], + }); + }); + + test('it returns only detection lists if both "showEndpoint" and "showDetection" are "true"', async () => { + const output = getIdsAndNamespaces({ + lists: [ + { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, + { + id: 'myListIdEndpoint', + listId: 'list_id_endpoint', + namespaceType: 'agnostic', + type: 'endpoint', + }, + ], + showDetection: true, + showEndpoint: true, + }); + + expect(output).toEqual({ + ids: ['list_id'], + namespaces: ['single'], + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.ts new file mode 100644 index 0000000000000..25a7ae1931e18 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_ids_and_namespaces/index.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import { ExceptionListIdentifiers, NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; + +export const getIdsAndNamespaces = ({ + lists, + showDetection, + showEndpoint, +}: { + lists: ExceptionListIdentifiers[]; + showDetection: boolean; + showEndpoint: boolean; +}): { ids: string[]; namespaces: NamespaceType[] } => + lists + .filter((list) => { + if (showDetection) { + return list.type === 'detection'; + } else if (showEndpoint) { + return list.type === 'endpoint'; + } else { + return true; + } + }) + .reduce<{ ids: string[]; namespaces: NamespaceType[] }>( + (acc, { listId, namespaceType }) => ({ + ids: [...acc.ids, listId], + namespaces: [...acc.namespaces, namespaceType], + }), + { ids: [], namespaces: [] } + ); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_saved_object_type/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_saved_object_type/index.ts new file mode 100644 index 0000000000000..0ee1b134333ca --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_saved_object_type/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import type { NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; + +import { + exceptionListAgnosticSavedObjectType, + exceptionListSavedObjectType, + SavedObjectType, +} from '../types'; + +export const getSavedObjectType = ({ + namespaceType, +}: { + namespaceType: NamespaceType; +}): SavedObjectType => { + if (namespaceType === 'agnostic') { + return exceptionListAgnosticSavedObjectType; + } else { + return exceptionListSavedObjectType; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_saved_object_types/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_saved_object_types/index.ts new file mode 100644 index 0000000000000..92b6ff4a92631 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/get_saved_object_types/index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import type { NamespaceTypeArray } from '@kbn/securitysolution-io-ts-list-types'; + +import { SavedObjectType } from '../types'; +import { getSavedObjectType } from '../get_saved_object_type'; + +export const getSavedObjectTypes = ({ + namespaceType, +}: { + namespaceType: NamespaceTypeArray; +}): SavedObjectType[] => { + return namespaceType.map((singleNamespaceType) => + getSavedObjectType({ namespaceType: singleNamespaceType }) + ); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/has_large_value_list/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/has_large_value_list/index.ts new file mode 100644 index 0000000000000..350cb581153b5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/has_large_value_list/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types'; + +export const hasLargeValueList = (entries: EntriesArray): boolean => { + const found = entries.filter(({ type }) => type === 'list'); + return found.length > 0; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts new file mode 100644 index 0000000000000..fe75ad88e0129 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts @@ -0,0 +1,375 @@ +/* + * 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. + */ + +import { + getMappingConflictsInfo, + fieldSupportsMatches, + hasWrongOperatorWithWildcard, + hasPartialCodeSignatureEntry, +} from '.'; + +describe('Helpers', () => { + describe('getMappingConflictsInfo', () => { + test('it return null if there are not conflicts', () => { + const field = { + name: 'field1', + type: 'string', + }; + const conflictsInfo = getMappingConflictsInfo(field); + + expect(conflictsInfo).toBeNull(); + }); + test('it groups ".ds-" data stream indices', () => { + const field = { + name: 'field1', + type: 'conflict', + conflictDescriptions: { + text: [ + '.ds-logs-default-2023.01.18-000001', + '.ds-logs-default-2023.01.18-000002', + '.ds-logs-tortilla.process-default-2022.11.20-000011', + '.ds-logs-tortilla.process-default-2022.11.20-000012', + '.ds-logs-tortilla.process-default-2022.11.20-000016', + ], + long: [ + '.ds-logs-default-2023.01.18-000004', + '.ds-logs-default-2023.01.18-000005', + 'partial-.ds-logs-gcp.audit-2021.12.22-000240', + 'partial-.ds-logs-gcp.audit-2021.12.22-000242', + ], + }, + }; + const conflictsInfo = getMappingConflictsInfo(field); + + expect(conflictsInfo).toEqual([ + { + type: 'text', + totalIndexCount: 5, + groupedIndices: [ + { name: 'logs-tortilla.process-default', count: 3 }, + { name: 'logs-default', count: 2 }, + ], + }, + { + type: 'long', + totalIndexCount: 4, + groupedIndices: [ + { name: 'logs-default', count: 2 }, + { name: 'logs-gcp.audit', count: 2 }, + ], + }, + ]); + }); + test('it groups old ".siem-" indices', () => { + const field = { + name: 'field1', + type: 'conflict', + conflictDescriptions: { + text: [ + '.siem-signals-default-000001', + '.siem-signals-default-000002', + '.siem-signals-default-000011', + '.siem-signals-default-000012', + ], + unmapped: [ + '.siem-signals-default-000004', + '.siem-signals-default-000005', + '.siem-signals-default-000240', + ], + }, + }; + const conflictsInfo = getMappingConflictsInfo(field); + + expect(conflictsInfo).toEqual([ + { + type: 'text', + totalIndexCount: 4, + groupedIndices: [{ name: '.siem-signals-default', count: 4 }], + }, + { + type: 'unmapped', + totalIndexCount: 3, + groupedIndices: [{ name: '.siem-signals-default', count: 3 }], + }, + ]); + }); + test('it groups mixed indices', () => { + const field = { + name: 'field1', + type: 'conflict', + conflictDescriptions: { + boolean: [ + '.ds-logs-default-2023.01.18-000001', + '.ds-logs-tortilla.process-default-2022.11.20-000011', + '.ds-logs-tortilla.process-default-2022.11.20-000012', + '.ds-logs-tortilla.process-default-2022.11.20-000016', + '.siem-signals-default-000001', + '.siem-signals-default-000002', + '.siem-signals-default-000012', + 'my-own-index-1', + 'my-own-index-2', + ], + unmapped: [ + '.siem-signals-default-000004', + 'partial-.ds-logs-gcp.audit-2021.12.22-000240', + 'partial-.ds-logs-gcp.audit-2021.12.22-000242', + 'my-own-index-3', + ], + }, + }; + const conflictsInfo = getMappingConflictsInfo(field); + + expect(conflictsInfo).toEqual([ + { + type: 'boolean', + totalIndexCount: 9, + groupedIndices: [ + { name: 'logs-tortilla.process-default', count: 3 }, + { name: '.siem-signals-default', count: 3 }, + { name: 'logs-default', count: 1 }, + { name: 'my-own-index-1', count: 1 }, + { name: 'my-own-index-2', count: 1 }, + ], + }, + { + type: 'unmapped', + totalIndexCount: 4, + groupedIndices: [ + { name: 'logs-gcp.audit', count: 2 }, + { name: '.siem-signals-default', count: 1 }, + { name: 'my-own-index-3', count: 1 }, + ], + }, + ]); + }); + }); + + describe('fieldSupportsMatches', () => { + test('it returns true if esTypes is keyword', () => { + expect( + fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['keyword'] }) + ).toBeTruthy(); + }); + + test('it returns true if one of the esTypes is kibana type string and another is not', () => { + expect( + fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['keyword', 'object'] }) + ).toBeTruthy(); + }); + + test('it returns true if one of the esTypes is keyword', () => { + expect( + fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['keyword', 'unmapped'] }) + ).toBeTruthy(); + }); + + test('it returns true if one of the esTypes is text', () => { + expect( + fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['text', 'unmapped'] }) + ).toBeTruthy(); + }); + + test('it returns true if all of the esTypes is map to kibana type string', () => { + expect( + fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['text', 'keyword'] }) + ).toBeTruthy(); + }); + + test('it returns false if none of the esTypes map to kibana type string', () => { + expect( + fieldSupportsMatches({ name: 'field', type: 'conflict', esTypes: ['bool', 'unmapped'] }) + ).toBeFalsy(); + }); + }); + describe('hasWrongOperatorWithWildcard', () => { + test('it returns true if there is at least one exception entry with a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard*', field: '', operator: 'included' }], + }, + ]) + ).toBeTruthy(); + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard?', field: '', operator: 'included' }], + }, + ]) + ).toBeTruthy(); + }); + + test('it returns true if there are entries joined with an OR that have a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard?', field: '', operator: 'included' }], + }, + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard?*', field: '', operator: 'included' }], + }, + ]) + ).toBeTruthy(); + }); + + test('it returns false if there are no exception entries with a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [ + { type: 'match', value: 'nowildcard', field: '', operator: 'excluded' }, + { type: 'wildcard', value: 'withwildcard*?', field: '', operator: 'included' }, + ], + }, + ]) + ).toBeFalsy(); + }); + + test('it returns true if there are nested entries with a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [ + { type: 'match', value: 'nowildcard', field: '', operator: 'excluded' }, + { + field: '', + type: 'nested', + entries: [{ type: 'match', value: 'wildcard?', field: '', operator: 'excluded' }], + }, + ], + }, + ]) + ).toBeTruthy(); + }); + }); + + describe('hasPartialCodeSignatureEntry', () => { + it('returns false if the entry has neither code signature subject name nor trusted field', () => { + expect( + hasPartialCodeSignatureEntry([ + { + description: '', + name: '', + type: 'simple', + os_types: ['windows'], + entries: [{ type: 'match', value: 'asdf', field: 'someField', operator: 'excluded' }], + }, + ]) + ).toBeFalsy(); + }); + it('returns true if the entry has code signature subject name but not trusted field', () => { + expect( + hasPartialCodeSignatureEntry([ + { + description: '', + name: '', + type: 'simple', + os_types: ['windows'], + entries: [ + { + type: 'match', + value: 'asdf', + field: 'process.code_signature.subject_name', + operator: 'excluded', + }, + ], + }, + ]) + ).toBeTruthy(); + }); + it('returns true if the entry has code signature trusted but not the subject name field', () => { + expect( + hasPartialCodeSignatureEntry([ + { + description: '', + name: '', + type: 'simple', + os_types: ['windows'], + entries: [ + { + type: 'match', + value: 'asdf', + field: 'process.code_signature.trusted', + operator: 'excluded', + }, + ], + }, + ]) + ).toBeTruthy(); + }); + it('returns false if the entry has both code signature subject name and trusted field', () => { + expect( + hasPartialCodeSignatureEntry([ + { + description: '', + name: '', + type: 'simple', + os_types: ['windows'], + entries: [ + { + type: 'match', + value: 'asdf', + field: 'process.code_signature.subject_name', + operator: 'excluded', + }, + { + type: 'match', + value: 'true', + field: 'process.code_signature.trusted', + operator: 'excluded', + }, + ], + }, + ]) + ).toBeFalsy(); + }); + it('returns false if the entry has both code signature team_id and trusted fields for mac os', () => { + expect( + hasPartialCodeSignatureEntry([ + { + description: '', + name: '', + type: 'simple', + os_types: ['macos'], + entries: [ + { + type: 'match', + value: 'asdf', + field: 'process.code_signature.team_id', + operator: 'excluded', + }, + { + type: 'match', + value: 'true', + field: 'process.code_signature.trusted', + operator: 'excluded', + }, + ], + }, + ]) + ).toBeFalsy(); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/helpers/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/helpers/index.ts new file mode 100644 index 0000000000000..6cbdbe55cfeb6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/helpers/index.ts @@ -0,0 +1,1088 @@ +/* + * 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. + */ + +import { v4 as uuidv4 } from 'uuid'; +import { + addIdToItem, + removeIdFromItem, + validateHasWildcardWithWrongOperator, +} from '@kbn/securitysolution-utils'; +import { validate } from '@kbn/securitysolution-io-ts-utils'; +import { + CreateExceptionListItemSchema, + EntriesArray, + Entry, + EntryNested, + ExceptionListType, + ListSchema, + NamespaceType, + ListOperatorEnum as OperatorEnum, + ListOperatorTypeEnum as OperatorTypeEnum, + createExceptionListItemSchema, + entriesList, + entriesNested, + entry, + exceptionListItemSchema, + nestedEntryItem, + CreateRuleExceptionListItemSchema, + createRuleExceptionListItemSchema, +} from '@kbn/securitysolution-io-ts-list-types'; +import { + DataViewBase, + DataViewFieldBase, + getDataViewFieldSubtypeNested, + isDataViewFieldSubtypeNested, +} from '@kbn/es-query'; +import { castEsToKbnFieldTypeName, KBN_FIELD_TYPES } from '@kbn/field-types'; + +import { + ALL_OPERATORS, + EXCEPTION_OPERATORS_SANS_LISTS, + doesNotExistOperator, + existsOperator, + isNotOperator, + isOneOfOperator, + isOperator, + DETECTION_ENGINE_EXCEPTION_OPERATORS, + isNotOneOfOperator, + isInListOperator, + isNotInListOperator, + matchesOperator, + doesNotMatchOperator, +} from '../autocomplete_operators'; + +import { + BuilderEntry, + CreateExceptionListItemBuilderSchema, + DataViewField, + EmptyEntry, + EmptyNestedEntry, + ExceptionsBuilderExceptionItem, + ExceptionsBuilderReturnExceptionItem, + FormattedBuilderEntry, + OperatorOption, + SavedObjectType, +} from '../types'; + +export const isEntryNested = (item: BuilderEntry): item is EntryNested => { + return (item as EntryNested).entries != null; +}; + +export const filterExceptionItems = ( + exceptions: ExceptionsBuilderExceptionItem[] +): ExceptionsBuilderReturnExceptionItem[] => { + return exceptions.reduce((acc, exception) => { + const entries = exception.entries.reduce((nestedAcc, singleEntry) => { + const strippedSingleEntry = removeIdFromItem(singleEntry); + if (entriesNested.is(strippedSingleEntry)) { + const nestedEntriesArray = strippedSingleEntry.entries.filter((singleNestedEntry) => { + const noIdSingleNestedEntry = removeIdFromItem(singleNestedEntry); + const [validatedNestedEntry] = validate(noIdSingleNestedEntry, nestedEntryItem); + return validatedNestedEntry != null; + }); + const noIdNestedEntries = nestedEntriesArray.map((singleNestedEntry) => + removeIdFromItem(singleNestedEntry) + ); + + const [validatedNestedEntry] = validate( + { ...strippedSingleEntry, entries: noIdNestedEntries }, + entriesNested + ); + + if (validatedNestedEntry != null) { + return [...nestedAcc, { ...singleEntry, entries: nestedEntriesArray }]; + } + return nestedAcc; + } else { + const [validatedEntry] = validate(strippedSingleEntry, entry); + if (validatedEntry != null) { + return [...nestedAcc, singleEntry]; + } + return nestedAcc; + } + }, []); + + if (entries.length === 0) { + return acc; + } + + const item = { ...exception, entries }; + + if (exceptionListItemSchema.is(item)) { + return [...acc, item]; + } else if ( + createExceptionListItemSchema.is(item) || + createRuleExceptionListItemSchema.is(item) + ) { + const { meta, ...rest } = item; + const itemSansMetaId: CreateExceptionListItemSchema | CreateRuleExceptionListItemSchema = { + ...rest, + meta: undefined, + }; + return [...acc, itemSansMetaId]; + } else { + return acc; + } + }, []); +}; + +export const addIdToEntries = (entries: EntriesArray): EntriesArray => { + return entries.map((singleEntry) => { + if (singleEntry.type === 'nested') { + return addIdToItem({ + ...singleEntry, + entries: singleEntry.entries.map((nestedEntry) => addIdToItem(nestedEntry)), + }); + } else { + return addIdToItem(singleEntry); + } + }); +}; + +export const getNewExceptionItem = ({ + listId, + namespaceType, + name, +}: { + listId: string | undefined; + namespaceType: NamespaceType | undefined; + name: string; +}): CreateExceptionListItemBuilderSchema => { + return { + comments: [], + description: `Exception list item`, + entries: addIdToEntries([ + { + field: '', + operator: 'included', + type: 'match', + value: '', + }, + ]), + item_id: undefined, + list_id: listId, + meta: { + temporaryUuid: uuidv4(), + }, + name, + namespace_type: namespaceType, + tags: [], + type: 'simple', + }; +}; + +/** + * Returns the operator type, may not need this if using io-ts types + * + * @param item a single ExceptionItem entry + */ +export const getOperatorType = (item: BuilderEntry): OperatorTypeEnum => { + switch (item.type) { + case 'match': + return OperatorTypeEnum.MATCH; + case 'match_any': + return OperatorTypeEnum.MATCH_ANY; + case 'wildcard': + return OperatorTypeEnum.WILDCARD; + case 'list': + return OperatorTypeEnum.LIST; + default: + return OperatorTypeEnum.EXISTS; + } +}; + +/** + * Determines operator selection (is/is not/is one of, etc.) + * Default operator is "is" + * + * @param item a single ExceptionItem entry + */ +export const getExceptionOperatorSelect = (item: BuilderEntry): OperatorOption => { + if (item.type === 'nested') { + return isOperator; + } else { + const operatorType = getOperatorType(item); + const foundOperator = ALL_OPERATORS.find((operatorOption) => { + return item.operator === operatorOption.operator && operatorType === operatorOption.type; + }); + + return foundOperator != null ? foundOperator : isOperator; + } +}; + +/** + * Returns the fields corresponding value for an entry + * + * @param item a single ExceptionItem entry + */ +export const getEntryValue = (item: BuilderEntry): string | string[] | undefined => { + switch (item.type) { + case OperatorTypeEnum.MATCH: + case OperatorTypeEnum.MATCH_ANY: + case OperatorTypeEnum.WILDCARD: + return item.value; + case OperatorTypeEnum.EXISTS: + return undefined; + case OperatorTypeEnum.LIST: + return item.list.id; + default: + return undefined; + } +}; + +/** + * Determines whether an entire entry, exception item, or entry within a nested + * entry needs to be removed + * + * @param exceptionItem + * @param entryIndex index of given entry, for nested entries, this will correspond + * to their parent index + * @param nestedEntryIndex index of nested entry + * + */ +export const getUpdatedEntriesOnDelete = ( + exceptionItem: ExceptionsBuilderExceptionItem, + entryIndex: number, + nestedParentIndex: number | null +): ExceptionsBuilderExceptionItem => { + const itemOfInterest: BuilderEntry = + exceptionItem.entries[nestedParentIndex != null ? nestedParentIndex : entryIndex]; + + if (nestedParentIndex != null && itemOfInterest.type === OperatorTypeEnum.NESTED) { + const updatedEntryEntries = [ + ...itemOfInterest.entries.slice(0, entryIndex), + ...itemOfInterest.entries.slice(entryIndex + 1), + ]; + + if (updatedEntryEntries.length === 0) { + return { + ...exceptionItem, + entries: [ + ...exceptionItem.entries.slice(0, nestedParentIndex), + ...exceptionItem.entries.slice(nestedParentIndex + 1), + ], + }; + } else { + const { field } = itemOfInterest; + const updatedItemOfInterest: EntryNested | EmptyNestedEntry = { + entries: updatedEntryEntries, + field, + id: itemOfInterest.id != null ? itemOfInterest.id : `${entryIndex}`, + type: OperatorTypeEnum.NESTED, + }; + + return { + ...exceptionItem, + entries: [ + ...exceptionItem.entries.slice(0, nestedParentIndex), + updatedItemOfInterest, + ...exceptionItem.entries.slice(nestedParentIndex + 1), + ], + }; + } + } else { + return { + ...exceptionItem, + entries: [ + ...exceptionItem.entries.slice(0, entryIndex), + ...exceptionItem.entries.slice(entryIndex + 1), + ], + }; + } +}; + +/** + * Returns filtered index patterns based on the field - if a user selects to + * add nested entry, should only show nested fields, if item is the parent + * field of a nested entry, we only display the parent field + * + * @param patterns DataViewBase containing available fields on rule index + * @param item exception item entry + * set to add a nested field + */ +export const getFilteredIndexPatterns = ( + patterns: DataViewBase, + item: FormattedBuilderEntry +): DataViewBase => { + if (item.nested === 'child' && item.parent != null) { + // when user has selected a nested entry, only fields with the common parent are shown + return { + ...patterns, + fields: patterns.fields + .filter((indexField) => { + const subTypeNested = getDataViewFieldSubtypeNested(indexField); + const fieldHasCommonParentPath = + subTypeNested && + item.parent != null && + subTypeNested.nested.path === item.parent.parent.field; + + return fieldHasCommonParentPath; + }) + .map((f) => { + const [fieldNameWithoutParentPath] = f.name.split('.').slice(-1); + return { ...f, name: fieldNameWithoutParentPath }; + }), + }; + } else if (item.nested === 'parent' && item.field != null) { + // when user has selected a nested entry, right above it we show the common parent + return { ...patterns, fields: [item.field] }; + } else if (item.nested === 'parent' && item.field == null) { + // when user selects to add a nested entry, only nested fields are shown as options + return { + ...patterns, + fields: patterns.fields.filter((field) => isDataViewFieldSubtypeNested(field)), + }; + } else { + return patterns; + } +}; + +/** + * Determines proper entry update when user selects new field + * + * @param item - current exception item entry values + * @param newField - newly selected field + * + */ +export const getEntryOnFieldChange = ( + item: FormattedBuilderEntry, + newField: DataViewFieldBase +): { index: number; updatedEntry: BuilderEntry } => { + const { parent, entryIndex, nested } = item; + const newChildFieldValue = newField != null ? newField.name.split('.').slice(-1)[0] : ''; + + if (nested === 'parent') { + // For nested entries, when user first selects to add a nested + // entry, they first see a row similar to what is shown for when + // a user selects "exists", as soon as they make a selection + // we can now identify the 'parent' and 'child' this is where + // we first convert the entry into type "nested" + const subTypeNested = getDataViewFieldSubtypeNested(newField); + const newParentFieldValue = subTypeNested?.nested.path || ''; + + return { + index: entryIndex, + updatedEntry: { + entries: [ + addIdToItem({ + field: newChildFieldValue != null ? newChildFieldValue : '', + operator: isOperator.operator, + type: OperatorTypeEnum.MATCH, + value: '', + }), + ], + field: newParentFieldValue, + id: item.id, + type: OperatorTypeEnum.NESTED, + }, + }; + } else if (nested === 'child' && parent != null) { + return { + index: parent.parentIndex, + updatedEntry: { + ...parent.parent, + entries: [ + ...parent.parent.entries.slice(0, entryIndex), + { + field: newChildFieldValue != null ? newChildFieldValue : '', + id: item.id, + operator: isOperator.operator, + type: OperatorTypeEnum.MATCH, + value: '', + }, + ...parent.parent.entries.slice(entryIndex + 1), + ], + }, + }; + } else { + return { + index: entryIndex, + updatedEntry: { + field: newField != null ? newField.name : '', + id: item.id, + operator: isOperator.operator, + type: OperatorTypeEnum.MATCH, + value: '', + }, + }; + } +}; + +/** + * Determines proper entry update when user updates value + * when operator is of type "list" + * + * @param item - current exception item entry values + * @param newField - newly selected list + * + */ +export const getEntryOnListChange = ( + item: FormattedBuilderEntry, + newField: ListSchema +): { index: number; updatedEntry: BuilderEntry } => { + const { entryIndex, field, operator } = item; + const { id, type } = newField; + + return { + index: entryIndex, + updatedEntry: { + field: field != null ? field.name : '', + id: item.id, + list: { id, type }, + operator: operator.operator, + type: OperatorTypeEnum.LIST, + }, + }; +}; + +/** + * Determines proper entry update when user updates value + * when operator is of type "match_any" + * + * @param item - current exception item entry values + * @param newField - newly entered value + * + */ +export const getEntryOnMatchAnyChange = ( + item: FormattedBuilderEntry, + newField: string[] +): { index: number; updatedEntry: BuilderEntry } => { + const { nested, parent, entryIndex, field, operator } = item; + + if (nested != null && parent != null) { + const fieldName = field != null ? field.name.split('.').slice(-1)[0] : ''; + + return { + index: parent.parentIndex, + updatedEntry: { + ...parent.parent, + entries: [ + ...parent.parent.entries.slice(0, entryIndex), + { + field: fieldName, + id: item.id, + operator: operator.operator, + type: OperatorTypeEnum.MATCH_ANY, + value: newField, + }, + ...parent.parent.entries.slice(entryIndex + 1), + ], + }, + }; + } else { + return { + index: entryIndex, + updatedEntry: { + field: field != null ? field.name : '', + id: item.id, + operator: operator.operator, + type: OperatorTypeEnum.MATCH_ANY, + value: newField, + }, + }; + } +}; + +/** + * Determines proper entry update when user updates value + * when operator is of type "match" + * + * @param item - current exception item entry values + * @param newField - newly entered value + * + */ +export const getEntryOnMatchChange = ( + item: FormattedBuilderEntry, + newField: string +): { index: number; updatedEntry: BuilderEntry } => { + const { nested, parent, entryIndex, field, operator } = item; + + if (nested != null && parent != null) { + const fieldName = field != null ? field.name.split('.').slice(-1)[0] : ''; + + return { + index: parent.parentIndex, + updatedEntry: { + ...parent.parent, + entries: [ + ...parent.parent.entries.slice(0, entryIndex), + { + field: fieldName, + id: item.id, + operator: operator.operator, + type: OperatorTypeEnum.MATCH, + value: newField, + }, + ...parent.parent.entries.slice(entryIndex + 1), + ], + }, + }; + } else { + return { + index: entryIndex, + updatedEntry: { + field: field != null ? field.name : '', + id: item.id, + operator: operator.operator, + type: OperatorTypeEnum.MATCH, + value: newField, + }, + }; + } +}; + +/** + * Determines proper entry update when user updates value + * when operator is of type "wildcard" + * + * @param item - current exception item entry values + * @param newField - newly entered value + * + */ +export const getEntryOnWildcardChange = ( + item: FormattedBuilderEntry, + newField: string +): { index: number; updatedEntry: BuilderEntry } => { + const { nested, parent, entryIndex, field, operator } = item; + + if (nested != null && parent != null) { + const fieldName = field != null ? field.name.split('.').slice(-1)[0] : ''; + + return { + index: parent.parentIndex, + updatedEntry: { + ...parent.parent, + entries: [ + ...parent.parent.entries.slice(0, entryIndex), + { + field: fieldName, + id: item.id, + operator: operator.operator, + type: OperatorTypeEnum.WILDCARD, + value: newField, + }, + ...parent.parent.entries.slice(entryIndex + 1), + ], + }, + }; + } else { + return { + index: entryIndex, + updatedEntry: { + field: field != null ? field.name : '', + id: item.id, + operator: operator.operator, + type: OperatorTypeEnum.WILDCARD, + value: newField, + }, + }; + } +}; + +/** + * On operator change, determines whether value needs to be cleared or not + * + * @param field + * @param selectedOperator + * @param currentEntry + * + */ +export const getEntryFromOperator = ( + selectedOperator: OperatorOption, + currentEntry: FormattedBuilderEntry +): Entry & { id?: string } => { + const isSameOperatorType = currentEntry.operator.type === selectedOperator.type; + const fieldValue = currentEntry.field != null ? currentEntry.field.name : ''; + switch (selectedOperator.type) { + case 'match': + return { + field: fieldValue, + id: currentEntry.id, + operator: selectedOperator.operator, + type: OperatorTypeEnum.MATCH, + value: + isSameOperatorType && typeof currentEntry.value === 'string' ? currentEntry.value : '', + }; + case 'match_any': + return { + field: fieldValue, + id: currentEntry.id, + operator: selectedOperator.operator, + type: OperatorTypeEnum.MATCH_ANY, + value: isSameOperatorType && Array.isArray(currentEntry.value) ? currentEntry.value : [], + }; + case 'list': + return { + field: fieldValue, + id: currentEntry.id, + list: { id: '', type: 'ip' }, + operator: selectedOperator.operator, + type: OperatorTypeEnum.LIST, + }; + case 'wildcard': + return { + field: fieldValue, + id: currentEntry.id, + operator: selectedOperator.operator, + type: OperatorTypeEnum.WILDCARD, + value: + isSameOperatorType && typeof currentEntry.value === 'string' ? currentEntry.value : '', + }; + default: + return { + field: fieldValue, + id: currentEntry.id, + operator: selectedOperator.operator, + type: OperatorTypeEnum.EXISTS, + }; + } +}; + +/** + * Determines proper entry update when user selects new operator + * + * @param item - current exception item entry values + * @param newOperator - newly selected operator + * + */ +export const getEntryOnOperatorChange = ( + item: FormattedBuilderEntry, + newOperator: OperatorOption +): { updatedEntry: BuilderEntry; index: number } => { + const { parent, entryIndex, field, nested } = item; + const newEntry = getEntryFromOperator(newOperator, item); + + if (!entriesList.is(newEntry) && nested != null && parent != null) { + return { + index: parent.parentIndex, + updatedEntry: { + ...parent.parent, + entries: [ + ...parent.parent.entries.slice(0, entryIndex), + { + ...newEntry, + field: field != null ? field.name.split('.').slice(-1)[0] : '', + }, + ...parent.parent.entries.slice(entryIndex + 1), + ], + }, + }; + } else { + return { index: entryIndex, updatedEntry: newEntry }; + } +}; + +export const isKibanaStringType = (type: string) => { + const kbnFieldType = castEsToKbnFieldTypeName(type); + return kbnFieldType === KBN_FIELD_TYPES.STRING; +}; + +export const fieldSupportsMatches = (field: DataViewFieldBase) => { + return field.esTypes?.some(isKibanaStringType); +}; + +/** + * Determines which operators to make available + * + * @param item + * @param listType + * @param isBoolean + * @param includeValueListOperators whether or not to include the 'is in list' and 'is not in list' operators + */ +export const getOperatorOptions = ( + item: FormattedBuilderEntry, + listType: ExceptionListType, + isBoolean: boolean, + includeValueListOperators = true +): OperatorOption[] => { + if (item.nested === 'parent' || item.field == null) { + return [isOperator]; + } else if (listType === 'endpoint') { + if (isBoolean) { + return [isOperator]; + } else { + return fieldSupportsMatches(item.field) + ? [isOperator, isOneOfOperator, matchesOperator, doesNotMatchOperator] + : [isOperator, isOneOfOperator]; + } + } else if (item.nested != null && listType === 'detection') { + return isBoolean ? [isOperator, existsOperator] : [isOperator, isOneOfOperator, existsOperator]; + } else if (isBoolean) { + return [isOperator, isNotOperator, existsOperator, doesNotExistOperator]; + } else if (!includeValueListOperators) { + return fieldSupportsMatches(item.field) + ? EXCEPTION_OPERATORS_SANS_LISTS + : [ + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + existsOperator, + doesNotExistOperator, + ]; + } else { + return listType === 'detection' + ? fieldSupportsMatches(item.field) + ? DETECTION_ENGINE_EXCEPTION_OPERATORS + : [ + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + existsOperator, + doesNotExistOperator, + isInListOperator, + isNotInListOperator, + ] + : ALL_OPERATORS; + } +}; + +/** + * Fields of type 'text' do not generate autocomplete values, we want + * to find it's corresponding keyword type (if available) which does + * generate autocomplete values + * + * @param fields DataViewFieldBase fields + * @param selectedField the field name that was selected + * @param isTextType we only want a corresponding keyword field if + * the selected field is of type 'text' + * + */ +export const getCorrespondingKeywordField = ({ + fields, + selectedField, +}: { + fields: DataViewFieldBase[]; + selectedField: string | undefined; +}): DataViewFieldBase | undefined => { + const selectedFieldBits = + selectedField != null && selectedField !== '' ? selectedField.split('.') : []; + const selectedFieldIsTextType = selectedFieldBits.slice(-1)[0] === 'text'; + + if (selectedFieldIsTextType && selectedFieldBits.length > 0) { + const keywordField = selectedFieldBits.slice(0, selectedFieldBits.length - 1).join('.'); + const [foundKeywordField] = fields.filter( + ({ name }) => keywordField !== '' && keywordField === name + ); + return foundKeywordField; + } + + return undefined; +}; + +/** + * Formats the entry into one that is easily usable for the UI, most of the + * complexity was introduced with nested fields + * + * @param patterns DataViewBase containing available fields on rule index + * @param item exception item entry + * @param itemIndex entry index + * @param parent nested entries hold copy of their parent for use in various logic + * @param parentIndex corresponds to the entry index, this might seem obvious, but + * was added to ensure that nested items could be identified with their parent entry + * @param allowCustomFieldOptions determines if field must be found to match in indexPattern or not + */ +export const getFormattedBuilderEntry = ( + indexPattern: DataViewBase, + item: BuilderEntry, + itemIndex: number, + parent: EntryNested | undefined, + parentIndex: number | undefined, + allowCustomFieldOptions: boolean +): FormattedBuilderEntry => { + const { fields } = indexPattern; + const field = parent != null ? `${parent.field}.${item.field}` : item.field; + const [foundField] = fields.filter(({ name }) => field != null && field === name); + const correspondingKeywordField = getCorrespondingKeywordField({ + fields, + selectedField: field, + }); + + if (parent != null && parentIndex != null) { + return { + correspondingKeywordField, + entryIndex: itemIndex, + field: + foundField != null + ? { ...foundField, name: foundField.name.split('.').slice(-1)[0] } + : foundField, + id: item.id != null ? item.id : `${itemIndex}`, + nested: 'child', + operator: getExceptionOperatorSelect(item), + parent: { parent, parentIndex }, + value: getEntryValue(item), + }; + } else { + const fieldToUse = allowCustomFieldOptions + ? foundField ?? { name: item.field, type: 'keyword' } + : foundField; + + return { + correspondingKeywordField, + entryIndex: itemIndex, + field: fieldToUse, + id: item.id != null ? item.id : `${itemIndex}`, + nested: undefined, + operator: getExceptionOperatorSelect(item), + parent: undefined, + value: getEntryValue(item), + }; + } +}; + +/** + * Formats the entries to be easily usable for the UI, most of the + * complexity was introduced with nested fields + * + * @param patterns DataViewBase containing available fields on rule index + * @param entries exception item entries + * @param allowCustomFieldOptions determines if field must be found to match in indexPattern or not + * @param parent nested entries hold copy of their parent for use in various logic + * @param parentIndex corresponds to the entry index, this might seem obvious, but + * was added to ensure that nested items could be identified with their parent entry + */ +export const getFormattedBuilderEntries = ( + indexPattern: DataViewBase, + entries: BuilderEntry[], + allowCustomFieldOptions: boolean, + parent?: EntryNested, + parentIndex?: number +): FormattedBuilderEntry[] => { + return entries.reduce((acc, item, index) => { + const isNewNestedEntry = item.type === 'nested' && item.entries.length === 0; + if (item.type !== 'nested' && !isNewNestedEntry) { + const newItemEntry: FormattedBuilderEntry = getFormattedBuilderEntry( + indexPattern, + item, + index, + parent, + parentIndex, + allowCustomFieldOptions + ); + return [...acc, newItemEntry]; + } else { + const parentEntry: FormattedBuilderEntry = { + correspondingKeywordField: undefined, + entryIndex: index, + field: isNewNestedEntry + ? undefined + : // This type below is really a FieldSpec type from "src/plugins/data/common/index_patterns/fields/types.ts", we cast it here to keep using the DataViewFieldBase interface + ({ + aggregatable: false, + esTypes: ['nested'], + name: item.field != null ? item.field : '', + searchable: false, + type: 'string', + } as DataViewFieldBase), + id: item.id != null ? item.id : `${index}`, + nested: 'parent', + operator: isOperator, + parent: undefined, + value: undefined, + }; + + // User has selected to add a nested field, but not yet selected the field + if (isNewNestedEntry) { + return [...acc, parentEntry]; + } + + if (isEntryNested(item)) { + const nestedItems = getFormattedBuilderEntries( + indexPattern, + item.entries, + allowCustomFieldOptions, + item, + index + ); + + return [...acc, parentEntry, ...nestedItems]; + } + + return [...acc]; + } + }, []); +}; + +export const getDefaultEmptyEntry = (): EmptyEntry => ({ + field: '', + id: uuidv4(), + operator: OperatorEnum.INCLUDED, + type: OperatorTypeEnum.MATCH, + value: '', +}); + +export const getDefaultNestedEmptyEntry = (): EmptyNestedEntry => ({ + entries: [], + field: '', + id: uuidv4(), + type: OperatorTypeEnum.NESTED, +}); + +export const containsValueListEntry = (items: ExceptionsBuilderExceptionItem[]): boolean => + items.some((item) => item.entries.some(({ type }) => type === OperatorTypeEnum.LIST)); + +export const buildShowActiveExceptionsFilter = (savedObjectPrefix: SavedObjectType[]): string => { + const now = new Date().toISOString(); + const filters = savedObjectPrefix.map( + (prefix) => + `${prefix}.attributes.expire_time > "${now}" OR NOT ${prefix}.attributes.expire_time: *` + ); + return filters.join(','); +}; + +export const buildShowExpiredExceptionsFilter = (savedObjectPrefix: SavedObjectType[]): string => { + const now = new Date().toISOString(); + const filters = savedObjectPrefix.map((prefix) => `${prefix}.attributes.expire_time <= "${now}"`); + return filters.join(','); +}; + +const getIndexGroupName = (indexName: string): string => { + // Check whether it is a Data Stream index + const dataStreamExp = /.ds-(.*?)-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-[0-9]{6}/; + let result = indexName.match(dataStreamExp); + if (result && result.length === 2) { + return result[1]; + } + + // Check whether it is an old '.siem' index group + const siemSignalsExp = /.siem-(.*?)-[0-9]{6}/; + result = indexName.match(siemSignalsExp); + if (result && result.length === 2) { + return `.siem-${result[1]}`; + } + + // Otherwise return index name + return indexName; +}; + +export interface FieldConflictsInfo { + /** + * Kibana field type + */ + type: string; + /** + * Total count of the indices of this type + */ + totalIndexCount: number; + /** + * Grouped indices info + */ + groupedIndices: Array<{ + /** + * Index group name (like '.ds-...' or '.siem-signals-...') + */ + name: string; + /** + * Count of indices in the group + */ + count: number; + }>; +} + +export const getMappingConflictsInfo = (field: DataViewField): FieldConflictsInfo[] | null => { + if (!field.conflictDescriptions) { + return null; + } + const conflicts: FieldConflictsInfo[] = []; + for (const [key, value] of Object.entries(field.conflictDescriptions)) { + const groupedIndices: Array<{ + name: string; + count: number; + }> = []; + + // Group indices and calculate count of indices in each group + const groupedInfo: { [key: string]: number } = {}; + value.forEach((index) => { + const groupName = getIndexGroupName(index); + if (!groupedInfo[groupName]) { + groupedInfo[groupName] = 0; + } + groupedInfo[groupName]++; + }); + for (const [name, count] of Object.entries(groupedInfo)) { + groupedIndices.push({ + name, + count, + }); + } + + // Sort groups by the indices count + groupedIndices.sort((group1, group2) => { + return group2.count - group1.count; + }); + + conflicts.push({ + type: key, + totalIndexCount: value.length, + groupedIndices, + }); + } + return conflicts; +}; + +/** + * Given an exceptions list, determine if any entries have an "IS" operator with a wildcard value + */ +export const hasWrongOperatorWithWildcard = ( + items: ExceptionsBuilderReturnExceptionItem[] +): boolean => { + // flattens array of multiple entries added with OR + const multipleEntries = items.flatMap((item) => item.entries); + // flattens nested entries + const allEntries = multipleEntries.flatMap((item) => { + if (item.type === 'nested') { + return item.entries; + } + return item; + }); + + // eslint-disable-next-line array-callback-return + return allEntries.some((e) => { + if (e.type !== 'list' && 'value' in e) { + return validateHasWildcardWithWrongOperator({ + operator: e.type, + value: e.value, + }); + } + }); +}; + +/** + * Event filters helper where given an exceptions list, + * determine if both 'subject_name' and 'trusted' are + * included in an entry with 'code_signature' + */ +export const hasPartialCodeSignatureEntry = ( + items: ExceptionsBuilderReturnExceptionItem[] +): boolean => { + const { os_types: os = ['windows'], entries = [] } = items[0] || {}; + let name = false; + let trusted = false; + + for (const e of entries) { + if (e.type === 'nested' && e.field === 'process.Ext.code_signature') { + const includesNestedName = e.entries.some( + (nestedEntry) => nestedEntry.field === 'subject_name' + ); + const includesNestedTrusted = e.entries.some( + (nestedEntry) => nestedEntry.field === 'trusted' + ); + if (includesNestedName !== includesNestedTrusted) { + return true; + } + } else if ( + e.field === 'process.code_signature.subject_name' || + (os.includes('macos') && e.field === 'process.code_signature.team_id') + ) { + name = true; + } else if (e.field === 'process.code_signature.trusted') { + trusted = true; + } + } + return name !== trusted; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/types/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/types/index.ts new file mode 100644 index 0000000000000..1730a0e9a8291 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/src/types/index.ts @@ -0,0 +1,122 @@ +/* + * 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. + */ + +import { DataViewFieldBase } from '@kbn/es-query'; +import type { + CreateExceptionListItemSchema, + CreateRuleExceptionListItemSchema, + Entry, + EntryExists, + EntryMatch, + EntryMatchAny, + EntryMatchWildcard, + EntryNested, + ExceptionListItemSchema, + ListOperatorEnum as OperatorEnum, + ListOperatorTypeEnum as OperatorTypeEnum, + NamespaceType, +} from '@kbn/securitysolution-io-ts-list-types'; +import { + EXCEPTION_LIST_NAMESPACE, + EXCEPTION_LIST_NAMESPACE_AGNOSTIC, +} from '@kbn/securitysolution-list-constants'; + +export interface DataViewField extends DataViewFieldBase { + conflictDescriptions?: Record; +} + +export interface OperatorOption { + message: string; + value: string; + operator: OperatorEnum; + type: OperatorTypeEnum; +} + +export interface FormattedBuilderEntry { + id: string; + field: DataViewField | undefined; + operator: OperatorOption; + value: string | string[] | undefined; + nested: 'parent' | 'child' | undefined; + entryIndex: number; + parent: { parent: BuilderEntryNested; parentIndex: number } | undefined; + correspondingKeywordField: DataViewFieldBase | undefined; +} + +export interface EmptyEntry { + id: string; + field: string | undefined; + operator: OperatorEnum; + type: OperatorTypeEnum.MATCH | OperatorTypeEnum.MATCH_ANY | OperatorTypeEnum.WILDCARD; + value: string | string[] | undefined; +} + +export interface EmptyListEntry { + id: string; + field: string | undefined; + operator: OperatorEnum; + type: OperatorTypeEnum.LIST; + list: { id: string | undefined; type: string | undefined }; +} + +export interface EmptyNestedEntry { + id: string; + field: string | undefined; + type: OperatorTypeEnum.NESTED; + entries: Array< + | (EntryMatch & { id?: string }) + | (EntryMatchAny & { id?: string }) + | (EntryMatchWildcard & { id?: string }) + | (EntryExists & { id?: string }) + >; +} + +export type BuilderEntry = + | (Entry & { id?: string }) + | EmptyListEntry + | EmptyEntry + | BuilderEntryNested + | EmptyNestedEntry; + +export type BuilderEntryNested = Omit & { + id?: string; + entries: Array< + | (EntryMatch & { id?: string }) + | (EntryMatchAny & { id?: string }) + | (EntryMatchWildcard & { id?: string }) + | (EntryExists & { id?: string }) + >; +}; + +export type ExceptionListItemBuilderSchema = Omit & { + entries: BuilderEntry[]; +}; + +export type CreateExceptionListItemBuilderSchema = Omit< + CreateExceptionListItemSchema, + 'meta' | 'entries' | 'list_id' | 'namespace_type' +> & { + meta: { temporaryUuid: string }; + entries: BuilderEntry[]; + list_id: string | undefined; + namespace_type: NamespaceType | undefined; +}; + +export type ExceptionsBuilderExceptionItem = + | ExceptionListItemBuilderSchema + | CreateExceptionListItemBuilderSchema; + +export type ExceptionsBuilderReturnExceptionItem = + | ExceptionListItemSchema + | CreateExceptionListItemSchema + | CreateRuleExceptionListItemSchema; + +export const exceptionListSavedObjectType = EXCEPTION_LIST_NAMESPACE; +export const exceptionListAgnosticSavedObjectType = EXCEPTION_LIST_NAMESPACE_AGNOSTIC; +export type SavedObjectType = + | typeof EXCEPTION_LIST_NAMESPACE + | typeof EXCEPTION_LIST_NAMESPACE_AGNOSTIC; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/tsconfig.json new file mode 100644 index 0000000000000..0b6eb353950df --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-list-utils/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "kbn_references": [ + "@kbn/es-query", + "@kbn/i18n", + "@kbn/securitysolution-io-ts-list-types", + "@kbn/securitysolution-io-ts-utils", + "@kbn/securitysolution-list-constants", + "@kbn/securitysolution-utils", + "@kbn/field-types" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-lists-common/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/README.md similarity index 100% rename from packages/kbn-securitysolution-lists-common/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts new file mode 100644 index 0000000000000..cf603f3ac3bdb --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { + ListId, + ListName, + ListDescription, + ListType, + ListMetadata, +} from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type CreateListRequestBody = z.infer; +export const CreateListRequestBody = z.object({ + id: ListId.optional(), + name: ListName, + description: ListDescription, + type: ListType, + serializer: z.string().optional(), + deserializer: z.string().optional(), + meta: ListMetadata.optional(), + version: z.number().int().min(1).optional().default(1), +}); +export type CreateListRequestBodyInput = z.input; + +export type CreateListResponse = z.infer; +export const CreateListResponse = List; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml new file mode 100644 index 0000000000000..df3e6b35ef65a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml @@ -0,0 +1,81 @@ +openapi: 3.0.0 +info: + title: Create list API endpoint + version: '2023-10-31' +paths: + /api/lists: + post: + x-labels: [serverless, ess] + operationId: CreateList + x-codegen-enabled: true + summary: Create a list + description: Create a new list. + requestBody: + description: List's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + name: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' + description: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' + type: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListType' + serializer: + type: string + deserializer: + type: string + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' + version: + type: integer + minimum: 1 + default: 1 + required: + - name + - description + - type + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: List already exists response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts new file mode 100644 index 0000000000000..7eb20ada7f322 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create list DS API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +export type CreateListIndexResponse = z.infer; +export const CreateListIndexResponse = z.object({ + acknowledged: z.boolean(), +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml new file mode 100644 index 0000000000000..8ff9ad6ab1b2e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml @@ -0,0 +1,55 @@ +openapi: 3.0.0 +info: + title: Create list DS API endpoint + version: '2023-10-31' +paths: + /api/lists/index: + post: + x-labels: [serverless, ess] + operationId: CreateListIndex + x-codegen-enabled: true + summary: Create list data streams + description: Create `.lists` and `.items` data streams in the relevant space. + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + required: [acknowledged] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: List data stream exists response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts new file mode 100644 index 0000000000000..ce4744f3c4418 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create list item API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListItemId, ListId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type CreateListItemRequestBody = z.infer; +export const CreateListItemRequestBody = z.object({ + id: ListItemId.optional(), + list_id: ListId, + value: ListItemValue, + meta: ListItemMetadata.optional(), + /** + * Determines when changes made by the request are made visible to search + */ + refresh: z.enum(['true', 'false', 'wait_for']).optional(), +}); +export type CreateListItemRequestBodyInput = z.input; + +export type CreateListItemResponse = z.infer; +export const CreateListItemResponse = ListItem; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml new file mode 100644 index 0000000000000..01d024f8b40d8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml @@ -0,0 +1,82 @@ +openapi: 3.0.0 +info: + title: Create list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + post: + x-labels: [serverless, ess] + operationId: CreateListItem + x-codegen-enabled: true + summary: Create a list item + description: | + Create a list item and associate it with the specified list. + + All list items in the same list must be the same type. For example, each list item in an `ip` list must define a specific IP address. + > info + > Before creating a list item, you must create a list. + requestBody: + description: List item's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' + list_id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + value: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' + refresh: + type: string + enum: + - 'true' + - 'false' + - wait_for + description: Determines when changes made by the request are made visible to search + required: + - list_id + - value + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: List item already exists response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts new file mode 100644 index 0000000000000..3dd638be564ee --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Delete list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; +import { BooleanFromString } from '@kbn/zod-helpers'; + +import { ListId } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type DeleteListRequestQuery = z.infer; +export const DeleteListRequestQuery = z.object({ + /** + * List's `id` value + */ + id: ListId, + deleteReferences: BooleanFromString.optional().default(false), + ignoreReferences: BooleanFromString.optional().default(false), +}); +export type DeleteListRequestQueryInput = z.input; + +export type DeleteListResponse = z.infer; +export const DeleteListResponse = List; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml new file mode 100644 index 0000000000000..e8caef0eb2c6c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml @@ -0,0 +1,73 @@ +openapi: 3.0.0 +info: + title: Delete list API endpoint + version: '2023-10-31' +paths: + /api/lists: + delete: + x-labels: [serverless, ess] + operationId: DeleteList + x-codegen-enabled: true + summary: Delete a list + description: | + Delete a list using the list ID. + > info + > When you delete a list, all of its list items are also deleted. + parameters: + - name: id + in: query + required: true + description: List's `id` value + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: deleteReferences + in: query + required: false + schema: + type: boolean + default: false + - name: ignoreReferences + in: query + required: false + schema: + type: boolean + default: false + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts new file mode 100644 index 0000000000000..4ffd90f6fb8b0 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Delete list DS API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +export type DeleteListIndexResponse = z.infer; +export const DeleteListIndexResponse = z.object({ + acknowledged: z.boolean(), +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml new file mode 100644 index 0000000000000..ae43c58726d52 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml @@ -0,0 +1,55 @@ +openapi: 3.0.0 +info: + title: Delete list DS API endpoint + version: '2023-10-31' +paths: + /api/lists/index: + delete: + x-labels: [serverless, ess] + operationId: DeleteListIndex + x-codegen-enabled: true + summary: Delete list data streams + description: Delete the `.lists` and `.items` data streams. + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + required: [acknowledged] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List data stream not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts similarity index 76% rename from packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts index 178641cd8d6af..fe9f7bee0e688 100644 --- a/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml new file mode 100644 index 0000000000000..b95afcdc1ed3b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml @@ -0,0 +1,82 @@ +openapi: 3.0.0 +info: + title: Delete list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + delete: + x-labels: [serverless, ess] + operationId: DeleteListItem + x-codegen-enabled: true + summary: Delete a list item + description: Delete a list item using its `id`, or its `list_id` and `value` fields. + parameters: + - name: id + in: query + required: false + description: Required if `list_id` and `value` are not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: list_id + in: query + required: false + description: Required if `id` is not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: value + in: query + required: false + description: Required if `id` is not specified + schema: + type: string + - name: refresh + in: query + required: false + description: Determines when changes made by the request are made visible to search + schema: + type: string + enum: ['true', 'false', 'wait_for'] + default: 'false' + responses: + 200: + description: Successful response + content: + application/json: + schema: + oneOf: + - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + - type: array + items: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.gen.ts new file mode 100644 index 0000000000000..87e05bd24e481 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.gen.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Export list items API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListId } from '../model/list_common.gen'; + +export type ExportListItemsRequestQuery = z.infer; +export const ExportListItemsRequestQuery = z.object({ + /** + * List's id to export + */ + list_id: ListId, +}); +export type ExportListItemsRequestQueryInput = z.input; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.schema.yaml new file mode 100644 index 0000000000000..999eb4a0ae42d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/export_list_items/export_list_items.schema.yaml @@ -0,0 +1,60 @@ +openapi: 3.0.0 +info: + title: Export list items API endpoint + version: '2023-10-31' +paths: + /api/lists/items/_export: + post: + x-labels: [serverless, ess] + operationId: ExportListItems + x-codegen-enabled: true + summary: Export list items + description: Export list item values from the specified list. + parameters: + - name: list_id + in: query + required: true + description: List's id to export + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + responses: + 200: + description: Successful response + content: + application/ndjson: + schema: + type: string + format: binary + description: A `.txt` file containing list items from the specified list + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.gen.ts similarity index 85% rename from packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.gen.ts index f693965e91e2e..e40c6fe9e2fc1 100644 --- a/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.schema.yaml similarity index 77% rename from packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.schema.yaml index 21cf4ffd61841..746b3e9fdbe37 100644 --- a/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_list_items/find_list_items.schema.yaml @@ -34,7 +34,7 @@ paths: required: false description: Determines which field is used to sort the results schema: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - name: sort_order in: query required: false @@ -94,31 +94,31 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: schemas: FindListItemsCursor: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' FindListItemsFilter: type: string diff --git a/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.gen.ts similarity index 84% rename from packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.gen.ts index ec104f2e6c2b1..74f8ba0217d68 100644 --- a/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.schema.yaml similarity index 76% rename from packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.schema.yaml index 3bb55decacff6..9b0012e8d6968 100644 --- a/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/find_lists/find_lists.schema.yaml @@ -28,7 +28,7 @@ paths: required: false description: Determines which field is used to sort the results schema: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' - name: sort_order in: query required: false @@ -88,31 +88,31 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: schemas: FindListsCursor: - $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' FindListsFilter: type: string diff --git a/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.gen.ts similarity index 77% rename from packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.gen.ts index b71b05bd75955..baf9d9308a93c 100644 --- a/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.schema.yaml similarity index 75% rename from packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.schema.yaml index 520213e949c1d..f3fae45159346 100644 --- a/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/import_list_items/import_list_items.schema.yaml @@ -73,29 +73,29 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 409: description: List with specified list_id does not exist response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/index.ts new file mode 100644 index 0000000000000..6ff15e6109c68 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +export * from './model/list_common.gen'; +export * from './model/list_schemas.gen'; +export * from './create_list_index/create_list_index.gen'; +export * from './create_list_item/create_list_item.gen'; +export * from './create_list/create_list.gen'; +export * from './delete_list_index/delete_list_index.gen'; +export * from './delete_list_item/delete_list_item.gen'; +export * from './delete_list/delete_list.gen'; +export * from './find_list_items/find_list_items.gen'; +export * from './find_lists/find_lists.gen'; +export * from './export_list_items/export_list_items.gen'; +export * from './import_list_items/import_list_items.gen'; +export * from './patch_list_item/patch_list_item.gen'; +export * from './patch_list/patch_list.gen'; +export * from './read_list_index/read_list_index.gen'; +export * from './read_list_item/read_list_item.gen'; +export * from './read_list/read_list.gen'; +export * from './update_list_item/update_list_item.gen'; +export * from './update_list/update_list.gen'; diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts similarity index 82% rename from packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts index 9a51bd0eeb5ad..536e0b859e45a 100644 --- a/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml new file mode 100644 index 0000000000000..808e99c7b1e13 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml @@ -0,0 +1,59 @@ +openapi: 3.0.0 +info: + title: Common List Attributes + version: 'not applicable' +paths: {} +components: + schemas: + ListId: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListType: + type: string + enum: + - binary + - boolean + - byte + - date + - date_nanos + - date_range + - double + - double_range + - float + - float_range + - geo_point + - geo_shape + - half_float + - integer + - integer_range + - ip + - ip_range + - keyword + - long + - long_range + - shape + - short + - text + + ListName: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListDescription: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListMetadata: + type: object + additionalProperties: true + + ListItemId: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListItemValue: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListItemDescription: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListItemMetadata: + type: object + additionalProperties: true diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts similarity index 80% rename from packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts index 14d9547c35b59..cd95d20853c11 100644 --- a/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts new file mode 100644 index 0000000000000..f2a67181d396d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Patch list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListId, ListName, ListDescription, ListMetadata } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type PatchListRequestBody = z.infer; +export const PatchListRequestBody = z.object({ + id: ListId, + name: ListName.optional(), + description: ListDescription.optional(), + meta: ListMetadata.optional(), + version: z.number().int().min(1).optional(), + _version: z.string().optional(), +}); +export type PatchListRequestBodyInput = z.input; + +export type PatchListResponse = z.infer; +export const PatchListResponse = List; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml new file mode 100644 index 0000000000000..6a61e668ced87 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml @@ -0,0 +1,74 @@ +openapi: 3.0.0 +info: + title: Patch list API endpoint + version: '2023-10-31' +paths: + /api/lists: + patch: + x-labels: [serverless, ess] + operationId: PatchList + x-codegen-enabled: true + summary: Patch a list + description: Update specific fields of an existing list using the list ID. + requestBody: + description: List's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + name: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' + description: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' + version: + type: integer + minimum: 1 + _version: + type: string + required: + - id + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts new file mode 100644 index 0000000000000..e5c06ddd7c251 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Patch list item API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListItemId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type PatchListItemRequestBody = z.infer; +export const PatchListItemRequestBody = z.object({ + id: ListItemId, + value: ListItemValue.optional(), + meta: ListItemMetadata.optional(), + _version: z.string().optional(), + /** + * Determines when changes made by the request are made visible to search + */ + refresh: z.enum(['true', 'false', 'wait_for']).optional(), +}); +export type PatchListItemRequestBodyInput = z.input; + +export type PatchListItemResponse = z.infer; +export const PatchListItemResponse = ListItem; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml new file mode 100644 index 0000000000000..fdd7a020d098f --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml @@ -0,0 +1,76 @@ +openapi: 3.0.0 +info: + title: Patch list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + patch: + x-labels: [serverless, ess] + operationId: PatchListItem + x-codegen-enabled: true + summary: Patch a list item + description: Update specific fields of an existing list item using the list item ID. + requestBody: + description: List item's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' + value: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' + _version: + type: string + refresh: + type: string + enum: + - 'true' + - 'false' + - wait_for + description: Determines when changes made by the request are made visible to search + required: + - id + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts new file mode 100644 index 0000000000000..232f4b00540c5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts @@ -0,0 +1,428 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Lists API client for quickstart + * version: Bundle (no version) + */ + +import type { KbnClient } from '@kbn/test'; +import { ToolingLog } from '@kbn/tooling-log'; +import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { catchAxiosErrorFormatAndThrow } from '@kbn/securitysolution-utils'; + +import type { CreateListIndexResponse } from './create_list_index/create_list_index.gen'; +import type { + CreateListItemRequestBodyInput, + CreateListItemResponse, +} from './create_list_item/create_list_item.gen'; +import type { CreateListRequestBodyInput, CreateListResponse } from './create_list/create_list.gen'; +import type { DeleteListIndexResponse } from './delete_list_index/delete_list_index.gen'; +import type { + DeleteListItemRequestQueryInput, + DeleteListItemResponse, +} from './delete_list_item/delete_list_item.gen'; +import type { + DeleteListRequestQueryInput, + DeleteListResponse, +} from './delete_list/delete_list.gen'; +import type { ExportListItemsRequestQueryInput } from './export_list_items/export_list_items.gen'; +import type { + FindListItemsRequestQueryInput, + FindListItemsResponse, +} from './find_list_items/find_list_items.gen'; +import type { FindListsRequestQueryInput, FindListsResponse } from './find_lists/find_lists.gen'; +import type { + ImportListItemsRequestQueryInput, + ImportListItemsResponse, +} from './import_list_items/import_list_items.gen'; +import type { + PatchListItemRequestBodyInput, + PatchListItemResponse, +} from './patch_list_item/patch_list_item.gen'; +import type { PatchListRequestBodyInput, PatchListResponse } from './patch_list/patch_list.gen'; +import type { ReadListIndexResponse } from './read_list_index/read_list_index.gen'; +import type { + ReadListItemRequestQueryInput, + ReadListItemResponse, +} from './read_list_item/read_list_item.gen'; +import type { ReadListPrivilegesResponse } from './read_list_privileges/read_list_privileges.gen'; +import type { ReadListRequestQueryInput, ReadListResponse } from './read_list/read_list.gen'; +import type { + UpdateListItemRequestBodyInput, + UpdateListItemResponse, +} from './update_list_item/update_list_item.gen'; +import type { UpdateListRequestBodyInput, UpdateListResponse } from './update_list/update_list.gen'; + +export interface ClientOptions { + kbnClient: KbnClient; + log: ToolingLog; +} + +export class Client { + readonly kbnClient: KbnClient; + readonly log: ToolingLog; + + constructor(options: ClientOptions) { + this.kbnClient = options.kbnClient; + this.log = options.log; + } + /** + * Create a new list. + */ + async createList(props: CreateListProps) { + this.log.info(`${new Date().toISOString()} Calling API CreateList`); + return this.kbnClient + .request({ + path: '/api/lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Create `.lists` and `.items` data streams in the relevant space. + */ + async createListIndex() { + this.log.info(`${new Date().toISOString()} Calling API CreateListIndex`); + return this.kbnClient + .request({ + path: '/api/lists/index', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Create a list item and associate it with the specified list. + +All list items in the same list must be the same type. For example, each list item in an `ip` list must define a specific IP address. +> info +> Before creating a list item, you must create a list. + + */ + async createListItem(props: CreateListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API CreateListItem`); + return this.kbnClient + .request({ + path: '/api/lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Delete a list using the list ID. +> info +> When you delete a list, all of its list items are also deleted. + + */ + async deleteList(props: DeleteListProps) { + this.log.info(`${new Date().toISOString()} Calling API DeleteList`); + return this.kbnClient + .request({ + path: '/api/lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'DELETE', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Delete the `.lists` and `.items` data streams. + */ + async deleteListIndex() { + this.log.info(`${new Date().toISOString()} Calling API DeleteListIndex`); + return this.kbnClient + .request({ + path: '/api/lists/index', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'DELETE', + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Delete a list item using its `id`, or its `list_id` and `value` fields. + */ + async deleteListItem(props: DeleteListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API DeleteListItem`); + return this.kbnClient + .request({ + path: '/api/lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'DELETE', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Export list item values from the specified list. + */ + async exportListItems(props: ExportListItemsProps) { + this.log.info(`${new Date().toISOString()} Calling API ExportListItems`); + return this.kbnClient + .request({ + path: '/api/lists/items/_export', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get all list items in the specified list. + */ + async findListItems(props: FindListItemsProps) { + this.log.info(`${new Date().toISOString()} Calling API FindListItems`); + return this.kbnClient + .request({ + path: '/api/lists/items/_find', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get a paginated subset of lists. By default, the first page is returned, with 20 results per page. + */ + async findLists(props: FindListsProps) { + this.log.info(`${new Date().toISOString()} Calling API FindLists`); + return this.kbnClient + .request({ + path: '/api/lists/_find', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Import list items from a TXT or CSV file. The maximum file size is 9 million bytes. + +You can import items to a new or existing list. + + */ + async importListItems(props: ImportListItemsProps) { + this.log.info(`${new Date().toISOString()} Calling API ImportListItems`); + return this.kbnClient + .request({ + path: '/api/lists/items/_import', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'POST', + body: props.attachment, + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Update specific fields of an existing list using the list ID. + */ + async patchList(props: PatchListProps) { + this.log.info(`${new Date().toISOString()} Calling API PatchList`); + return this.kbnClient + .request({ + path: '/api/lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'PATCH', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Update specific fields of an existing list item using the list item ID. + */ + async patchListItem(props: PatchListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API PatchListItem`); + return this.kbnClient + .request({ + path: '/api/lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'PATCH', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get the details of a list using the list ID. + */ + async readList(props: ReadListProps) { + this.log.info(`${new Date().toISOString()} Calling API ReadList`); + return this.kbnClient + .request({ + path: '/api/lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Verify that `.lists` and `.items` data streams exist. + */ + async readListIndex() { + this.log.info(`${new Date().toISOString()} Calling API ReadListIndex`); + return this.kbnClient + .request({ + path: '/api/lists/index', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Get the details of a list item. + */ + async readListItem(props: ReadListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API ReadListItem`); + return this.kbnClient + .request({ + path: '/api/lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + + query: props.query, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + async readListPrivileges() { + this.log.info(`${new Date().toISOString()} Calling API ReadListPrivileges`); + return this.kbnClient + .request({ + path: '/api/lists/privileges', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'GET', + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Update a list using the list ID. The original list is replaced, and all unspecified fields are deleted. +> info +> You cannot modify the `id` value. + + */ + async updateList(props: UpdateListProps) { + this.log.info(`${new Date().toISOString()} Calling API UpdateList`); + return this.kbnClient + .request({ + path: '/api/lists', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'PUT', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } + /** + * Update a list item using the list item ID. The original list item is replaced, and all unspecified fields are deleted. +> info +> You cannot modify the `id` value. + + */ + async updateListItem(props: UpdateListItemProps) { + this.log.info(`${new Date().toISOString()} Calling API UpdateListItem`); + return this.kbnClient + .request({ + path: '/api/lists/items', + headers: { + [ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31', + }, + method: 'PUT', + body: props.body, + }) + .catch(catchAxiosErrorFormatAndThrow); + } +} + +export interface CreateListProps { + body: CreateListRequestBodyInput; +} +export interface CreateListItemProps { + body: CreateListItemRequestBodyInput; +} +export interface DeleteListProps { + query: DeleteListRequestQueryInput; +} +export interface DeleteListItemProps { + query: DeleteListItemRequestQueryInput; +} +export interface ExportListItemsProps { + query: ExportListItemsRequestQueryInput; +} +export interface FindListItemsProps { + query: FindListItemsRequestQueryInput; +} +export interface FindListsProps { + query: FindListsRequestQueryInput; +} +export interface ImportListItemsProps { + query: ImportListItemsRequestQueryInput; + attachment: FormData; +} +export interface PatchListProps { + body: PatchListRequestBodyInput; +} +export interface PatchListItemProps { + body: PatchListItemRequestBodyInput; +} +export interface ReadListProps { + query: ReadListRequestQueryInput; +} +export interface ReadListItemProps { + query: ReadListItemRequestQueryInput; +} +export interface UpdateListProps { + body: UpdateListRequestBodyInput; +} +export interface UpdateListItemProps { + body: UpdateListItemRequestBodyInput; +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts new file mode 100644 index 0000000000000..d2967d71d57e5 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Read list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListId } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type ReadListRequestQuery = z.infer; +export const ReadListRequestQuery = z.object({ + /** + * List's `id` value + */ + id: ListId, +}); +export type ReadListRequestQueryInput = z.input; + +export type ReadListResponse = z.infer; +export const ReadListResponse = List; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml new file mode 100644 index 0000000000000..280a6fdab7543 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml @@ -0,0 +1,58 @@ +openapi: 3.0.0 +info: + title: Read list API endpoint + version: '2023-10-31' +paths: + /api/lists: + get: + x-labels: [serverless, ess] + operationId: ReadList + x-codegen-enabled: true + summary: Get list details + description: Get the details of a list using the list ID. + parameters: + - name: id + in: query + required: true + description: List's `id` value + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts new file mode 100644 index 0000000000000..bf0aec4dc6bcf --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Read list DS existence status API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +export type ReadListIndexResponse = z.infer; +export const ReadListIndexResponse = z.object({ + list_index: z.boolean(), + list_item_index: z.boolean(), +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml new file mode 100644 index 0000000000000..40dbddf25e69e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml @@ -0,0 +1,57 @@ +openapi: 3.0.0 +info: + title: Read list DS existence status API endpoint + version: '2023-10-31' +paths: + /api/lists/index: + get: + x-labels: [serverless, ess] + operationId: ReadListIndex + x-codegen-enabled: true + summary: Get status of list data streams + description: Verify that `.lists` and `.items` data streams exist. + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + list_index: + type: boolean + list_item_index: + type: boolean + required: [list_index, list_item_index] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List data stream(s) not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts new file mode 100644 index 0000000000000..d22ee46022266 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts @@ -0,0 +1,40 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Read list item API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListId } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type ReadListItemRequestQuery = z.infer; +export const ReadListItemRequestQuery = z.object({ + /** + * Required if `list_id` and `value` are not specified + */ + id: ListId.optional(), + /** + * Required if `id` is not specified + */ + list_id: ListId.optional(), + /** + * Required if `id` is not specified + */ + value: z.string().optional(), +}); +export type ReadListItemRequestQueryInput = z.input; + +export type ReadListItemResponse = z.infer; +export const ReadListItemResponse = z.union([ListItem, z.array(ListItem)]); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml new file mode 100644 index 0000000000000..a41fb497f611a --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml @@ -0,0 +1,74 @@ +openapi: 3.0.0 +info: + title: Read list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + get: + x-labels: [serverless, ess] + operationId: ReadListItem + x-codegen-enabled: true + summary: Get a list item + description: Get the details of a list item. + parameters: + - name: id + in: query + required: false + description: Required if `list_id` and `value` are not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: list_id + in: query + required: false + description: Required if `id` is not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: value + in: query + required: false + description: Required if `id` is not specified + schema: + type: string + responses: + 200: + description: Successful response + content: + application/json: + schema: + oneOf: + - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + - type: array + items: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.gen.ts similarity index 76% rename from packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.gen.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.gen.ts index 356915ba03cff..da6e7e95076da 100644 --- a/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.gen.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.gen.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ /* diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.schema.yaml similarity index 78% rename from packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.schema.yaml index ec8604e80694e..df7b4a5f5174b 100644 --- a/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.schema.yaml +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/read_list_privileges/read_list_privileges.schema.yaml @@ -33,26 +33,26 @@ paths: application/json: schema: oneOf: - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' - - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' 401: description: Unsuccessful authentication response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 403: description: Not enough privileges response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' 500: description: Internal server error response content: application/json: schema: - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' components: schemas: diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts new file mode 100644 index 0000000000000..ffb28c3d0b530 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Update list API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListId, ListName, ListDescription, ListMetadata } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type UpdateListRequestBody = z.infer; +export const UpdateListRequestBody = z.object({ + id: ListId, + name: ListName, + description: ListDescription, + meta: ListMetadata.optional(), + version: z.number().int().min(1).optional(), + _version: z.string().optional(), +}); +export type UpdateListRequestBodyInput = z.input; + +export type UpdateListResponse = z.infer; +export const UpdateListResponse = List; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml new file mode 100644 index 0000000000000..a059ede38584c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml @@ -0,0 +1,79 @@ +openapi: 3.0.0 +info: + title: Update list API endpoint + version: '2023-10-31' +paths: + /api/lists: + put: + x-labels: [serverless, ess] + operationId: UpdateList + x-codegen-enabled: true + summary: Update a list + description: | + Update a list using the list ID. The original list is replaced, and all unspecified fields are deleted. + > info + > You cannot modify the `id` value. + requestBody: + description: List's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + name: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' + description: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' + version: + type: integer + minimum: 1 + _version: + type: string + required: + - id + - name + - description + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts new file mode 100644 index 0000000000000..f5667676ab4c6 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Update list item API endpoint + * version: 2023-10-31 + */ + +import { z } from '@kbn/zod'; + +import { ListItemId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type UpdateListItemRequestBody = z.infer; +export const UpdateListItemRequestBody = z.object({ + id: ListItemId, + value: ListItemValue, + meta: ListItemMetadata.optional(), + _version: z.string().optional(), +}); +export type UpdateListItemRequestBodyInput = z.input; + +export type UpdateListItemResponse = z.infer; +export const UpdateListItemResponse = ListItem; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml new file mode 100644 index 0000000000000..04d86cf1947a9 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml @@ -0,0 +1,73 @@ +openapi: 3.0.0 +info: + title: Update list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + put: + x-labels: [serverless, ess] + operationId: UpdateListItem + x-codegen-enabled: true + summary: Update a list item + description: | + Update a list item using the list item ID. The original list item is replaced, and all unspecified fields are deleted. + > info + > You cannot modify the `id` value. + requestBody: + description: List item's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' + value: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' + _version: + type: string + required: + - id + - value + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../../../../../packages/kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/docs/openapi/ess/security_solution_lists_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/docs/openapi/ess/security_solution_lists_api_2023_10_31.bundled.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-lists-common/docs/openapi/ess/security_solution_lists_api_2023_10_31.bundled.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/docs/openapi/ess/security_solution_lists_api_2023_10_31.bundled.schema.yaml diff --git a/packages/kbn-securitysolution-lists-common/docs/openapi/serverless/security_solution_lists_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/docs/openapi/serverless/security_solution_lists_api_2023_10_31.bundled.schema.yaml similarity index 100% rename from packages/kbn-securitysolution-lists-common/docs/openapi/serverless/security_solution_lists_api_2023_10_31.bundled.schema.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/docs/openapi/serverless/security_solution_lists_api_2023_10_31.bundled.schema.yaml diff --git a/packages/kbn-securitysolution-lists-common/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-lists-common/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/package.json new file mode 100644 index 0000000000000..4e2b035218592 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/package.json @@ -0,0 +1,11 @@ +{ + "description": "Security Solution Lists common package", + "license": "Elastic License 2.0", + "name": "@kbn/securitysolution-lists-common", + "private": true, + "version": "1.0.0", + "scripts": { + "openapi:generate": "node scripts/openapi_generate", + "openapi:bundle": "node scripts/openapi_bundle" + } +} diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js new file mode 100644 index 0000000000000..609ed8bb08078 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +require('../../../../../../src/setup_node_env'); +// eslint-disable-next-line import/no-nodejs-modules +const { join, resolve } = require('path'); +const { bundle } = require('@kbn/openapi-bundler'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await bundle({ + sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), + outputFilePath: join( + ROOT, + 'docs/openapi/serverless/security_solution_lists_api_{version}.bundled.schema.yaml' + ), + options: { + includeLabels: ['serverless'], + prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/lists_serverless.info.yaml'), + }, + }); + + await bundle({ + sourceGlob: join(ROOT, 'api/**/*.schema.yaml'), + outputFilePath: join( + ROOT, + 'docs/openapi/ess/security_solution_lists_api_{version}.bundled.schema.yaml' + ), + options: { + includeLabels: ['ess'], + prototypeDocument: join(ROOT, 'scripts/openapi_bundle_info/lists_ess.info.yaml'), + }, + }); +})(); diff --git a/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_ess.info.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_ess.info.yaml similarity index 100% rename from packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_ess.info.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_ess.info.yaml diff --git a/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_serverless.info.yaml b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_serverless.info.yaml similarity index 100% rename from packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_serverless.info.yaml rename to x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle_info/lists_serverless.info.yaml diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js new file mode 100644 index 0000000000000..ecda1a791e1fc --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js @@ -0,0 +1,51 @@ +/* + * 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. + */ + +require('../../../../../../src/setup_node_env'); +// eslint-disable-next-line import/no-nodejs-modules +const { join, resolve } = require('path'); +const { generate } = require('@kbn/openapi-generator'); +const { REPO_ROOT } = require('@kbn/repo-info'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await generate({ + title: 'OpenAPI Lists API Schemas', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'zod_operation_schema', + }); + + await generate({ + title: 'Lists API client for tests', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'api_client_supertest', + skipLinting: true, + bundle: { + outFile: join( + REPO_ROOT, + 'x-pack/test/api_integration/services/security_solution_lists_api.gen.ts' + ), + }, + }); + + await generate({ + title: 'Lists API client for quickstart', + rootDir: ROOT, + sourceGlob: './api/**/*.schema.yaml', + templateName: 'api_client_quickstart', + skipLinting: true, + bundle: { + outFile: join( + REPO_ROOT, + 'x-pack/solutions/security/packages/kbn-securitysolution-lists-common/api/quickstart_client.gen.ts' + ), + }, + }); +})(); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/tsconfig.json new file mode 100644 index 0000000000000..6a6637ff64a2c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-lists-common/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "exclude": ["target/**/*"], + "extends": "../../../../../tsconfig.base.json", + "include": ["**/*.ts"], + "kbn_references": [ + "@kbn/zod-helpers", + "@kbn/openapi-common", + "@kbn/test", + "@kbn/tooling-log", + "@kbn/core-http-common", + "@kbn/securitysolution-utils", + "@kbn/zod", + ] +} diff --git a/packages/kbn-securitysolution-t-grid/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/README.md similarity index 100% rename from packages/kbn-securitysolution-t-grid/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-t-grid/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/index.ts new file mode 100644 index 0000000000000..371d48e06c148 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export * from './src/constants'; +export * from './src/utils'; +// eslint-disable-next-line @kbn/imports/no_boundary_crossing +export * from './src/mock'; diff --git a/packages/kbn-securitysolution-t-grid/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-t-grid/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-t-grid/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/package.json new file mode 100644 index 0000000000000..d2f04084da369 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/securitysolution-t-grid", + "version": "1.0.0", + "description": "security solution t-grid packages will allow sharing components between timelines and security_solution plugin until we transfer all functionality to timelines plugin", + "license": "Elastic License 2.0", + "private": true +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/constants/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/constants/index.ts new file mode 100644 index 0000000000000..a57893d639955 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/constants/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +export const HIGHLIGHTED_DROP_TARGET_CLASS_NAME = 'highlighted-drop-target'; +export const EMPTY_PROVIDERS_GROUP_CLASS_NAME = 'empty-providers-group'; + +/** The draggable will move this many pixels via the keyboard when the arrow key is pressed */ +export const KEYBOARD_DRAG_OFFSET = 20; + +export const DRAGGABLE_KEYBOARD_WRAPPER_CLASS_NAME = 'draggable-keyboard-wrapper'; + +export const ROW_RENDERER_CLASS_NAME = 'row-renderer'; + +export const NOTES_CONTAINER_CLASS_NAME = 'notes-container'; + +export const NOTE_CONTENT_CLASS_NAME = 'note-content'; + +/** This class is added to the document body while dragging */ +export const IS_DRAGGING_CLASS_NAME = 'is-dragging'; + +export const HOVER_ACTIONS_ALWAYS_SHOW_CLASS_NAME = 'hover-actions-always-show'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/mock/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/mock/index.ts new file mode 100644 index 0000000000000..770bf1ffb0189 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/mock/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export * from './mock_event_details'; diff --git a/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts similarity index 97% rename from packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts index 5152132cda4bb..538f6fa2cadc0 100644 --- a/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ export const eventHit = { diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/api/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/api/index.ts new file mode 100644 index 0000000000000..add7df10fe13e --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/api/index.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import { has } from 'lodash/fp'; + +export interface AppError extends Error { + body: { + message: string; + }; +} + +export interface KibanaError extends AppError { + body: { + message: string; + statusCode: number; + }; +} + +export interface SecurityAppError extends AppError { + body: { + message: string; + status_code: number; + }; +} + +export const isKibanaError = (error: unknown): error is KibanaError => + has('message', error) && has('body.message', error) && has('body.statusCode', error); + +export const isSecurityAppError = (error: unknown): error is SecurityAppError => + has('message', error) && has('body.message', error) && has('body.status_code', error); + +export const isAppError = (error: unknown): error is AppError => + isKibanaError(error) || isSecurityAppError(error); + +export const isNotFoundError = (error: unknown) => + (isKibanaError(error) && error.body.statusCode === 404) || + (isSecurityAppError(error) && error.body.status_code === 404); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/drag_and_drop/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/drag_and_drop/index.ts new file mode 100644 index 0000000000000..d954ebb055f1d --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/drag_and_drop/index.ts @@ -0,0 +1,132 @@ +/* + * 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. + */ + +import type { DropResult } from '@hello-pangea/dnd'; + +export const draggableIdPrefix = 'draggableId'; + +export const droppableIdPrefix = 'droppableId'; + +export const draggableContentPrefix = `${draggableIdPrefix}.content.`; + +export const draggableTimelineProvidersPrefix = `${draggableIdPrefix}.timelineProviders.`; + +export const draggableFieldPrefix = `${draggableIdPrefix}.field.`; + +export const droppableContentPrefix = `${droppableIdPrefix}.content.`; + +export const droppableFieldPrefix = `${droppableIdPrefix}.field.`; + +export const droppableTimelineProvidersPrefix = `${droppableIdPrefix}.timelineProviders.`; + +export const droppableTimelineColumnsPrefix = `${droppableIdPrefix}.timelineColumns.`; + +export const droppableTimelineFlyoutBottomBarPrefix = `${droppableIdPrefix}.flyoutButton.`; + +export const getDraggableId = (dataProviderId: string): string => + `${draggableContentPrefix}${dataProviderId}`; + +export const getDraggableFieldId = ({ + contextId, + fieldId, +}: { + contextId: string; + fieldId: string; +}): string => `${draggableFieldPrefix}${escapeContextId(contextId)}.${escapeFieldId(fieldId)}`; + +export const getTimelineProviderDroppableId = ({ + groupIndex, + timelineId, +}: { + groupIndex: number; + timelineId: string; +}): string => `${droppableTimelineProvidersPrefix}${timelineId}.group.${groupIndex}`; + +export const getTimelineProviderDraggableId = ({ + dataProviderId, + groupIndex, + timelineId, +}: { + dataProviderId: string; + groupIndex: number; + timelineId: string; +}): string => + `${draggableTimelineProvidersPrefix}${timelineId}.group.${groupIndex}.${dataProviderId}`; + +export const getDroppableId = (visualizationPlaceholderId: string): string => + `${droppableContentPrefix}${visualizationPlaceholderId}`; + +export const sourceIsContent = (result: DropResult): boolean => + result.source.droppableId.startsWith(droppableContentPrefix); + +export const sourceAndDestinationAreSameTimelineProviders = (result: DropResult): boolean => { + const regex = /^droppableId\.timelineProviders\.(\S+)\./; + const sourceMatches = result.source.droppableId.match(regex) || []; + const destinationMatches = + (result.destination && result.destination.droppableId.match(regex)) || []; + + return ( + sourceMatches.length >= 2 && + destinationMatches.length >= 2 && + sourceMatches[1] === destinationMatches[1] + ); +}; + +export const draggableIsContent = (result: DropResult | { draggableId: string }): boolean => + result.draggableId.startsWith(draggableContentPrefix); + +export const draggableIsField = (result: DropResult | { draggableId: string }): boolean => + result.draggableId.startsWith(draggableFieldPrefix); + +export const reasonIsDrop = (result: DropResult): boolean => result.reason === 'DROP'; + +export const destinationIsTimelineProviders = (result: DropResult): boolean => + result.destination != null && + result.destination.droppableId.startsWith(droppableTimelineProvidersPrefix); + +export const destinationIsTimelineColumns = (result: DropResult): boolean => + result.destination != null && + result.destination.droppableId.startsWith(droppableTimelineColumnsPrefix); + +export const destinationIsTimelineButton = (result: DropResult): boolean => + result.destination != null && + result.destination.droppableId.startsWith(droppableTimelineFlyoutBottomBarPrefix); + +export const getProviderIdFromDraggable = (result: DropResult): string => + result.draggableId.substring(result.draggableId.lastIndexOf('.') + 1); + +export const getFieldIdFromDraggable = (result: DropResult): string => + unEscapeFieldId(result.draggableId.substring(result.draggableId.lastIndexOf('.') + 1)); + +export const escapeDataProviderId = (path: string) => path.replace(/\./g, '_'); + +export const escapeContextId = (path: string) => path.replace(/\./g, '_'); + +export const escapeFieldId = (path: string) => path.replace(/\./g, '!!!DOT!!!'); + +export const unEscapeFieldId = (path: string) => path.replace(/!!!DOT!!!/g, '.'); + +export const providerWasDroppedOnTimeline = (result: DropResult): boolean => + reasonIsDrop(result) && + draggableIsContent(result) && + sourceIsContent(result) && + destinationIsTimelineProviders(result); + +export const userIsReArrangingProviders = (result: DropResult): boolean => + reasonIsDrop(result) && sourceAndDestinationAreSameTimelineProviders(result); + +export const fieldWasDroppedOnTimelineColumns = (result: DropResult): boolean => + reasonIsDrop(result) && draggableIsField(result) && destinationIsTimelineColumns(result); + +/** + * Prevents fields from being dragged or dropped to any area other than column + * header drop zone in the timeline + */ +export const DRAG_TYPE_FIELD = 'drag-type-field'; + +/** This class is added to the document body while timeline field dragging */ +export const IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME = 'is-timeline-field-dragging'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/index.ts new file mode 100644 index 0000000000000..cafe8ec570c86 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/src/utils/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export * from './api'; +export * from './drag_and_drop'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/tsconfig.json new file mode 100644 index 0000000000000..131ff3e6bb433 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-t-grid/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-securitysolution-utils/README.md b/x-pack/solutions/security/packages/kbn-securitysolution-utils/README.md similarity index 100% rename from packages/kbn-securitysolution-utils/README.md rename to x-pack/solutions/security/packages/kbn-securitysolution-utils/README.md diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/index.ts new file mode 100644 index 0000000000000..dcf5ee7c47791 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './src/add_remove_id_to_item'; +export * from './src/axios'; +export * from './src/transform_data_to_ndjson'; +export * from './src/path_validations'; +export * from './src/esql'; +export * from './src/debounce_async/debounce_async'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/jest.config.js b/x-pack/solutions/security/packages/kbn-securitysolution-utils/jest.config.js new file mode 100644 index 0000000000000..c25893390c684 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/jest.config.js @@ -0,0 +1,12 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/packages/kbn-securitysolution-utils'], +}; diff --git a/packages/kbn-securitysolution-utils/kibana.jsonc b/x-pack/solutions/security/packages/kbn-securitysolution-utils/kibana.jsonc similarity index 100% rename from packages/kbn-securitysolution-utils/kibana.jsonc rename to x-pack/solutions/security/packages/kbn-securitysolution-utils/kibana.jsonc diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/package.json b/x-pack/solutions/security/packages/kbn-securitysolution-utils/package.json new file mode 100644 index 0000000000000..d9311ef37a28b --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/securitysolution-utils", + "version": "1.0.0", + "description": "security solution utilities to use across plugins such lists, security_solution, cases, etc...", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.test.ts new file mode 100644 index 0000000000000..13d13b2acf89c --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.test.ts @@ -0,0 +1,77 @@ +/* + * 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. + */ + +import { addIdToItem, removeIdFromItem } from '.'; + +jest.mock('uuid', () => ({ + v4: jest.fn().mockReturnValue('123'), +})); + +describe('add_remove_id_to_item', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('addIdToItem', () => { + test('it adds an id to an empty item', () => { + expect(addIdToItem({})).toEqual({ id: '123' }); + }); + + test('it adds a complex object', () => { + expect( + addIdToItem({ + field: '', + type: 'mapping', + value: '', + }) + ).toEqual({ + id: '123', + field: '', + type: 'mapping', + value: '', + }); + }); + + test('it adds an id to an existing item', () => { + expect(addIdToItem({ test: '456' })).toEqual({ id: '123', test: '456' }); + }); + + test('it does not change the id if it already exists', () => { + expect(addIdToItem({ id: '456' })).toEqual({ id: '456' }); + }); + + test('it returns the same reference if it has an id already', () => { + const obj = { id: '456' }; + expect(addIdToItem(obj)).toBe(obj); + }); + + test('it returns a new reference if it adds an id to an item', () => { + const obj = { test: '456' }; + expect(addIdToItem(obj)).not.toBe(obj); + }); + }); + + describe('removeIdFromItem', () => { + test('it removes an id from an item', () => { + expect(removeIdFromItem({ id: '456' })).toEqual({}); + }); + + test('it returns a new reference if it removes an id from an item', () => { + const obj = { id: '123', test: '456' }; + expect(removeIdFromItem(obj)).not.toBe(obj); + }); + + test('it does not effect an item without an id', () => { + expect(removeIdFromItem({ test: '456' })).toEqual({ test: '456' }); + }); + + test('it returns the same reference if it does not have an id already', () => { + const obj = { test: '456' }; + expect(removeIdFromItem(obj)).toBe(obj); + }); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.ts new file mode 100644 index 0000000000000..5133a13bdbecf --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/add_remove_id_to_item/index.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import { v4 as uuidv4 } from 'uuid'; + +/** + * This is useful for when you have arrays without an ID and need to add one for + * ReactJS keys. I break the types slightly by introducing an id to an arbitrary item + * but then cast it back to the regular type T. + * Usage of this could be considered tech debt as I am adding an ID when the backend + * could be doing the same thing but it depends on how you want to model your data and + * if you view modeling your data with id's to please ReactJS a good or bad thing. + * @param item The item to add an id to. + */ +type NotArray = T extends unknown[] ? never : T; +export const addIdToItem = (item: NotArray): T => { + const maybeId = item as typeof item & { id?: string }; + if (maybeId.id != null) { + return item; + } else { + return { ...item, id: uuidv4() }; + } +}; + +/** + * This is to reverse the id you added to your arrays for ReactJS keys. + * @param item The item to remove the id from. + */ +export const removeIdFromItem = ( + item: NotArray +): + | T + | Pick< + T & { + id?: string | undefined; + }, + Exclude + > => { + const maybeId = item as typeof item & { id?: string }; + if (maybeId.id != null) { + const { id, ...noId } = maybeId; + return noId; + } else { + return item; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/axios/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/axios/index.ts new file mode 100644 index 0000000000000..44972dba93565 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/axios/index.ts @@ -0,0 +1,71 @@ +/* + * 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. + */ + +import { AxiosError } from 'axios'; + +export class FormattedAxiosError extends Error { + public readonly request: { + method: string; + url: string; + data: unknown; + }; + public readonly response: { + status: number; + statusText: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: any; + }; + + constructor(axiosError: AxiosError) { + const method = axiosError.config?.method ?? ''; + const url = axiosError.config?.url ?? ''; + + super( + `${axiosError.message}${ + axiosError?.response?.data ? `: ${JSON.stringify(axiosError?.response?.data)}` : '' + }${url ? `\n(Request: ${method} ${url})` : ''}` + ); + + this.request = { + method, + url, + data: axiosError.config?.data ?? '', + }; + + this.response = { + status: axiosError?.response?.status ?? 0, + statusText: axiosError?.response?.statusText ?? '', + data: axiosError?.response?.data, + }; + + this.name = this.constructor.name; + } + + toJSON() { + return { + message: this.message, + request: this.request, + response: this.response, + }; + } + + toString() { + return JSON.stringify(this.toJSON(), null, 2); + } +} + +/** + * Used with `promise.catch()`, it will format the Axios error to a new error and will re-throw + * @param error + */ +export const catchAxiosErrorFormatAndThrow = (error: Error): never => { + if (error instanceof AxiosError) { + throw new FormattedAxiosError(error); + } + + throw error; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/client_concurrency/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/client_concurrency/index.ts new file mode 100644 index 0000000000000..3a44e5061d095 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/client_concurrency/index.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import limit from 'p-limit'; + +/** + * This type is just an async function's type + */ +type RequestFactory = () => Promise; + +/** + * Helper function to call a large number of async functions with limited concurrency. + * Example pattern of how to create functions to pass in: + * + * const ruleCopies = duplicateRuleParams(basicRule, 200); + * const functions = ruleCopies.map((rule) => () => detectionsClient.createRule({ body: rule })); + * + * Note that the `map` call in the example returns a *function* that calls detectionsClient.createRule, it doesn't call createRule immediately. + * + * @param functions Async functions to call with limited concurrency + * @param concurrency Maximum number of concurrent function calls + * @returns Results from all functions passed in + */ +export const concurrentlyExec = async ( + requestFactories: Array>, + concurrency: number = 10 +) => { + const limiter = limit(concurrency); + const promises = requestFactories.map((f) => limiter(f)); + return Promise.all(promises); +}; diff --git a/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.test.ts similarity index 77% rename from packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.test.ts index d7e1201e44e8d..7508e99a891fa 100644 --- a/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { debounceAsync } from './debounce_async'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.ts new file mode 100644 index 0000000000000..ac9f2348d0be8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/debounce_async/debounce_async.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/** + * Unlike lodash's debounce, which resolves intermediate calls with the most + * recent value, this implementation waits to resolve intermediate calls until + * the next invocation resolves. + * + * @param fn an async function + * + * @returns A debounced async function that resolves on the next invocation + */ +export function debounceAsync( + fn: (...args: Args) => Result, + intervalMs: number +): (...args: Args) => Promise> { + let timeoutId: ReturnType | undefined; + let resolve: (value: Awaited) => void; + let promise = new Promise>((_resolve) => { + resolve = _resolve; + }); + + return (...args) => { + if (timeoutId) { + clearTimeout(timeoutId); + } + + timeoutId = setTimeout(async () => { + resolve(await fn(...args)); + promise = new Promise((_resolve) => { + resolve = _resolve; + }); + }, intervalMs); + + return promise; + }; +} diff --git a/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.test.ts similarity index 84% rename from packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.test.ts index cb92d34b33ec7..41268ac0fa851 100644 --- a/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { computeIsESQLQueryAggregating } from './compute_if_esql_query_aggregating'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.ts new file mode 100644 index 0000000000000..d38abdaa481a8 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/compute_if_esql_query_aggregating.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { type ESQLAstQueryExpression, parse } from '@kbn/esql-ast'; + +export const isAggregatingQuery = (astExpression: ESQLAstQueryExpression): boolean => + astExpression.commands.some((command) => command.name === 'stats'); + +/** + * compute if esqlQuery is aggregating/grouping, i.e. using STATS...BY command + * @param esqlQuery + * @returns boolean + */ +export const computeIsESQLQueryAggregating = (esqlQuery: string): boolean => { + const { root } = parse(esqlQuery); + return isAggregatingQuery(root); +}; diff --git a/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.test.ts similarity index 80% rename from packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.test.ts index 7a7726c47e143..39dc934dcdd2d 100644 --- a/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.ts new file mode 100644 index 0000000000000..654f09cd0b846 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/get_index_list_from_esql_query.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; + +/** + * parses ES|QL query and returns array of indices + */ +export const getIndexListFromEsqlQuery = (query: string | undefined): string[] => { + try { + const indexString = getIndexPatternFromESQLQuery(query); + + return getIndexListFromIndexString(indexString); + } catch (e) { + return []; + } +}; + +/** + * transforms sting of indices, separated by commas to array + * index*, index2* => [index*, index2*] + */ +export const getIndexListFromIndexString = (indexString: string | undefined): string[] => { + if (!indexString) { + return []; + } + return indexString.split(',').map((index) => index.trim()); +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/index.ts new file mode 100644 index 0000000000000..ff6f8a4552446 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +export * from './compute_if_esql_query_aggregating'; +export * from './get_index_list_from_esql_query'; +export * from './parse_esql_query'; diff --git a/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.test.ts similarity index 90% rename from packages/kbn-securitysolution-utils/src/esql/parse_esql_query.test.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.test.ts index 6c4fdafd8e70b..1e7484fd6e4b5 100644 --- a/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.test.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.test.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { parseEsqlQuery } from './parse_esql_query'; diff --git a/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.ts similarity index 83% rename from packages/kbn-securitysolution-utils/src/esql/parse_esql_query.ts rename to x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.ts index 2a62aed8873a0..6e088bf386fbb 100644 --- a/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.ts +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/esql/parse_esql_query.ts @@ -1,10 +1,8 @@ /* * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * 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. */ import { type ESQLAstQueryExpression, parse, ESQLCommandOption, EditorError } from '@kbn/esql-ast'; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts new file mode 100644 index 0000000000000..5304c3a710613 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts @@ -0,0 +1,758 @@ +/* + * 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. + */ + +import { + isPathValid, + hasSimpleExecutableName, + OperatingSystem, + ConditionEntryField, + validateWildcardInput, + validateHasWildcardWithWrongOperator, + validatePotentialWildcardInput, + validateFilePathInput, + WILDCARD_WARNING, + FILEPATH_WARNING, +} from '.'; + +describe('validatePotentialWildcardInput', () => { + it('warns on wildcard when field is file.path.text', () => { + expect( + validatePotentialWildcardInput({ + field: 'file.path.text', + os: OperatingSystem.WINDOWS, + value: 'c:\\path*.exe', + }) + ).toEqual(WILDCARD_WARNING); + }); + it('warns on wildcard when field is not file.path.text', () => { + expect( + validatePotentialWildcardInput({ + field: 'event.category', + os: OperatingSystem.WINDOWS, + value: 'some*value', + }) + ).toEqual(WILDCARD_WARNING); + }); +}); + +describe('validateWildcardInput', () => { + it('warns on wildcard for fields that are not file paths', () => { + expect(validateWildcardInput('*')).toEqual(WILDCARD_WARNING); + }); + it('does not warn if no wildcard', () => { + expect(validateWildcardInput('non-wildcard')).toEqual(undefined); + }); +}); + +describe('validateFilePathInput', () => { + describe('windows', () => { + const os = OperatingSystem.WINDOWS; + + it('does not warn on valid filenames', () => { + expect( + validateFilePathInput({ + os, + value: 'C:\\Windows\\*\\FILENAME.EXE-1231205124.gz', + }) + ).not.toBeDefined(); + expect( + validateFilePathInput({ + os, + value: "C:\\Windows\\*\\test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", + }) + ).toEqual(undefined); + }); + + it('warns on wildcard in file name at the end of the path', () => { + expect(validateFilePathInput({ os, value: 'c:\\path*.exe' })).toEqual(WILDCARD_WARNING); + expect( + validateFilePathInput({ + os, + value: 'C:\\Windows\\*\\FILENAME.EXE-*.gz', + }) + ).toEqual(WILDCARD_WARNING); + }); + + it('warns on unix paths or non-windows paths', () => { + expect(validateFilePathInput({ os, value: '/opt/bin' })).toEqual(FILEPATH_WARNING); + }); + + it('warns on malformed paths', () => { + expect(validateFilePathInput({ os, value: 'c:\\path/opt' })).toEqual(FILEPATH_WARNING); + expect(validateFilePathInput({ os, value: '1242' })).toEqual(FILEPATH_WARNING); + expect(validateFilePathInput({ os, value: 'w12efdfa' })).toEqual(FILEPATH_WARNING); + expect(validateFilePathInput({ os, value: 'c:\\folder\\' })).toEqual(FILEPATH_WARNING); + }); + }); + describe('unix paths', () => { + const os = + parseInt((Math.random() * 2).toString(), 10) === 1 + ? OperatingSystem.MAC + : OperatingSystem.LINUX; + + it('does not warn on valid filenames', () => { + expect( + validateFilePathInput({ + os, + value: '/opt/*/FILENAME.EXE-1231205124.gz', + }) + ).not.toEqual(WILDCARD_WARNING); + expect( + validateFilePathInput({ + os, + value: "/opt/*/test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", + }) + ).not.toEqual(WILDCARD_WARNING); + }); + it('warns on wildcard in file name at the end of the path', () => { + expect(validateFilePathInput({ os, value: '/opt/bin*' })).toEqual(WILDCARD_WARNING); + expect(validateFilePathInput({ os, value: '/opt/FILENAME.EXE-*.gz' })).toEqual( + WILDCARD_WARNING + ); + }); + + it('warns on windows paths', () => { + expect(validateFilePathInput({ os, value: 'd:\\path\\file.exe' })).toEqual(FILEPATH_WARNING); + }); + + it('warns on malformed paths', () => { + expect(validateFilePathInput({ os, value: 'opt/bin\\file.exe' })).toEqual(FILEPATH_WARNING); + expect(validateFilePathInput({ os, value: '1242' })).toEqual(FILEPATH_WARNING); + expect(validateFilePathInput({ os, value: 'w12efdfa' })).toEqual(FILEPATH_WARNING); + expect(validateFilePathInput({ os, value: '/folder/' })).toEqual(FILEPATH_WARNING); + }); + }); +}); + +describe('Wildcard and invalid operator', () => { + it('should return TRUE when operator is not "WILDCARD" and value contains a wildcard', () => { + expect(validateHasWildcardWithWrongOperator({ operator: 'match', value: 'asdf*' })).toEqual( + true + ); + }); + it('should return FALSE when operator is not "WILDCARD" and value does not contain a wildcard', () => { + expect(validateHasWildcardWithWrongOperator({ operator: 'match', value: 'asdf' })).toEqual( + false + ); + }); + it('should return FALSE when operator is "WILDCARD" and value contains a wildcard', () => { + expect(validateHasWildcardWithWrongOperator({ operator: 'wildcard', value: 'asdf*' })).toEqual( + false + ); + }); + it('should return FALSE when operator is "WILDCARD" and value does not contain a wildcard', () => { + expect(validateHasWildcardWithWrongOperator({ operator: 'wildcard', value: 'asdf' })).toEqual( + false + ); + }); +}); + +describe('No Warnings', () => { + it('should not show warnings on non path entries ', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.HASH, + type: 'match', + value: '5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e', + }) + ).toEqual(true); + + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.SIGNER, + type: 'match', + value: '', + }) + ).toEqual(true); + }); +}); + +describe('Unacceptable Windows wildcard paths', () => { + it('should not accept paths that do not have a folder name with a wildcard ', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'c:\\folder', + }) + ).toEqual(false); + }); + + it('should not accept paths that do not have a file name with a wildcard ', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'c:\\path.exe', + }) + ).toEqual(false); + }); + + it('should not accept nested paths that do not have a wildcard', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'c:\\folder\\path.exe', + }) + ).toEqual(false); + }); + + it('should not accept paths with * wildcard and /', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'c:/**/path.exe', + }) + ).toEqual(false); + }); + + it('should not accept paths with ? wildcard and /', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'C:/?indows/pat?', + }) + ).toEqual(false); + }); +}); + +describe('Acceptable Windows wildcard paths', () => { + it('should accept wildcards for folders', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'c:\\**\\path.exe', + }) + ).toEqual(true); + }); + + it('should accept wildcards for folders and files', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'e:\\**\\*.exe', + }) + ).toEqual(true); + }); + + it('should accept paths with single wildcard', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'f:\\*', + }) + ).toEqual(true); + + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'f:\\?', + }) + ).toEqual(true); + }); + + it('should accept paths that have wildcard in filenames', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'a:\\*.*', + }) + ).toEqual(true); + }); + + it('should accept paths with ? as wildcard', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'C:\\?indows\\pat?', + }) + ).toEqual(true); + }); + + it('should accept paths with both ? and * as wildcards', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'C:\\*?', + }) + ).toEqual(true); + }); + + it('should accept paths with multiple wildcards', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'C:\\**', + }) + ).toEqual(true); + + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'C:\\??', + }) + ).toEqual(true); + }); +}); + +describe('Acceptable Windows exact paths', () => { + it('should accept paths when it ends with a folder name', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'match', + value: 'c:\\folder', + }) + ).toEqual(true); + }); + + it('should accept paths when it ends with a file name', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'match', + value: 'c:\\path.exe', + }) + ).toEqual(true); + }); + + it('should accept paths when it ends with a filename in a folder', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'match', + value: 'c:\\folder\\path.exe', + }) + ).toEqual(true); + }); +}); + +describe('Acceptable Windows exact paths with hyphens', () => { + it('should accept paths when paths have folder names with hyphens', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'match', + value: 'c:\\hype-folder-name', + }) + ).toEqual(true); + }); + + it('should accept paths when file names have hyphens', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'match', + value: 'c:\\file-name.exe', + }) + ).toEqual(true); + }); +}); + +describe('Unacceptable Windows exact paths', () => { + it('should not accept paths with /', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'match', + value: 'c:/folder/path.exe', + }) + ).toEqual(false); + }); + + it('should not accept paths not having a in the suffix', () => { + expect( + isPathValid({ + os: OperatingSystem.WINDOWS, + field: ConditionEntryField.PATH, + type: 'match', + value: '\\folder\\path.exe', + }) + ).toEqual(false); + }); +}); + +/// +describe('Unacceptable Mac/Linux wildcard paths', () => { + it('should not accept paths that do not have a folder name with a wildcard ', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/folder', + }) + ).toEqual(false); + }); + + it('should not accept paths that do not have a file name with a wildcard ', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/zip.zip', + }) + ).toEqual(false); + }); + + it('should not accept nested paths that do not have a wildcard', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/opt/pack.tar', + }) + ).toEqual(false); + }); + + it('should not accept paths with * wildcard and \\', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'c:\\**\\path.exe', + }) + ).toEqual(false); + }); + + it('should not accept paths with ? wildcard and \\', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: 'C:\\?indows\\pat?', + }) + ).toEqual(false); + }); +}); + +describe('Acceptable Mac/Linux wildcard paths', () => { + it('should accept wildcards for folders', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/**/file.', + }) + ).toEqual(true); + }); + + it('should accept wildcards for folders and files', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/usr/bi?/*.js', + }) + ).toEqual(true); + }); + + it('should accept paths with single wildcard', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/op*', + }) + ).toEqual(true); + + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/op?', + }) + ).toEqual(true); + }); + + it('should accept paths that have wildcard in filenames', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/*.*', + }) + ).toEqual(true); + }); + + it('should accept paths with ? as wildcard', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/usr/?inux/pat?', + }) + ).toEqual(true); + }); + + it('should accept paths with both ? and * as wildcards', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/usr/*?', + }) + ).toEqual(true); + }); + + it('should accept paths with multiple wildcards', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/usr/**', + }) + ).toEqual(true); + + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'wildcard', + value: '/opt/??', + }) + ).toEqual(true); + }); +}); + +describe('Acceptable Mac/Linux exact paths', () => { + it('should accept paths when it is the root path', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'match', + value: '/', + }) + ).toEqual(true); + }); + + it('should accept paths when it ends with a file name', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'match', + value: '/usr/file.ts', + }) + ).toEqual(true); + }); + + it('should accept paths when it ends with a filename in a folder', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'match', + value: '/opt/z.dmg', + }) + ).toEqual(true); + }); +}); + +describe('Acceptable Mac/Linux exact paths with hyphens', () => { + it('should accept paths when paths have folder names with hyphens', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'match', + value: '/hype-folder-name', + }) + ).toEqual(true); + }); + + it('should accept paths when file names have hyphens', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'match', + value: '/file-name.dmg', + }) + ).toEqual(true); + }); +}); + +describe('Unacceptable Mac/Linux exact paths', () => { + it('should not accept paths with \\', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'match', + value: 'c:\\folder\\path.exe', + }) + ).toEqual(false); + }); + + it('should not accept paths not starting with /', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'match', + value: 'opt/bin', + }) + ).toEqual(false); + }); + + it('should not accept paths ending with /', () => { + expect( + isPathValid({ + os: OperatingSystem.MAC, + field: ConditionEntryField.PATH, + type: 'match', + value: '/opt/bin/', + }) + ).toEqual(false); + }); + + it('should not accept file extensions with hyphens', () => { + expect( + isPathValid({ + os: OperatingSystem.LINUX, + field: ConditionEntryField.PATH, + type: 'match', + value: '/opt/bin/file.d-mg', + }) + ).toEqual(false); + }); +}); + +describe('hasSimpleExecutableName', () => { + it('should return TRUE when MAC/LINUX wildcard paths have an executable name', () => { + const os = + parseInt((Math.random() * 2).toString(), 10) === 1 + ? OperatingSystem.MAC + : OperatingSystem.LINUX; + + expect( + hasSimpleExecutableName({ + os, + type: 'wildcard', + value: '/opt/*/app', + }) + ).toEqual(true); + expect( + hasSimpleExecutableName({ + os, + type: 'wildcard', + value: '/op*/**/app.dmg', + }) + ).toEqual(true); + expect( + hasSimpleExecutableName({ + os, + type: 'wildcard', + value: "/sy*/test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", + }) + ).toEqual(true); + }); + + it('should return FALSE when MAC/LINUX wildcard paths have a wildcard in executable name', () => { + const os = + parseInt((Math.random() * 2).toString(), 10) === 1 + ? OperatingSystem.MAC + : OperatingSystem.LINUX; + + expect( + hasSimpleExecutableName({ + os, + type: 'wildcard', + value: '/op/*/*pp', + }) + ).toEqual(false); + expect( + hasSimpleExecutableName({ + os, + type: 'wildcard', + value: '/op*/b**/ap.m**', + }) + ).toEqual(false); + }); + + it('should return TRUE when WINDOWS wildcards paths have a executable name', () => { + expect( + hasSimpleExecutableName({ + os: OperatingSystem.WINDOWS, + type: 'wildcard', + value: 'c:\\**\\path.exe', + }) + ).toEqual(true); + expect( + hasSimpleExecutableName({ + os: OperatingSystem.WINDOWS, + type: 'wildcard', + value: 'C:\\*\\file-name.path华语 1234.txt', + }) + ).toEqual(true); + expect( + hasSimpleExecutableName({ + os: OperatingSystem.WINDOWS, + type: 'wildcard', + value: "C:\\*\\test$ as2@13---12!@#A,DS.#$^&$!#~ 'as'd.华语.txt", + }) + ).toEqual(true); + }); + + it('should return FALSE when WINDOWS wildcards paths have a wildcard in executable name', () => { + expect( + hasSimpleExecutableName({ + os: OperatingSystem.WINDOWS, + type: 'wildcard', + value: 'c:\\**\\pa*h.exe', + }) + ).toEqual(false); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/path_validations/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/path_validations/index.ts new file mode 100644 index 0000000000000..965a5b9fbe0fe --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/path_validations/index.ts @@ -0,0 +1,243 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const WILDCARD_WARNING = i18n.translate('utils.wildcardWarning', { + defaultMessage: `Using wildcards can impact Endpoint performance`, +}); + +export const FILEPATH_WARNING = i18n.translate('utils.filename.pathWarning', { + defaultMessage: `Path may be formed incorrectly; verify value`, +}); + +export enum ConditionEntryField { + HASH = 'process.hash.*', + PATH = 'process.executable.caseless', + SIGNER = 'process.Ext.code_signature', + SIGNER_MAC = 'process.code_signature', +} + +export enum EntryFieldType { + HASH = '.hash.', + EXECUTABLE = '.executable.caseless', + PATH = '.path', + SIGNER = '.code_signature', +} + +export type TrustedAppConditionEntryField = + | 'process.hash.*' + | 'process.executable.caseless' + | 'process.Ext.code_signature' + | 'process.code_signature'; + +export type BlocklistConditionEntryField = + | 'file.hash.*' + | 'file.path' + | 'file.Ext.code_signature' + | 'file.path.caseless'; +export type AllConditionEntryFields = + | TrustedAppConditionEntryField + | BlocklistConditionEntryField + | 'file.path.text'; + +export enum OperatingSystem { + LINUX = 'linux', + MAC = 'macos', + WINDOWS = 'windows', +} + +export type EntryTypes = 'match' | 'wildcard' | 'match_any'; +export type TrustedAppEntryTypes = Extract; +export type EventFiltersTypes = EntryTypes | 'exists' | 'nested'; + +export const validatePotentialWildcardInput = ({ + field = '', + os, + value = '', +}: { + field?: string; + os: OperatingSystem; + value?: string; +}): string | undefined => { + const textInput = value.trim(); + if (field === 'file.path.text') { + return validateFilePathInput({ os, value: textInput }); + } + return validateWildcardInput(textInput); +}; + +export const validateFilePathInput = ({ + os, + value, +}: { + os: OperatingSystem; + value: string; +}): string | undefined => { + const isValidFilePath = isPathValid({ + os, + field: 'file.path.text', + type: 'wildcard', + value, + }); + const hasSimpleFileName = hasSimpleExecutableName({ + os, + type: 'wildcard', + value, + }); + + if (!value.length) { + return FILEPATH_WARNING; + } + + if (isValidFilePath) { + if (hasSimpleFileName !== undefined && !hasSimpleFileName) { + return WILDCARD_WARNING; + } + } else { + return FILEPATH_WARNING; + } +}; + +export const validateWildcardInput = (value: string | string[]): string | undefined => { + const wildcardRegex = /[*?]/; + if (Array.isArray(value)) { + const doesAnyValueContainWildcardInput = value.some((v) => wildcardRegex.test(v)); + if (doesAnyValueContainWildcardInput) { + return WILDCARD_WARNING; + } + } else { + if (wildcardRegex.test(value)) { + return WILDCARD_WARNING; + } + } +}; + +export const validateHasWildcardWithWrongOperator = ({ + operator, + value, +}: { + operator: TrustedAppEntryTypes | EventFiltersTypes; + value: string | string[]; +}): boolean => { + if (operator !== 'wildcard' && validateWildcardInput(value)) { + return true; + } else { + return false; + } +}; + +export const hasSimpleExecutableName = ({ + os, + type, + value, +}: { + os: OperatingSystem; + type: EntryTypes; + value: string; +}): boolean | undefined => { + const separator = os === OperatingSystem.WINDOWS ? '\\' : '/'; + const lastString = value.split(separator).pop(); + if (!lastString) { + return; + } + if (type === 'wildcard') { + return (lastString.split('*').length || lastString.split('?').length) === 1; + } + return true; +}; + +export const isPathValid = ({ + os, + field, + type, + value, +}: { + os: OperatingSystem; + field: AllConditionEntryFields; + type: EntryTypes; + value: string; +}): boolean => { + const pathFields: AllConditionEntryFields[] = [ + 'process.executable.caseless', + 'file.path', + 'file.path.text', + ]; + if (pathFields.includes(field)) { + if (type === 'wildcard') { + return os === OperatingSystem.WINDOWS + ? isWindowsWildcardPathValid(value) + : isLinuxMacWildcardPathValid(value); + } + return doesPathMatchRegex({ value, os }); + } + return true; +}; + +const doesPathMatchRegex = ({ os, value }: { os: OperatingSystem; value: string }): boolean => { + if (os === OperatingSystem.WINDOWS) { + const filePathRegex = + /^[a-z]:(?:|\\\\[^<>:"'/\\|?*]+\\[^<>:"'/\\|?*]+|%\w+%|)[\\](?:[^<>:"'/\\|?*]+[\\/])*([^<>:"'/\\|?*])+$/i; + return filePathRegex.test(value); + } + return /^(\/|(\/[\w\-]+)+|\/[\w\-]+\.[\w]+|(\/[\w-]+)+\/[\w\-]+\.[\w]+)$/i.test(value); +}; + +const isWindowsWildcardPathValid = (path: string): boolean => { + const firstCharacter = path[0]; + const lastCharacter = path.slice(-1); + const trimmedValue = path.trim(); + const hasSlash = /\//.test(trimmedValue); + if (path.length === 0) { + return false; + } else if ( + hasSlash || + trimmedValue.length !== path.length || + firstCharacter === '^' || + lastCharacter === '\\' || + !hasWildcard({ path, isWindowsPath: true }) + ) { + return false; + } else { + return true; + } +}; + +const isLinuxMacWildcardPathValid = (path: string): boolean => { + const firstCharacter = path[0]; + const lastCharacter = path.slice(-1); + const trimmedValue = path.trim(); + if (path.length === 0) { + return false; + } else if ( + trimmedValue.length !== path.length || + firstCharacter !== '/' || + lastCharacter === '/' || + path.length > 1024 === true || + path.includes('//') === true || + !hasWildcard({ path, isWindowsPath: false }) + ) { + return false; + } else { + return true; + } +}; + +const hasWildcard = ({ + path, + isWindowsPath, +}: { + path: string; + isWindowsPath: boolean; +}): boolean => { + for (const pathComponent of path.split(isWindowsPath ? '\\' : '/')) { + if (/[\*|\?]+/.test(pathComponent) === true) { + return true; + } + } + return false; +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts new file mode 100644 index 0000000000000..d91eb687d86db --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts @@ -0,0 +1,83 @@ +/* + * 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. + */ + +import { transformDataToNdjson } from '.'; + +export const ANCHOR_DATE = '2020-02-20T03:57:54.037Z'; + +const getRulesSchemaMock = (anchorDate: string = ANCHOR_DATE) => ({ + author: [], + id: '7a7065d7-6e8b-4aae-8d20-c93613dec9f9', + created_at: new Date(anchorDate).toISOString(), + updated_at: new Date(anchorDate).toISOString(), + created_by: 'elastic', + description: 'some description', + enabled: true, + false_positives: ['false positive 1', 'false positive 2'], + from: 'now-6m', + immutable: false, + name: 'Query with a rule id', + query: 'user.name: root or user.name: admin', + references: ['test 1', 'test 2'], + severity: 'high', + severity_mapping: [], + updated_by: 'elastic_kibana', + tags: ['some fake tag 1', 'some fake tag 2'], + to: 'now', + type: 'query', + threat: [], + version: 1, + output_index: '.siem-signals-default', + max_signals: 100, + risk_score: 55, + risk_score_mapping: [], + language: 'kuery', + rule_id: 'query-rule-id', + interval: '5m', + exceptions_list: [], +}); + +describe('transformDataToNdjson', () => { + test('if rules are empty it returns an empty string', () => { + const ruleNdjson = transformDataToNdjson([]); + expect(ruleNdjson).toEqual(''); + }); + + test('single rule will transform with new line ending character for ndjson', () => { + const rule = getRulesSchemaMock(); + const ruleNdjson = transformDataToNdjson([rule]); + expect(ruleNdjson.endsWith('\n')).toBe(true); + }); + + test('multiple rules will transform with two new line ending characters for ndjson', () => { + const result1 = getRulesSchemaMock(); + const result2 = getRulesSchemaMock(); + result2.id = 'some other id'; + result2.rule_id = 'some other id'; + result2.name = 'Some other rule'; + + const ruleNdjson = transformDataToNdjson([result1, result2]); + // this is how we count characters in JavaScript :-) + const count = ruleNdjson.split('\n').length - 1; + expect(count).toBe(2); + }); + + test('you can parse two rules back out without errors', () => { + const result1 = getRulesSchemaMock(); + const result2 = getRulesSchemaMock(); + result2.id = 'some other id'; + result2.rule_id = 'some other id'; + result2.name = 'Some other rule'; + + const ruleNdjson = transformDataToNdjson([result1, result2]); + const ruleStrings = ruleNdjson.split('\n'); + const reParsed1 = JSON.parse(ruleStrings[0]); + const reParsed2 = JSON.parse(ruleStrings[1]); + expect(reParsed1).toEqual(result1); + expect(reParsed2).toEqual(result2); + }); +}); diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.ts b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.ts new file mode 100644 index 0000000000000..572b777731c48 --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export const transformDataToNdjson = (data: unknown[]): string => { + if (data.length !== 0) { + const dataString = data.map((item) => JSON.stringify(item)).join('\n'); + return `${dataString}\n`; + } else { + return ''; + } +}; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-utils/tsconfig.json b/x-pack/solutions/security/packages/kbn-securitysolution-utils/tsconfig.json new file mode 100644 index 0000000000000..063735a114dad --- /dev/null +++ b/x-pack/solutions/security/packages/kbn-securitysolution-utils/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "kbn_references": [ + "@kbn/i18n", + "@kbn/esql-utils", + "@kbn/esql-ast", + "@kbn/esql-validation-autocomplete" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/x-pack/plugins/lists/.storybook/main.js b/x-pack/solutions/security/plugins/lists/.storybook/main.js similarity index 100% rename from x-pack/plugins/lists/.storybook/main.js rename to x-pack/solutions/security/plugins/lists/.storybook/main.js diff --git a/x-pack/plugins/lists/README.md b/x-pack/solutions/security/plugins/lists/README.md similarity index 98% rename from x-pack/plugins/lists/README.md rename to x-pack/solutions/security/plugins/lists/README.md index 02be757303417..b04d7097ddc6d 100644 --- a/x-pack/plugins/lists/README.md +++ b/x-pack/solutions/security/plugins/lists/README.md @@ -42,7 +42,7 @@ xpack.lists.listItemIndex: '.items-your-name' Restart Kibana and ensure that you are using `--no-base-path` as changing the base path is a feature but will get in the way of the CURL scripts written as is. -Go to the scripts folder `cd kibana/x-pack/plugins/lists/server/scripts` and run: +Go to the scripts folder `cd kibana/x-pack/solutions/security/plugins/lists/server/scripts` and run: ```sh ./hard_reset.sh diff --git a/x-pack/plugins/lists/common/api/exceptions/create_exception_list/create_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/common/api/exceptions/create_exception_list/create_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/common/api/exceptions/create_exception_list/create_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/common/api/exceptions/create_exception_list/create_exception_list_route.ts diff --git a/x-pack/plugins/lists/common/api/exceptions/get_exception_filter/get_exception_filter_route.ts b/x-pack/solutions/security/plugins/lists/common/api/exceptions/get_exception_filter/get_exception_filter_route.ts similarity index 100% rename from x-pack/plugins/lists/common/api/exceptions/get_exception_filter/get_exception_filter_route.ts rename to x-pack/solutions/security/plugins/lists/common/api/exceptions/get_exception_filter/get_exception_filter_route.ts diff --git a/x-pack/plugins/lists/common/api/index.ts b/x-pack/solutions/security/plugins/lists/common/api/index.ts similarity index 100% rename from x-pack/plugins/lists/common/api/index.ts rename to x-pack/solutions/security/plugins/lists/common/api/index.ts diff --git a/x-pack/plugins/lists/common/api/values/find_lists_by_size/find_lists_by_size_route.ts b/x-pack/solutions/security/plugins/lists/common/api/values/find_lists_by_size/find_lists_by_size_route.ts similarity index 100% rename from x-pack/plugins/lists/common/api/values/find_lists_by_size/find_lists_by_size_route.ts rename to x-pack/solutions/security/plugins/lists/common/api/values/find_lists_by_size/find_lists_by_size_route.ts diff --git a/x-pack/plugins/lists/common/constants.mock.ts b/x-pack/solutions/security/plugins/lists/common/constants.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/constants.mock.ts rename to x-pack/solutions/security/plugins/lists/common/constants.mock.ts diff --git a/x-pack/plugins/lists/common/index.ts b/x-pack/solutions/security/plugins/lists/common/index.ts similarity index 100% rename from x-pack/plugins/lists/common/index.ts rename to x-pack/solutions/security/plugins/lists/common/index.ts diff --git a/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/create_exception_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/create_exception_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/create_exception_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/create_exception_list_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/create_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/create_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/create_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/create_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/create_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/create_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/create_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/create_list_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/get_exception_filter_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/get_exception_filter_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/get_exception_filter_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/get_exception_filter_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/import_exceptions_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/import_exceptions_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/import_exceptions_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/import_exceptions_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/import_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/import_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/import_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/update_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/update_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/update_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/update_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/request/update_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/request/update_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/request/update_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/request/update_list_schema.mock.ts diff --git a/x-pack/solutions/security/plugins/lists/common/schemas/response/acknowledge_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/acknowledge_schema.mock.ts new file mode 100644 index 0000000000000..0aa6990d44b3d --- /dev/null +++ b/x-pack/solutions/security/plugins/lists/common/schemas/response/acknowledge_schema.mock.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +import type { AcknowledgeSchema } from '@kbn/securitysolution-io-ts-list-types'; + +export const getAcknowledgeSchemaResponseMock = (): AcknowledgeSchema => ({ + acknowledged: true, +}); diff --git a/x-pack/plugins/lists/common/schemas/response/exception_export_details_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/exception_export_details_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/exception_export_details_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/exception_export_details_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/exception_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/exception_list_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/exception_list_summary_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/exception_list_summary_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/exception_list_summary_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/exception_list_summary_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/found_all_list_items_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/found_all_list_items_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/found_all_list_items_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/found_all_list_items_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/found_exception_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/found_exception_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/found_exception_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/found_exception_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/found_exception_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/found_exception_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/found_exception_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/found_exception_list_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/found_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/found_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/found_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/found_list_item_schema.mock.ts diff --git a/x-pack/solutions/security/plugins/lists/common/schemas/response/found_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/found_list_schema.mock.ts new file mode 100644 index 0000000000000..1691221842d39 --- /dev/null +++ b/x-pack/solutions/security/plugins/lists/common/schemas/response/found_list_schema.mock.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +import type { FoundListSchema } from '@kbn/securitysolution-io-ts-list-types'; + +import { getListResponseMock } from './list_schema.mock'; + +export const getFoundListSchemaMock = (): FoundListSchema => ({ + cursor: '123', + data: [getListResponseMock()], + page: 1, + per_page: 1, + total: 1, +}); diff --git a/x-pack/plugins/lists/common/schemas/response/found_lists_by_size_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/found_lists_by_size_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/found_lists_by_size_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/found_lists_by_size_schema.mock.ts diff --git a/x-pack/solutions/security/plugins/lists/common/schemas/response/list_item_index_exist_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/list_item_index_exist_schema.mock.ts new file mode 100644 index 0000000000000..afbb03cab870d --- /dev/null +++ b/x-pack/solutions/security/plugins/lists/common/schemas/response/list_item_index_exist_schema.mock.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +import type { ListItemIndexExistSchema } from '@kbn/securitysolution-io-ts-list-types'; + +export const getListItemIndexExistSchemaResponseMock = (): ListItemIndexExistSchema => ({ + list_index: true, + list_item_index: true, +}); diff --git a/x-pack/plugins/lists/common/schemas/response/list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/list_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/response/search_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/response/search_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/response/search_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/response/search_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/comment.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/comment.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/comment.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/comment.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/create_comment.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/create_comment.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/create_comment.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/create_comment.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/entries.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/entries.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/entries.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/entries.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/entry_exists.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/entry_exists.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/entry_exists.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/entry_exists.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/entry_list.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/entry_list.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/entry_list.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/entry_list.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/entry_match.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/entry_match.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/entry_match.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/entry_match.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/entry_match_any.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/entry_match_any.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/entry_match_any.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/entry_match_any.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/entry_match_wildcard.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/entry_match_wildcard.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/entry_match_wildcard.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/entry_match_wildcard.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/entry_nested.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/entry_nested.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/entry_nested.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/entry_nested.mock.ts diff --git a/x-pack/plugins/lists/common/schemas/types/update_comment.mock.ts b/x-pack/solutions/security/plugins/lists/common/schemas/types/update_comment.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/schemas/types/update_comment.mock.ts rename to x-pack/solutions/security/plugins/lists/common/schemas/types/update_comment.mock.ts diff --git a/x-pack/solutions/security/plugins/lists/jest.config.js b/x-pack/solutions/security/plugins/lists/jest.config.js new file mode 100644 index 0000000000000..3bbf109f51ab5 --- /dev/null +++ b/x-pack/solutions/security/plugins/lists/jest.config.js @@ -0,0 +1,18 @@ +/* + * 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. + */ + +module.exports = { + collectCoverageFrom: [ + '/x-pack/solutions/security/plugins/lists/{common,public,server}/**/*.{ts,tsx}', + ], + coverageDirectory: + '/target/kibana-coverage/jest/x-pack/solutions/security/plugins/lists', + coverageReporters: ['text', 'html'], + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/x-pack/solutions/security/plugins/lists'], +}; diff --git a/x-pack/plugins/lists/kibana.jsonc b/x-pack/solutions/security/plugins/lists/kibana.jsonc similarity index 100% rename from x-pack/plugins/lists/kibana.jsonc rename to x-pack/solutions/security/plugins/lists/kibana.jsonc diff --git a/x-pack/plugins/lists/public/common/empty_value.ts b/x-pack/solutions/security/plugins/lists/public/common/empty_value.ts similarity index 100% rename from x-pack/plugins/lists/public/common/empty_value.ts rename to x-pack/solutions/security/plugins/lists/public/common/empty_value.ts diff --git a/x-pack/plugins/lists/public/exceptions/api.test.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/api.test.ts similarity index 100% rename from x-pack/plugins/lists/public/exceptions/api.test.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/api.test.ts diff --git a/x-pack/plugins/lists/public/exceptions/components/__mock__/show_value_list_modal.mock.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/__mock__/show_value_list_modal.mock.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/__mock__/show_value_list_modal.mock.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/__mock__/show_value_list_modal.mock.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/index.stories.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/index.stories.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/index.stories.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/index.stories.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/index.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/index.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/index.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/index.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/index.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/index.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/index.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/index.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/rounded_badge_antenna.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/and_or_badge/translations.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/translations.ts similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/and_or_badge/translations.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/and_or_badge/translations.ts diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/and_badge.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/and_badge.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/and_badge.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/and_badge.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/and_badge.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/and_badge.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/and_badge.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/and_badge.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/builder.stories.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/builder.stories.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/builder.stories.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/builder.stories.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_delete_button.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_delete_button.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/entry_delete_button.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_delete_button.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_delete_button.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_delete_button.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/entry_delete_button.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_delete_button.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_item_renderer.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_item_renderer.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_items_renderer.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_items_renderer.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/helpers.test.ts similarity index 99% rename from x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/helpers.test.ts index 2c0f8b198b384..c5afe22bb73c8 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/helpers.test.ts @@ -1669,7 +1669,7 @@ describe('Exception builder helpers', () => { }); describe('#filterExceptionItems', () => { - // Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes + // Please see `x-pack/solutions/security/plugins/lists/public/exceptions/transforms.ts` doc notes // for context around the temporary `id` test('it correctly validates entries that include a temporary `id`', () => { const output: ExceptionsBuilderReturnExceptionItem[] = filterExceptionItems([ diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/index.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/index.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/index.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/index.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.test.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/logic_buttons.test.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.test.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/logic_buttons.test.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/reducer.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/reducer.ts similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/reducer.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/reducer.ts diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/selectors.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/selectors.ts similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/selectors.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/selectors.ts diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/translations.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/translations.ts similarity index 100% rename from x-pack/plugins/lists/public/exceptions/components/builder/translations.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/components/builder/translations.ts diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts similarity index 96% rename from x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts index 95ca6285f0d74..029488f850d43 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts @@ -17,7 +17,7 @@ import { getExceptionListItemSchemaMock } from '../../../common/schemas/response const mockKibanaHttpService = coreMock.createStart().http; -// TODO: Port this test over to packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.test.ts once the other mocks are added to the kbn package system +// TODO: Port this test over to x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_item/index.test.ts once the other mocks are added to the kbn package system describe('usePersistExceptionItem', () => { let addExceptionListItemSpy: jest.SpyInstance>; diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts similarity index 95% rename from x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts index c27888b6d8cc6..159426d711601 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts @@ -18,7 +18,7 @@ const mockKibanaHttpService = coreMock.createStart().http; jest.mock('@kbn/securitysolution-list-api'); -// TODO: Port this to the kbn package of: packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.test.ts once the kibana mocks are ported +// TODO: Port this to the kbn package of: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_persist_exception_list/index.test.ts once the kibana mocks are ported describe('usePersistExceptionList', () => { const onError = jest.fn(); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/use_api.test.ts similarity index 99% rename from x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/hooks/use_api.test.ts index a980261ba5f86..2ceaab63cc044 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/use_api.test.ts @@ -32,7 +32,7 @@ jest.mock('uuid', () => ({ const mockKibanaHttpService = coreMock.createStart().http; -// TODO: Once the mocks are figured out and the types are moved into kbn core this test should be moved next to the file: packages/kbn-securitysolution-list-hooks/src/use_api/index.test.ts +// TODO: Once the mocks are figured out and the types are moved into kbn core this test should be moved next to the file: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_api/index.test.ts describe('useApi', () => { const onErrorMock = jest.fn(); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts similarity index 97% rename from x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts index 6c684d199e538..db01cc54e855f 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts @@ -20,7 +20,7 @@ const mockKibanaHttpService = coreMock.createStart().http; const mockKibanaNotificationsService = coreMock.createStart().notifications; jest.mock('@kbn/securitysolution-list-api'); -// TODO: Move this test to the kbn package: packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.test.ts once mocks are ported over +// TODO: Move this test to the kbn package: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_exception_lists/index.test.ts once mocks are ported over describe('useExceptionLists', () => { beforeEach(() => { diff --git a/x-pack/plugins/lists/public/exceptions/transforms.test.ts b/x-pack/solutions/security/plugins/lists/public/exceptions/transforms.test.ts similarity index 100% rename from x-pack/plugins/lists/public/exceptions/transforms.test.ts rename to x-pack/solutions/security/plugins/lists/public/exceptions/transforms.test.ts diff --git a/x-pack/plugins/lists/public/index.ts b/x-pack/solutions/security/plugins/lists/public/index.ts similarity index 100% rename from x-pack/plugins/lists/public/index.ts rename to x-pack/solutions/security/plugins/lists/public/index.ts diff --git a/x-pack/plugins/lists/public/lists/hooks/use_create_list_index.test.ts b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_create_list_index.test.ts similarity index 93% rename from x-pack/plugins/lists/public/lists/hooks/use_create_list_index.test.ts rename to x-pack/solutions/security/plugins/lists/public/lists/hooks/use_create_list_index.test.ts index 7021d49940f26..806d8b6337088 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_create_list_index.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_create_list_index.test.ts @@ -15,7 +15,7 @@ import { createQueryWrapperMock } from '../mocks/query_wrapper'; jest.mock('@kbn/securitysolution-list-api'); -// TODO: This test should be ported to the package: packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.test.ts once we have mocks in kbn packages +// TODO: This test should be ported to the package: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.test.ts once we have mocks in kbn packages const { wrapper: queryWrapper, queryClient } = createQueryWrapperMock(); diff --git a/x-pack/plugins/lists/public/lists/hooks/use_delete_list.test.ts b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_delete_list.test.ts similarity index 86% rename from x-pack/plugins/lists/public/lists/hooks/use_delete_list.test.ts rename to x-pack/solutions/security/plugins/lists/public/lists/hooks/use_delete_list.test.ts index 7a339f3e12a4a..72276e7c474de 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_delete_list.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_delete_list.test.ts @@ -14,7 +14,7 @@ import { getListResponseMock } from '../../../common/schemas/response/list_schem jest.mock('@kbn/securitysolution-list-api'); -// TODO: This test should be ported to the package: packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.test.ts once we have mocks in kbn packages +// TODO: This test should be ported to the package: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.test.ts once we have mocks in kbn packages describe('useDeleteList', () => { let httpMock: ReturnType; diff --git a/x-pack/plugins/lists/public/lists/hooks/use_export_list.test.ts b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_export_list.test.ts similarity index 86% rename from x-pack/plugins/lists/public/lists/hooks/use_export_list.test.ts rename to x-pack/solutions/security/plugins/lists/public/lists/hooks/use_export_list.test.ts index 8f08ad5c8bd03..6cafd4958f7a7 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_export_list.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_export_list.test.ts @@ -12,7 +12,7 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; jest.mock('@kbn/securitysolution-list-api'); -// TODO: Move this test to the kbn package: packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts once Mocks are ported from Kibana +// TODO: Move this test to the kbn package: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts once Mocks are ported from Kibana describe('useExportList', () => { let httpMock: ReturnType; diff --git a/x-pack/plugins/lists/public/lists/hooks/use_import_list.test.ts b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_import_list.test.ts similarity index 94% rename from x-pack/plugins/lists/public/lists/hooks/use_import_list.test.ts rename to x-pack/solutions/security/plugins/lists/public/lists/hooks/use_import_list.test.ts index d56478a0321be..00a3a39f1f1aa 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_import_list.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_import_list.test.ts @@ -14,7 +14,7 @@ import { getListResponseMock } from '../../../common/schemas/response/list_schem jest.mock('@kbn/securitysolution-list-api'); -// TODO: Port this test over to: packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts once mocks are moved to packages +// TODO: Port this test over to: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts once mocks are moved to packages describe('useImportList', () => { let httpMock: ReturnType; diff --git a/x-pack/plugins/lists/public/lists/hooks/use_read_list_index.test.ts b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_read_list_index.test.ts similarity index 91% rename from x-pack/plugins/lists/public/lists/hooks/use_read_list_index.test.ts rename to x-pack/solutions/security/plugins/lists/public/lists/hooks/use_read_list_index.test.ts index 643ac2df5b05b..cd36b6d531061 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_read_list_index.test.ts +++ b/x-pack/solutions/security/plugins/lists/public/lists/hooks/use_read_list_index.test.ts @@ -17,7 +17,7 @@ jest.mock('@kbn/securitysolution-list-api'); const { wrapper: queryWrapper } = createQueryWrapperMock(); -// TODO: Port this code over to the package: packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.test.ts once kibana has mocks in packages +// TODO: Port this code over to the package: x-pack/solutions/security/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.test.ts once kibana has mocks in packages // FLAKY: https://github.com/elastic/kibana/issues/178026 describe.skip('useReadListIndex', () => { diff --git a/x-pack/plugins/lists/public/lists/mocks/query_wrapper.tsx b/x-pack/solutions/security/plugins/lists/public/lists/mocks/query_wrapper.tsx similarity index 100% rename from x-pack/plugins/lists/public/lists/mocks/query_wrapper.tsx rename to x-pack/solutions/security/plugins/lists/public/lists/mocks/query_wrapper.tsx diff --git a/x-pack/plugins/lists/public/lists/types.ts b/x-pack/solutions/security/plugins/lists/public/lists/types.ts similarity index 100% rename from x-pack/plugins/lists/public/lists/types.ts rename to x-pack/solutions/security/plugins/lists/public/lists/types.ts diff --git a/x-pack/plugins/lists/public/plugin.ts b/x-pack/solutions/security/plugins/lists/public/plugin.ts similarity index 100% rename from x-pack/plugins/lists/public/plugin.ts rename to x-pack/solutions/security/plugins/lists/public/plugin.ts diff --git a/x-pack/plugins/lists/public/shared_exports.ts b/x-pack/solutions/security/plugins/lists/public/shared_exports.ts similarity index 100% rename from x-pack/plugins/lists/public/shared_exports.ts rename to x-pack/solutions/security/plugins/lists/public/shared_exports.ts diff --git a/x-pack/plugins/lists/public/types.ts b/x-pack/solutions/security/plugins/lists/public/types.ts similarity index 100% rename from x-pack/plugins/lists/public/types.ts rename to x-pack/solutions/security/plugins/lists/public/types.ts diff --git a/x-pack/plugins/lists/scripts/storybook.js b/x-pack/solutions/security/plugins/lists/scripts/storybook.js similarity index 100% rename from x-pack/plugins/lists/scripts/storybook.js rename to x-pack/solutions/security/plugins/lists/scripts/storybook.js diff --git a/x-pack/plugins/lists/server/config.mock.ts b/x-pack/solutions/security/plugins/lists/server/config.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/config.mock.ts rename to x-pack/solutions/security/plugins/lists/server/config.mock.ts diff --git a/x-pack/plugins/lists/server/config.test.ts b/x-pack/solutions/security/plugins/lists/server/config.test.ts similarity index 100% rename from x-pack/plugins/lists/server/config.test.ts rename to x-pack/solutions/security/plugins/lists/server/config.test.ts diff --git a/x-pack/plugins/lists/server/config.ts b/x-pack/solutions/security/plugins/lists/server/config.ts similarity index 100% rename from x-pack/plugins/lists/server/config.ts rename to x-pack/solutions/security/plugins/lists/server/config.ts diff --git a/x-pack/plugins/lists/server/error_with_status_code.ts b/x-pack/solutions/security/plugins/lists/server/error_with_status_code.ts similarity index 100% rename from x-pack/plugins/lists/server/error_with_status_code.ts rename to x-pack/solutions/security/plugins/lists/server/error_with_status_code.ts diff --git a/x-pack/plugins/lists/server/get_space_id.test.ts b/x-pack/solutions/security/plugins/lists/server/get_space_id.test.ts similarity index 100% rename from x-pack/plugins/lists/server/get_space_id.test.ts rename to x-pack/solutions/security/plugins/lists/server/get_space_id.test.ts diff --git a/x-pack/plugins/lists/server/get_space_id.ts b/x-pack/solutions/security/plugins/lists/server/get_space_id.ts similarity index 100% rename from x-pack/plugins/lists/server/get_space_id.ts rename to x-pack/solutions/security/plugins/lists/server/get_space_id.ts diff --git a/x-pack/plugins/lists/server/get_user.test.ts b/x-pack/solutions/security/plugins/lists/server/get_user.test.ts similarity index 100% rename from x-pack/plugins/lists/server/get_user.test.ts rename to x-pack/solutions/security/plugins/lists/server/get_user.test.ts diff --git a/x-pack/plugins/lists/server/get_user.ts b/x-pack/solutions/security/plugins/lists/server/get_user.ts similarity index 100% rename from x-pack/plugins/lists/server/get_user.ts rename to x-pack/solutions/security/plugins/lists/server/get_user.ts diff --git a/x-pack/plugins/lists/server/handlers/create_exception_list_handler.ts b/x-pack/solutions/security/plugins/lists/server/handlers/create_exception_list_handler.ts similarity index 100% rename from x-pack/plugins/lists/server/handlers/create_exception_list_handler.ts rename to x-pack/solutions/security/plugins/lists/server/handlers/create_exception_list_handler.ts diff --git a/x-pack/plugins/lists/server/index.ts b/x-pack/solutions/security/plugins/lists/server/index.ts similarity index 100% rename from x-pack/plugins/lists/server/index.ts rename to x-pack/solutions/security/plugins/lists/server/index.ts diff --git a/x-pack/plugins/lists/server/mocks.ts b/x-pack/solutions/security/plugins/lists/server/mocks.ts similarity index 100% rename from x-pack/plugins/lists/server/mocks.ts rename to x-pack/solutions/security/plugins/lists/server/mocks.ts diff --git a/x-pack/plugins/lists/server/plugin.ts b/x-pack/solutions/security/plugins/lists/server/plugin.ts similarity index 100% rename from x-pack/plugins/lists/server/plugin.ts rename to x-pack/solutions/security/plugins/lists/server/plugin.ts diff --git a/x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/create_endpoint_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/create_endpoint_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/create_endpoint_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/create_endpoint_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/create_exception_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/create_exception_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/create_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/create_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/create_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/create_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/delete_endpoint_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/delete_endpoint_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/delete_exception_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/delete_exception_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/delete_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/delete_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/delete_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/delete_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/duplicate_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/duplicate_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/duplicate_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/duplicate_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/endpoint_disallowed_fields.ts b/x-pack/solutions/security/plugins/lists/server/routes/endpoint_disallowed_fields.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/endpoint_disallowed_fields.ts rename to x-pack/solutions/security/plugins/lists/server/routes/endpoint_disallowed_fields.ts diff --git a/x-pack/plugins/lists/server/routes/export_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/export_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/export_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/export_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/find_endpoint_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/find_endpoint_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/find_exception_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/find_exception_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/find_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/find_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/find_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/find_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/import_exceptions_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/import_exceptions_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/import_exceptions_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/import_exceptions_route.ts diff --git a/x-pack/plugins/lists/server/routes/index.ts b/x-pack/solutions/security/plugins/lists/server/routes/index.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/index.ts rename to x-pack/solutions/security/plugins/lists/server/routes/index.ts diff --git a/x-pack/plugins/lists/server/routes/init_routes.ts b/x-pack/solutions/security/plugins/lists/server/routes/init_routes.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/init_routes.ts rename to x-pack/solutions/security/plugins/lists/server/routes/init_routes.ts diff --git a/x-pack/plugins/lists/server/routes/internal/create_exception_filter_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/internal/create_exception_filter_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/internal/create_exception_filter_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/internal/create_exception_filter_route.ts diff --git a/x-pack/plugins/lists/server/routes/internal/create_exceptions_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/internal/create_exceptions_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/internal/create_exceptions_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/internal/create_exceptions_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/internal/find_lists_by_size_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/internal/find_lists_by_size_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/internal/find_lists_by_size_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/internal/find_lists_by_size_route.ts diff --git a/x-pack/plugins/lists/server/routes/list/create_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list/create_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list/create_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list/create_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/list/delete_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list/delete_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list/delete_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list/delete_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/list/import_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list/import_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list/import_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list/import_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list/patch_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list/patch_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list/patch_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list/patch_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/list/read_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list/read_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list/read_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list/read_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/list/update_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list/update_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list/update_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list/update_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_index/create_list_index_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_index/create_list_index_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_index/delete_list_index_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_index/delete_list_index_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_index/export_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_index/export_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_index/find_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_index/find_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_index/find_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_index/find_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_index/read_list_index_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_index/read_list_index_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_item/create_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_item/create_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_item/delete_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_item/delete_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_item/find_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_item/find_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_item/patch_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_item/patch_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_item/read_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_item/read_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_item/update_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_item/update_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/list_privileges/read_list_privileges_route.mock.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_privileges/read_list_privileges_route.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_privileges/read_list_privileges_route.mock.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_privileges/read_list_privileges_route.mock.ts diff --git a/x-pack/plugins/lists/server/routes/list_privileges/read_list_privileges_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/list_privileges/read_list_privileges_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/list_privileges/read_list_privileges_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/list_privileges/read_list_privileges_route.ts diff --git a/x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/read_endpoint_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/read_endpoint_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/read_exception_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/read_exception_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/read_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/read_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/read_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/read_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/summary_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/summary_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/summary_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/summary_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/update_endpoint_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/update_endpoint_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/update_exception_list_item_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/update_exception_list_item_route.ts diff --git a/x-pack/plugins/lists/server/routes/update_exception_list_route.ts b/x-pack/solutions/security/plugins/lists/server/routes/update_exception_list_route.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/update_exception_list_route.ts rename to x-pack/solutions/security/plugins/lists/server/routes/update_exception_list_route.ts diff --git a/x-pack/plugins/lists/server/routes/utils/build_siem_response.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/build_siem_response.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/build_siem_response.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/build_siem_response.ts diff --git a/x-pack/plugins/lists/server/routes/utils/create_stream_from_buffer.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/create_stream_from_buffer.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/create_stream_from_buffer.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/create_stream_from_buffer.ts diff --git a/x-pack/plugins/lists/server/routes/utils/get_error_message_exception_list.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/get_error_message_exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/get_error_message_exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/get_error_message_exception_list.ts diff --git a/x-pack/plugins/lists/server/routes/utils/get_error_message_exception_list_item.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/get_error_message_exception_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/get_error_message_exception_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/get_error_message_exception_list_item.ts diff --git a/x-pack/plugins/lists/server/routes/utils/get_exception_list_client.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/get_exception_list_client.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/get_exception_list_client.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/get_exception_list_client.ts diff --git a/x-pack/plugins/lists/server/routes/utils/get_internal_list_client.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/get_internal_list_client.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/get_internal_list_client.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/get_internal_list_client.ts diff --git a/x-pack/plugins/lists/server/routes/utils/get_list_client.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/get_list_client.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/get_list_client.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/get_list_client.ts diff --git a/x-pack/plugins/lists/server/routes/utils/index.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/index.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/index.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/index.ts diff --git a/x-pack/plugins/lists/server/routes/utils/route_validation.test.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/route_validation.test.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/route_validation.test.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/route_validation.test.ts diff --git a/x-pack/plugins/lists/server/routes/utils/route_validation.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/route_validation.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/route_validation.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/route_validation.ts diff --git a/x-pack/plugins/lists/server/routes/utils/validate_comments_to_update.test.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/validate_comments_to_update.test.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/validate_comments_to_update.test.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/validate_comments_to_update.test.ts diff --git a/x-pack/plugins/lists/server/routes/utils/validate_comments_to_update.ts b/x-pack/solutions/security/plugins/lists/server/routes/utils/validate_comments_to_update.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/utils/validate_comments_to_update.ts rename to x-pack/solutions/security/plugins/lists/server/routes/utils/validate_comments_to_update.ts diff --git a/x-pack/plugins/lists/server/routes/validate.ts b/x-pack/solutions/security/plugins/lists/server/routes/validate.ts similarity index 100% rename from x-pack/plugins/lists/server/routes/validate.ts rename to x-pack/solutions/security/plugins/lists/server/routes/validate.ts diff --git a/x-pack/plugins/lists/server/saved_objects/exception_list.ts b/x-pack/solutions/security/plugins/lists/server/saved_objects/exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/saved_objects/exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/saved_objects/exception_list.ts diff --git a/x-pack/plugins/lists/server/saved_objects/index.ts b/x-pack/solutions/security/plugins/lists/server/saved_objects/index.ts similarity index 100% rename from x-pack/plugins/lists/server/saved_objects/index.ts rename to x-pack/solutions/security/plugins/lists/server/saved_objects/index.ts diff --git a/x-pack/plugins/lists/server/saved_objects/init_saved_objects.ts b/x-pack/solutions/security/plugins/lists/server/saved_objects/init_saved_objects.ts similarity index 100% rename from x-pack/plugins/lists/server/saved_objects/init_saved_objects.ts rename to x-pack/solutions/security/plugins/lists/server/saved_objects/init_saved_objects.ts diff --git a/x-pack/plugins/lists/server/saved_objects/migrations.test.ts b/x-pack/solutions/security/plugins/lists/server/saved_objects/migrations.test.ts similarity index 100% rename from x-pack/plugins/lists/server/saved_objects/migrations.test.ts rename to x-pack/solutions/security/plugins/lists/server/saved_objects/migrations.test.ts diff --git a/x-pack/plugins/lists/server/saved_objects/migrations.ts b/x-pack/solutions/security/plugins/lists/server/saved_objects/migrations.ts similarity index 100% rename from x-pack/plugins/lists/server/saved_objects/migrations.ts rename to x-pack/solutions/security/plugins/lists/server/saved_objects/migrations.ts diff --git a/x-pack/plugins/lists/server/schemas/common/get_shard.mock.ts b/x-pack/solutions/security/plugins/lists/server/schemas/common/get_shard.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/common/get_shard.mock.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/common/get_shard.mock.ts diff --git a/x-pack/plugins/lists/server/schemas/common/schemas.test.ts b/x-pack/solutions/security/plugins/lists/server/schemas/common/schemas.test.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/common/schemas.test.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/common/schemas.test.ts diff --git a/x-pack/plugins/lists/server/schemas/common/schemas.ts b/x-pack/solutions/security/plugins/lists/server/schemas/common/schemas.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/common/schemas.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/common/schemas.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/create_es_bulk_type.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/create_es_bulk_type.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/create_es_bulk_type.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/create_es_bulk_type.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/index.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/index.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_item_schema.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_schema.mock.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_schema.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/index_es_list_schema.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/index_es_list_schema.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/update_es_list_item_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/update_es_list_item_schema.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/update_es_list_item_schema.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/update_es_list_item_schema.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_query/update_es_list_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/update_es_list_schema.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_query/update_es_list_schema.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_query/update_es_list_schema.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/index.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/index.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_response/index.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/index.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.test.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.test.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.test.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.test.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.test.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.test.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.test.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.test.ts diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts diff --git a/x-pack/plugins/lists/server/schemas/saved_objects/exceptions_list_so_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/saved_objects/exceptions_list_so_schema.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/saved_objects/exceptions_list_so_schema.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/saved_objects/exceptions_list_so_schema.ts diff --git a/x-pack/plugins/lists/server/schemas/saved_objects/index.ts b/x-pack/solutions/security/plugins/lists/server/schemas/saved_objects/index.ts similarity index 100% rename from x-pack/plugins/lists/server/schemas/saved_objects/index.ts rename to x-pack/solutions/security/plugins/lists/server/schemas/saved_objects/index.ts diff --git a/x-pack/plugins/lists/server/scripts/check_env_variables.sh b/x-pack/solutions/security/plugins/lists/server/scripts/check_env_variables.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/check_env_variables.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/check_env_variables.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_all_exception_lists.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_all_exception_lists.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_all_exception_lists.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_all_exception_lists.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_endpoint_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_endpoint_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_endpoint_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_endpoint_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_endpoint_list_item_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_endpoint_list_item_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_endpoint_list_item_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_endpoint_list_item_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_exception_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_exception_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_exception_list_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_exception_list_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_exception_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_exception_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_exception_list_item_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list_item_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_exception_list_item_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_exception_list_item_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_list.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_list_index.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_list_index.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_list_index.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_list_index.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_list_item_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_list_item_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_list_item_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_list_item_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/delete_list_item_by_value.sh b/x-pack/solutions/security/plugins/lists/server/scripts/delete_list_item_by_value.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/delete_list_item_by_value.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/delete_list_item_by_value.sh diff --git a/x-pack/plugins/lists/server/scripts/download_load_lists_example.sh b/x-pack/solutions/security/plugins/lists/server/scripts/download_load_lists_example.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/download_load_lists_example.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/download_load_lists_example.sh diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/files/import.ndjson b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/files/import.ndjson similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/files/import.ndjson rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/files/import.ndjson diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/endpoint_list_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/endpoint_list_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/endpoint_list_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/endpoint_list_item.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_agnostic.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_agnostic.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_agnostic.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_agnostic.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_auto_id.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_auto_id.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_auto_id.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_auto_id.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_agnostic.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_agnostic.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_agnostic.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_agnostic.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_bad_ip_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_bad_ip_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_bad_ip_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_bad_ip_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/exception_list_item_with_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_1.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_1.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_1.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_1.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_2_agnostic.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_2_agnostic.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_2_agnostic.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_2_agnostic.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_3.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_3.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_3.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_detection_3.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_multi_value_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_multi_value_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_multi_value_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_multi_value_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_non_value_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_non_value_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_non_value_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_1_non_value_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_multi_value_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_multi_value_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_multi_value_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_multi_value_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_non_value_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_non_value_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_non_value_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_2_non_value_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_non_value_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_non_value_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_non_value_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_non_value_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_single_value_list.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_single_value_list.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_single_value_list.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/references/exception_list_item_3_single_value_list.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/trusted_app_list_item_agnostic.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/trusted_app_list_item_agnostic.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/new/trusted_app_list_item_agnostic.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/new/trusted_app_list_item_agnostic.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/updates/simple_update.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/updates/simple_update.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_agnostic.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/updates/simple_update_agnostic.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_agnostic.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/updates/simple_update_agnostic.json diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json diff --git a/x-pack/plugins/lists/server/scripts/export_list_items.sh b/x-pack/solutions/security/plugins/lists/server/scripts/export_list_items.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/export_list_items.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/export_list_items.sh diff --git a/x-pack/plugins/lists/server/scripts/export_list_items_to_file.sh b/x-pack/solutions/security/plugins/lists/server/scripts/export_list_items_to_file.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/export_list_items_to_file.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/export_list_items_to_file.sh diff --git a/x-pack/plugins/lists/server/scripts/find_endpoint_list_items.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_endpoint_list_items.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_endpoint_list_items.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_endpoint_list_items.sh diff --git a/x-pack/plugins/lists/server/scripts/find_exception_list_items.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_exception_list_items.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_exception_list_items.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_exception_list_items.sh diff --git a/x-pack/plugins/lists/server/scripts/find_exception_list_items_by_filter.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_exception_list_items_by_filter.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_exception_list_items_by_filter.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_exception_list_items_by_filter.sh diff --git a/x-pack/plugins/lists/server/scripts/find_exception_lists.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_exception_lists.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_exception_lists.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_exception_lists.sh diff --git a/x-pack/plugins/lists/server/scripts/find_exception_lists_by_filter.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_exception_lists_by_filter.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_exception_lists_by_filter.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_exception_lists_by_filter.sh diff --git a/x-pack/plugins/lists/server/scripts/find_list_items.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_list_items.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_list_items.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_list_items.sh diff --git a/x-pack/plugins/lists/server/scripts/find_list_items_with_cursor.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_list_items_with_cursor.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_list_items_with_cursor.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_list_items_with_cursor.sh diff --git a/x-pack/plugins/lists/server/scripts/find_list_items_with_sort.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_list_items_with_sort.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_list_items_with_sort.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_list_items_with_sort.sh diff --git a/x-pack/plugins/lists/server/scripts/find_list_items_with_sort_cursor.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_list_items_with_sort_cursor.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_list_items_with_sort_cursor.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_list_items_with_sort_cursor.sh diff --git a/x-pack/plugins/lists/server/scripts/find_lists.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_lists.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_lists.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_lists.sh diff --git a/x-pack/plugins/lists/server/scripts/find_lists_with_cursor.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_cursor.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_lists_with_cursor.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_cursor.sh diff --git a/x-pack/plugins/lists/server/scripts/find_lists_with_filter.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_filter.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_lists_with_filter.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_filter.sh diff --git a/x-pack/plugins/lists/server/scripts/find_lists_with_sort.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_sort.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_lists_with_sort.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_sort.sh diff --git a/x-pack/plugins/lists/server/scripts/find_lists_with_sort_cursor.sh b/x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_sort_cursor.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/find_lists_with_sort_cursor.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/find_lists_with_sort_cursor.sh diff --git a/x-pack/plugins/lists/server/scripts/get_endpoint_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_endpoint_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_endpoint_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_endpoint_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/get_endpoint_list_item_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_endpoint_list_item_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_endpoint_list_item_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_endpoint_list_item_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/get_exception_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_exception_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list.sh diff --git a/x-pack/plugins/lists/server/scripts/get_exception_list_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_exception_list_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/get_exception_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_exception_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/get_exception_list_item_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list_item_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_exception_list_item_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_exception_list_item_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/get_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_list.sh diff --git a/x-pack/plugins/lists/server/scripts/get_list_item_by_id.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_list_item_by_id.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_list_item_by_id.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_list_item_by_id.sh diff --git a/x-pack/plugins/lists/server/scripts/get_list_item_by_value.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_list_item_by_value.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_list_item_by_value.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_list_item_by_value.sh diff --git a/x-pack/plugins/lists/server/scripts/get_privileges.sh b/x-pack/solutions/security/plugins/lists/server/scripts/get_privileges.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/get_privileges.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/get_privileges.sh diff --git a/x-pack/plugins/lists/server/scripts/hard_reset.sh b/x-pack/solutions/security/plugins/lists/server/scripts/hard_reset.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/hard_reset.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/hard_reset.sh diff --git a/x-pack/plugins/lists/server/scripts/import_exception_lists.sh b/x-pack/solutions/security/plugins/lists/server/scripts/import_exception_lists.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/import_exception_lists.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/import_exception_lists.sh diff --git a/x-pack/plugins/lists/server/scripts/import_list_items.sh b/x-pack/solutions/security/plugins/lists/server/scripts/import_list_items.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/import_list_items.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/import_list_items.sh diff --git a/x-pack/plugins/lists/server/scripts/import_list_items_by_filename.sh b/x-pack/solutions/security/plugins/lists/server/scripts/import_list_items_by_filename.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/import_list_items_by_filename.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/import_list_items_by_filename.sh diff --git a/x-pack/plugins/lists/server/scripts/lists/files/binary.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/binary.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/binary.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/binary.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/boolean.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/boolean.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/boolean.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/boolean.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/byte.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/byte.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/byte.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/byte.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/date.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/date.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/date_nanos.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date_nanos.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/date_nanos.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date_nanos.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/date_range.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date_range.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/date_range.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date_range.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/date_range_custom_format.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date_range_custom_format.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/date_range_custom_format.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/date_range_custom_format.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/double.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/double.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/double.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/double.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/double_range.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/double_range.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/double_range.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/double_range.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/float.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/float.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/float.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/float.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/float_range.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/float_range.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/float_range.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/float_range.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/geo_hash.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/geo_hash.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/geo_hash.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/geo_hash.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/geo_point.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/geo_point.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/geo_point.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/geo_point.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/geo_point_wkt.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/geo_point_wkt.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/geo_point_wkt.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/geo_point_wkt.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/half_float.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/half_float.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/half_float.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/half_float.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/hosts.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/hosts.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/hosts.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/hosts.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/integer.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/integer.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/integer.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/integer.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/integer_range.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/integer_range.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/integer_range.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/integer_range.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/ip_range.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ip_range.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/ip_range.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ip_range.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/ip_range_cidr.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ip_range_cidr.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/ip_range_cidr.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ip_range_cidr.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/ip_range_mixed.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ip_range_mixed.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/ip_range_mixed.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ip_range_mixed.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/ips.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ips.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/ips.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/ips.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/long.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/long.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/long.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/long.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/long_range.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/long_range.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/long_range.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/long_range.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/short.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/short.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/short.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/short.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/files/text.txt b/x-pack/solutions/security/plugins/lists/server/scripts/lists/files/text.txt similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/files/text.txt rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/files/text.txt diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/binary_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/binary_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/binary_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/binary_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/boolean_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/boolean_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/boolean_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/boolean_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/byte_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/byte_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/byte_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/byte_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/date_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/date_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/date_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/date_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/date_nanos_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/date_nanos_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/date_nanos_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/date_nanos_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/date_range_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/date_range_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/date_range_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/date_range_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/double_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/double_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/double_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/double_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/double_range_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/double_range_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/double_range_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/double_range_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/float_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/float_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/float_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/float_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/float_range_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/float_range_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/float_range_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/float_range_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/geo_point_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/geo_point_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/geo_point_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/geo_point_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/geo_shape_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/geo_shape_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/geo_shape_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/geo_shape_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/half_float_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/half_float_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/half_float_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/half_float_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/integer_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/integer_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/integer_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/integer_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/integer_range_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/integer_range_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/integer_range_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/integer_range_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/ip_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/ip_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/ip_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/ip_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/ip_item_everything.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/ip_item_everything.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/ip_item_everything.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/ip_item_everything.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/ip_range_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/ip_range_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/ip_range_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/ip_range_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/keyword_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/keyword_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/keyword_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/keyword_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/long_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/long_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/long_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/long_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/long_range_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/long_range_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/long_range_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/long_range_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/shape_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/shape_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/shape_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/shape_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/short_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/short_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/short_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/short_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/items/text_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/text_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/items/text_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/items/text_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/list_ip_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/list_ip_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/list_ip_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/list_ip_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/list_keyword_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/list_keyword_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/list_keyword_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/list_keyword_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/auto_id.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/auto_id.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/auto_id.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/auto_id.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/binary.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/binary.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/binary.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/binary.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/boolean.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/boolean.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/boolean.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/boolean.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/byte.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/byte.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/byte.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/byte.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/date.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/date.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/date_nanos.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date_nanos.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/date_nanos.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date_nanos.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/date_range.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date_range.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/date_range.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date_range.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/date_range_custom_format.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date_range_custom_format.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/date_range_custom_format.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/date_range_custom_format.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/double.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/double.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/double.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/double.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/double_range.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/double_range.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/double_range.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/double_range.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/everything.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/everything.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/everything.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/everything.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/float.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/float.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/float.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/float.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/float_range.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/float_range.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/float_range.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/float_range.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/geo_point.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/geo_point.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/geo_point.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/geo_point.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/geo_shape.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/geo_shape.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/geo_shape.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/geo_shape.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/half_float.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/half_float.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/half_float.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/half_float.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/integer.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/integer.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/integer.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/integer.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/integer_range.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/integer_range.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/integer_range.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/integer_range.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/ip.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/ip.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/ip_custom_format.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip_custom_format.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/ip_custom_format.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip_custom_format.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/ip_no_id.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip_no_id.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/ip_no_id.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip_no_id.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/ip_range.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip_range.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/ip_range.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/ip_range.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/keyword.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/keyword.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/keyword.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/keyword.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/keyword_custom_format.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/keyword_custom_format.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/keyword_custom_format.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/keyword_custom_format.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/long.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/long.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/long.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/long.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/shape.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/shape.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/shape.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/shape.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/short.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/short.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/short.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/short.json diff --git a/x-pack/plugins/lists/server/scripts/lists/new/lists/text.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/text.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/new/lists/text.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/new/lists/text.json diff --git a/x-pack/plugins/lists/server/scripts/lists/patches/ip_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/patches/ip_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/patches/ip_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/patches/ip_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/patches/simplest_updated_name.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/patches/simplest_updated_name.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/patches/simplest_updated_name.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/patches/simplest_updated_name.json diff --git a/x-pack/plugins/lists/server/scripts/lists/updates/ip_item.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/updates/ip_item.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/updates/ip_item.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/updates/ip_item.json diff --git a/x-pack/plugins/lists/server/scripts/lists/updates/simple_update.json b/x-pack/solutions/security/plugins/lists/server/scripts/lists/updates/simple_update.json similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists/updates/simple_update.json rename to x-pack/solutions/security/plugins/lists/server/scripts/lists/updates/simple_update.json diff --git a/x-pack/plugins/lists/server/scripts/lists_index_exists.sh b/x-pack/solutions/security/plugins/lists/server/scripts/lists_index_exists.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/lists_index_exists.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/lists_index_exists.sh diff --git a/x-pack/plugins/lists/server/scripts/patch_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/patch_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/patch_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/patch_list.sh diff --git a/x-pack/plugins/lists/server/scripts/patch_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/patch_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/patch_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/patch_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/post_endpoint_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_endpoint_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_endpoint_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_endpoint_list.sh diff --git a/x-pack/plugins/lists/server/scripts/post_endpoint_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_endpoint_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_endpoint_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_endpoint_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/post_exception_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_exception_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_exception_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_exception_list.sh diff --git a/x-pack/plugins/lists/server/scripts/post_exception_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_exception_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_exception_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_exception_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/post_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_list.sh diff --git a/x-pack/plugins/lists/server/scripts/post_list_index.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_list_index.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_list_index.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_list_index.sh diff --git a/x-pack/plugins/lists/server/scripts/post_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/post_x_exception_list_items.sh b/x-pack/solutions/security/plugins/lists/server/scripts/post_x_exception_list_items.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/post_x_exception_list_items.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/post_x_exception_list_items.sh diff --git a/x-pack/plugins/lists/server/scripts/quick_start.sh b/x-pack/solutions/security/plugins/lists/server/scripts/quick_start.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/quick_start.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/quick_start.sh diff --git a/x-pack/plugins/lists/server/scripts/quick_start_value_list_references.sh b/x-pack/solutions/security/plugins/lists/server/scripts/quick_start_value_list_references.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/quick_start_value_list_references.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/quick_start_value_list_references.sh diff --git a/x-pack/plugins/lists/server/scripts/summary_exception_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/summary_exception_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/summary_exception_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/summary_exception_list.sh diff --git a/x-pack/plugins/lists/server/scripts/update_endpoint_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/update_endpoint_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/update_endpoint_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/update_endpoint_item.sh diff --git a/x-pack/plugins/lists/server/scripts/update_exception_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/update_exception_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/update_exception_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/update_exception_list.sh diff --git a/x-pack/plugins/lists/server/scripts/update_exception_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/update_exception_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/update_exception_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/update_exception_list_item.sh diff --git a/x-pack/plugins/lists/server/scripts/update_list.sh b/x-pack/solutions/security/plugins/lists/server/scripts/update_list.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/update_list.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/update_list.sh diff --git a/x-pack/plugins/lists/server/scripts/update_list_item.sh b/x-pack/solutions/security/plugins/lists/server/scripts/update_list_item.sh similarity index 100% rename from x-pack/plugins/lists/server/scripts/update_list_item.sh rename to x-pack/solutions/security/plugins/lists/server/scripts/update_list_item.sh diff --git a/x-pack/plugins/lists/server/services/exception_lists/build_exception_filter.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/build_exception_filter.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/build_exception_filter.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/build_exception_filter.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/build_exception_filter.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/build_exception_filter.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/build_exception_filter.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/build_exception_filter.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/bulk_create_exception_list_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/bulk_create_exception_list_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/bulk_create_exception_list_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/bulk_create_exception_list_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/close_point_in_time.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/close_point_in_time.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/close_point_in_time.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/close_point_in_time.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/create_endpoint_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_endpoint_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/create_endpoint_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_endpoint_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/create_endpoint_trusted_apps_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_endpoint_trusted_apps_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/create_endpoint_trusted_apps_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_endpoint_trusted_apps_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/create_exception_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/create_exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_exception_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/create_exception_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_exception_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/create_exception_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_exception_list_item.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/delete_exception_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/delete_exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/delete_exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/delete_exception_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/delete_exception_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/delete_exception_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/delete_exception_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/delete_exception_list_item.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/delete_exception_list_items_by_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/delete_exception_list_items_by_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/delete_exception_list_items_by_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/delete_exception_list_items_by_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/duplicate_exception_list.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/duplicate_exception_list.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/duplicate_exception_list.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/duplicate_exception_list.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/duplicate_exception_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/duplicate_exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/duplicate_exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/duplicate_exception_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/exception_list_client.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client_types.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/exception_list_client_types.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/export_exception_list_and_items.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/export_exception_list_and_items.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/export_exception_list_and_items.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/export_exception_list_and_items.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/export_exception_list_and_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/export_exception_list_and_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/export_exception_list_and_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/export_exception_list_and_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_item.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item_point_in_time_finder.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_item_point_in_time_finder.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item_point_in_time_finder.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_item_point_in_time_finder.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items_point_in_time_finder.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_items_point_in_time_finder.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items_point_in_time_finder.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_items_point_in_time_finder.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_point_in_time_finder.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_point_in_time_finder.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_exception_list_point_in_time_finder.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_exception_list_point_in_time_finder.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items_point_in_time_finder.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items_point_in_time_finder.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items_point_in_time_finder.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/find_value_list_exception_list_items_point_in_time_finder.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/get_exception_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/get_exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/get_exception_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/get_exception_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list_item.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/get_exception_list_summary.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list_summary.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/get_exception_list_summary.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list_summary.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/get_exception_list_summary.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list_summary.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/get_exception_list_summary.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/get_exception_list_summary.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/import_exception_list_and_items.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/import_exception_list_and_items.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/import_exception_list_and_items.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/import_exception_list_and_items.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/import_exception_list_and_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/import_exception_list_and_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/import_exception_list_and_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/import_exception_list_and_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/index.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/index.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/index.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/open_point_in_time.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/open_point_in_time.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/open_point_in_time.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/open_point_in_time.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/update_exception_list.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/update_exception_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/update_exception_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/update_exception_list.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/update_exception_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/update_exception_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/update_exception_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/update_exception_list_item.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/update_overwrite_exception_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/update_overwrite_exception_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/update_overwrite_exception_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/update_overwrite_exception_list_item.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/errors.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/errors.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/errors.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/errors.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_list_filter.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/get_exception_lists_item_filter.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_create_imported_lists.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/bulk_update_imported_lists.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/dedupe_incoming_lists.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/delete_list_items_to_overwrite.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_item_types.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/find_all_exception_list_types.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/import_exception_list_items.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/import_exception_list_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/import_exception_list_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/import_exception_list_items.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/import_exception_lists.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/import_exception_lists.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/import_exception_lists.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/import_exception_lists.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/is_import_regular.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_or_update.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_or_update.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_or_update.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_or_update.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_update.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_update.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_update.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_items_to_create_update.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_or_update.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_or_update.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_or_update.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_or_update.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_update.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_update.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_update.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_update.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_by_namespace.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/import/sort_import_responses.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/index.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/index.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/index.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/index.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/index.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/index.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/index.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/validate_data.test.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/validate_data.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/validate_data.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/validate_data.test.ts diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/validate_data.ts b/x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/validate_data.ts similarity index 100% rename from x-pack/plugins/lists/server/services/exception_lists/utils/validate_data.ts rename to x-pack/solutions/security/plugins/lists/server/services/exception_lists/utils/validate_data.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/errors.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/errors.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/errors.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/errors.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/extension_point_storage.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/extension_point_storage.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage.mock.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/extension_point_storage.test.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/extension_point_storage.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage.test.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/extension_point_storage.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/extension_point_storage.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/extension_point_storage_client.test.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage_client.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/extension_point_storage_client.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage_client.test.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/extension_point_storage_client.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage_client.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/extension_point_storage_client.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/extension_point_storage_client.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/index.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/index.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/index.ts diff --git a/x-pack/plugins/lists/server/services/extension_points/types.ts b/x-pack/solutions/security/plugins/lists/server/services/extension_points/types.ts similarity index 100% rename from x-pack/plugins/lists/server/services/extension_points/types.ts rename to x-pack/solutions/security/plugins/lists/server/services/extension_points/types.ts diff --git a/x-pack/plugins/lists/server/services/items/buffer_lines.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/buffer_lines.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/buffer_lines.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/buffer_lines.test.ts diff --git a/x-pack/plugins/lists/server/services/items/buffer_lines.ts b/x-pack/solutions/security/plugins/lists/server/services/items/buffer_lines.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/buffer_lines.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/buffer_lines.ts diff --git a/x-pack/plugins/lists/server/services/items/create_list_item.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/create_list_item.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/create_list_item.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/create_list_item.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/create_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/create_list_item.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/create_list_item.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/create_list_item.test.ts diff --git a/x-pack/plugins/lists/server/services/items/create_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/items/create_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/create_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/create_list_item.ts diff --git a/x-pack/plugins/lists/server/services/items/create_list_items_bulk.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/create_list_items_bulk.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/create_list_items_bulk.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/create_list_items_bulk.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/create_list_items_bulk.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/create_list_items_bulk.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/create_list_items_bulk.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/create_list_items_bulk.test.ts diff --git a/x-pack/plugins/lists/server/services/items/create_list_items_bulk.ts b/x-pack/solutions/security/plugins/lists/server/services/items/create_list_items_bulk.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/create_list_items_bulk.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/create_list_items_bulk.ts diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/delete_list_item.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/delete_list_item.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item.test.ts diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/delete_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item.ts diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item_by_value.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item_by_value.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/delete_list_item_by_value.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item_by_value.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item_by_value.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item_by_value.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/delete_list_item_by_value.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item_by_value.test.ts diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item_by_value.ts b/x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item_by_value.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/delete_list_item_by_value.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/delete_list_item_by_value.ts diff --git a/x-pack/plugins/lists/server/services/items/find_all_list_items.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/find_all_list_items.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/find_all_list_items.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/find_all_list_items.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/find_all_list_items.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/find_all_list_items.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/find_all_list_items.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/find_all_list_items.test.ts diff --git a/x-pack/plugins/lists/server/services/items/find_all_list_items.ts b/x-pack/solutions/security/plugins/lists/server/services/items/find_all_list_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/find_all_list_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/find_all_list_items.ts diff --git a/x-pack/plugins/lists/server/services/items/find_list_item.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/find_list_item.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/find_list_item.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/find_list_item.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/find_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/find_list_item.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/find_list_item.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/find_list_item.test.ts diff --git a/x-pack/plugins/lists/server/services/items/find_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/items/find_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/find_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/find_list_item.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item.test.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_value.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_value.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_by_value.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_value.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_value.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_value.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_by_value.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_value.test.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_value.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_value.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_by_value.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_value.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_values.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_values.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_by_values.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_values.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_values.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_values.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_by_values.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_values.test.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_values.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_values.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_by_values.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_by_values.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_index.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_index.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_index.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_index.test.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_index.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_index.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_index.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_template.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_template.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_template.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_template.test.ts diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_template.ts b/x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_template.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/get_list_item_template.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/get_list_item_template.ts diff --git a/x-pack/plugins/lists/server/services/items/index.ts b/x-pack/solutions/security/plugins/lists/server/services/items/index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/index.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/index.ts diff --git a/x-pack/plugins/lists/server/services/items/list_item_mappings.json b/x-pack/solutions/security/plugins/lists/server/services/items/list_item_mappings.json similarity index 100% rename from x-pack/plugins/lists/server/services/items/list_item_mappings.json rename to x-pack/solutions/security/plugins/lists/server/services/items/list_item_mappings.json diff --git a/x-pack/plugins/lists/server/services/items/list_item_policy.json b/x-pack/solutions/security/plugins/lists/server/services/items/list_item_policy.json similarity index 100% rename from x-pack/plugins/lists/server/services/items/list_item_policy.json rename to x-pack/solutions/security/plugins/lists/server/services/items/list_item_policy.json diff --git a/x-pack/plugins/lists/server/services/items/search_list_item_by_values.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/search_list_item_by_values.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/search_list_item_by_values.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/search_list_item_by_values.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/search_list_item_by_values.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/search_list_item_by_values.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/search_list_item_by_values.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/search_list_item_by_values.test.ts diff --git a/x-pack/plugins/lists/server/services/items/search_list_item_by_values.ts b/x-pack/solutions/security/plugins/lists/server/services/items/search_list_item_by_values.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/search_list_item_by_values.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/search_list_item_by_values.ts diff --git a/x-pack/plugins/lists/server/services/items/test_readable.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/test_readable.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/test_readable.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/test_readable.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/update_list_item.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/update_list_item.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/update_list_item.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/update_list_item.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/update_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/update_list_item.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/update_list_item.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/update_list_item.test.ts diff --git a/x-pack/plugins/lists/server/services/items/update_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/items/update_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/update_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/update_list_item.ts diff --git a/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/write_lines_to_bulk_list_items.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/write_lines_to_bulk_list_items.test.ts diff --git a/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts b/x-pack/solutions/security/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts diff --git a/x-pack/plugins/lists/server/services/items/write_list_items_to_stream.test.ts b/x-pack/solutions/security/plugins/lists/server/services/items/write_list_items_to_stream.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/write_list_items_to_stream.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/write_list_items_to_stream.test.ts diff --git a/x-pack/plugins/lists/server/services/items/write_list_items_to_stream.ts b/x-pack/solutions/security/plugins/lists/server/services/items/write_list_items_to_stream.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/write_list_items_to_stream.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/write_list_items_to_stream.ts diff --git a/x-pack/plugins/lists/server/services/items/write_list_items_to_streams.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/items/write_list_items_to_streams.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/items/write_list_items_to_streams.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/items/write_list_items_to_streams.mock.ts diff --git a/x-pack/plugins/lists/server/services/lists/create_list.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/create_list.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/create_list.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/create_list.mock.ts diff --git a/x-pack/plugins/lists/server/services/lists/create_list.test.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/create_list.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/create_list.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/create_list.test.ts diff --git a/x-pack/plugins/lists/server/services/lists/create_list.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/create_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/create_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/create_list.ts diff --git a/x-pack/plugins/lists/server/services/lists/create_list_if_it_does_not_exist.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/create_list_if_it_does_not_exist.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/create_list_if_it_does_not_exist.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/create_list_if_it_does_not_exist.ts diff --git a/x-pack/plugins/lists/server/services/lists/delete_list.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/delete_list.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/delete_list.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/delete_list.mock.ts diff --git a/x-pack/plugins/lists/server/services/lists/delete_list.test.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/delete_list.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/delete_list.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/delete_list.test.ts diff --git a/x-pack/plugins/lists/server/services/lists/delete_list.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/delete_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/delete_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/delete_list.ts diff --git a/x-pack/plugins/lists/server/services/lists/find_list.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/find_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/find_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/find_list.ts diff --git a/x-pack/plugins/lists/server/services/lists/get_list.test.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/get_list.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/get_list.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/get_list.test.ts diff --git a/x-pack/plugins/lists/server/services/lists/get_list.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/get_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/get_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/get_list.ts diff --git a/x-pack/plugins/lists/server/services/lists/get_list_index.test.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/get_list_index.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/get_list_index.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/get_list_index.test.ts diff --git a/x-pack/plugins/lists/server/services/lists/get_list_index.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/get_list_index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/get_list_index.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/get_list_index.ts diff --git a/x-pack/plugins/lists/server/services/lists/get_list_template.test.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/get_list_template.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/get_list_template.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/get_list_template.test.ts diff --git a/x-pack/plugins/lists/server/services/lists/get_list_template.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/get_list_template.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/get_list_template.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/get_list_template.ts diff --git a/x-pack/plugins/lists/server/services/lists/index.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/index.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/index.ts diff --git a/x-pack/plugins/lists/server/services/lists/list_client.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/list_client.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/list_client.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/list_client.mock.ts diff --git a/x-pack/plugins/lists/server/services/lists/list_client.test.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/list_client.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/list_client.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/list_client.test.ts diff --git a/x-pack/plugins/lists/server/services/lists/list_client.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/list_client.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/list_client.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/list_client.ts diff --git a/x-pack/plugins/lists/server/services/lists/list_client_types.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/list_client_types.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/list_client_types.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/list_client_types.ts diff --git a/x-pack/plugins/lists/server/services/lists/list_mappings.json b/x-pack/solutions/security/plugins/lists/server/services/lists/list_mappings.json similarity index 100% rename from x-pack/plugins/lists/server/services/lists/list_mappings.json rename to x-pack/solutions/security/plugins/lists/server/services/lists/list_mappings.json diff --git a/x-pack/plugins/lists/server/services/lists/list_policy.json b/x-pack/solutions/security/plugins/lists/server/services/lists/list_policy.json similarity index 100% rename from x-pack/plugins/lists/server/services/lists/list_policy.json rename to x-pack/solutions/security/plugins/lists/server/services/lists/list_policy.json diff --git a/x-pack/plugins/lists/server/services/lists/types.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/types.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/types.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/types.ts diff --git a/x-pack/plugins/lists/server/services/lists/update_list.mock.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/update_list.mock.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/update_list.mock.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/update_list.mock.ts diff --git a/x-pack/plugins/lists/server/services/lists/update_list.test.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/update_list.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/update_list.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/update_list.test.ts diff --git a/x-pack/plugins/lists/server/services/lists/update_list.ts b/x-pack/solutions/security/plugins/lists/server/services/lists/update_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/lists/update_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/lists/update_list.ts diff --git a/x-pack/plugins/lists/server/services/utils/calculate_scroll_math.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/calculate_scroll_math.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/calculate_scroll_math.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/calculate_scroll_math.ts diff --git a/x-pack/plugins/lists/server/services/utils/check_version_conflict.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/check_version_conflict.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/check_version_conflict.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/check_version_conflict.ts diff --git a/x-pack/plugins/lists/server/services/utils/encode_decode_cursor.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/encode_decode_cursor.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/encode_decode_cursor.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/encode_decode_cursor.ts diff --git a/x-pack/plugins/lists/server/services/utils/escape_query.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/escape_query.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/escape_query.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/escape_query.ts diff --git a/x-pack/plugins/lists/server/services/utils/find_source_type.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_type.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/find_source_type.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/find_source_type.test.ts diff --git a/x-pack/plugins/lists/server/services/utils/find_source_type.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_type.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/find_source_type.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/find_source_type.ts diff --git a/x-pack/plugins/lists/server/services/utils/find_source_value.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/find_source_value.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.test.ts diff --git a/x-pack/plugins/lists/server/services/utils/find_source_value.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/find_source_value.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_query_filter.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_query_filter.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter.test.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_query_filter.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_query_filter.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter_from_type_value.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter_from_type_value.test.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_search_after_scroll.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_search_after_scroll.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_search_after_scroll.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_search_after_scroll.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts diff --git a/x-pack/plugins/lists/server/services/utils/get_source_with_tie_breaker.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/get_source_with_tie_breaker.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/get_source_with_tie_breaker.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/get_source_with_tie_breaker.ts diff --git a/x-pack/plugins/lists/server/services/utils/index.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/index.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/index.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/index.ts diff --git a/x-pack/plugins/lists/server/services/utils/scroll_to_start_page.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/scroll_to_start_page.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/scroll_to_start_page.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/scroll_to_start_page.ts diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.test.ts diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/transform_elastic_to_list.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.ts diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts diff --git a/x-pack/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.test.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.test.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.test.ts diff --git a/x-pack/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/transform_list_item_to_elastic_query.ts diff --git a/x-pack/plugins/lists/server/services/utils/wait_until_document_indexed.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/wait_until_document_indexed.ts similarity index 100% rename from x-pack/plugins/lists/server/services/utils/wait_until_document_indexed.ts rename to x-pack/solutions/security/plugins/lists/server/services/utils/wait_until_document_indexed.ts diff --git a/x-pack/plugins/lists/server/types.ts b/x-pack/solutions/security/plugins/lists/server/types.ts similarity index 100% rename from x-pack/plugins/lists/server/types.ts rename to x-pack/solutions/security/plugins/lists/server/types.ts diff --git a/x-pack/solutions/security/plugins/lists/tsconfig.json b/x-pack/solutions/security/plugins/lists/tsconfig.json new file mode 100644 index 0000000000000..c0f751d665ee8 --- /dev/null +++ b/x-pack/solutions/security/plugins/lists/tsconfig.json @@ -0,0 +1,50 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + // have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636 + "server/**/*.json" + ], + "kbn_references": [ + "@kbn/core", + "@kbn/spaces-plugin", + "@kbn/security-plugin", + "@kbn/unified-search-plugin", + "@kbn/securitysolution-io-ts-list-types", + "@kbn/securitysolution-list-constants", + "@kbn/securitysolution-list-hooks", + "@kbn/securitysolution-list-api", + "@kbn/securitysolution-lists-common", + "@kbn/securitysolution-exceptions-common", + "@kbn/securitysolution-endpoint-exceptions-common", + "@kbn/kibana-react-plugin", + "@kbn/i18n", + "@kbn/data-plugin", + "@kbn/securitysolution-list-utils", + "@kbn/securitysolution-utils", + "@kbn/es-query", + "@kbn/i18n-react", + "@kbn/securitysolution-autocomplete", + "@kbn/config-schema", + "@kbn/securitysolution-io-ts-utils", + "@kbn/core-http-server", + "@kbn/securitysolution-es-utils", + "@kbn/securitysolution-io-ts-types", + "@kbn/std", + "@kbn/utils", + "@kbn/logging-mocks", + "@kbn/utility-types", + "@kbn/core-elasticsearch-client-server-mocks", + "@kbn/core-saved-objects-server", + "@kbn/zod-helpers", + "@kbn/core-security-server", + "@kbn/core-http-server-mocks", + "@kbn/core-http-server-utils" + ], + "exclude": ["target/**/*"] +} diff --git a/x-pack/solutions/security/plugins/security_solution/docs/openapi/README.md b/x-pack/solutions/security/plugins/security_solution/docs/openapi/README.md index 4c3b55c8ab23d..3cbe1c1f42336 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/openapi/README.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/openapi/README.md @@ -32,8 +32,8 @@ Security Solution has multiple API domains scattered across Kibana. Currently th - Security Endpoint Exceptions - - Bundling script: `packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js` - - Bundles location: `packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/{ess|serverless}` + - Bundling script: `x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/scripts/openapi_bundle.js` + - Bundles location: `x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common/docs/openapi/{ess|serverless}` - Security Endpoint Management @@ -47,13 +47,13 @@ Security Solution has multiple API domains scattered across Kibana. Currently th - Security Security Exceptions - - Bundling script: `packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js` - - Bundles location: `packages/kbn-securitysolution-exceptions-common/docs/openapi/{ess|serverless}` + - Bundling script: `x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/scripts/openapi_bundle.js` + - Bundles location: `x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common/docs/openapi/{ess|serverless}` - Security Lists - - Bundling script: `packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js` - - Bundles location: `packages/kbn-securitysolution-lists-common/docs/openapi/{ess|serverless}` + - Bundling script: `x-pack/solutions/security/packages/kbn-securitysolution-lists-common/scripts/openapi_bundle.js` + - Bundles location: `x-pack/solutions/security/packages/kbn-securitysolution-lists-common/docs/openapi/{ess|serverless}` - Security Osquery diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/README.md b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/README.md index f159a2c5b2480..b60033b731778 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/README.md +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/README.md @@ -172,5 +172,5 @@ To test out the functionality of large lists with rules, the user will need to i * First, set the appropriate env var in order to enable exceptions features`export ELASTIC_XPACK_SECURITY_SOLUTION_LISTS_FEATURE=true` and `export ELASTIC_XPACK_SECURITY_SOLUTION_EXCEPTIONS_LISTS=true` and start kibana * Second, import a list of ips from a file called `ci-badguys.txt`. The command should look like this: -`cd $HOME/kibana/x-pack/plugins/lists/server/scripts && ./import_list_items_by_filename.sh ip ~/ci-badguys.txt` +`cd $HOME/kibana/x-pack/solutions/security/plugins/lists/server/scripts && ./import_list_items_by_filename.sh ip ~/ci-badguys.txt` * Then, from the detection engine scripts folder (`cd kibana/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/scripts`) run `./post_rule.sh rules/queries/lists/query_with_list_plugin.json` diff --git a/yarn.lock b/yarn.lock index 561c7c92280e2..4e68732c9f818 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6137,7 +6137,7 @@ version "0.0.0" uid "" -"@kbn/lists-plugin@link:x-pack/plugins/lists": +"@kbn/lists-plugin@link:x-pack/solutions/security/plugins/lists": version "0.0.0" uid "" @@ -7129,7 +7129,7 @@ version "0.0.0" uid "" -"@kbn/securitysolution-autocomplete@link:packages/kbn-securitysolution-autocomplete": +"@kbn/securitysolution-autocomplete@link:x-pack/solutions/security/packages/kbn-securitysolution-autocomplete": version "0.0.0" uid "" @@ -7141,71 +7141,71 @@ version "0.0.0" uid "" -"@kbn/securitysolution-endpoint-exceptions-common@link:packages/kbn-securitysolution-endpoint-exceptions-common": +"@kbn/securitysolution-endpoint-exceptions-common@link:x-pack/solutions/security/packages/kbn-securitysolution-endpoint-exceptions-common": version "0.0.0" uid "" -"@kbn/securitysolution-es-utils@link:packages/kbn-securitysolution-es-utils": +"@kbn/securitysolution-es-utils@link:src/platform/packages/shared/kbn-securitysolution-es-utils": version "0.0.0" uid "" -"@kbn/securitysolution-exception-list-components@link:packages/kbn-securitysolution-exception-list-components": +"@kbn/securitysolution-exception-list-components@link:x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components": version "0.0.0" uid "" -"@kbn/securitysolution-exceptions-common@link:packages/kbn-securitysolution-exceptions-common": +"@kbn/securitysolution-exceptions-common@link:x-pack/solutions/security/packages/kbn-securitysolution-exceptions-common": version "0.0.0" uid "" -"@kbn/securitysolution-hook-utils@link:packages/kbn-securitysolution-hook-utils": +"@kbn/securitysolution-hook-utils@link:x-pack/solutions/security/packages/kbn-securitysolution-hook-utils": version "0.0.0" uid "" -"@kbn/securitysolution-io-ts-alerting-types@link:packages/kbn-securitysolution-io-ts-alerting-types": +"@kbn/securitysolution-io-ts-alerting-types@link:x-pack/solutions/security/packages/kbn-securitysolution-io-ts-alerting-types": version "0.0.0" uid "" -"@kbn/securitysolution-io-ts-list-types@link:packages/kbn-securitysolution-io-ts-list-types": +"@kbn/securitysolution-io-ts-list-types@link:x-pack/solutions/security/packages/kbn-securitysolution-io-ts-list-types": version "0.0.0" uid "" -"@kbn/securitysolution-io-ts-types@link:packages/kbn-securitysolution-io-ts-types": +"@kbn/securitysolution-io-ts-types@link:src/platform/packages/shared/kbn-securitysolution-io-ts-types": version "0.0.0" uid "" -"@kbn/securitysolution-io-ts-utils@link:packages/kbn-securitysolution-io-ts-utils": +"@kbn/securitysolution-io-ts-utils@link:src/platform/packages/shared/kbn-securitysolution-io-ts-utils": version "0.0.0" uid "" -"@kbn/securitysolution-list-api@link:packages/kbn-securitysolution-list-api": +"@kbn/securitysolution-list-api@link:x-pack/solutions/security/packages/kbn-securitysolution-list-api": version "0.0.0" uid "" -"@kbn/securitysolution-list-constants@link:packages/kbn-securitysolution-list-constants": +"@kbn/securitysolution-list-constants@link:x-pack/solutions/security/packages/kbn-securitysolution-list-constants": version "0.0.0" uid "" -"@kbn/securitysolution-list-hooks@link:packages/kbn-securitysolution-list-hooks": +"@kbn/securitysolution-list-hooks@link:x-pack/solutions/security/packages/kbn-securitysolution-list-hooks": version "0.0.0" uid "" -"@kbn/securitysolution-list-utils@link:packages/kbn-securitysolution-list-utils": +"@kbn/securitysolution-list-utils@link:x-pack/solutions/security/packages/kbn-securitysolution-list-utils": version "0.0.0" uid "" -"@kbn/securitysolution-lists-common@link:packages/kbn-securitysolution-lists-common": +"@kbn/securitysolution-lists-common@link:x-pack/solutions/security/packages/kbn-securitysolution-lists-common": version "0.0.0" uid "" -"@kbn/securitysolution-rules@link:packages/kbn-securitysolution-rules": +"@kbn/securitysolution-rules@link:src/platform/packages/shared/kbn-securitysolution-rules": version "0.0.0" uid "" -"@kbn/securitysolution-t-grid@link:packages/kbn-securitysolution-t-grid": +"@kbn/securitysolution-t-grid@link:x-pack/solutions/security/packages/kbn-securitysolution-t-grid": version "0.0.0" uid "" -"@kbn/securitysolution-utils@link:packages/kbn-securitysolution-utils": +"@kbn/securitysolution-utils@link:x-pack/solutions/security/packages/kbn-securitysolution-utils": version "0.0.0" uid ""