From 844781d25d1b33b6496dc86c554cdb0c6671d70c Mon Sep 17 00:00:00 2001 From: abhilash-aot Date: Tue, 28 Dec 2021 20:51:50 +0530 Subject: [PATCH] v4.0.4 Changes (#193) * v4.0.4 Changes Co-authored-by: abhilash-aot Co-authored-by: Kurian Benoy <70306694+kurianbenoy-aot@users.noreply.github.com> Co-authored-by: McCoySmith <53832516+McCoySmith@users.noreply.github.com> Co-authored-by: Shibin Thomas <83489861+shibin-aot@users.noreply.github.com> Co-authored-by: twinkle-joseph-aot Co-authored-by: Abil P Raju <83952803+abilpraju-aot@users.noreply.github.com> Co-authored-by: sumathi-thirumani-aot <57740789+sumathi-thirumani-aot@users.noreply.github.com> Co-authored-by: athira-aot <86649870+athira-aot@users.noreply.github.com> Co-authored-by: seethalelias-aot <83584866+seethalelias-aot@users.noreply.github.com> Co-authored-by: Bonymol-aot Co-authored-by: Bonymol Baby <88372115+Bonymol-aot@users.noreply.github.com> Co-authored-by: sneha Co-authored-by: SnehaSuresh-aot <85665463+SnehaSuresh-aot@users.noreply.github.com> Co-authored-by: shibin-aot Co-authored-by: unknown Co-authored-by: Krishnan Subramanian <84348052+krishnan-aot@users.noreply.github.com> Co-authored-by: sreehari-aot <93634377+sreehari-aot@users.noreply.github.com> Co-authored-by: seethalelias-aot Co-authored-by: alanraju-aot <94040192+alanraju-aot@users.noreply.github.com> Co-authored-by: shuhaib s <95394061+shuhaib-aot@users.noreply.github.com> Co-authored-by: abilpraju-aot Co-authored-by: shuhaibzahir Co-authored-by: root --- .DS_Store | Bin 14340 -> 0 bytes .gitignore | 3 + .project | 11 + CHANGELOG.md | 208 +- DEPENDENCIES.md | 62 +- README.md | 132 +- deployment/README.md | 5 + deployment/docker/README.md | 42 +- deployment/docker/docker-compose-linux.yml | 16 +- deployment/docker/docker-compose-windows.yml | 16 +- deployment/docker/sample.env | 9 + deployment/nginx/conf.d/app.conf | 17 +- deployment/openshift/README.md | 30 +- deployment/openshift/camunda_dc.yaml | 14 +- deployment/openshift/camunda_param.yaml | 2 +- deployment/openshift/formio_dc.yaml | 7 +- deployment/openshift/formio_secrets.yaml | 4 + .../openshift/formio_secrets_param.yaml | 3 +- deployment/openshift/redash_bc.yaml | 10 +- deployment/openshift/redash_dc.yaml | 1227 +- deployment/openshift/redash_param.yaml | 14 +- deployment/openshift/web_dc.yaml | 24 +- deployment/openshift/web_param.yaml | 7 +- deployment/openshift/webapi_bc.yaml | 4 +- deployment/openshift/webapi_dc.yaml | 128 +- deployment/openshift/webapi_param.yaml | 22 +- forms-flow-analytics/LICENSE | 203 + forms-flow-analytics/README.md | 70 +- forms-flow-analytics/docker-compose-linux.yml | 30 +- .../docker-compose-windows.yml | 24 +- forms-flow-analytics/sample.env | 14 +- forms-flow-api/Dockerfile | 2 +- forms-flow-api/LICENSE | 203 + forms-flow-api/Makefile | 8 +- forms-flow-api/README.md | 59 +- forms-flow-api/docker-compose-linux.yml | 8 +- forms-flow-api/docker-compose-windows.yml | 6 + forms-flow-api/entrypoint | 2 +- forms-flow-api/gunicorn_config.py | 8 +- forms-flow-api/manage.py | 6 +- forms-flow-api/requirements.txt | 37 +- forms-flow-api/requirements/dev.txt | 3 + forms-flow-api/sample.env | 25 +- forms-flow-api/setup.cfg | 7 +- forms-flow-api/setup.py | 26 +- forms-flow-api/src/api/models/__init__.py | 13 - forms-flow-api/src/api/models/application.py | 303 - .../api/models/application_communication.py | 16 - .../src/api/models/enums/__init__.py | 4 - .../src/api/models/enums/base_enum.py | 29 - .../api/models/enums/form_process_mapper.py | 10 - forms-flow-api/src/api/models/formio_token.py | 14 - forms-flow-api/src/api/models/tenant.py | 25 - .../src/api/resources/formiotoken.py | 26 - forms-flow-api/src/api/resources/task.py | 197 - forms-flow-api/src/api/resources/tenant.py | 38 - forms-flow-api/src/api/schemas/__init__.py | 23 - forms-flow-api/src/api/schemas/task.py | 40 - forms-flow-api/src/api/schemas/tenant.py | 17 - forms-flow-api/src/api/services/__init__.py | 19 - forms-flow-api/src/api/services/process.py | 117 - forms-flow-api/src/api/services/task.py | 60 - forms-flow-api/src/api/utils/__init__.py | 14 - forms-flow-api/src/api/utils/roles.py | 9 - forms-flow-api/src/formsflow_api/__init__.py | 5 + .../{api/__init__.py => formsflow_api/app.py} | 31 +- .../src/{api => formsflow_api}/config.py | 38 +- .../exceptions/__init__.py | 1 - .../src/{api => formsflow_api}/logging.conf | 0 .../src/formsflow_api/models/__init__.py | 10 + .../src/formsflow_api/models/application.py | 568 + .../models/application_history.py | 7 +- .../models/audit_mixin.py | 2 +- .../models/base_model.py | 2 +- .../src/{api => formsflow_api}/models/db.py | 0 .../models/form_process_mapper.py | 16 +- .../resources/__init__.py | 32 +- .../resources/application.py | 158 +- .../resources/application_history.py | 14 +- .../resources/checkpoint.py | 2 +- .../src/formsflow_api/resources/dashboards.py | 80 + .../resources/form_process_mapper.py | 8 +- .../src/formsflow_api/resources/groups.py | 112 + .../resources/metrics.py | 11 +- .../resources/process.py | 70 +- .../src/formsflow_api/schemas/__init__.py | 21 + .../schemas/aggregated_application.py | 8 +- .../schemas/application.py | 28 +- .../schemas/application_history.py | 0 .../schemas/form_process_mapper.py | 0 .../formsflow_api/schemas/keycloak_groups.py | 13 + .../{api => formsflow_api}/schemas/process.py | 45 +- .../src/formsflow_api/schemas/tenant.py | 17 + .../src/formsflow_api/services/__init__.py | 18 + .../services/application.py | 166 +- .../services/application_history.py | 4 +- .../services/external/__init__.py | 0 .../services/external/analytics_api.py | 25 + .../services/external/base_bpm.py | 2 +- .../services/external/bpm.py | 0 .../services/external/keycloak.py | 81 + .../services/form_process_mapper.py | 6 +- .../services/formio_token.py | 0 .../src/formsflow_api/services/process.py | 65 + .../{api => formsflow_api}/services/tenant.py | 0 .../src/formsflow_api/utils/__init__.py | 19 + .../src/{api => formsflow_api}/utils/auth.py | 4 +- .../{api => formsflow_api}/utils/constants.py | 8 +- .../src/formsflow_api/utils/enums.py | 26 + .../{api => formsflow_api}/utils/format.py | 0 .../{api => formsflow_api}/utils/logging.py | 0 .../{api => formsflow_api}/utils/profiler.py | 0 .../src/formsflow_api/utils/roles.py | 9 + .../src/{api => formsflow_api}/utils/util.py | 24 + forms-flow-api/tests/conftest.py | 58 +- .../tests/docker/docker-compose.yml | 69 + .../docker/imports/formsflow-ai-realm.json | 2476 ++++ forms-flow-api/tests/unit/api/__init__.py | 1 + .../tests/unit/api/test_application.py | 211 + .../unit/api/test_application_history.py | 66 + .../tests/unit/api/test_checkpoint.py | 20 + .../tests/unit/api/test_dashboards.py | 32 + .../unit/api/test_form_process_mapper.py | 50 + .../tests/unit/api/test_keycloak_groups.py | 86 + forms-flow-api/tests/unit/api/test_metrics.py | 86 + forms-flow-api/tests/unit/api/test_process.py | 19 + .../tests/unit/conf/test_configuration.py | 22 +- .../tests/unit/models/test_application.py | 42 +- .../unit/models/test_application_audit.py | 17 +- .../unit/models/test_form_process_mapper.py | 18 +- .../tests/unit/services/test_application.py | 4 + .../unit/services/test_application_history.py | 28 + .../unit/services/test_form_process_mapper.py | 45 + forms-flow-api/tests/unit/utils/logging.conf | 2 +- .../tests/unit/utils/test_logging.py | 4 +- .../tests/unit/utils/test_util_cors.py | 25 +- forms-flow-api/tests/utilities/base_test.py | 130 + forms-flow-api/wsgi.py | 4 +- forms-flow-bpm/.DS_Store | Bin 6148 -> 0 bytes forms-flow-bpm/.gitignore | 25 + forms-flow-bpm/Dockerfile | 4 +- forms-flow-bpm/LICENSE | 203 + forms-flow-bpm/README.md | 4 +- forms-flow-bpm/docker-compose-linux.yml | 2 + forms-flow-bpm/docker-compose-windows.yml | 2 + forms-flow-bpm/downgrade/README.md | 10 + .../downgrade/process-engine_7.15_to_7.13.sql | 13 + forms-flow-bpm/pom-docker.xml | 155 +- forms-flow-bpm/sample.env | 6 +- forms-flow-bpm/src/.DS_Store | Bin 6148 -> 0 bytes .../bpm/extension/CamundaApplication.java | 96 + .../support/ApplicationAccessHandler.java | 40 +- .../connector/support/FormAccessHandler.java | 68 +- .../support/FormTokenAccessHandler.java | 49 +- .../io/event/CamundaEventListener.java | 4 +- .../hooks/controllers/AdminController.java | 49 +- .../hooks/controllers/TaskController.java | 70 +- .../hooks/controllers/data/Authorization.java | 4 +- .../hooks/controllers/data/Task.java | 16 + .../hooks/controllers/data/Variable.java | 13 + .../mapper/TaskResultSetExtractor.java | 45 + .../delegates/FormTextAnalysisDelegate.java | 43 +- .../delegates/data/TextSentimentData.java | 16 + .../delegates/data/TextSentimentRequest.java | 16 + .../listeners/ApplicationStateListener.java | 1 - .../BPMFormDataPipelineListener.java | 2 +- .../listeners/FormSubmissionListener.java | 3 - .../execution/EmailAttributesListener.java | 6 +- .../execution/ExternalSubmissionListener.java | 2 +- .../hooks/listeners/task/NotifyListener.java | 12 +- .../hooks/services/FormSubmissionService.java | 101 +- .../{showcase => }/ProcessConstants.java | 2 +- .../plugin/KeycloakIdentityProvider.java | 2 +- .../keycloak/rest/AudienceValidator.java | 34 + .../rest/KeycloakAuthenticationConverter.java | 2 +- .../rest/KeycloakAuthenticationFilter.java | 100 + .../rest/RestApiSecurityConfig.java | 90 +- ...estApiSecurityConfigurationProperties.java | 44 + .../rest/client/WebClientOauth2Config.java | 86 + .../keycloak/showcase/CamundaApplication.java | 170 - .../rest/KeycloakAuthenticationFilter.java | 90 - ...estApiSecurityConfigurationProperties.java | 71 - .../showcase/sso/WebAppSecurityConfig.java | 87 - .../keycloak/{showcase => }/sso/AESUtils.java | 2 +- .../{showcase => }/sso/CustomCorsFilter.java | 8 +- .../sso/CustomHttpRequestWrapper.java | 2 +- .../sso/KeycloakAuthenticationProvider.java | 33 +- .../sso/KeycloakLogoutHandler.java | 21 +- .../sso/OAuth2LoginSecurityConfig.java | 96 + .../{showcase => }/task/LoggerDelegate.java | 2 +- .../camunda/app/admin/custom/logout.js | 40 +- .../camunda/app/admin/scripts/config.js | 6 + .../camunda/app/cockpit/custom/logout.js | 40 +- .../camunda/app/cockpit/scripts/config.js | 7 + .../camunda/app/tasklist/custom/logout.js | 40 +- .../camunda/app/tasklist/scripts/config.js | 6 + .../camunda/app/welcome/custom/logout.js | 40 +- .../camunda/app/welcome/scripts/config.js | 6 + .../src/main/resources/application.yaml | 80 +- .../bpm/extension/CamundaApplicationTest.java | 23 + .../support/ApplicationAccessHandlerTest.java | 71 + .../support/FormAccessHandlerTest.java | 297 + .../support/FormTokenAccessHandlerTest.java | 65 + .../io/event/CamundaEventListenerTest.java | 125 + .../controllers/AdminControllerTest.java | 132 + .../hooks/controllers/TaskControllerTest.java | 128 + .../controllers/stubs/AuthorizationStub.java | 16 + .../hooks/controllers/stubs/TaskStub.java | 22 + .../hooks/controllers/stubs/VariableStub.java | 15 + .../FormDocumentTransformerTest.java | 55 + .../FormTextAnalysisDelegateTest.java | 107 + .../ApplicationAuditListenerTest.java | 194 + .../ApplicationStateListenerTest.java | 209 + .../BPMFormDataPipelineListenerTest.java | 289 + .../FormBPMDataPipelineListenerTest.java | 130 + .../listeners/FormSubmissionListenerTest.java | 125 + .../EmailAttributesListenerTest.java | 261 + .../ExternalSubmissionListenerTest.java | 239 + .../FormAccessTokenCacheListenerTest.java | 57 + .../hooks/listeners/stubs/CustomUserStub.java | 7 + .../hooks/listeners/stubs/IdentityStub.java | 22 + .../hooks/listeners/stubs/UserStub.java | 18 + .../task/FormConnectorListenerTest.java | 242 + .../listeners/task/NotifyListenerTest.java | 355 + .../TaskDurationAttributesListenerTest.java | 88 + .../task/TimeoutNotifyListenerTest.java | 345 + .../services/FormSubmissionServiceTest.java | 211 + .../rest/ConfigurationPropertyTest.java | 33 + .../KeycloakAuthenticationFilterTest.java | 91 + .../rest/RestApiSecurityConfigTest.java | 90 + .../keycloak/task/LoggerDelegateTest.java | 55 + .../integration/ProcessIntegrationTest.java | 15 +- .../test/bpm/local/ProcessLocalTest.java | 10 +- .../test/util/ProcessTestAssertions.java | 2 +- .../process/OneStepApprovalTest.java | 57 + .../extension/process/SampleWorkflowTest.java | 31 + .../process/TwoStepApprovalTest.java | 11 + .../src/test/resources/application.yaml | 30 +- ...{camunda.local.cfg.xml => camunda.cfg.xml} | 11 + .../src/test/resources/one-step-approval.bpmn | 117 + .../processes/two-step-approval.bpmn | 309 + forms-flow-bpm/upgrade/UPGRADE.md | 20 + .../upgrade/process-engine_7.13_to_7.15.sql | 27 + forms-flow-forms/Changelog.md | 449 +- forms-flow-forms/Dockerfile | 7 +- forms-flow-forms/README.md | 98 +- forms-flow-forms/docker-compose-linux.yml | 4 +- forms-flow-forms/docker-compose-windows.yml | 4 +- forms-flow-forms/index.js | 23 +- forms-flow-forms/package-lock.json | 5838 ++++----- forms-flow-forms/package.json | 76 +- forms-flow-forms/sample.env | 5 +- forms-flow-forms/src/actions/EmailAction.js | 40 +- forms-flow-forms/src/actions/LoginAction.js | 23 +- forms-flow-forms/src/actions/ResetPassword.js | 7 +- .../src/actions/SaveSubmission.js | 39 +- forms-flow-forms/src/actions/WebhookAction.js | 78 +- forms-flow-forms/src/actions/actions.js | 146 +- forms-flow-forms/src/actions/fields/index.js | 2 - .../src/actions/fields/password.js | 2 +- forms-flow-forms/src/actions/fields/radio.js | 18 - forms-flow-forms/src/actions/fields/select.js | 19 - .../src/actions/fields/signature.js | 4 +- .../src/actions/properties/reference.js | 1 + forms-flow-forms/src/authentication/index.js | 23 +- forms-flow-forms/src/cache/cache.js | 6 +- forms-flow-forms/src/db/index.js | 135 +- forms-flow-forms/src/db/tools.js | 4 +- forms-flow-forms/src/db/updates/2.3.0.js | 6 +- forms-flow-forms/src/db/updates/2.3.2.js | 4 +- forms-flow-forms/src/db/updates/2.4.1.js | 2 +- forms-flow-forms/src/db/updates/2.4.2.js | 8 +- forms-flow-forms/src/db/updates/2.4.3.js | 3 +- forms-flow-forms/src/db/updates/3.0.0.js | 12 +- forms-flow-forms/src/db/updates/3.0.2.js | 2 +- forms-flow-forms/src/db/updates/3.1.2.js | 2 +- forms-flow-forms/src/db/updates/3.1.3.js | 2 +- forms-flow-forms/src/export/export.js | 8 +- .../src/export/exporters/CSVExporter.js | 109 +- .../src/middleware/bootstrapFormAccess.js | 29 +- .../src/middleware/deleteRoleHandler.js | 4 + .../src/middleware/filterProtectedFields.js | 2 +- .../src/middleware/formHandler.js | 6 +- forms-flow-forms/src/middleware/middleware.js | 2 + .../src/middleware/permissionHandler.js | 44 +- forms-flow-forms/src/middleware/recaptcha.js | 18 +- .../src/middleware/revisionLoader.js | 32 + .../submissionFieldMatchAccessFilter.js | 9 +- .../src/middleware/submissionHandler.js | 79 +- .../src/middleware/tokenHandler.js | 6 +- .../src/middleware/tokenVerify.js | 72 + forms-flow-forms/src/models/Action.js | 10 + forms-flow-forms/src/models/ActionItem.js | 18 +- forms-flow-forms/src/models/BaseModel.js | 2 +- .../FieldMatchAccessPermissionSchema.js | 12 +- forms-flow-forms/src/models/Form.js | 37 +- forms-flow-forms/src/models/Submission.js | 6 + forms-flow-forms/src/models/Token.js | 8 +- forms-flow-forms/src/plugins/timestamps.js | 24 +- .../src/resources/FormResource.js | 8 +- .../src/resources/LegacyValidator.js | 1111 -- .../src/resources/SubmissionResource.js | 23 +- forms-flow-forms/src/resources/Validator.js | 20 +- forms-flow-forms/src/templates/default.json | 28 +- forms-flow-forms/src/templates/empty.json | 28 +- forms-flow-forms/src/templates/import.js | 424 +- forms-flow-forms/src/util/email.js | 78 +- forms-flow-forms/src/util/fetch.js | 8 +- forms-flow-forms/src/util/util.js | 75 +- forms-flow-forms/src/worker/Worker.js | 2 +- forms-flow-forms/test/actions.js | 591 +- forms-flow-forms/test/auth.js | 50 +- .../test/export/CSVExporter/CSVExporter.js | 82 +- .../test/fixtures/email/test3/form.json | 99 + .../test/fixtures/email/test3/message.html | 1 + .../test/fixtures/email/test3/submission.json | 72 + .../test/fixtures/forms/complex.js | 10 +- .../test/fixtures/forms/fileComponent.js | 33 + .../test/fixtures/forms/servercalculate.js | 151 + forms-flow-forms/test/fixtures/template.js | 3 +- forms-flow-forms/test/form.js | 208 + forms-flow-forms/test/helper.js | 141 +- forms-flow-forms/test/roles.js | 28 +- forms-flow-forms/test/submission-access.js | 13 + forms-flow-forms/test/submission.js | 276 +- forms-flow-forms/test/unit.js | 247 +- forms-flow-idm/.DS_Store | Bin 6148 -> 0 bytes forms-flow-idm/LICENSE | 203 + forms-flow-idm/keycloak/README.md | 80 +- .../keycloak/imports/formsflow-ai-realm.json | 49 +- forms-flow-web/Dockerfile | 7 +- forms-flow-web/LICENSE | 203 + forms-flow-web/README.md | 14 +- forms-flow-web/docker-compose.yml | 3 +- forms-flow-web/jest.config.json | 23 + forms-flow-web/package-lock.json | 10752 ++++++++-------- forms-flow-web/package.json | 22 +- forms-flow-web/public/config/config.sample.js | 6 +- forms-flow-web/sample.env | 6 +- .../test-components/baserouting.test.js | 62 + .../test-components/test-BPMN/constants.js | 5 + .../test-BPMN/processDiagramhook.test.js | 43 + .../test-components/test-admin/constants.js | 104 + .../test-admin/dashboardReducer.test.js | 15 + .../test-components/test-admin/index.test.js | 34 + .../test-admin/insightdashboard.test.js | 55 + .../ApplicationHistory.test.js | 88 + .../test-application/Constants.js | 152 + .../test-application/Constatnts.js | 138 + .../test-application/ViewApplication.test.js | 99 + .../test-application/index.test.js | 35 + .../test-application/list.test.js | 78 + .../test-details/ApplicationDetails.test.js | 76 + .../test-application/test-details/constant.js | 45 + .../test-details/nodata.test.js | 10 + .../test-dashboard/ApplicationCounter.test.js | 22 + .../test-dashboard/Constants.js | 30 + .../test-dashboard/dashboard.test.js | 101 + .../test-dashboard/index.test.js | 38 + .../test-error/LoadError.test.js | 15 + .../test-components/test-error/index.test.js | 7 + .../test-footer/Footer.test.js | 8 + .../test-components/test-footer/index.test.js | 7 + .../test-components/test-form/constants.js | 866 ++ .../test-components/test-form/create.test.js | 46 + .../test-components/test-form/index.test.js | 139 + .../test-components/test-form/list.test.js | 75 + .../test-components/test-form/stepper.test.js | 59 + .../test-form/test-item/constatnts-edit.js | 254 + .../test-form/test-item/edit.test.js | 58 + .../test-submission/test-item/constant.js | 27 + .../test-item/constants/constant.js | 27 + .../constants/formListConstants.test.js | 9 + .../test-form/test-item/view.test.js | 51 + .../test-insights/Nodashboard.test.js | 8 + .../test-components/test-insights/constant.js | 12 + .../test-insights/index.test.js | 9 + .../test-insights/insight.test.js | 27 + .../test-loading/Loading.test.js | 8 + .../test-loading/index.test.js | 8 + .../test-components/test-nodata/index.test.js | 7 + .../test-nodata/nodata.test.js | 8 + .../test-notfound/index.test.js | 9 + .../test-serviceflow/constants.js | 167 + .../details/Addgroupmodal.test.js | 43 + .../details/Taskheader.test.js | 66 + .../test-serviceflow/index.test.js | 49 + .../test-components/test-task/constants.js | 151 + .../test-components/test-task/index.test.js | 49 + .../test-components/test-task/list.test.js | 39 + .../test-components/test-task/nodata.test.js | 8 + .../test-task/viewtask.test.js | 99 + .../_tests_/test-containers/Confirm.test.js | 6 + .../_tests_/test-containers/Loading.test.js | 7 + .../test-containers/SpinnerSVG.test.js | 6 + .../_tests_/test-containers/navbar.test.js | 52 + .../_tests_/test-containers/sidebar.test.js | 57 + .../src/_tests_/test-helpers/helper.test.js | 6 + .../src/_tests_/test-helpers/user.test.js | 56 + .../test-redux-states/redux-state-sample.js | 136 + forms-flow-web/src/actions/actionConstants.js | 18 +- .../src/actions/applicationActions.js | 29 + forms-flow-web/src/actions/bpmActions.js | 1 + forms-flow-web/src/actions/bpmTaskActions.js | 1 + .../src/actions/checkListActions.js | 1 + .../src/actions/dashboardActions.js | 61 + forms-flow-web/src/actions/formActions.js | 1 + forms-flow-web/src/actions/insightActions.js | 1 + forms-flow-web/src/actions/menuActions.js | 1 + forms-flow-web/src/actions/metricsActions.js | 1 + forms-flow-web/src/actions/processActions.js | 1 + forms-flow-web/src/actions/taskActions.js | 1 + .../src/actions/validationActions.js | 1 + .../src/apiManager/endpoints/config.js | 12 +- .../src/apiManager/endpoints/index.js | 10 +- .../apiManager/httpRequestHandler/index.js | 11 + .../services/applicationServices.js | 81 +- .../apiManager/services/bpmFormServices.js | 1 + .../src/apiManager/services/bpmServices.js | 1 + .../apiManager/services/bpmTaskServices.js | 67 +- .../apiManager/services/dashboardsService.js | 144 + .../services/filterListFormatterService.js | 1 + .../apiManager/services/formatterService.js | 1 + .../apiManager/services/insightServices.js | 88 +- .../apiManager/services/metricsServices.js | 16 +- .../apiManager/services/processServices.js | 1 + .../taskSearchParamsFormatterService.js | 1 + .../src/apiManager/services/taskServices.js | 1 + .../src/components/Admin/Insightdashboard.js | 211 + forms-flow-web/src/components/Admin/index.js | 35 + .../components/Admin/insightDashboard.scss | 27 + .../components/Application/Application.scss | 4 + .../Application/Details/ApplicationDetails.js | 12 +- .../src/components/Application/List.js | 76 +- .../src/components/Application/table.js | 211 +- .../src/components/Dashboard/Dashboard.js | 8 +- .../Form/FileUpload/SelectFormForDownload.js | 2 +- .../Form/FileUpload/fileUploadModal.js | 1 - .../src/components/Form/Item/View.js | 2 +- forms-flow-web/src/components/Form/List.js | 4 +- forms-flow-web/src/components/Form/List.scss | 2 +- forms-flow-web/src/components/Form/index.js | 2 +- .../src/components/Insights/Insights.js | 28 +- .../src/components/Loading/Loading.js | 2 +- .../src/components/PrivateRoute.jsx | 3 +- .../constants/userSearchFilterTypes.js | 1 + .../ServiceFlow/details/AddGroupModal.js | 4 +- .../ServiceFlow/details/TaskHeader.js | 4 +- .../src/components/ServiceFlow/index.js | 4 - .../ServiceFlow/list/ServiceTaskList.js | 4 +- .../src/constants/applicationConstants.js | 1 + forms-flow-web/src/constants/constants.js | 4 + .../src/constants/socketIOConstants.js | 1 + forms-flow-web/src/constants/userContants.js | 1 + forms-flow-web/src/containers/Loading.js | 2 +- forms-flow-web/src/containers/NavBar.jsx | 13 +- forms-flow-web/src/helper/user.js | 15 +- forms-flow-web/src/index.js | 1 + .../src/modules/applicationsReducer.js | 22 +- forms-flow-web/src/modules/bpmFormReducer.js | 2 +- forms-flow-web/src/modules/bpmTaskReducer.js | 2 +- .../src/modules/dashboardReducer.js | 79 + forms-flow-web/src/modules/index.js | 6 +- forms-flow-web/src/serviceWorker.js | 1 + forms-flow-web/src/services/FileService.js | 1 + .../src/services/PdfDownloadService.js | 1 + .../src/services/SocketIOService.js | 1 + forms-flow-web/src/services/UserService.js | 6 +- forms-flow-web/src/styles.scss | 6 + package-lock.json | 3 - utils/formioupgrade.sh | 39 +- 471 files changed, 29604 insertions(+), 14629 deletions(-) delete mode 100644 .DS_Store create mode 100644 .project create mode 100644 forms-flow-analytics/LICENSE create mode 100644 forms-flow-api/LICENSE delete mode 100644 forms-flow-api/src/api/models/__init__.py delete mode 100644 forms-flow-api/src/api/models/application.py delete mode 100644 forms-flow-api/src/api/models/application_communication.py delete mode 100644 forms-flow-api/src/api/models/enums/__init__.py delete mode 100644 forms-flow-api/src/api/models/enums/base_enum.py delete mode 100644 forms-flow-api/src/api/models/enums/form_process_mapper.py delete mode 100644 forms-flow-api/src/api/models/formio_token.py delete mode 100644 forms-flow-api/src/api/models/tenant.py delete mode 100644 forms-flow-api/src/api/resources/formiotoken.py delete mode 100644 forms-flow-api/src/api/resources/task.py delete mode 100644 forms-flow-api/src/api/resources/tenant.py delete mode 100644 forms-flow-api/src/api/schemas/__init__.py delete mode 100644 forms-flow-api/src/api/schemas/task.py delete mode 100644 forms-flow-api/src/api/schemas/tenant.py delete mode 100644 forms-flow-api/src/api/services/__init__.py delete mode 100644 forms-flow-api/src/api/services/process.py delete mode 100644 forms-flow-api/src/api/services/task.py delete mode 100644 forms-flow-api/src/api/utils/__init__.py delete mode 100644 forms-flow-api/src/api/utils/roles.py create mode 100644 forms-flow-api/src/formsflow_api/__init__.py rename forms-flow-api/src/{api/__init__.py => formsflow_api/app.py} (84%) rename forms-flow-api/src/{api => formsflow_api}/config.py (70%) rename forms-flow-api/src/{api => formsflow_api}/exceptions/__init__.py (97%) rename forms-flow-api/src/{api => formsflow_api}/logging.conf (100%) create mode 100644 forms-flow-api/src/formsflow_api/models/__init__.py create mode 100644 forms-flow-api/src/formsflow_api/models/application.py rename forms-flow-api/src/{api => formsflow_api}/models/application_history.py (91%) rename forms-flow-api/src/{api => formsflow_api}/models/audit_mixin.py (96%) rename forms-flow-api/src/{api => formsflow_api}/models/base_model.py (96%) rename forms-flow-api/src/{api => formsflow_api}/models/db.py (100%) rename forms-flow-api/src/{api => formsflow_api}/models/form_process_mapper.py (93%) rename forms-flow-api/src/{api => formsflow_api}/resources/__init__.py (61%) rename forms-flow-api/src/{api => formsflow_api}/resources/application.py (63%) rename forms-flow-api/src/{api => formsflow_api}/resources/application_history.py (84%) rename forms-flow-api/src/{api => formsflow_api}/resources/checkpoint.py (90%) create mode 100644 forms-flow-api/src/formsflow_api/resources/dashboards.py rename forms-flow-api/src/{api => formsflow_api}/resources/form_process_mapper.py (96%) create mode 100644 forms-flow-api/src/formsflow_api/resources/groups.py rename forms-flow-api/src/{api => formsflow_api}/resources/metrics.py (92%) rename forms-flow-api/src/{api => formsflow_api}/resources/process.py (67%) create mode 100644 forms-flow-api/src/formsflow_api/schemas/__init__.py rename forms-flow-api/src/{api => formsflow_api}/schemas/aggregated_application.py (81%) rename forms-flow-api/src/{api => formsflow_api}/schemas/application.py (63%) rename forms-flow-api/src/{api => formsflow_api}/schemas/application_history.py (100%) rename forms-flow-api/src/{api => formsflow_api}/schemas/form_process_mapper.py (100%) create mode 100644 forms-flow-api/src/formsflow_api/schemas/keycloak_groups.py rename forms-flow-api/src/{api => formsflow_api}/schemas/process.py (70%) create mode 100644 forms-flow-api/src/formsflow_api/schemas/tenant.py create mode 100644 forms-flow-api/src/formsflow_api/services/__init__.py rename forms-flow-api/src/{api => formsflow_api}/services/application.py (68%) rename forms-flow-api/src/{api => formsflow_api}/services/application_history.py (84%) rename forms-flow-api/src/{api => formsflow_api}/services/external/__init__.py (100%) create mode 100644 forms-flow-api/src/formsflow_api/services/external/analytics_api.py rename forms-flow-api/src/{api => formsflow_api}/services/external/base_bpm.py (97%) rename forms-flow-api/src/{api => formsflow_api}/services/external/bpm.py (100%) create mode 100644 forms-flow-api/src/formsflow_api/services/external/keycloak.py rename forms-flow-api/src/{api => formsflow_api}/services/form_process_mapper.py (95%) rename forms-flow-api/src/{api => formsflow_api}/services/formio_token.py (100%) create mode 100644 forms-flow-api/src/formsflow_api/services/process.py rename forms-flow-api/src/{api => formsflow_api}/services/tenant.py (100%) create mode 100644 forms-flow-api/src/formsflow_api/utils/__init__.py rename forms-flow-api/src/{api => formsflow_api}/utils/auth.py (92%) rename forms-flow-api/src/{api => formsflow_api}/utils/constants.py (59%) create mode 100644 forms-flow-api/src/formsflow_api/utils/enums.py rename forms-flow-api/src/{api => formsflow_api}/utils/format.py (100%) rename forms-flow-api/src/{api => formsflow_api}/utils/logging.py (100%) rename forms-flow-api/src/{api => formsflow_api}/utils/profiler.py (100%) create mode 100644 forms-flow-api/src/formsflow_api/utils/roles.py rename forms-flow-api/src/{api => formsflow_api}/utils/util.py (51%) create mode 100644 forms-flow-api/tests/docker/docker-compose.yml create mode 100644 forms-flow-api/tests/docker/imports/formsflow-ai-realm.json create mode 100644 forms-flow-api/tests/unit/api/__init__.py create mode 100644 forms-flow-api/tests/unit/api/test_application.py create mode 100644 forms-flow-api/tests/unit/api/test_application_history.py create mode 100644 forms-flow-api/tests/unit/api/test_checkpoint.py create mode 100644 forms-flow-api/tests/unit/api/test_dashboards.py create mode 100644 forms-flow-api/tests/unit/api/test_form_process_mapper.py create mode 100644 forms-flow-api/tests/unit/api/test_keycloak_groups.py create mode 100644 forms-flow-api/tests/unit/api/test_metrics.py create mode 100644 forms-flow-api/tests/unit/api/test_process.py create mode 100644 forms-flow-api/tests/unit/services/test_application.py create mode 100644 forms-flow-api/tests/unit/services/test_application_history.py create mode 100644 forms-flow-api/tests/unit/services/test_form_process_mapper.py create mode 100644 forms-flow-api/tests/utilities/base_test.py delete mode 100644 forms-flow-bpm/.DS_Store create mode 100644 forms-flow-bpm/LICENSE create mode 100644 forms-flow-bpm/downgrade/README.md create mode 100644 forms-flow-bpm/downgrade/process-engine_7.15_to_7.13.sql delete mode 100644 forms-flow-bpm/src/.DS_Store create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/CamundaApplication.java create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Task.java create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Variable.java create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/mapper/TaskResultSetExtractor.java create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentData.java create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentRequest.java rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/ProcessConstants.java (75%) rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/plugin/KeycloakIdentityProvider.java (85%) create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/AudienceValidator.java rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/rest/KeycloakAuthenticationConverter.java (97%) create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/rest/RestApiSecurityConfig.java (52%) create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigurationProperties.java create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/client/WebClientOauth2Config.java delete mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/CamundaApplication.java delete mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/KeycloakAuthenticationFilter.java delete mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/RestApiSecurityConfigurationProperties.java delete mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/WebAppSecurityConfig.java rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/sso/AESUtils.java (98%) rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/sso/CustomCorsFilter.java (95%) rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/sso/CustomHttpRequestWrapper.java (96%) rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/sso/KeycloakAuthenticationProvider.java (52%) rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/sso/KeycloakLogoutHandler.java (84%) create mode 100644 forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java rename forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/{showcase => }/task/LoggerDelegate.java (94%) create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/CamundaApplicationTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandlerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandlerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandlerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/AdminControllerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/TaskControllerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/AuthorizationStub.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/TaskStub.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/VariableStub.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormDocumentTransformerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegateTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationAuditListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormBPMDataPipelineListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/FormAccessTokenCacheListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/CustomUserStub.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/IdentityStub.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/UserStub.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/FormConnectorListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TaskDurationAttributesListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TimeoutNotifyListenerTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/services/FormSubmissionServiceTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/ConfigurationPropertyTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilterTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/task/LoggerDelegateTest.java rename forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/{showcase => }/test/bpm/integration/ProcessIntegrationTest.java (87%) rename forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/{showcase => }/test/bpm/local/ProcessLocalTest.java (93%) rename forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/{showcase => }/test/util/ProcessTestAssertions.java (99%) create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/OneStepApprovalTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/SampleWorkflowTest.java create mode 100644 forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/TwoStepApprovalTest.java rename forms-flow-bpm/src/test/resources/{camunda.local.cfg.xml => camunda.cfg.xml} (66%) create mode 100644 forms-flow-bpm/src/test/resources/one-step-approval.bpmn create mode 100644 forms-flow-bpm/src/test/resources/processes/two-step-approval.bpmn create mode 100644 forms-flow-bpm/upgrade/UPGRADE.md create mode 100644 forms-flow-bpm/upgrade/process-engine_7.13_to_7.15.sql delete mode 100644 forms-flow-forms/src/actions/fields/radio.js delete mode 100644 forms-flow-forms/src/actions/fields/select.js create mode 100644 forms-flow-forms/src/middleware/revisionLoader.js create mode 100644 forms-flow-forms/src/middleware/tokenVerify.js delete mode 100644 forms-flow-forms/src/resources/LegacyValidator.js create mode 100644 forms-flow-forms/test/fixtures/email/test3/form.json create mode 100644 forms-flow-forms/test/fixtures/email/test3/message.html create mode 100644 forms-flow-forms/test/fixtures/email/test3/submission.json create mode 100644 forms-flow-forms/test/fixtures/forms/fileComponent.js create mode 100644 forms-flow-forms/test/fixtures/forms/servercalculate.js delete mode 100644 forms-flow-idm/.DS_Store create mode 100644 forms-flow-idm/LICENSE create mode 100644 forms-flow-web/LICENSE create mode 100644 forms-flow-web/jest.config.json create mode 100644 forms-flow-web/src/_tests_/test-components/baserouting.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-BPMN/constants.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-BPMN/processDiagramhook.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-admin/constants.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-admin/dashboardReducer.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-admin/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-admin/insightdashboard.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/ApplicationHistory.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/Constants.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/Constatnts.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/ViewApplication.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/list.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/test-details/ApplicationDetails.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/test-details/constant.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-application/test-details/nodata.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-dashboard/ApplicationCounter.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-dashboard/Constants.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-dashboard/dashboard.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-dashboard/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-error/LoadError.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-error/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-footer/Footer.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-footer/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/constants.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/create.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/list.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/stepper.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/test-item/constatnts-edit.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/test-item/edit.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/test-item/test-submission/test-item/constant.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/test-item/test-submission/test-item/constants/constant.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/test-item/test-submission/test-item/constants/formListConstants.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-form/test-item/view.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-insights/Nodashboard.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-insights/constant.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-insights/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-insights/insight.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-loading/Loading.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-loading/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-nodata/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-nodata/nodata.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-notfound/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-serviceflow/constants.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-serviceflow/details/Addgroupmodal.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-serviceflow/details/Taskheader.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-serviceflow/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-task/constants.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-task/index.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-task/list.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-task/nodata.test.js create mode 100644 forms-flow-web/src/_tests_/test-components/test-task/viewtask.test.js create mode 100644 forms-flow-web/src/_tests_/test-containers/Confirm.test.js create mode 100644 forms-flow-web/src/_tests_/test-containers/Loading.test.js create mode 100644 forms-flow-web/src/_tests_/test-containers/SpinnerSVG.test.js create mode 100644 forms-flow-web/src/_tests_/test-containers/navbar.test.js create mode 100644 forms-flow-web/src/_tests_/test-containers/sidebar.test.js create mode 100644 forms-flow-web/src/_tests_/test-helpers/helper.test.js create mode 100644 forms-flow-web/src/_tests_/test-helpers/user.test.js create mode 100644 forms-flow-web/src/_tests_/test-redux-states/redux-state-sample.js create mode 100644 forms-flow-web/src/actions/dashboardActions.js create mode 100644 forms-flow-web/src/apiManager/services/dashboardsService.js create mode 100644 forms-flow-web/src/components/Admin/Insightdashboard.js create mode 100644 forms-flow-web/src/components/Admin/index.js create mode 100644 forms-flow-web/src/components/Admin/insightDashboard.scss create mode 100644 forms-flow-web/src/modules/dashboardReducer.js delete mode 100644 package-lock.json mode change 100644 => 100755 utils/formioupgrade.sh diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index d0ff5ce527b227a7c8207f531e3c330d2e499991..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14340 zcmeHNdvH`&8UMbJz`d6RZXgM}NtP@LuRsVP36SvW=0zTWK@uS074~rnJM8WayPJeS zsraDkNS|75X*&w)Xa&cP@=`maRAgzJ42GSZxYv9H;z-%vF(nJxapJ@%GHIUXoOap9vaL~;{rx6|&AzwP^!6-Z{ zXB3`a6emA`=Q)hfX@rMG$VEwpi&7{=(Qq+Ph*Q3URj1Htgoi~a!~umkpz&rjJQU<_ zCpibN4(JqN`kB^1S_9W=U=n3bO6q&-t$y9(_Umq{MH35;P&n^He(|PKNHQPYki6vX z^ZUY)ii(#pV_as|_z9AvNXjH-N5>w0up{D%^oQ$Rp=~U+!4=u#HsYPS?vKS??#(`J zut&{l(1Q_|FQ|pMu+OVemF-)6L9aeoulEPNVct%MD3Bysl6zF^!GlYxE6N;IRn>>e z90!*zqj+`I(nE)2Y5MHNt6Fyjh7KIO`_Mg)@lF96YYa>g>Dcoa#Zq+H=NT}%j6aBW z`46fZ?X;{+v`m^jMa`Z%EjuSWH#awLdal)GE9gH9vOGLh&7NYlSqmh!MC$5y`}XzwB11gaGQ;YS)ics|FTHKO?qw}{Mg1ApS(3Dk z(#tc400t- z1BSfcCC&-~5SbW?9V(#_*1;~?sXPex!J}{-PQzI^2S0}w;AMCn-h#ivd+>Mo2Yi4T zI1aOLJWfF?+OPl%u@oz@ije6fRJP$dT#p-Z8*ay)*n?gSU=aIo9}ePS{3L!FKZ8f{ z5&SYfhR5*hcnZIZ-@~WzCwLJr;qy3*zri=~Eqoi_7atfy_Ii2c7$Dsfk2VfLn90kKxTYf>I z-BPrPpsDRoHdE9I41^M|J+ru|NM+~~$%%7{EHpi2UN(OYm1P(u<%_6f9L)q#R#j~& zQnLv3LawIPVo@_`R*2G7tEqH6;a?gqu;p7V4VEUEO-&X4LjXSyFTtAx-hUzxWGCV@ z0_{wkiwkiXEu(eVh)uW#+i4-~z)svmkllqYbmLwQTOIe~0lXUz;XU|S{5*bvpnD%d z_fdlGBuBSuV2)i^6B(|jotlR9s@Rkh{Y3ZqiyX`N{0_&aQlnX;swNmxbr z+if<-Y?GA}0;Tgwz$L7l_{{P}GMPDHg%wzf%W(yq!K|%2(aZVg?3@F%o8FCd36Gt4idwQt;jyp zt}-x*zCcmO5tL<~ELSS*Y8IhZlvXKA6g88vH(pw!EVrxU3BaOs zl~SmvKqid6Mz+sU$S+GlvqlHw2{;Kqf?vXA0^x7r4fqpWfe#3PG7+rl1iyT=;|#J` zr8pnU$Zjpg8iL{qTuGLznH+&Of@3Fc#x2;5ThW6W?#4anLk7lvB3=6p(scyy#|H?O z50UNqDt_Ap!WNN^KJlsRfzV{1CJ=pWg$8JXkC6k@lxUIgU1}}f!Ioho)vP1Zxt_vu zI$rlCO27(|cr?x>kABz~!vd<8Ne%bXNqZ!*X*^G5$K#rg)w@$oVXT9uF;k)nA|>@g zkpHNlB`S-J1MZJg)>Qg&K?e`)r3E!aKQeeI6`-Y6rynFVYHx^A{!!YH;@U{IxVfpF zfJt^M4c4Nu%HF91m{MW>-o+i{9`^B>vEW~?P?);@h{r!Pn)S$A)7)~4tj9@9Zhnz4 z8+C&FOjTms$IN2lxes#{1ovU&A#Zw~Z4{1Em^b5EPoCE=%qt#^4i za_8S5hyDuujmXY>h(vQH647CPQ85vn*<@#!GryEPBxYmQ@Xe-n>>~TZoOp zGNOK0GK!PHT*l0IIGe~XPz;J=#{CGz5l%U$I1W2e9PX5JDl*HiaHpIl=FOrq=9IHU z*+ME2PB}|1u2hKaaHpIlmo8I??Qo}@C0DGZQsI=dq_d7nfp3`IEX#S0yzy5!$N7uF zaceHrf!%k=GuTgJ-| zv(HPpjGJtEvW+mWd3OMpP|HuoS=1Dgx0^k!s-?q@>Kb;~QBzSvhaHubAL(HSDJ#L6 zvO!3`$4Ir~!SUjWW7}Ss!NHM2r2%~e8e@}40LFE{$OMaI5aR!znyA)kYW!FnFjC6i zZqWFs&cRZ4dK7S^tRD}Lcb1>4HQ;d_nGt}DRmKdFwEv&>|Nnpe|17acR#1weUn9)DWdGVZ=-x#)tMgO3*+p?KLJwAjCHU`nl#nP{ u!}6jRl{s0Q!own@7+wGS9|4mcbEN(M6u+e0!~tE}|Cew2l;gke|Nk5N_2u9I diff --git a/.gitignore b/.gitignore index 9a33af6733..87c0080dfb 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,9 @@ yarn-error.log* .idea *.iml +#Visual Studio Code +.vscode + #Database postgres/ mongodb/ diff --git a/.project b/.project new file mode 100644 index 0000000000..c62bcbaf33 --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + forms-flow-ai-dev + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index c43ad6c290..179a92beee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,141 @@ # Changelog for formsflow.ai -Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upcoming Features` + +Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upcoming Features`, `Known Issues` + +## 4.0.4 - 2021-12-27 + +`Added` + +**forms-flow-bpm** + +* Added test cases and code coverage. + +*Upgrade notes:* + +New environment variables `DATA_BUFFER_SIZE`, `IDENTITY_PROVIDER_MAX_RESULT_SIZE`. + +**forms-flow-web** + +* Admin page to map insights dashboards to keycloak groups. +* Added test cases and code coverage, check out the [details here](./forms-flow-web/README.md#code-coverage). + +*Upgrade notes:* + +New environment variables `FORMIO_JWT_SECRET`. It's highly recommended to change this environment variable for existing installations. + +**forms-flow-api** + +* Added `pagination`, `sorting` and `filtering` for Application Page. +* Added new APIs which acts as a gateway for calling forms-flow-analytics APIs. +* Added new API for modifying group details in Keycloak with the help of Keycloak admin APIs. +* Add application status list API. +* Added unit test cases and new script for CI operations. + +*Upgrade notes:* + +New environment variables `KEYCLOAK_ADMIN_USERNAME`, `KEYCLOAK_ADMIN_PASSWORD`, `INSIGHT_API_URL`, `INSIGHT_API_KEY`. + + +**forms-flow-analytics** + +* Added Dashboard authorisation at Redash dashboard level. + +**forms-flow-forms** + +* Added indexes in Submission collection for applicationId, process_pid. +* Added authentication for publicly exposed urls. + +*Upgrade notes:* + +New environment variables `FORMIO_JWT_SECRET`. It's highly recommended to change this environment variable for existing installations. + +**forms-flow-idm** + +* Added new groups and mapper for Dashboard authorisation at Redash dashboard level. + +*Upgrade notes:* + +* To enable dashboards, and provide authorization the following changes are required in existing installations: + +1. Create a new main group called `formsflow-analytics`, and create as many subgroups as you want to associate various dashboards from Admin UI(in Designer) +2. Create a new mapper under forms-flow-web client in Keycloak, by following below steps: + +``` +* Name = dashboard-mapper +* Mapper Type = User Attribute +* User Attribute = dashboards +* Token Claim Name = dashboards +* Add to ID Token = ON +* Add to access token = ON +* Add to userinfo = ON +* Multivalued = ON +* Aggregate attribute values = ON +* Click Save +``` + +3. Corresponding to each user, add the dashboard-groups you want to enable for dashboard authorization. +This will give users permission to as many dashboards which the group have been enabled with from Admin. + +`Fixed` + +**forms-flow-api** + +* Fixed application metrics showing incorrect results by changing date to filtered based on timezone. + +**forms-flow-bpm** + +* Improved token creation logic using Oauth2RestTemplate. +* Code cleanup and optimization. + +**forms-flow-web** + +* Fixed total task count shown on the task LHS side and updated only after refreshing the page. +* Tasklist API updated. + +`Modified` + +**forms-flow-web** + +*Upgrade notes:* + +Removed environment variables `INSIGHT_API_URL`, `INSIGHT_API_KEY` + +`Solution Component Upgrades` + +**forms-flow-bpm** + +* Camunda upgrade from `7.13.0` to `7.15.0`. +* Upgraded springboot from `2.4.2` to `2.4.8` +* Upgraded spring-security-oauth2 from `2.4.2` to `2.4.8` + +*Upgrade notes:* + +After v4.0.4 version upgrade, Run the migrations with [upgrade file](https://github.com/AOT-Technologies/forms-flow-ai-dev/blob/develop/forms-flow-bpm/upgrade/process-engine_7.13_to_7.15.sql). + +**forms-flow-analytics** + +* Upgraded redash library to version from `9.0.0-beta` to `10.1.0` + +*Upgrade notes:* + +After v4.0.4 version upgrade, run the following command first to run the necessary migrations with the command: + +``` +docker-compose -f docker-compose-linux.yml run --rm server manage db upgrade +docker-compose -f docker-compose-linux.yml up --force-recreate --build +``` +In case you want to downgrade to the v9.0-beta of forms-flow-analytics component after formsflow.ai version upgrade. +To update the migrations and rebuild formsflow.ai. Use [the below commands which was used in setup](./forms-flow-analytics/README.md/#running-the-application). +Also note that we are not supporting downgrade to any version below Redash v9.0(which has be used from formsflow.ai v4.0 onwards). + +**forms-flow-forms** + +* Formio upgrade from `2.0.0-rc.34` to `2.3.0`. + +`Known Issues` + +* In case you are facing mongodb connection refused error for forms-flow-forms, downgrade to the next lowest mongo stable [version](https://docs.mongodb.com/manual/release-notes/) +* Consoles related to Api Failing. The console messages can be ignored. Please refer to [Issue-#106](https://github.com/AOT-Technologies/forms-flow-ai/issues/106) for more details. ## 4.0.3 - 2021-10-22 @@ -59,7 +195,7 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc **forms-flow-bpm** -* Added task listener events as configurable one's in application property. New property added is websocket.messageEvents . +* Added task listener events as configurable one's in application property. New property added is websocket.messageEvents . `Fixed` @@ -82,7 +218,6 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc * Resolved the issue of form data is not being updated from cache on claiming the form. * Identified & removed redundant calls on updating the task details. - `Modified` **forms-flow-api** @@ -100,23 +235,28 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc * Application status component created as a hidden element by default during form design. `Generic Changes` -* Added gitter community + +* Added gitter community ## 4.0.1 - 2021-07-13 `Added` **forms-flow-api** + * Support for allowing CORS with multiple comma-separated origins. * Added authorization on the application details page based on user roles. **forms-flow-bpm** + * Added new workflows - `One-Step Approval Process` and `Two-Step Approval Process`. **forms-flow-forms** + * Added new forms- `Create New Business License Application` and `Freedom of Information and Protection of Privacy`. **forms-flow-web** + * Show/hide Application Menu based on keycloak group. * Show/hide View Submissions button in form webpage based on keycloak group. * Add 404 page. @@ -125,47 +265,56 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc `Fixed` **forms-flow-analytics** + * Fixed the failing installation of the analytics component. **forms-flow-api** + * Fix application details API not displaying values to client users. * Fixed the issue of not creating applications when called from the BPM side with process-instance-id. **forms-flow-bpm** + * Fix done for authentication issue with Keycloak in the Keycloak configuration. * Fix done for single result query fetching multiple record's during formio REST call. **forms-flow-web** -* Resolve Last Modified column on the client Application page is not working. -* Fix Application search icons breaking. -* Resolve Mime type issue in the webpage. + +* Resolve Last Modified column on the client Application page is not working. +* Fix Application search icons breaking. +* Resolve Mime type issue in the webpage. `Modified` **forms-flow-bpm** + * formio token generation cycle reduced from 24 hours to 3.50 Hours. * Modified checked exception's on Listener services to Runtime exception. * Modified application logging package to Camunda base package level. **forms-flow-web** + * Modify WebSocket implementation to support reconnection in Task Menu. * Footer was modified to display formsflow.ai with the version number. `Generic Changes` + * Improved the README to document supported version for Keycloak. * Updated [usage docs](./USAGE.md) with the latest form and workflow. -* v1.0.7 release for `camunda-formio-tasklist-vue`,a Vue.js-based package for easy integration of formsflow.ai to existing projects. To know more details checkout [formsflow-ai-extension repository](https://github.com/AOT-Technologies/forms-flow-ai-extensions/tree/master/camunda-formio-tasklist-vue) +* v1.0.7 release for `camunda-formio-tasklist-vue`,a Vue.js-based package for easy integration of formsflow.ai to existing projects. To know more details checkout [formsflow-ai-extension repository](https://github.com/AOT-Technologies/forms-flow-ai-extensions/tree/master/camunda-formio-tasklist-vue) `Known Issues` -* Consoles related to http://localhost:3001/current Api Failing. The console messages can be ignored. Please refer to [Issue-#106](https://github.com/AOT-Technologies/forms-flow-ai/issues/106) for more details. + +* Consoles related to Api Failing. The console messages can be ignored. Please refer to [Issue-#106](https://github.com/AOT-Technologies/forms-flow-ai/issues/106) for more details. ## 4.0.0 - 2021-06-11 `Added` + * Added support for http calls which introduces the ability to make http calls across components for quicker and easier setup. Earlier versions required SSL support which required a lot of time and effort to setup, with a need for Keycloak server with SSL support. * User can *claim/view* the Tasklist in realtime. It provides live updates to tasks, allowing teams to collaborate on a single task list in real time. Used websockets support under the hood to make real time communication(component: forms-flow-web, forms-flow-bpm) * Automated installation steps for keycloak setup. It provides a bundled, pre-configured keycloak package for a local setup to simplify the installation process -* Automated manual steps for resource id generation, included batch and shell scripts to simplify the process. +* Automated manual steps for resource id generation, included batch and shell scripts to simplify the process. * New UI for formsflow.ai based on Vue.js for easy integration of formsflow.ai to existing projects. To know more details checkout [formsflow-ai-extension repository](https://github.com/AOT-Technologies/forms-flow-ai-extensions/tree/master/camunda-formio-tasklist-vue) and to install our [NPM package go here](https://www.npmjs.com/package/camunda-formio-tasklist-vue).(component: forms-flow-ai-extensions) * New API for health check has been included. (component : forms-flow-api) * Added confirmation messages to notify the users on save actions. (component: forms-flow-web) @@ -175,8 +324,9 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc * Added Semantic UI css for forms design (component: forms-flow-web) * Listeners are well-documented with information on purpose, how-it-works and how-to-use (component : forms-flow-bpm) [Link](./forms-flow-bpm/starter-examples/listeners/listeners-readme.md) * Support to associate an unique form at every manual task in workflow process (Component: forms-flow-bpm) - + `Modified` + * Task dashboard has been revamped with new look and feel- which would allow more control on data and stream updates. * Enhanced Form Process Mapper API and Application API endpoints (component : forms-flow-api) * Improved exception handling of python to provide meaningful error messages (component : forms-flow-api) @@ -187,11 +337,13 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc * Removed *edit/delete* submission buttons from submission list view of reviewers. `Fixed` + * Cosmetic changes to show success message after loading is completed. * Custom component (Text Area with analytics) not retaining the value after submission. (component: forms-flow-forms) * UI layout fixes (component: forms-flow-web) `Solution Component Upgrades` + * React library upgraded to latest version-17.0.2 and fixed security vulnerabilities (Component : forms-flow-web) * Spring boot upgraded to latest version-2.4.2 (Component : forms-flow-bpm) * Redash upgraded to latest version:v9 (component : forms-flow-analytics) @@ -199,10 +351,13 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc * Fixed Form.io security vulnerabilities. (component : forms-flow-forms) `Known Issues` -* Consoles related to http://localhost:3001/current Api Failing. The console messages can be ignored. Please refer to [Issue-#106](https://github.com/AOT-Technologies/forms-flow-ai/issues/106) for more details. - + +* Consoles related to Api Failing. The console messages can be ignored. Please refer to [Issue-#106](https://github.com/AOT-Technologies/forms-flow-ai/issues/106) for more details. + ## 3.1.0 - 2020-12-17 + `Modified` + * Formio upgraded to latest version-2.0.0.rc34 (Component : forms-flow-forms) * In application & task dashboard, the process diagram navigation is highlighted on the diagram (Component : forms-flow-web) * Made cosmetic changes to menu icons (Component: forms-flow-web) @@ -210,67 +365,78 @@ Mark items as `Added`, `Changed`, `Fixed`, `Removed`, `Untested Features`, `Upc * For the designer's edit scenario, by default the workflow selection & association is rendered as read-only with an option to toggle and edit(Component: forms-flow-web) `Untested Features` + * Support to associate an unique form at every manual task in workflow process (Component: forms-flow-bpm) `Fixed` + * Support to access forms-flow-ai solution in mobile(Component: forms-flow-web) * Forms flow Edit/submission Routing Fix for User with Multiple Role (Component: forms-flow-web) `Upcoming Features` + * Refactoring python api to use module *flask-resk-jsonapi* (Component: forms-flow-api) * Enhanced sorting, searching and pagination (Component: forms-flow-web) `Known Issues` + * Custom component (Text Area with analytics) not retaining the value after submission * Cosmetic changes to show success message after loading is completed ## 3.0.1 - 2020-10-08 + `Modified` + * In application dashboard, the "Application Status" column search component has been enhanced to show all possible values in dropdown (Component : forms-flow-web) * In application dashboard, the button label has been modified to show as "Acknowledge" for status "Awaiting Acknowledgement" (Component : forms-flow-web) ## 3.0.0 - 2020-10-07 + `Added` + * Logo & UI Styling * Introduced Applications menu * Versioning of form submissions * Task menu - Process Diagram, Application History * UI for configuration of forms with workflow (Designer) * Custom component `Text Area with analytics` (with configurable topics) -* Sentiment analysis API using nltk and spacy +* Sentiment analysis API using nltk and spacy `Known Issues` + * Custom component (Text Area with analytics) not retaining the value after submission * Cosmetic changes to show success message after loading is completed ## 2.0.1 - 2020-07-27 + `Added` + * This file (CHANGELOG.md) * CONTRIBUTING.md ## 2.0.0 - 2020-07-24 + `Added` + * ReDash implementation under forms-flow-analytics * Deployment folder with docker and nginx * formsflow.ai UI task dashboard -* formsflow.ai UI metrics dashboard +* formsflow.ai UI metrics dashboard * Single component installations with docker and docker-compose * Native windows intallation docker-compose-windows.yml * Native Linux installation docker-compose-linux.yml `Removed` + * forms-flow-db folder `Changed` + * All README.md files cleaned up throughout project * Environment variables rationalised and renamed to be globally generic ## 1.0.0 - 2020-04-15 -`Added` -* Initial release - - - - +`Added` +* Initial release diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index c7126d25d0..0effdc63f3 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -1,63 +1,71 @@ # Dependencies Details + In the following document, we’ll describe the details of dependencies of various components in the **formsflow.ai** solution. - ## 1. forms-flow-analytics +## 1. forms-flow-analytics + To build interactive dashboards and gain insights. - + | Component | Version| | --- | ----- | - | Redash | V9(beta)| - + | Redash | 10.1.0 | +
## 2. forms-flow-api + REST API to formsflow.ai integration components - + | Component | Version | | --- | ----- | | Python | 3.9 | | Flask | 1.1.4 | | Postgres | 11.0 | - +
- ## 3. forms-flow-bpm +## 3. forms-flow-bpm + For workflow and decision automation
- + | Component | Version| | --- | ----- | - | Camunda | 17.13.0| - | SpringBoot | 2.2.7 | - | Postgres | Latest | + | Camunda | 7.15| + | SpringBoot | 2.4.8 | + | Postgres | Latest |
- ## 4. forms-flow-forms +## 4. forms-flow-forms + To build data management applications
- + | Component | Version| | --- | ----- | - | Formio | 2.0.0--rc.34 | + | Formio | 2.3.0 | + | Mongo | 5.0 |
- - ## 5. forms-flow-idm + +## 5. forms-flow-idm + Identity Management
- + | Component | Version| | --- | ----- | | Keycloak | 7.0 and above |
- - #### NOTE: - * If you are using keycloak version **11.0 and above**, you can use the keycloak import script [mentioned here](https://github.com/AOT-Technologies/forms-flow-ai/blob/master/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json) . - * If you are in keycloak version **7.0 and above**, refer our [guide](https://github.com/AOT-Technologies/forms-flow-ai/blob/master/forms-flow-idm/keycloak/README.md#create-realm) on how to manually setup keycloak roles/users . + +#### NOTE + +* If you are using keycloak version **11.0 and above**, you can use the keycloak import script [mentioned here](https://github.com/AOT-Technologies/forms-flow-ai/blob/master/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json) . +* If you are in keycloak version **7.0 and above**, refer our [guide](https://github.com/AOT-Technologies/forms-flow-ai/blob/master/forms-flow-idm/keycloak/README.md#create-realm) on how to manually setup keycloak roles/users .
- - ## 6. forms-flow-web + +## 6. forms-flow-web + Delivers progressive web application
- + | Component | Version | | --- | --- | | React | 17.0.2 | - | Formio | 2.0.0-rc.34 | -
- + | Formio | 2.3.0 | +
diff --git a/README.md b/README.md index a50a5788e6..1b0fc9a212 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,15 @@ -
+

-[![Join the chat at https://gitter.im/forms-flow-ai/community](https://badges.gitter.im/forms-flow-ai/community.svg)](https://gitter.im/forms-flow-ai/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Join the chat at https://gitter.im/forms-flow-ai/community](https://badges.gitter.im/forms-flow-ai/community.svg)](https://gitter.im/forms-flow-ai/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://stackoverflow.com/questions/tagged/formsflow.ai](https://img.shields.io/badge/ask%20-on%20%20stackoverflow-F47F24)](https://stackoverflow.com/questions/tagged/formsflow.ai?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - + - -**formsflow.ai** is an open source solution framework developed and maintained by [AOT Technologies](https://www.aot-technologies.com/). The framework combines selected open source Forms, Workflow, Analytics, and Security products with custom-built integration code to provide a seamless solution that provides a viable alternative to expensive, enterprise software products. - - +**formsflow.ai** is an open source solution framework developed and maintained by [AOT Technologies](https://www.aot-technologies.com/). The framework combines selected open source Forms, Workflow, Analytics, and Security products with custom-built integration code to provide a seamless solution that provides a viable alternative to expensive, enterprise software products. ## Table of Contents + 1. [Introduction](#introduction) 2. [About the Project](#about-the-project) * [Features](#features) @@ -28,12 +26,14 @@ 10. [Links](#links) ## Introduction + > A brief introduction about formsflow.ai is given below. [![Introduction](./.images/formsflow-introduction.PNG)](https://youtu.be/_H-P3Av3gqg) ## About the Project -The project was initiated by [AOT Technologies](https://www.aot-technologies.com/) as a means of addressing the general situation whereby end-users fill in a form, the form is processed and there may be a requirement to report on the form metrics or data. + +The project was initiated by [AOT Technologies](https://www.aot-technologies.com/) as a means of addressing the general situation whereby end-users fill in a form, the form is processed and there may be a requirement to report on the form metrics or data. Typical use cases are: @@ -51,79 +51,80 @@ Typical use cases are: ### Features -- Drag-and-drop forms-builder with rich UI components -- Lightweight server-based workflow engine with full capabilities including human, parallel, asynchronous and timed flows, decision engine, and graphical designer -- Notifications engine for notifications, reminders, and alerts on tasks and even data thresholds. -- Metrics and data visualization dashboards for the display of key workflow and form data -- (future) Multi-tenancy isolation -- Containerized deployment with docker, docker-compose, and Openshift -- Flexible Identity Management uses existing IDM systems for authentication and single sign-on +* Drag-and-drop forms-builder with rich UI components +* Lightweight server-based workflow engine with full capabilities including human, parallel, asynchronous and timed flows, decision engine, and graphical designer +* Notifications engine for notifications, reminders, and alerts on tasks and even data thresholds. +* Metrics and data visualization dashboards for the display of key workflow and form data +* (future) Multi-tenancy isolation +* Containerized deployment with docker, docker-compose, and Openshift +* Flexible Identity Management uses existing IDM systems for authentication and single sign-on ## Download and Installation + If you want to download and setup, follow the [installation guide](./deployment), you will find step-by-step instructions to download and install. ### Project Tree - * [deployment](./deployment) Deployment of complete framework - * [docker](./deployment/docker) Deployment using docker - * [nginx](./deployment/nginx) Deployment on a remote host using nginx - * [Openshift](./deployment/openshift) Deployment using openshift platform - * [forms-flow-idm](./forms-flow-idm) Identity Management (Keycloak) - * [forms-flow-forms](./forms-flow-forms) form.io deployment and integration - * [forms-flow-bpm](./forms-flow-bpm) Camunda Workflow deployment and integration - * [forms-flow-web](./forms-flow-web) formsflow.ai integration web UI - * [forms-flow-api](./forms-flow-api) REST API to formsflow.ai integration components - * [forms-flow-analytics](./forms-flow-analytics) Redash analytics components - -Features ------------------- -- Drag-and-drop forms-builder with rich UI components -- Lightweight server-based workflow engine with full capabilities including human, parallel, asynchronous and timed flows, decision engine, and graphical designer -- Notifications engine for notifications, reminders, and alerts on tasks and even data thresholds. -- Metrics and data visualization dashboards for the display of key workflow and form data -- (future) Multi-tenancy isolation -- Containerized deployment with docker, docker-compose, and Openshift -- Flexible Identity Management uses existing IDM systems for authentication and single sign-on +* [deployment](./deployment) Deployment of complete framework + * [docker](./deployment/docker) Deployment using docker + * [nginx](./deployment/nginx) Deployment on a remote host using nginx + * [Openshift](./deployment/openshift) Deployment using openshift platform +* [forms-flow-idm](./forms-flow-idm) Identity Management (Keycloak) +* [forms-flow-forms](./forms-flow-forms) form.io deployment and integration +* [forms-flow-bpm](./forms-flow-bpm) Camunda Workflow deployment and integration +* [forms-flow-web](./forms-flow-web) formsflow.ai integration web UI +* [forms-flow-api](./forms-flow-api) REST API to formsflow.ai integration components +* [forms-flow-analytics](./forms-flow-analytics) Redash analytics components ## System Architecture - ![formsflowai component architecture](./.images/formsflow-ai-components.png) -## Components +## Components The components of the system are: + #### formsflow UI + Browser-based React integration web UI Most of the day-to-day end-user and review tasks are performed from this application, built specifically to act as a common UI combining forms, workflow, and analytics functionality. The web application is written as a [progressive](https://en.wikipedia.org/wiki/Progressive_web_application) app with the potential for offline data-entry. formsflow UI accesses the individual system component data through native API's using OIDC or SAML access tokens. #### formsflow UI Extension for Vue.js (optional) + There is a Vue.js based web user interface for easy integration of formsflow.ai to your existing User Interface. This extension provides components for easily using Forms, Tasklist by installing as a npm package. To know more details checkout [formsflow-ai-extension repository](https://github.com/AOT-Technologies/forms-flow-ai-extensions/tree/master/camunda-formio-tasklist-vue) and to install package [go here](https://www.npmjs.com/package/camunda-formio-tasklist-vue). #### Redash Admin UI + The native admin interface to Redash (bundled and unchanged). Use this to build analytics dashboards. #### Redash API + The REST interface to the Redash core. Bundled and unchanged #### Form.io API + The REST interface to the form.io core #### Camunda Admin UI + The native admin interface to Camunda (bundled and unchanged) . Use this to define workflows and to manage workflow tasks as an admin. #### REST API + Python REST API providing business logic around the internal formsflow.ai Postgres database. This API is used extensively by the formsflow.ai UI to synchronize, maintain state, extend functionality, and integrate between components. + #### Nginx Web server (optional) -Webserver providing reverse-proxy redirection and SSL to components for remote deployments. ( bundled and configured ) -#### Keycloak Identity management server -The system uses an existing (your) Keycloak server which provides a common identity management capability. The system provides default installation and provisioning of the Keycloak server for local setup, steps are mentioned [here](./forms-flow-idm/keycloak/README.md#local-keycloak-setup). -However, you can setup your own Keycloak server and follow the provisioning steps [here](./forms-flow-idm/keycloak/README.md#server-keycloak-setup). +Webserver providing reverse-proxy redirection and SSL to components for remote deployments. ( bundled and configured ) + +#### Keycloak Identity management server +The system uses an existing (your) Keycloak server which provides a common identity management capability. The system provides default installation and provisioning of the Keycloak server for local setup, steps are mentioned [here](./forms-flow-idm/keycloak/README.md#local-keycloak-setup). +However, you can setup your own Keycloak server and follow the provisioning steps [here](./forms-flow-idm/keycloak/README.md#server-keycloak-setup). ## Security Instructions + To secure formsflow.ai and understand authorization roles follow the documentation on [Security Setup](./forms-flow-idm ). ## System Operation @@ -133,9 +134,10 @@ In general, the operation is as follows : **Note** The URL links assume a local installation on the default ports as per the [installation instructions](./deployment ): #### Client -* End-user logs into formsflow.ai UI at URL- http://localhost:3000/ + +* End-user logs into formsflow.ai UI at URL- * User is redirected to Keycloak via OIDC where user's roles are returned as OIDC claims in a JWT -* User selects a form from the list of forms available. The available forms can be filtered by the user group with advanced configuration, by default the user sees all forms published. Form details are provided through form.io +* User selects a form from the list of forms available. The available forms can be filtered by the user group with advanced configuration, by default the user sees all forms published. Form details are provided through form.io * The user fills in the form and submits it * The form data is added to the Mongo DB. Details of the transaction are added to the Postgress DB * A task is created on the Camunda server corresponding to the form type @@ -143,50 +145,51 @@ In general, the operation is as follows : #### Reviewer -* Reviewer logs into formsflow.ai UI at URL- http://localhost:3000/ +* Reviewer logs into formsflow.ai UI at URL- * Reviewer is redirected to Keycloak via OIDC where the user's roles are returned as OIDC claims in a JWT. The fact that the reviewer has a reviewer role from Keycloak enables additional capabilities in the UI. -* Reviewer accesses task from task list. Tasks are retrieved through the Camunda API, filtered by the reviewer group memberships mapped between Keycloak and native Camunda. +* Reviewer accesses task from task list. Tasks are retrieved through the Camunda API, filtered by the reviewer group memberships mapped between Keycloak and native Camunda. * Reviewer claims a task and processes it. The task moves to the next step in the workflow, with appropriate notifications and actions specific to that workflow. * Reviewer can access forms from the forms list, filtered by the group permissions of the user groups as per advanced configuration. -* Reviewer can access metrics data from the Postgres database filtered according to the configuration. formsflow.ai UI renders these metrics into usable pages. -* Reviewer can access Redash analytics dashboards (as iframes). +* Reviewer can access metrics data from the Postgres database filtered according to the configuration. formsflow.ai UI renders these metrics into usable pages. +* Reviewer can access Redash analytics dashboards (as iframes). #### Designer These users are responsible for accessing the native capabilities of the embedded products to configure analytics dashboards, create and manage workflows, and create and manage forms. It is beyond the scope of this document to describe the detailed functionality of these products, however, the general process is : * Access product URL as follows: - * forms-flow-bpm: http://localhost:8000/camunda/ - * forms-flow-forms: http://localhost:3001/ (the form designer is embedded into the formsflow.ai UI) - * forms-flow-analytics: http://localhost:7000/ -* The login process is the same for all of them except for forms-flow-forms where separate credentials can be configured, redirect to Keycloak as OIDC (SAML for Redash), and obtain the appropriate JWT + claims. + * forms-flow-bpm: + * forms-flow-forms: (the form designer is embedded into the formsflow.ai UI) + * forms-flow-analytics: +* The login process is the same for all of them except for forms-flow-forms where separate credentials can be configured, redirect to Keycloak as OIDC (SAML for Redash), and obtain the appropriate JWT + claims. * For the forms designer, the FormFlow UI recognizes the additional role of forms-flow-designer and enables a form design capability * For Redash and Camunda, there is a mapping in the configuration file which needs to be setup between forms-flow-analytics and forms-flow-bpm and the corresponding groups in Redash and Camunda respectively. This is all covered in the installation instructions. ### Managing Forms - * Login to **http://localhost:3000/** using valid **[designer](./forms-flow-idm/keycloak/README.md#health-check)** credentials - * Navigate to menu **Forms** - * Click the button **+ Create Form** to launch the form designer studio. - * Design the form using **Drag and Drop** of components from LHS to RHS and publish by clicking the button **Create Form**. +* Login to **** using valid **[designer](./forms-flow-idm/keycloak/README.md#health-check)** credentials +* Navigate to menu **Forms** +* Click the button **+ Create Form** to launch the form designer studio. +* Design the form using **Drag and Drop** of components from LHS to RHS and publish by clicking the button **Create Form**. -To know more about form.io, go to https://help.form.io/userguide/introduction/. +To know more about form.io, [go to](https://help.form.io/userguide/introduction/). ### Managing Workflows -* You would need the Camunda Modeler to design your BPMN: https://camunda.com/download/modeler/ -* To learn about designing your BPMN, go to https://docs.camunda.org/get-started/quick-start/service-task/ -* To learn about deploying your BPMN, go to https://docs.camunda.org/get-started/quick-start/deploy/. Note that your default endpoint for Camunda's REST API is http://localhost:8000/camunda/engine-rest +* You would need the [Camunda Modeler to design your BPMN:](https://camunda.com/download/modeler/) +* To learn about [designing your BPMN, go to:](https://docs.camunda.org/get-started/quick-start/service-task/) +* To learn about [deploying your BPMN, go to:](https://docs.camunda.org/get-started/quick-start/deploy/). Note that your [default endpoint for Camunda's REST API is](http://localhost:8000/camunda/engine-rest). ### Managing Analytics Dashboard -* Login to **http://localhost:7000/** using valid **admin** credentials -* Create the dashboard by following the Redash [userguide](https://redash.io/help/user-guide/getting-started) +* Login to **** using valid **admin** credentials +* Create the dashboard by following the Redash [userguide](https://redash.io/help/user-guide/getting-started). + +## Quick Start - ## Quick Start We recommend you visit [Web site](https://formsflow.ai/) and read the "Getting Started" page. - - ## License + +## License Copyright 2020 AppsOnTime-Technologies 2020 @@ -206,4 +209,3 @@ limitations under the License. * [Web site](https://formsflow.ai/) * [Source code](https://github.com/AOT-Technologies/forms-flow-ai) - diff --git a/deployment/README.md b/deployment/README.md index 499feadd06..43d0d7185f 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -1,7 +1,9 @@ # Download and Installation + In the following document, we’ll describe about the different project dependencies, and the installation options being supported. ## Table of Contents + 1. [Prerequisites](#prerequisites) 2. [Project Dependencies](#project-dependencies) 3. [Download the formsflow.ai](#download-the-formsflowai) @@ -42,6 +44,7 @@ There are multiple options for installing formsflow.ai. They are given below - [Openshift Full Deployment](#Openshift-Full-Deployment) ### Docker Based Installation + ------------------ #### Docker Full Deployment @@ -58,8 +61,10 @@ Install the components in the listed order. *(NOTE: Keycloak, form.io and redash * [forms-flow-web](../forms-flow-web) formsflow.ai integration web UI ### Openshift Based Installation + ------------------ #### Openshift Full Deployment + Follow the instructions on [openshift installation guide](./openshift) ## Verifying the Installation status diff --git a/deployment/docker/README.md b/deployment/docker/README.md index 038fe694e0..2a5fda859f 100644 --- a/deployment/docker/README.md +++ b/deployment/docker/README.md @@ -1,4 +1,4 @@ -# formsflow.ai +# formsflow.ai - Docker Setup This page elaborates how to setup the overall solution using docker. @@ -77,6 +77,8 @@ Start the **analytics server** by following the instructions given [here](../../ `FORMIO_DEFAULT_PROJECT_URL`:triangular_flag_on_post:|The URL of the forms-flow-forms server||`http://{your-ip-address}:3001` `FORMIO_ROOT_EMAIL`|forms-flow-forms admin login|eg. admin@example.com|`admin@example.com` `FORMIO_ROOT_PASSWORD`|forms-flow-forms admin password|eg.changeme|`changeme` +`FORMIO_JWT_SECRET`|forms-flow-forms jwt secret| |`--- change me now ---` + * Follow the below steps for mapping the role IDs. @@ -117,6 +119,8 @@ Variable name | Meaning | Possible values | Default value | --- | --- | --- | --- `KEYCLOAK_URL`:triangular_flag_on_post:| URL to your Keycloak server || `http://{your-ip-address}:8080` `KEYCLOAK_URL_REALM`|The Keycloak realm to use|eg. forms-flow-ai | `forms-flow-ai` +`KEYCLOAK_ADMIN_USERNAME` :triangular_flag_on_post: | The admin username for Keycloak. This is used for using Keycloak internal APIs | | | +`KEYCLOAK_ADMIN_PASSWORD` :triangular_flag_on_post: | The admin password for Keycloak. | | | `KEYCLOAK_BPM_CLIENT_ID`|Client ID for Camunda to register with Keycloak|eg. forms-flow-bpm|`forms-flow-bpm` `KEYCLOAK_BPM_CLIENT_SECRET`:triangular_flag_on_post:|Client Secret of Camunda client in realm|eg. 22ce6557-6b86-4cf4-ac3b-42338c7b1ac12|must be set to your Keycloak client secret. Follow the 'Get the keycloak client secret' steps from [Here](../../forms-flow-idm/keycloak/README.md#get-the-keycloak-client-secret) `KEYCLOAK_WEB_CLIENT_ID`|Client ID for formsflow.ai to register with Keycloak|eg. forms-flow-web|`forms-flow-web` @@ -188,28 +192,28 @@ Variable name | Meaning | Possible values | Default value | ##### Camunda System Tuning ---------------------------- - - Variable name | Meaning | Possible values | Default value | - --- | --- | --- | --- - `CAMUNDA_JOB_CORE_POOL_SIZE`|Job-Executor Configuration Properties||`10` - `CAMUNDA_JOB_MAX_POOL_SIZE`|Job-Executor Configuration Properties||`20` - `CAMUNDA_JOB_QUEUE_SIZE`|Job-Executor Configuration Properties||`10` - `CAMUNDA_JOB_LOCK_TIME_MILLIS`|Job-Executor Configuration Properties||`300000` - `CAMUNDA_JOB_MAXJOBS_PER_ACQUISITION`|Job-Executor Configuration Properties||`10` - `CAMUNDA_JOB_WAIT_TIME_MILLIS`|Job-Executor Configuration Properties||`5000` - `CAMUNDA_JOB_MAX_WAIT`|Job-Executor Configuration Properties||`60000` - `CAMUNDA_METRICS_FLAG`|Job-Executor Configuration Properties||`false` + +Variable name | Meaning | Possible values | Default value | +--- | --- | --- | --- +`CAMUNDA_JOB_CORE_POOL_SIZE`|Job-Executor Configuration Properties||`10` +`CAMUNDA_JOB_MAX_POOL_SIZE`|Job-Executor Configuration Properties||`20` +`CAMUNDA_JOB_QUEUE_SIZE`|Job-Executor Configuration Properties||`10` +`CAMUNDA_JOB_LOCK_TIME_MILLIS`|Job-Executor Configuration Properties||`300000` +`CAMUNDA_JOB_MAXJOBS_PER_ACQUISITION`|Job-Executor Configuration Properties||`10` +`CAMUNDA_JOB_WAIT_TIME_MILLIS`|Job-Executor Configuration Properties||`5000` +`CAMUNDA_JOB_MAX_WAIT`|Job-Executor Configuration Properties||`60000` +`CAMUNDA_METRICS_FLAG`|Job-Executor Configuration Properties||`false` ##### Camunda formsflow.ai Integration variable settings ------------------------------------------------ - Variable name | Meaning | Possible values | Default value | - --- | --- | --- | --- - `WEBSOCKET_SECURITY_ORIGIN` :triangular_flag_on_post:|Camunda task event streaming. Origin setting, for multiple origins you can separate host address using a comma |eg:`host1, host2`|`http://{your-ip-address}:3000` - `WEBSOCKET_MESSAGE_TYPE`|Camunda task event streaming. Message type ||`TASK_EVENT` - `WEBSOCKET_ENCRYPT_KEY`|Camunda task event streaming. AES encryption of token||`giert989jkwrgb@DR55` +Variable name | Meaning | Possible values | Default value | +--- | --- | --- | --- +`WEBSOCKET_SECURITY_ORIGIN` :triangular_flag_on_post:|Camunda task event streaming. Origin setting, for multiple origins you can separate host address using a comma |eg:`host1, host2`|`http://{your-ip-address}:3000` +`WEBSOCKET_MESSAGE_TYPE`|Camunda task event streaming. Message type ||`TASK_EVENT` +`WEBSOCKET_ENCRYPT_KEY`|Camunda task event streaming. AES encryption of token||`giert989jkwrgb@DR55` - ``` +``` Modify the file **mail-config.properties** (under `forms-flow-bpm/src/main/resources/`). The default settings provided are for the Gmail server, and you need to change the credentials at the bottom of the file. Note that you want to configure your own Gmail setting to allow unsecure apps first. ``` @@ -220,6 +224,8 @@ Modify the file **mail-config.properties** (under `forms-flow-bpm/src/main/resou --- | --- | --- | --- `APP_SECURITY_ORIGIN`|CORS setup, for multiple origins you can separate host address using a comma |eg:`host1, host2`| `*` `CAMUNDA_APP_ROOT_LOG_FLAG`|Log level setting||`error` + `DATA_BUFFER_SIZE`|Configure a limit on the number of bytes that can be buffered for webclient||`2 (In MB)` + `IDENTITY_PROVIDER_MAX_RESULT_SIZE`|Maximum result size for Keycloak user queries||`250` ### Running the application * For Linux, diff --git a/deployment/docker/docker-compose-linux.yml b/deployment/docker/docker-compose-linux.yml index b3b1e25cc6..5b99a0fc2b 100644 --- a/deployment/docker/docker-compose-linux.yml +++ b/deployment/docker/docker-compose-linux.yml @@ -60,12 +60,14 @@ services: - WEBSOCKET_SECURITY_ORIGIN=${WEBSOCKET_SECURITY_ORIGIN} - WEBSOCKET_MESSAGE_TYPE=${WEBSOCKET_MESSAGE_TYPE:-TASK_EVENT} - WEBSOCKET_ENCRYPT_KEY=${WEBSOCKET_ENCRYPT_KEY:-giert989jkwrgb@DR55} + - DATA_BUFFER_SIZE=${DATA_BUFFER_SIZE:-2} + - IDENTITY_PROVIDER_MAX_RESULT_SIZE=${IDENTITY_PROVIDER_MAX_RESULT_SIZE:-250} networks: - forms-flow-network forms-flow-forms-db: container_name: forms-flow-forms-db - image: mongo + image: mongo:5.0 restart: always hostname: forms-flow-forms-db ports: @@ -102,6 +104,8 @@ services: ROOT_EMAIL: ${FORMIO_ROOT_EMAIL:-admin@example.com} ROOT_PASSWORD: ${FORMIO_ROOT_PASSWORD:-changeme} FORMIO_DOMAIN: ${FORMIO_DEFAULT_PROJECT_URL} + FORMIO_JWT_SECRET: ${FORMIO_JWT_SECRET:---- change me now ---} + stdin_open: true # -i tty: true # -t networks: @@ -127,8 +131,6 @@ services: - REACT_APP_API_PROJECT_URL=${FORMIO_DEFAULT_PROJECT_URL} - REACT_APP_KEYCLOAK_CLIENT=${KEYCLOAK_WEB_CLIENT_ID:-forms-flow-web} - REACT_APP_ANONYMOUS_ID=${ANONYMOUS_ID} - - REACT_APP_INSIGHT_API_BASE=${INSIGHT_API_URL} - - REACT_APP_INSIGHTS_API_KEY=${INSIGHT_API_KEY} - REACT_APP_WEB_BASE_URL=${FORMSFLOW_API_URL} - REACT_APP_CAMUNDA_API_URI=${CAMUNDA_API_URL} - REACT_APP_WEBSOCKET_ENCRYPT_KEY=${WEBSOCKET_ENCRYPT_KEY:-giert989jkwrgb@DR55} @@ -137,6 +139,7 @@ services: - REACT_APP_APPLICATION_NAME=${APPLICATION_NAME:-formsflow.ai} - REACT_APP_USER_ACCESS_PERMISSIONS=${USER_ACCESS_PERMISSIONS} - REACT_APP_WEB_BASE_CUSTOM_URL=${WEB_BASE_CUSTOM_URL:-} + - REACT_APP_FORMIO_JWT_SECRET=${FORMIO_JWT_SECRET:---- change me now ---} volumes: - '.:/app' - '/app/node_modules' @@ -176,6 +179,8 @@ services: volumes: - ./:/app:rw environment: + INSIGHT_API_KEY: ${INSIGHT_API_KEY} + INSIGHT_API_URL: ${INSIGHT_API_URL} DATABASE_URL: ${FORMSFLOW_API_DB_URL:-postgresql://postgres:changeme@forms-flow-webapi-db:5432/webapi} BPM_TOKEN_API: ${KEYCLOAK_URL}/auth/realms/${KEYCLOAK_URL_REALM:-forms-flow-ai}/protocol/openid-connect/token BPM_CLIENT_ID: ${KEYCLOAK_BPM_CLIENT_ID:-forms-flow-bpm} @@ -189,8 +194,11 @@ services: JWT_OIDC_AUDIENCE: ${KEYCLOAK_WEB_CLIENT_ID:-forms-flow-web} JWT_OIDC_CACHING_ENABLED: 'True' JWT_OIDC_JWKS_CACHE_TIMEOUT: 300 + KEYCLOAK_URL: ${KEYCLOAK_URL} + KEYCLOAK_URL_REALM: ${KEYCLOAK_URL_REALM:-forms-flow-ai} + KEYCLOAK_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USERNAME} + KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} WEB_API_BASE_URL: ${FORMSFLOW_API_URL} - # MONGODB_URI: ${FORMSFLOW_API_ANALYTICS_DB_URL:-mongodb://changeme:analytics@forms-flow-webapi-analytics-db:27017/analytics?authSource=admin&authMechanism=SCRAM-SHA-256} stdin_open: true # -i tty: true # -t networks: diff --git a/deployment/docker/docker-compose-windows.yml b/deployment/docker/docker-compose-windows.yml index 83bee356d1..a97ea14c40 100644 --- a/deployment/docker/docker-compose-windows.yml +++ b/deployment/docker/docker-compose-windows.yml @@ -60,12 +60,14 @@ services: - WEBSOCKET_SECURITY_ORIGIN=${WEBSOCKET_SECURITY_ORIGIN} - WEBSOCKET_MESSAGE_TYPE=${WEBSOCKET_MESSAGE_TYPE:-TASK_EVENT} - WEBSOCKET_ENCRYPT_KEY=${WEBSOCKET_ENCRYPT_KEY:-giert989jkwrgb@DR55} + - DATA_BUFFER_SIZE=${DATA_BUFFER_SIZE:-2} + - IDENTITY_PROVIDER_MAX_RESULT_SIZE=${IDENTITY_PROVIDER_MAX_RESULT_SIZE:-250} networks: - forms-flow-network forms-flow-forms-db: container_name: forms-flow-forms-db - image: mongo + image: mongo:5.0 restart: always hostname: forms-flow-forms-db ports: @@ -102,6 +104,8 @@ services: ROOT_EMAIL: ${FORMIO_ROOT_EMAIL:-admin@example.com} ROOT_PASSWORD: ${FORMIO_ROOT_PASSWORD:-changeme} FORMIO_DOMAIN: ${FORMIO_DEFAULT_PROJECT_URL} + FORMIO_JWT_SECRET: ${FORMIO_JWT_SECRET:---- change me now ---} + stdin_open: true # -i tty: true # -t networks: @@ -128,8 +132,6 @@ services: - REACT_APP_API_PROJECT_URL=${FORMIO_DEFAULT_PROJECT_URL} - REACT_APP_KEYCLOAK_CLIENT=${KEYCLOAK_WEB_CLIENT_ID:-forms-flow-web} - REACT_APP_ANONYMOUS_ID=${ANONYMOUS_ID} - - REACT_APP_INSIGHT_API_BASE=${INSIGHT_API_URL} - - REACT_APP_INSIGHTS_API_KEY=${INSIGHT_API_KEY} - REACT_APP_WEB_BASE_URL=${FORMSFLOW_API_URL} - REACT_APP_CAMUNDA_API_URI=${CAMUNDA_API_URL} - REACT_APP_WEBSOCKET_ENCRYPT_KEY=${WEBSOCKET_ENCRYPT_KEY:-giert989jkwrgb@DR55} @@ -138,6 +140,7 @@ services: - REACT_APP_APPLICATION_NAME=${APPLICATION_NAME:-formsflow.ai} - REACT_APP_USER_ACCESS_PERMISSIONS=${USER_ACCESS_PERMISSIONS} - REACT_APP_WEB_BASE_CUSTOM_URL=${WEB_BASE_CUSTOM_URL:-} + - REACT_APP_FORMIO_JWT_SECRET=${FORMIO_JWT_SECRET:---- change me now ---} volumes: - '.:/app' - '/app/node_modules' @@ -176,6 +179,8 @@ services: volumes: - ./:/app:rw environment: + INSIGHT_API_KEY: ${INSIGHT_API_KEY} + INSIGHT_API_URL: ${INSIGHT_API_URL} DATABASE_URL: ${FORMSFLOW_API_DB_URL:-postgresql://postgres:changeme@forms-flow-webapi-db:5432/webapi} BPM_TOKEN_API: ${KEYCLOAK_URL}/auth/realms/${KEYCLOAK_URL_REALM:-forms-flow-ai}/protocol/openid-connect/token BPM_CLIENT_ID: ${KEYCLOAK_BPM_CLIENT_ID:-forms-flow-bpm} @@ -189,8 +194,11 @@ services: JWT_OIDC_AUDIENCE: ${KEYCLOAK_WEB_CLIENT_ID:-forms-flow-web} JWT_OIDC_CACHING_ENABLED: 'True' JWT_OIDC_JWKS_CACHE_TIMEOUT: 300 + KEYCLOAK_URL: ${KEYCLOAK_URL} + KEYCLOAK_URL_REALM: ${KEYCLOAK_URL_REALM:-forms-flow-ai} + KEYCLOAK_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USERNAME} + KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} WEB_API_BASE_URL: ${FORMSFLOW_API_URL} - # MONGODB_URI: ${FORMSFLOW_API_ANALYTICS_DB_URL:-mongodb://changeme:analytics@forms-flow-webapi-analytics-db:27017/analytics?authSource=admin&authMechanism=SCRAM-SHA-256} stdin_open: true # -i tty: true # -t networks: diff --git a/deployment/docker/sample.env b/deployment/docker/sample.env index 9a2f936d77..237df1a5bb 100644 --- a/deployment/docker/sample.env +++ b/deployment/docker/sample.env @@ -13,6 +13,8 @@ ##URL of forms-flow-forms FORMIO_DEFAULT_PROJECT_URL=http://{your-ip-address}:3001 +#FORMIO_JWT_SECRET=--- change me now --- + #-----Environment Variables for FormIO Datastore-----# @@ -49,6 +51,10 @@ FORMIO_DEFAULT_PROJECT_URL=http://{your-ip-address}:3001 KEYCLOAK_URL=http://{your-ip-address}:8080 ##Client Secret of Camunda client in realm KEYCLOAK_BPM_CLIENT_SECRET={Client secret of forms-flow-bpm client} +# The Keycloak instances'admin username +KEYCLOAK_ADMIN_USERNAME={Keycloak admin username} +# The Keycloak instances'admin password +KEYCLOAK_ADMIN_PASSWORD={Keycloak admin password} #++++++++++++++++--- Keycloak ENV Variables - END ---+++++++++++++++++++++++++# @@ -160,5 +166,8 @@ WEBSOCKET_SECURITY_ORIGIN=http://{your-ip-address}:3000 #APP_SECURITY_ORIGIN=* #Log Settings #CAMUNDA_APP_ROOT_LOG_FLAG=error +#DATA_BUFFER_SIZE=2 +#IDENTITY_PROVIDER_MAX_RESULT_SIZE=250 #++++++++++++++++--- BPM (Camunda) ENV variable settings - END ---+++++++++++++++++++++++++# + diff --git a/deployment/nginx/conf.d/app.conf b/deployment/nginx/conf.d/app.conf index 0fbc8a5c18..9201ae2135 100644 --- a/deployment/nginx/conf.d/app.conf +++ b/deployment/nginx/conf.d/app.conf @@ -13,27 +13,22 @@ server { proxy_pass http://localhost:3000; proxy_redirect off; } - location /swagger.json { + location /swagger.json { add_header Access-Control-Allow-Origin *; - proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://207.216.46.125:5000/swagger.json; - proxy_redirect off; - } - location /swagger { - add_header Access-Control-Allow-Origin *; - proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://207.216.46.125:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://localhost:5000/swagger.json; proxy_redirect off; } location /api/ { rewrite ^/api/(.*)$ /$1 break; sub_filter ="/ ="/api/; - sub_filter ="/swagger ="/api/swagger; sub_filter_once off; sub_filter_types application/javascript text/xml text/css text/javascript application/json text/plain text/javascript"; - add_header Access-Control-Allow-Origin *; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/deployment/openshift/README.md b/deployment/openshift/README.md index ec1b0de53b..815a419216 100644 --- a/deployment/openshift/README.md +++ b/deployment/openshift/README.md @@ -1,28 +1,28 @@ -This page details deploying application in openshift. All the applicaiton are deployed using openshift templates. +# formsflow.ai - Openshift Setup + +This page details elaborates about deploying overall in openshift. All the applicaiton are deployed using openshift templates. _The templates are tested , ran and customised for running in BCGOV pathfinder OCP3 and Openshift 4 silver cluster , there could be particular places where the templates are opinionated. Feel free to alter them and generalise them for any kubernetes/openshift deployments_ - - -Every component has a build config [bc], Deployment config and might have a param file. The general syntax for running them is + +Every component has a build config [bc], Deployment config and might have a param file. The general syntax for running them is -`oc process -f web_dc.yaml --param-file=web_param.yaml |oc apply -f - --ignoreunknownparams` +`oc process -f web_dc.yaml --param-file=web_param.yaml |oc apply -f - --ignoreunknownparams` -an ideal topology will look like +an ideal topology will look like ![](forms-flow-topology.png "Deployment Topology") - Databases - ## Databases The application uses Postgres and Mongo DB for persistence.The below templates can be used as a reference to spin up new databases.Alternatively new databse schema can be created with in the existing database. ### how to deploy postgres + Postgres HA and Non-HA templates can be used. -A sample patroni templates can be found at [patroni-build.yaml](../openshift/Databases/patroni-build.yaml) , [patroni-build.yaml](../openshift/Databases/patroni-build.yaml) , [patroni-deployment.yaml](../openshift/Databases/patroni-deployment.yaml) , [patroni-deployment-prereq.yaml](../openshift/Databases/patroni-deployment-prereq.yaml) +A sample patroni templates can be found at [patroni-build.yaml](../openshift/Databases/patroni-build.yaml) , [patroni-build.yaml](../openshift/Databases/patroni-build.yaml) , [patroni-deployment.yaml](../openshift/Databases/patroni-deployment.yaml) , [patroni-deployment-prereq.yaml](../openshift/Databases/patroni-deployment-prereq.yaml) To avail the latest patroni templates ,Please refer to [BCDevOps/platform-services/patroni templates](https://github.com/BCDevOps/platform-services/tree/master/apps/pgsql/patroni) @@ -35,10 +35,10 @@ Mongo HA and Non-HA templates can be used. A sample Mongo HA template can be found at [mongo-ha.yaml](../openshift/Databases/mongo-ha.yaml) A sample Mongo non-HA templates can be found at [mongodb-nonha.yaml](../openshift/Databases/mongodb-nonha.yaml) - # Secrets and Config maps ## secrets + The forms-flow-ai secret contain most of the values which are mandatory for application to work. running the [formio_secrets_param.yaml](../openshift/formio_secrets.yaml) with proper values should create the required secret. @@ -47,18 +47,16 @@ There are other secrets which are needed as well. They are mostly Mongo , Postgr ![](secrets.png "Secrets") - ## config maps -the two major config which are required to run the application is the forms-flow-web-config and forms-flow-web-keycloak-config. +the two major config which are required to run the application is the forms-flow-web-config and forms-flow-web-keycloak-config. forms-flow-web-config contains the ids and urls required for web project to work. forms-flow-web-keycloak-config has the keycloak configs. ![](config-maps.png "Config maps") - ## Build Configs/Images - + Each project needs a build configuration and images/image stream to work with.An ideal build config will look like below. ![](bc.png "Build Config") @@ -73,14 +71,12 @@ An example deployment config will look like below [openshift_Dockerfile](/forms-flow-web/openshift_Dockerfile) [openshift_custom_Dockerfile](/forms-flow-web/openshift_custom_Dockerfile) - # Docker files the project has different deployment topoloiges and there are different docker files for each purpose as below - | filename | sample reference | Purpose | | ------------- |:-------------:| -----:| | Dockerfile | [Dockerfile](../../forms-flow-web/Dockerfile) | Dockerfile to support docker compose | | openshift_Dockerfile | [openshift_Dockerfile](../../forms-flow-web/openshift_Dockerfile) | Openshift based deployment | -| openshift_custom_Dockerfile | [openshift_custom_Dockerfile](../../forms-flow-web/openshift_custom_Dockerfile) | To allow customisation and build from this repo.Helps to copy stuff from the buidling repo and merge to the product. | \ No newline at end of file +| openshift_custom_Dockerfile | [openshift_custom_Dockerfile](../../forms-flow-web/openshift_custom_Dockerfile) | To allow customisation and build from this repo.Helps to copy stuff from the buidling repo and merge to the product. | diff --git a/deployment/openshift/camunda_dc.yaml b/deployment/openshift/camunda_dc.yaml index 4c438c6029..363f1b5851 100644 --- a/deployment/openshift/camunda_dc.yaml +++ b/deployment/openshift/camunda_dc.yaml @@ -228,6 +228,10 @@ objects: value: ${WEBSOCKET_MESSAGE_TYPE} - name: WEBSOCKET_SECURITY_ORIGIN value: ${WEBSOCKET_SECURITY_ORIGIN} + - name: DATA_BUFFER_SIZE + value: ${DATA_BUFFER_SIZE} + - name: IDENTITY_PROVIDER_MAX_RESULT_SIZE + value: ${IDENTITY_PROVIDER_MAX_RESULT_SIZE} imagePullPolicy: Always livenessProbe: failureThreshold: 3 @@ -447,4 +451,12 @@ parameters: - name: WEBSOCKET_SECURITY_ORIGIN description: WEBSOCKET_SECURITY_ORIGIN required: true - value: "" \ No newline at end of file + value: "" + - name: DATA_BUFFER_SIZE + description: Configure a limit on the number of bytes that can be buffered for webclient + required: true + value: "2097152" + - name: IDENTITY_PROVIDER_MAX_RESULT_SIZE + description: Maximum result size for Keycloak user queries + required: true + value: "250" diff --git a/deployment/openshift/camunda_param.yaml b/deployment/openshift/camunda_param.yaml index 377bfed645..76a3092074 100644 --- a/deployment/openshift/camunda_param.yaml +++ b/deployment/openshift/camunda_param.yaml @@ -10,5 +10,5 @@ CAMUNDA_JDBC_USER= CAMUNDA_FORMBUILDER_PIPELINE_BPM_URL= FORMSFLOW_API_URL= FORMIO_URL= -WEBSOCKET_ENCRYPT_KEY= #Should be same across keycloak value-can be any cvalue but should be the same +WEBSOCKET_ENCRYPT_KEY= #Should be same across Keycloak value-can be any value but should be the same WEBSOCKET_SECURITY_ORIGIN= diff --git a/deployment/openshift/formio_dc.yaml b/deployment/openshift/formio_dc.yaml index 2d3ab3a7c1..ef9bd24067 100644 --- a/deployment/openshift/formio_dc.yaml +++ b/deployment/openshift/formio_dc.yaml @@ -52,6 +52,11 @@ objects: secretKeyRef: key: formio_root_password name: ${FORMIO_SECRET} + - name: FORMIO_JWT_SECRET + valueFrom: + secretKeyRef: + key: formio_jwt_secret + name: ${FORMIO_SECRET} image: ${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} name: ${NAME} ports: @@ -199,4 +204,4 @@ parameters: description: Formio needs a default password to login generate: expression from: "[a-zA-Z0-9]{16}" - required: true \ No newline at end of file + required: true diff --git a/deployment/openshift/formio_secrets.yaml b/deployment/openshift/formio_secrets.yaml index 3d28deae1b..1689474c8a 100644 --- a/deployment/openshift/formio_secrets.yaml +++ b/deployment/openshift/formio_secrets.yaml @@ -19,6 +19,7 @@ objects: camunda_formbuilder_pipeline_username: "${CAMUNDA_FORMBUILDER_PIPELINE_USERNAME}" formio_root_email: "${FORMIO_ROOT_EMAIL}" formio_root_password: "${FORMIO_ROOT_PASSWORD}" + formio_jwt_secret: "${FORMIO_JWT_SECRET}" camunda_formbuilder_pipeline_password: "${CAMUNDA_FORMBUILDER_PIPELINE_PASSWORD}" camunda_analytics_jdbc_user: "${CAMUNDA_ANALYTICS_JDBC_USER}" camunda_analytics_jdbc_password: "${CAMUNDA_ANALYTICS_JDBC_PASSWORD}" @@ -53,6 +54,9 @@ parameters: - name: FORMIO_ROOT_PASSWORD description: FORMIO_ROOT_PASSWORD required: true + - name: FORMIO_JWT_SECRET + description: FORMIO_JWT_SECRET + required: true - name: CAMUNDA_FORMBUILDER_PIPELINE_PASSWORD description: CAMUNDA_FORMBUILDER_PIPELINE_PASSWORD required: true diff --git a/deployment/openshift/formio_secrets_param.yaml b/deployment/openshift/formio_secrets_param.yaml index 53c0818eee..ac9c28a2f8 100644 --- a/deployment/openshift/formio_secrets_param.yaml +++ b/deployment/openshift/formio_secrets_param.yaml @@ -7,6 +7,7 @@ keycloak_realm= CAMUNDA_FORMBUILDER_PIPELINE_USERNAME= FORMIO_ROOT_EMAIL= FORMIO_ROOT_PASSWORD= +FORMIO_JWT_SECRET= CAMUNDA_FORMBUILDER_PIPELINE_PASSWORD= CAMUNDA_ANALYTICS_JDBC_USER= CAMUNDA_ANALYTICS_JDBC_PASSWORD= @@ -19,4 +20,4 @@ DATABASE_SERVICE_NAME= DATABASE_PORT= DATABASE_NAME= MONGO_URI= -BPM_API_BASE= \ No newline at end of file +BPM_API_BASE= diff --git a/deployment/openshift/redash_bc.yaml b/deployment/openshift/redash_bc.yaml index d657a85b43..a374d8be8f 100644 --- a/deployment/openshift/redash_bc.yaml +++ b/deployment/openshift/redash_bc.yaml @@ -10,7 +10,7 @@ parameters: - name: SOURCE_REPOSITORY_URL displayName: Git Repository URL description: The URL of the repository with your application source code. - value: https://github.com/AOT-Technologies/redash + value: https://github.com/getredash/redash - name: SOURCE_REPOSITORY_REF displayName: Git Reference description: Set this to a branch name, tag or other ref of your repository if you are not using the default branch. @@ -30,10 +30,10 @@ objects: resources: limits: cpu: '2' - memory: 8Gi + memory: 4Gi requests: cpu: '1' - memory: 4Gi + memory: 2Gi source: git: ref: ${SOURCE_REPOSITORY_REF} @@ -45,9 +45,7 @@ objects: strategy: type: Docker dockerStrategy: - dockerfilePath: Dockerfile - pullSecret: - name: artifactory-creds + dockerfilePath: Dockerfile triggers: - type: ImageChange imageChange: {} diff --git a/deployment/openshift/redash_dc.yaml b/deployment/openshift/redash_dc.yaml index ab485be16e..08f2a5193a 100644 --- a/deployment/openshift/redash_dc.yaml +++ b/deployment/openshift/redash_dc.yaml @@ -1,592 +1,671 @@ apiVersion: template.openshift.io/v1 - kind: Template - metadata: - name: forms-flow-analytics - objects: - - kind: Secret - apiVersion: v1 - stringData: - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - PYTHONUNBUFFERED: "0" - REDASH_COOKIE_SECRET: redash-selfhosted - REDASH_DATABASE_URL: '${REDASH_DATABASE_URL}' - REDASH_HOST: '${REDASH_HOST}' - REDASH_LOG_LEVEL: INFO - REDASH_REDIS_URL: ${REDASH_REDIS_URL} - REDASH_SECRET_KEY: redash-selfhosted - metadata: - creationTimestamp: null - labels: - app: ${NAME} - name: ${NAME} +kind: Template +metadata: + name: forms-flow-analytics +objects: +- kind: Secret + apiVersion: v1 + stringData: + POSTGRES_HOST_AUTH_METHOD: trust + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + PYTHONUNBUFFERED: "0" + REDASH_DATABASE_URL: '${REDASH_DATABASE_URL}' + REDASH_HOST: '${REDASH_HOST}' + REDASH_LOG_LEVEL: INFO + REDASH_REDIS_URL: ${REDASH_REDIS_URL} + REDASH_SECRET_KEY: '${REDASH_SECRET_KEY}' + REDASH_COOKIE_SECRET: '${REDASH_COOKIE_SECRET}' + REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN: '${REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN}' + REDASH_REFERRER_POLICY: '${REDASH_REFERRER_POLICY}' + REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS: '${REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS}' - - kind: DeploymentConfig - apiVersion: apps.openshift.io/v1 - metadata: - name: ${NAME} - annotations: - creationTimestamp: null - labels: - app: ${NAME} - spec: - replicas: 1 - selector: - app: ${NAME} - strategy: - type: Rolling - rollingParams: - updatePeriodSeconds: 1 - intervalSeconds: 1 - timeoutSeconds: 600 - maxUnavailable: 25% - maxSurge: 25% - post: - execNewPod: - command: - - /bin/sh - - -c - - python ./manage.py database create_tables - failurePolicy: ignore - resources: - requests: - cpu: "${CPU_REQUEST}" - memory: "${MEMORY_REQUEST}" - limits: - cpu: "${CPU_LIMIT}" - memory: "${MEMORY_LIMIT}" - activeDeadlineSeconds: 21600 - template: - metadata: - creationTimestamp: null - labels: - app: ${NAME} - spec: - containers: - - args: - - server - env: - - name: POSTGRES_HOST_AUTH_METHOD - valueFrom: - secretKeyRef: - key: POSTGRES_HOST_AUTH_METHOD - name: ${NAME} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - key: POSTGRES_PASSWORD - name: ${NAME} - - name: PYTHONUNBUFFERED - valueFrom: - secretKeyRef: - key: PYTHONUNBUFFERED - name: ${NAME} - - name: REDASH_COOKIE_SECRET - valueFrom: - secretKeyRef: - key: REDASH_COOKIE_SECRET - name: ${NAME} - - name: REDASH_DATABASE_URL - valueFrom: - secretKeyRef: - key: REDASH_DATABASE_URL - name: ${NAME} - - name: REDASH_HOST - valueFrom: - secretKeyRef: - key: REDASH_HOST - name: ${NAME} - - name: REDASH_LOG_LEVEL - valueFrom: - secretKeyRef: - key: REDASH_LOG_LEVEL - name: ${NAME} - - name: REDASH_REDIS_URL - valueFrom: - secretKeyRef: - key: REDASH_REDIS_URL - name: ${NAME} - - name: REDASH_SECRET_KEY - valueFrom: - secretKeyRef: - key: REDASH_SECRET_KEY - name: ${NAME} - - name: REDASH_WEB_WORKERS - value: "4" - image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} - name: ${NAME} - ports: - - containerPort: 5000 - protocol: TCP - resources: {} - restartPolicy: Always - triggers: - - type: ConfigChange - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - ${NAME} - from: - kind: ImageStreamTag - namespace: "${IMAGE_NAMESPACE}" - name: "${NAME}:${TAG_NAME}" - status: {} + metadata: + creationTimestamp: null + labels: + app: ${NAME} + name: ${NAME} - - kind: DeploymentConfig - apiVersion: apps.openshift.io/v1 - metadata: - annotations: - creationTimestamp: null - labels: - app: ${NAME}-adhoc-worker - name: ${NAME}-adhoc-worker - spec: - replicas: 1 - selector: - app: ${NAME}-adhoc-worker - strategy: - resources: {} - template: - metadata: - creationTimestamp: null - labels: - app: ${NAME}-adhoc-worker - spec: - containers: - - args: - - worker - env: - - name: POSTGRES_HOST_AUTH_METHOD - valueFrom: - secretKeyRef: - key: POSTGRES_HOST_AUTH_METHOD - name: ${NAME} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - key: POSTGRES_PASSWORD - name: ${NAME} - - name: PYTHONUNBUFFERED - valueFrom: - secretKeyRef: - key: PYTHONUNBUFFERED - name: ${NAME} - - name: QUEUES - value: queries - - name: REDASH_COOKIE_SECRET - valueFrom: - secretKeyRef: - key: REDASH_COOKIE_SECRET - name: ${NAME} - - name: REDASH_DATABASE_URL - valueFrom: - secretKeyRef: - key: REDASH_DATABASE_URL - name: ${NAME} - - name: REDASH_HOST - valueFrom: - secretKeyRef: - key: REDASH_HOST - name: ${NAME} - - name: REDASH_LOG_LEVEL - valueFrom: - secretKeyRef: - key: REDASH_LOG_LEVEL - name: ${NAME} - - name: REDASH_REDIS_URL - valueFrom: - secretKeyRef: - key: REDASH_REDIS_URL - name: ${NAME} - - name: REDASH_SECRET_KEY - valueFrom: - secretKeyRef: - key: REDASH_SECRET_KEY - name: ${NAME} - - name: WORKERS_COUNT - value: "2" - image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} - name: ${NAME}-adhoc-worker - resources: {} - restartPolicy: Always - test: false - triggers: +- kind: DeploymentConfig + apiVersion: apps.openshift.io/v1 + metadata: + name: ${NAME} + annotations: + creationTimestamp: null + labels: + app: ${NAME} + spec: + replicas: 1 + selector: + app: ${NAME} + strategy: + type: Rolling + rollingParams: + updatePeriodSeconds: 1 + intervalSeconds: 1 + timeoutSeconds: 600 + maxUnavailable: 25% + maxSurge: 25% + post: + execNewPod: + command: + - /bin/sh + - -c + - python ./manage.py database create_tables + failurePolicy: ignore + resources: + requests: + cpu: "${CPU_REQUEST}" + memory: "${MEMORY_REQUEST}" + limits: + cpu: "${CPU_LIMIT}" + memory: "${MEMORY_LIMIT}" + activeDeadlineSeconds: 21600 + template: + metadata: + creationTimestamp: null + labels: + app: ${NAME} + spec: + containers: + - args: + - server + env: + - name: POSTGRES_HOST_AUTH_METHOD + valueFrom: + secretKeyRef: + key: POSTGRES_HOST_AUTH_METHOD + name: ${NAME} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: POSTGRES_PASSWORD + name: ${NAME} + - name: PYTHONUNBUFFERED + valueFrom: + secretKeyRef: + key: PYTHONUNBUFFERED + name: ${NAME} + - name: REDASH_COOKIE_SECRET + valueFrom: + secretKeyRef: + key: REDASH_COOKIE_SECRET + name: ${NAME} + - name: REDASH_DATABASE_URL + valueFrom: + secretKeyRef: + key: REDASH_DATABASE_URL + name: ${NAME} + - name: REDASH_HOST + valueFrom: + secretKeyRef: + key: REDASH_HOST + name: ${NAME} + - name: REDASH_LOG_LEVEL + valueFrom: + secretKeyRef: + key: REDASH_LOG_LEVEL + name: ${NAME} + - name: REDASH_REDIS_URL + valueFrom: + secretKeyRef: + key: REDASH_REDIS_URL + name: ${NAME} + - name: REDASH_SECRET_KEY + valueFrom: + secretKeyRef: + key: REDASH_SECRET_KEY + name: ${NAME} + - name: REDASH_REFERRER_POLICY + valueFrom: + secretKeyRef: + key: REDASH_REFERRER_POLICY + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + name: ${NAME} + - name: REDASH_WEB_WORKERS + value: "4" + image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} + name: ${NAME} + ports: + - containerPort: 5000 + protocol: TCP + resources: {} + restartPolicy: Always + triggers: - type: ConfigChange - - imageChangeParams: + - type: ImageChange + imageChangeParams: automatic: true containerNames: - - ${NAME}-adhoc-worker + - ${NAME} from: - kind: ImageStreamTag - namespace: "${IMAGE_NAMESPACE}" - name: "${NAME}:${TAG_NAME}" - type: ImageChange - status: {} + kind: ImageStreamTag + namespace: "${IMAGE_NAMESPACE}" + name: "${NAME}:${TAG_NAME}" + status: {} - - kind: DeploymentConfig - apiVersion: apps.openshift.io/v1 - metadata: - annotations: - creationTimestamp: null - labels: - app: ${NAME}-scheduled-worker - name: ${NAME}-scheduled-worker - spec: - replicas: 1 - selector: - app: ${NAME}-scheduled-worker - strategy: - resources: {} - template: - metadata: - creationTimestamp: null - labels: - app: ${NAME}-scheduled-worker - spec: - containers: - - args: - - worker - env: - - name: POSTGRES_HOST_AUTH_METHOD - valueFrom: - secretKeyRef: - key: POSTGRES_HOST_AUTH_METHOD - name: ${NAME} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - key: POSTGRES_PASSWORD - name: ${NAME} - - name: PYTHONUNBUFFERED - valueFrom: - secretKeyRef: - key: PYTHONUNBUFFERED - name: ${NAME} - - name: QUEUES - value: scheduled_queries,schemas - - name: REDASH_COOKIE_SECRET - valueFrom: - secretKeyRef: - key: REDASH_COOKIE_SECRET - name: ${NAME} - - name: REDASH_DATABASE_URL - valueFrom: - secretKeyRef: - key: REDASH_DATABASE_URL - name: ${NAME} - - name: REDASH_HOST - valueFrom: - secretKeyRef: - key: REDASH_HOST - name: ${NAME} - - name: REDASH_LOG_LEVEL - valueFrom: - secretKeyRef: - key: REDASH_LOG_LEVEL - name: ${NAME} - - name: REDASH_REDIS_URL - valueFrom: - secretKeyRef: - key: REDASH_REDIS_URL - name: ${NAME} - - name: REDASH_SECRET_KEY - valueFrom: - secretKeyRef: - key: REDASH_SECRET_KEY - name: ${NAME} - - name: WORKERS_COUNT - value: "1" - image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} - name: ${NAME}-scheduled-worker - resources: {} - restartPolicy: Always - test: false - triggers: - - type: ConfigChange - - imageChangeParams: - automatic: true - containerNames: - - ${NAME}-scheduled-worker - from: - kind: ImageStreamTag - namespace: "${IMAGE_NAMESPACE}" - name: "${NAME}:${TAG_NAME}" - type: ImageChange - status: {} +- kind: DeploymentConfig + apiVersion: apps.openshift.io/v1 + metadata: + annotations: + creationTimestamp: null + labels: + app: ${NAME}-adhoc-worker + name: ${NAME}-adhoc-worker + spec: + replicas: 1 + selector: + app: ${NAME}-adhoc-worker + strategy: + resources: {} + template: + metadata: + creationTimestamp: null + labels: + app: ${NAME}-adhoc-worker + spec: + containers: + - args: + - worker + env: + - name: POSTGRES_HOST_AUTH_METHOD + valueFrom: + secretKeyRef: + key: POSTGRES_HOST_AUTH_METHOD + name: ${NAME} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: POSTGRES_PASSWORD + name: ${NAME} + - name: PYTHONUNBUFFERED + valueFrom: + secretKeyRef: + key: PYTHONUNBUFFERED + name: ${NAME} + - name: QUEUES + value: queries + - name: REDASH_COOKIE_SECRET + valueFrom: + secretKeyRef: + key: REDASH_COOKIE_SECRET + name: ${NAME} + - name: REDASH_DATABASE_URL + valueFrom: + secretKeyRef: + key: REDASH_DATABASE_URL + name: ${NAME} + - name: REDASH_HOST + valueFrom: + secretKeyRef: + key: REDASH_HOST + name: ${NAME} + - name: REDASH_LOG_LEVEL + valueFrom: + secretKeyRef: + key: REDASH_LOG_LEVEL + name: ${NAME} + - name: REDASH_REDIS_URL + valueFrom: + secretKeyRef: + key: REDASH_REDIS_URL + name: ${NAME} + - name: REDASH_SECRET_KEY + valueFrom: + secretKeyRef: + key: REDASH_SECRET_KEY + name: ${NAME} + - name: REDASH_REFERRER_POLICY + valueFrom: + secretKeyRef: + key: REDASH_REFERRER_POLICY + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + name: ${NAME} + - name: WORKERS_COUNT + value: "2" + image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} + name: ${NAME}-adhoc-worker + resources: {} + restartPolicy: Always + test: false + triggers: + - type: ConfigChange + - imageChangeParams: + automatic: true + containerNames: + - ${NAME}-adhoc-worker + from: + kind: ImageStreamTag + namespace: "${IMAGE_NAMESPACE}" + name: "${NAME}:${TAG_NAME}" + type: ImageChange + status: {} - - kind: DeploymentConfig - apiVersion: apps.openshift.io/v1 - metadata: - annotations: - creationTimestamp: null - labels: - app: ${NAME}-scheduler - name: ${NAME}-scheduler - spec: - replicas: 1 - selector: - app: ${NAME}-scheduler - strategy: - resources: {} - template: - metadata: - creationTimestamp: null - labels: - app: ${NAME}-scheduler - spec: - containers: - - args: - - scheduler - env: - - name: POSTGRES_HOST_AUTH_METHOD - valueFrom: - secretKeyRef: - key: POSTGRES_HOST_AUTH_METHOD - name: ${NAME} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - key: POSTGRES_PASSWORD - name: ${NAME} - - name: PYTHONUNBUFFERED - valueFrom: - secretKeyRef: - key: PYTHONUNBUFFERED - name: ${NAME} - - name: REDASH_COOKIE_SECRET - valueFrom: - secretKeyRef: - key: REDASH_COOKIE_SECRET - name: ${NAME} - - name: REDASH_DATABASE_URL - valueFrom: - secretKeyRef: - key: REDASH_DATABASE_URL - name: ${NAME} - - name: REDASH_HOST - valueFrom: - secretKeyRef: - key: REDASH_HOST - name: ${NAME} - - name: REDASH_LOG_LEVEL - valueFrom: - secretKeyRef: - key: REDASH_LOG_LEVEL - name: ${NAME} - - name: REDASH_REDIS_URL - valueFrom: - secretKeyRef: - key: REDASH_REDIS_URL - name: ${NAME} - - name: REDASH_SECRET_KEY - valueFrom: - secretKeyRef: - key: REDASH_SECRET_KEY - name: ${NAME} - image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} - name: ${NAME}-scheduler - resources: {} - restartPolicy: Always - test: false - triggers: - - type: ConfigChange - - imageChangeParams: - automatic: true - containerNames: - - ${NAME}-scheduler - from: - kind: ImageStreamTag - namespace: "${IMAGE_NAMESPACE}" - name: "${NAME}:${TAG_NAME}" - type: ImageChange - status: {} +- kind: DeploymentConfig + apiVersion: apps.openshift.io/v1 + metadata: + annotations: + creationTimestamp: null + labels: + app: ${NAME}-scheduled-worker + name: ${NAME}-scheduled-worker + spec: + replicas: 1 + selector: + app: ${NAME}-scheduled-worker + strategy: + resources: {} + template: + metadata: + creationTimestamp: null + labels: + app: ${NAME}-scheduled-worker + spec: + containers: + - args: + - worker + env: + - name: POSTGRES_HOST_AUTH_METHOD + valueFrom: + secretKeyRef: + key: POSTGRES_HOST_AUTH_METHOD + name: ${NAME} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: POSTGRES_PASSWORD + name: ${NAME} + - name: PYTHONUNBUFFERED + valueFrom: + secretKeyRef: + key: PYTHONUNBUFFERED + name: ${NAME} + - name: QUEUES + value: scheduled_queries,schemas + - name: REDASH_COOKIE_SECRET + valueFrom: + secretKeyRef: + key: REDASH_COOKIE_SECRET + name: ${NAME} + - name: REDASH_DATABASE_URL + valueFrom: + secretKeyRef: + key: REDASH_DATABASE_URL + name: ${NAME} + - name: REDASH_HOST + valueFrom: + secretKeyRef: + key: REDASH_HOST + name: ${NAME} + - name: REDASH_LOG_LEVEL + valueFrom: + secretKeyRef: + key: REDASH_LOG_LEVEL + name: ${NAME} + - name: REDASH_REDIS_URL + valueFrom: + secretKeyRef: + key: REDASH_REDIS_URL + name: ${NAME} + - name: REDASH_SECRET_KEY + valueFrom: + secretKeyRef: + key: REDASH_SECRET_KEY + name: ${NAME} + - name: REDASH_REFERRER_POLICY + valueFrom: + secretKeyRef: + key: REDASH_REFERRER_POLICY + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + name: ${NAME} + - name: WORKERS_COUNT + value: "1" + image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} + name: ${NAME}-scheduled-worker + resources: {} + restartPolicy: Always + test: false + triggers: + - type: ConfigChange + - imageChangeParams: + automatic: true + containerNames: + - ${NAME}-scheduled-worker + from: + kind: ImageStreamTag + namespace: "${IMAGE_NAMESPACE}" + name: "${NAME}:${TAG_NAME}" + type: ImageChange + status: {} - - kind: DeploymentConfig - apiVersion: apps.openshift.io/v1 - metadata: - annotations: - creationTimestamp: null - labels: - app: ${NAME}-worker - name: ${NAME}-worker - spec: - replicas: 1 - selector: - app: ${NAME}-worker - strategy: - resources: {} - template: - metadata: - creationTimestamp: null - labels: - app: ${NAME}-worker - spec: - containers: - - args: - - worker - env: - - name: POSTGRES_HOST_AUTH_METHOD - valueFrom: - secretKeyRef: - key: POSTGRES_HOST_AUTH_METHOD - name: ${NAME} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - key: POSTGRES_PASSWORD - name: ${NAME} - - name: PYTHONUNBUFFERED - valueFrom: - secretKeyRef: - key: PYTHONUNBUFFERED - name: ${NAME} - - name: QUEUES - value: periodic emails default - - name: REDASH_COOKIE_SECRET - valueFrom: - secretKeyRef: - key: REDASH_COOKIE_SECRET - name: ${NAME} - - name: REDASH_DATABASE_URL - valueFrom: - secretKeyRef: - key: REDASH_DATABASE_URL - name: ${NAME} - - name: REDASH_HOST - valueFrom: - secretKeyRef: - key: REDASH_HOST - name: ${NAME} - - name: REDASH_LOG_LEVEL - valueFrom: - secretKeyRef: - key: REDASH_LOG_LEVEL - name: ${NAME} - - name: REDASH_REDIS_URL - valueFrom: - secretKeyRef: - key: REDASH_REDIS_URL - name: ${NAME} - - name: REDASH_SECRET_KEY - valueFrom: - secretKeyRef: - key: REDASH_SECRET_KEY - name: ${NAME} - - name: WORKERS_COUNT - value: "1" - image: ' ' - name: ${NAME}-worker - resources: {} - restartPolicy: Always - test: false - triggers: - - type: ConfigChange - - imageChangeParams: - automatic: true - containerNames: - - ${NAME}-worker - from: - kind: ImageStreamTag - namespace: "${IMAGE_NAMESPACE}" - name: "${NAME}:${TAG_NAME}" - type: ImageChange - status: {} +- kind: DeploymentConfig + apiVersion: apps.openshift.io/v1 + metadata: + annotations: + creationTimestamp: null + labels: + app: ${NAME}-scheduler + name: ${NAME}-scheduler + spec: + replicas: 1 + selector: + app: ${NAME}-scheduler + strategy: + resources: {} + template: + metadata: + creationTimestamp: null + labels: + app: ${NAME}-scheduler + spec: + containers: + - args: + - scheduler + env: + - name: POSTGRES_HOST_AUTH_METHOD + valueFrom: + secretKeyRef: + key: POSTGRES_HOST_AUTH_METHOD + name: ${NAME} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: POSTGRES_PASSWORD + name: ${NAME} + - name: PYTHONUNBUFFERED + valueFrom: + secretKeyRef: + key: PYTHONUNBUFFERED + name: ${NAME} + - name: REDASH_COOKIE_SECRET + valueFrom: + secretKeyRef: + key: REDASH_COOKIE_SECRET + name: ${NAME} + - name: REDASH_DATABASE_URL + valueFrom: + secretKeyRef: + key: REDASH_DATABASE_URL + name: ${NAME} + - name: REDASH_HOST + valueFrom: + secretKeyRef: + key: REDASH_HOST + name: ${NAME} + - name: REDASH_LOG_LEVEL + valueFrom: + secretKeyRef: + key: REDASH_LOG_LEVEL + name: ${NAME} + - name: REDASH_REDIS_URL + valueFrom: + secretKeyRef: + key: REDASH_REDIS_URL + name: ${NAME} + - name: REDASH_SECRET_KEY + valueFrom: + secretKeyRef: + key: REDASH_SECRET_KEY + name: ${NAME} + - name: REDASH_REFERRER_POLICY + valueFrom: + secretKeyRef: + key: REDASH_REFERRER_POLICY + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + name: ${NAME} + image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} + name: ${NAME}-scheduler + resources: {} + restartPolicy: Always + test: false + triggers: + - type: ConfigChange + - imageChangeParams: + automatic: true + containerNames: + - ${NAME}-scheduler + from: + kind: ImageStreamTag + namespace: "${IMAGE_NAMESPACE}" + name: "${NAME}:${TAG_NAME}" + type: ImageChange + status: {} - - kind: Service - apiVersion: v1 +- kind: DeploymentConfig + apiVersion: apps.openshift.io/v1 + metadata: + annotations: + creationTimestamp: null + labels: + app: ${NAME}-worker + name: ${NAME}-worker + spec: + replicas: 1 + selector: + app: ${NAME}-worker + strategy: + resources: {} + template: metadata: - name: ${NAME} - annotations: - creationTimestamp: null - labels: - app: ${NAME} - name: ${NAME} + creationTimestamp: null + labels: + app: ${NAME}-worker spec: - ports: - - name: "7000" - port: 7000 - targetPort: 5000 - selector: - app: ${NAME} - status: - loadBalancer: {} + containers: + - args: + - worker + env: + - name: POSTGRES_HOST_AUTH_METHOD + valueFrom: + secretKeyRef: + key: POSTGRES_HOST_AUTH_METHOD + name: ${NAME} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: POSTGRES_PASSWORD + name: ${NAME} + - name: PYTHONUNBUFFERED + valueFrom: + secretKeyRef: + key: PYTHONUNBUFFERED + name: ${NAME} + - name: QUEUES + value: periodic emails default + - name: REDASH_COOKIE_SECRET + valueFrom: + secretKeyRef: + key: REDASH_COOKIE_SECRET + name: ${NAME} + - name: REDASH_DATABASE_URL + valueFrom: + secretKeyRef: + key: REDASH_DATABASE_URL + name: ${NAME} + - name: REDASH_HOST + valueFrom: + secretKeyRef: + key: REDASH_HOST + name: ${NAME} + - name: REDASH_LOG_LEVEL + valueFrom: + secretKeyRef: + key: REDASH_LOG_LEVEL + name: ${NAME} + - name: REDASH_REDIS_URL + valueFrom: + secretKeyRef: + key: REDASH_REDIS_URL + name: ${NAME} + - name: REDASH_SECRET_KEY + valueFrom: + secretKeyRef: + key: REDASH_SECRET_KEY + name: ${NAME} + - name: REDASH_REFERRER_POLICY + valueFrom: + secretKeyRef: + key: REDASH_REFERRER_POLICY + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS + name: ${NAME} + - name: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + valueFrom: + secretKeyRef: + key: REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN + name: ${NAME} + - name: WORKERS_COUNT + value: "1" + image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} + name: ${NAME}-worker + resources: {} + restartPolicy: Always + test: false + triggers: + - type: ConfigChange + - imageChangeParams: + automatic: true + containerNames: + - ${NAME}-worker + from: + kind: ImageStreamTag + namespace: "${IMAGE_NAMESPACE}" + name: "${NAME}:${TAG_NAME}" + type: ImageChange + status: {} - - apiVersion: route.openshift.io/v1 - kind: Route +- kind: Service + apiVersion: v1 metadata: - labels: - app: ${NAME} name: ${NAME} + annotations: + creationTimestamp: null + labels: + app: ${NAME} + name: ${NAME} spec: - host: ${FFA_ANALYTICS_URL} - path: / - tls: - insecureEdgeTerminationPolicy: Redirect - termination: edge - to: - kind: Service - name: ${NAME} - port: - targetPort: '7000' - wildcardPolicy: None + ports: + - name: "7000" + port: 7000 + targetPort: 5000 + selector: + app: ${NAME} + status: + loadBalancer: {} + +- apiVersion: route.openshift.io/v1 + kind: Route + metadata: + labels: + app: ${NAME} + name: ${NAME} + spec: + host: ${FFA_ANALYTICS_URL} + path: / + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: ${NAME} + port: + targetPort: '7000' + wildcardPolicy: None - parameters: - - name: NAME - displayName: Name - description: The name assigned to all of the OpenShift resources associated to the - server instance. - required: true - value: forms-flow-analytics - - name: IMAGE_NAMESPACE - displayName: Image Namespace - required: true - description: The namespace of the OpenShift project containing the imagestream for - the application. - value: nzpnbz-tools - - name: TAG_NAME - displayName: Environment TAG name - description: The TAG name for this environment, e.g., dev, test, prod - required: true - value: latest - - name: CPU_REQUEST - displayName: Resources CPU Request - description: The resources CPU request (in cores) for this build. - required: true - value: 500m - - name: CPU_LIMIT - displayName: Resources CPU Limit - description: The resources CPU limit (in cores) for this build. - required: true - value: 1000m - - name: MEMORY_REQUEST - displayName: Resources Memory Request - description: The resources Memory request (in Mi, Gi, etc) for this build. - required: true - value: 1Gi - - name: MEMORY_LIMIT - displayName: Resources Memory Limit - description: The resources Memory limit (in Mi, Gi, etc) for this build. - required: true - value: 2Gi - - name: FFA_ANALYTICS_URL - displayName: FFA_ANALYTICS_URL - description: - Route to access FFA WEB API - required: true - - name: POSTGRES_PASSWORD - displayName: POSTGRES_PASSWORD - description: Postgres Password - required: true - - name: REDASH_DATABASE_URL - displayName: REDASH_DATABASE_URL - description: REDASH_DATABASE_URL - required: true - - name: REDASH_HOST - displayName: REDASH_HOST - description: REDASH_HOST - required: true - - name: REDASH_REDIS_URL - displayName: REDASH_REDIS_URL - description: REDASH_REDIS_URL - required: true +parameters: + - name: NAME + displayName: Name + description: The name assigned to all of the OpenShift resources associated to the + server instance. + required: true + value: forms-flow-analytics + - name: IMAGE_NAMESPACE + displayName: Image Namespace + required: true + description: The namespace of the OpenShift project containing the imagestream for + the application. + #value: 7d3aa1-dev + - name: TAG_NAME + displayName: Environment TAG name + description: The TAG name for this environment, e.g., dev, test, prod + required: true + value: latest + - name: CPU_REQUEST + displayName: Resources CPU Request + description: The resources CPU request (in cores) for this build. + required: true + value: 500m + - name: CPU_LIMIT + displayName: Resources CPU Limit + description: The resources CPU limit (in cores) for this build. + required: true + value: 1000m + - name: MEMORY_REQUEST + displayName: Resources Memory Request + description: The resources Memory request (in Mi, Gi, etc) for this build. + required: true + value: 1Gi + - name: MEMORY_LIMIT + displayName: Resources Memory Limit + description: The resources Memory limit (in Mi, Gi, etc) for this build. + required: true + value: 2Gi + - name: FFA_ANALYTICS_URL + displayName: FFA_ANALYTICS_URL + description: + Route to access FFA WEB API + required: true + - name: POSTGRES_PASSWORD + displayName: POSTGRES_PASSWORD + description: Postgres Password + required: true + - name: REDASH_DATABASE_URL + displayName: REDASH_DATABASE_URL + description: REDASH_DATABASE_URL + required: true + - name: REDASH_HOST + displayName: REDASH_HOST + description: REDASH_HOST + required: true + - name: REDASH_REDIS_URL + displayName: REDASH_REDIS_URL + description: REDASH_REDIS_URL + required: true diff --git a/deployment/openshift/redash_param.yaml b/deployment/openshift/redash_param.yaml index 8cbc38be5f..d6214aca8b 100644 --- a/deployment/openshift/redash_param.yaml +++ b/deployment/openshift/redash_param.yaml @@ -1,6 +1,12 @@ IMAGE_NAMESPACE= +TAG_NAME=latest FFA_ANALYTICS_URL= -POSTGRES_PASSWORD: -REDASH_DATABASE_URL: -REDASH_HOST: -REDASH_REDIS_URL: \ No newline at end of file +POSTGRES_PASSWORD= +REDASH_DATABASE_URL= +REDASH_HOST= +REDASH_REDIS_URL=redis://redis:6379/0 +REDASH_SECRET_KEY=redash-selfhosted +REDASH_COOKIE_SECRET=redash-selfhosted +REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN=* +REDASH_REFERRER_POLICY=no-referrer-when-downgrade +REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS=Content-Type, Authorization diff --git a/deployment/openshift/web_dc.yaml b/deployment/openshift/web_dc.yaml index 364fb33f5c..428b8940ff 100644 --- a/deployment/openshift/web_dc.yaml +++ b/deployment/openshift/web_dc.yaml @@ -45,12 +45,12 @@ objects: "REACT_APP_KEYCLOAK_CLIENT": "forms-flow-web", "REACT_APP_WEB_BASE_URL": "${REACT_APP_WEB_BASE_URL}", "REACT_APP_ANONYMOUS_ID": "${REACT_APP_ANONYMOUS_ID}", - "REACT_APP_INSIGHT_API_BASE": "${REACT_APP_INSIGHT_API_BASE}", - "REACT_APP_INSIGHTS_API_KEY": "{REACT_APP_INSIGHTS_API_KEY}", "REACT_APP_WEBSOCKET_ENCRYPT_KEY": "{REACT_APP_WEBSOCKET_ENCRYPT_KEY}", "REACT_APP_KEYCLOAK_URL_REALM": "${REALM}", "REACT_APP_KEYCLOAK_URL": "${REACT_APP_KEYCLOAK_URL}", - "REACT_APP_APPLICATION_NAME": "${REACT_APP_APPLICATION_NAME}" + "REACT_APP_APPLICATION_NAME": "${REACT_APP_APPLICATION_NAME}", + "REACT_APP_WEB_BASE_CUSTOM_URL": "${REACT_APP_WEB_BASE_CUSTOM_URL}", + "REACT_APP_USER_ACCESS_PERMISSIONS": "${REACT_APP_USER_ACCESS_PERMISSIONS}" } - @@ -265,14 +265,6 @@ parameters: description: Route to access Forms Flow AI Web site required: true - - name: REACT_APP_INSIGHT_API_BASE - displayName: REACT_APP_INSIGHT_API_BASE - description: - required: true - - name: REACT_APP_INSIGHTS_API_KEY - displayName: REACT_APP_INSIGHTS_API_KEY - description: - required: true - name: REACT_APP_WEBSOCKET_ENCRYPT_KEY displayName: REACT_APP_WEBSOCKET_ENCRYPT_KEY description: @@ -292,4 +284,12 @@ parameters: - name: REACT_APP_APPLICATION_NAME displayName: REACT_APP_APPLICATION_NAME description: the name displayed in the application home page - required: true \ No newline at end of file + required: true + - name: REACT_APP_USER_ACCESS_PERMISSIONS + displayName: REACT_APP_USER_ACCESS_PERMISSIONS + description: JSON formatted permissions to enable / disable few access on user login + required: true + - name: REACT_APP_WEB_BASE_CUSTOM_URL + displayName: REACT_APP_WEB_BASE_CUSTOM_URL + description: Clients can use this env variable to provide their custom URL + required: false diff --git a/deployment/openshift/web_param.yaml b/deployment/openshift/web_param.yaml index 477d32ed5b..ff1ed30968 100644 --- a/deployment/openshift/web_param.yaml +++ b/deployment/openshift/web_param.yaml @@ -12,6 +12,7 @@ REACT_APP_API_PROJECT_URL= REACT_APP_API_SERVER_URL= AUTH_SERVER_URL= REALM: -REACT_APP_INSIGHT_API_BASE: -REACT_APP_INSIGHTS_API_KEY: -REACT_APP_WEBSOCKET_ENCRYPT_KEY: \ No newline at end of file +REACT_APP_WEBSOCKET_ENCRYPT_KEY: +REACT_APP_APPLICATION_NAME= +REACT_APP_USER_ACCESS_PERMISSIONS={"accessAllowApplications":true, "accessAllowSubmissions":true} +REACT_APP_WEB_BASE_CUSTOM_URL= diff --git a/deployment/openshift/webapi_bc.yaml b/deployment/openshift/webapi_bc.yaml index 1f3a174872..f3996d09e5 100644 --- a/deployment/openshift/webapi_bc.yaml +++ b/deployment/openshift/webapi_bc.yaml @@ -46,7 +46,7 @@ objects: strategy: type: Docker dockerStrategy: - dockerfilePath: Openshift_Dockerfile + dockerfilePath: openshift_custom_Dockerfile triggers: - type: ImageChange imageChange: {} @@ -56,4 +56,4 @@ objects: apiVersion: image.openshift.io/v1 kind: ImageStream metadata: - name: forms-flow-webapi \ No newline at end of file + name: forms-flow-webapi diff --git a/deployment/openshift/webapi_dc.yaml b/deployment/openshift/webapi_dc.yaml index e0bfe8032a..9f8607e2dd 100644 --- a/deployment/openshift/webapi_dc.yaml +++ b/deployment/openshift/webapi_dc.yaml @@ -35,77 +35,94 @@ objects: spec: containers: - env: - - name: MONGODB_URI + - name: BPM_API_BASE + valueFrom: + configMapKeyRef: + key: CAMUNDA_API_URI + name: ${FORMSFLOW_CONFIG_NAME}-config + - name: INSIGHTS_API_BASE valueFrom: secretKeyRef: - key: MONGODB_URI - name: ${FORMIO_SECRET} - - name: BPM_API_BASE + key: INSIGHTS_API_BASE + name: ${FORMSFLOW_CONFIG_NAME}-config + - name: INSIGHTS_API_KEY + valueFrom: + secretKeyRef: + key: INSIGHTS_API_KEY + name: ${FORMSFLOW_CONFIG_NAME}-config + - name: KEYCLOAK_ADMIN_USERNAME valueFrom: secretKeyRef: - key: BPM_API_BASE - name: ${FORMIO_SECRET} + key: KEYCLOAK_ADMIN_USERNAME + name: ${FORMSFLOW_CONFIG_NAME}-config + - name: KEYCLOAK_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + key: KEYCLOAK_ADMIN_PASSWORD + name: ${FORMSFLOW_CONFIG_NAME}-config - name: BPM_CLIENT_ID valueFrom: secretKeyRef: key: BPM_CLIENT_ID - name: ${FORMIO_SECRET} + name: ${FORMSFLOW_SECRET} - name: BPM_CLIENT_SECRET valueFrom: secretKeyRef: key: BPM_CLIENT_SECRET - name: ${FORMIO_SECRET} + name: ${FORMSFLOW_SECRET} - name: BPM_TOKEN_API valueFrom: - secretKeyRef: - key: BPM_TOKEN_API - name: ${FORMIO_SECRET} + configMapKeyRef: + key: KEYCLOAK_TOKEN_URL + name: ${FORMSFLOW_CONFIG_NAME}-config - name: DATABASE_URL valueFrom: secretKeyRef: - key: DATABASE_URL - name: ${FORMIO_SECRET} + key: DATABASE_URL + name: "${WEBAPI_DB_RESOURCE_NAME}-${IMAGE_TAG}-secret" - name: JWT_OIDC_ALGORITHMS valueFrom: - secretKeyRef: - key: JWT_OIDC_ALGORITHMS - name: ${FORMIO_SECRET} + configMapKeyRef: + key: KEYCLOAK_JWT_OIDC_ALGORITHMS + name: ${FORMSFLOW_CONFIG_NAME}-config - name: JWT_OIDC_AUDIENCE valueFrom: secretKeyRef: - key: JWT_OIDC_AUDIENCE - name: ${FORMIO_SECRET} + key: WEB_CLIENTID + name: ${FORMSFLOW_SECRET} - name: JWT_OIDC_CACHING_ENABLED valueFrom: - secretKeyRef: - key: JWT_OIDC_CACHING_ENABLED - name: ${FORMIO_SECRET} + configMapKeyRef: + key: KEYCLOAK_JWT_OIDC_CACHING_ENABLED + name: ${FORMSFLOW_CONFIG_NAME}-config - name: JWT_OIDC_ISSUER valueFrom: - secretKeyRef: - key: JWT_OIDC_ISSUER - name: ${FORMIO_SECRET} + configMapKeyRef: + key: KEYCLOAK_JWT_OIDC_ISSUER + name: ${FORMSFLOW_CONFIG_NAME}-config - name: JWT_OIDC_JWKS_CACHE_TIMEOUT valueFrom: - secretKeyRef: - key: JWT_OIDC_JWKS_CACHE_TIMEOUT - name: ${FORMIO_SECRET} + configMapKeyRef: + key: KEYCLOAK_JWT_OIDC_JWKS_CACHE_TIMEOUT + name: ${FORMSFLOW_CONFIG_NAME}-config - name: JWT_OIDC_JWKS_URI valueFrom: - secretKeyRef: - key: JWT_OIDC_JWKS_URI - name: ${FORMIO_SECRET} + configMapKeyRef: + key: KEYCLOAK_JWT_OIDC_JWKS_URI + name: ${FORMSFLOW_CONFIG_NAME}-config - name: JWT_OIDC_WELL_KNOWN_CONFIG valueFrom: - secretKeyRef: - key: JWT_OIDC_WELL_KNOWN_CONFIG - name: ${FORMIO_SECRET} + configMapKeyRef: + key: KEYCLOAK_JWT_OIDC_CONFIG + name: ${FORMSFLOW_CONFIG_NAME}-config - name: WEB_API_BASE_URL valueFrom: - secretKeyRef: + configMapKeyRef: key: WEB_API_BASE_URL - name: ${FORMIO_SECRET} - image: ${IMAGE_NAMESPACE}/${NAME}:${TAG_NAME} + name: ${FORMSFLOW_CONFIG_NAME}-config + - name: FORMSFLOW_API_CORS_ORIGINS + value: '*' + image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME} name: ${NAME} ports: - containerPort: 5000 @@ -147,7 +164,7 @@ objects: app: ${NAME} name: ${NAME} spec: - host: ${WEBAPI_URL} + host: ${WEB_API_URL} tls: insecureEdgeTerminationPolicy: Redirect termination: edge @@ -162,14 +179,25 @@ parameters: description: The name assigned to all of the OpenShift resources associated to the server instance. required: true - value: forms-flow-api + value: forms-flow-webapi + - name: IMAGE_TAG + description: The image tag to pull for the deployment. + required: true - name: IMAGE_NAMESPACE displayName: Image Namespace required: true description: The namespace of the OpenShift project containing the imagestream for the application. - value: "" - - name: FORMIO_SECRET + value: formsflow-ai + - name: INSTANCE + description: The name of this instance of the application + displayName: Application Instance Name + required: true + - name: FORMSFLOW_CONFIG_NAME + description: Secrets are referred from this. + required: true + value: forms-flow-ai + - name: FORMSFLOW_SECRET description: Secrets are referred from this. required: true value: forms-flow-ai @@ -177,7 +205,7 @@ parameters: displayName: Environment TAG name description: The TAG name for this environment, e.g., dev, test, prod required: true - value: "" + value: latest - name: CPU_REQUEST displayName: Resources CPU Request description: The resources CPU request (in cores) for this build. @@ -206,18 +234,12 @@ parameters: - name: KEYCLOAK_URL description: The URL used to connnect to the OIDC provider. required: true - - name: WEBAPI_URL - displayName: WEBAPI_URL + - name: WEB_API_URL + displayName: WEB_API_URL description: - Route to access FFA WEB API + Web API URL without https prefix. required: true - - name: PATRONI_USERNAME - displayName: PATRONI_USERNAME - description: - PATRONI_USERNAME - required: true - - name: PATRONI_PASSWORD - displayName: PATRONI_PASSWORD - description: - PATRONI_PASSWORD + - name: WEBAPI_DB_RESOURCE_NAME + description: Name of database resources created for webapi. required: true + value: webapi-postgresql diff --git a/deployment/openshift/webapi_param.yaml b/deployment/openshift/webapi_param.yaml index 7eefbd2d11..f0aadad58a 100644 --- a/deployment/openshift/webapi_param.yaml +++ b/deployment/openshift/webapi_param.yaml @@ -1,7 +1,21 @@ IMAGE_NAMESPACE= KEYCLOAK_REALM= KEYCLOAK_URL= -WEBAPI_URL= -PATRONI_USERNAME= -PATRONI_PASSWORD= -MONGO_URI= +WEB_API_BASE_URL= +CAMUNDA_API_URI= +BPM_CLIENT_ID= +BPM_CLIENT_SECRET= +INSIGHTS_API_BASE= +INSIGHTS_API_KEY= +KEYCLOAK_ADMIN_USERNAME= +KEYCLOAK_ADMIN_PASSWORD= +JWT_OIDC_ALGORITHMS= +KEYCLOAK_TOKEN_URL= +DATABASE_URL= +KEYCLOAK_JWT_OIDC_ALGORITHMS= +WEB_CLIENTID= +KEYCLOAK_JWT_OIDC_CACHING_ENABLED= +KEYCLOAK_JWT_OIDC_ISSUER= +KEYCLOAK_JWT_OIDC_JWKS_CACHE_TIMEOUT= +KEYCLOAK_JWT_OIDC_JWKS_URI= +KEYCLOAK_JWT_OIDC_CONFIG= diff --git a/forms-flow-analytics/LICENSE b/forms-flow-analytics/LICENSE new file mode 100644 index 0000000000..cc235ca76b --- /dev/null +++ b/forms-flow-analytics/LICENSE @@ -0,0 +1,203 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + Copyright 2020 AppsOnTime Technologies Ltd. + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/forms-flow-analytics/README.md b/forms-flow-analytics/README.md index 122164bc8c..2c581dc1dd 100644 --- a/forms-flow-analytics/README.md +++ b/forms-flow-analytics/README.md @@ -1,12 +1,13 @@ # Analytics Engine -![Redash](https://img.shields.io/badge/Redash-v9(beta)-blue) +![Redash](https://img.shields.io/badge/Redash-10.1.0-blue) **formsflow.ai** leverages [Redash](https://github.com/getredash/redash) to build interactive dashboards and gain insights. To create meaningful visualization for your use case with formsflow.ai checkout [Redash Knowledge base](https://redash.io/help/). ## Table of Content + 1. [Prerequisites](#prerequisites) 2. [Solution Setup](#solution-setup) * [Step 1 : Keycloak Setup](#keycloak-setup) @@ -33,23 +34,22 @@ your use case with formsflow.ai checkout [Redash Knowledge base](https://redash. ### Installation - * Make sure you have a Docker machine up and running. - * Make sure your current working directory is "forms-flow-ai/forms-flow-analytics". - * Rename the file [sample.env](./sample.env) to **.env**. - * Modify the environment variables inside [.env](./sample.env) file if needed. Environment variables are given in the table below - * **NOTE : `{your-ip-address}` given inside the [redash.env](./redash.env) file should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards** +* Make sure you have a Docker machine up and running. +* Make sure your current working directory is "forms-flow-ai/forms-flow-analytics". +* Rename the file [sample.env](./sample.env) to **.env**. +* Modify the environment variables inside [.env](./sample.env) file if needed. Environment variables are given in the table below +* **NOTE : `{your-ip-address}` given inside the [.env](./sample.env) file should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards** > :information_source: Variables with trailing :triangular_flag_on_post: in below table should be updated in the `redash.env` file Variable name | Meaning | Possible values | Default value | --- | --- | --- | --- -`REDASH_HOST`:triangular_flag_on_post:| Base address of your Redash instance (the DNS name or IP) with the protocol | | http://{your-ip-address}:7000/redash +`REDASH_HOST`:triangular_flag_on_post:| Base address of your Redash instance (the DNS name or IP) with the protocol | | `PYTHONUNBUFFERED`|Log buffering setup|1 or 0 | 1 `REDASH_LOG_LEVEL`|Logging level|`CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET` | ERROR `REDASH_REDIS_URL`|Redis URL|Used on installation to create the database.Choose your own.|`redis://redis:6379/0` `REDASH_DATABASE_URL`|Postgres database URL|Used on installation to create the database.Choose your own.|`postgresql://postgres@postgres/postgres` `POSTGRES_PASSWORD`|Postgres database Password|Used on installation to create the database.Choose your own.|`postgres` -`POSTGRES_HOST_AUTH_METHOD`|Postgres authentication method|Used on installation to create the database.Choose your own.|`trust` `REDASH_COOKIE_SECRET`|Encryption for all configuration|Used on installation to create the database.Choose your own.|`redash-selfhosted` `REDASH_SECRET_KEY`|Encryption for datasource configuration|Used on installation to create the database.Choose your own.|`redash-selfhosted` `REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN`| To set allow origins to access Redash | `your-domain.com` | `*` @@ -63,7 +63,6 @@ Variable name | Meaning | Possible values | Default value | > The forked version of redash is being used to overcome the limited cors support in redash. The forked repo fixes the cors issues. But if the environment is setup in such a way that redash resides in the same url origin as forms web application , redash can be built from any redash images. - * For Linux, * Run `docker-compose -f docker-compose-linux.yml run --rm server create_db` to setup database and to create tables. * Run `docker-compose -f docker-compose-linux.yml up -d` to start. @@ -74,6 +73,7 @@ Variable name | Meaning | Possible values | Default value | *NOTE: Use --build command with the start command to reflect any future **.env** changes eg : `docker-compose -f docker-compose-windows.yml up --build -d`* #### To stop the application + * For Linux, * Run `docker-compose -f docker-compose-linux.yml stop` to stop. * For Windows, @@ -81,32 +81,38 @@ Variable name | Meaning | Possible values | Default value | ### Health Check - The application should be up and available for use at port defaulted to 7000 in http://localhost:7000/ - and register with any valid credentials. - +- Check the public endpoint : `{your-ip-address}:7000/ping` + +``` +RESPONSE +PONG. +``` + +- The application should be up and available for use at port defaulted to 7000 in and register with any valid credentials. + ### Configuration of Keycloak SAML Setup - - * Post registration, login to the application with admin credentials. - * Click the menu icon to the left of the username and navigate to **Edit Profile**. - * Go to tab "Settings", and then navigate to section "Authentication". - * Check the option "SAML". - * Set the field "SAML Metadata URL" with value of Keycloak SAML descriptor URL. Example. http://{your-ip-address}:8080/auth/realms/forms-flow-ai/protocol/saml/descriptor. {your-ip-address} should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards - * Set the field "SAML Entity ID" value to be `forms-flow-analytics`. - * Set the field "SAML NameID Format" value to be `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`. - * Logout and login again using valid formsflow.ai keycloak user credentials. Default user credentials are provided [here](../forms-flow-idm/keycloak/README.md#formsflow-ai-user-credentials). - + +* Post registration, login to the application with admin credentials. +* Click the menu icon to the left of the username and navigate to **Edit Profile**. +* Go to tab "Settings", and then navigate to section "Authentication". + * Check the option "SAML". + * Set the field "SAML Metadata URL" with value of Keycloak SAML descriptor URL. Example. . {your-ip-address} should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards + * Set the field "SAML Entity ID" value to be `forms-flow-analytics`. + * Set the field "SAML NameID Format" value to be `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`. +* Logout and login again using valid formsflow.ai keycloak user credentials. Default user credentials are provided [here](../forms-flow-idm/keycloak/README.md#formsflow-ai-user-credentials). + > forms-flow-analytic (REDASH) setup is successfully completed now. You can skip remaining sections in this page and continue with other installation steps. - + ## Get the Redash API Key - - * Login to redash hosted instance (i.e. http://localhost:7000/) using the admin credentials passed for registration / SAML credentials - * Go to User Icon -> Profile -> Settings - * Go to Account Section - * Copy API Key to Clipboard - -## Redash how to use guide -- Check our guide on [how to configure Redash and come up with awesome visualization using redash](./docs/README.md). +* Login to redash hosted instance (i.e. ) using the admin credentials passed for registration / SAML credentials +* Go to User Icon -> Profile -> Settings + * Go to Account Section + * Copy API Key to Clipboard + +## Redash how to use guide + +* Check our guide on [how to configure Redash and come up with awesome visualization using redash](./docs/README.md). -- If you want to visualize based on data in formsflow.ai, [a few sample queries for default forms are available](./docs/sample_queries.md). +* If you want to visualize based on data in formsflow.ai, [a few sample queries for default forms are available](./docs/sample_queries.md). diff --git a/forms-flow-analytics/docker-compose-linux.yml b/forms-flow-analytics/docker-compose-linux.yml index d2ec5392e4..56465cf3db 100644 --- a/forms-flow-analytics/docker-compose-linux.yml +++ b/forms-flow-analytics/docker-compose-linux.yml @@ -1,8 +1,8 @@ -# Author: Gurumoorthy Mohan +# Author: Gurumoorthy Mohan, Kurian Benoy version: "3.7" x-redash-service: &redash-service - build: https://github.com/AOT-Technologies/redash.git + image: redash/redash:10.1.0.b50633 depends_on: - postgres - redis @@ -12,32 +12,32 @@ x-redash-service: &redash-service services: server: <<: *redash-service - command: dev_server + command: server ports: - '7000:5000' environment: REDASH_WEB_WORKERS: 4 scheduler: <<: *redash-service - command: dev_scheduler + command: scheduler depends_on: - server + scheduled_worker: + <<: *redash-service + command: worker + adhoc_worker: + <<: *redash-service + command: worker worker: <<: *redash-service - command: dev_worker + command: worker environment: QUEUES: "periodic emails default" WORKERS_COUNT: 1 depends_on: - server - adhoc_worker: - <<: *redash-service - command: worker - environment: - QUEUES: "queries" - WORKERS_COUNT: 2 redis: - image: redis:3-alpine + image: redis:6-alpine restart: always postgres: image: postgres:9.6-alpine @@ -47,3 +47,9 @@ services: env_file: .env volumes: - ./postgres/analytics:/var/lib/postgresql/data + # Uncomment the following to enable redash mail server + # email: + # image: djfarrelly/maildev + # ports: + # - "1080:80" + # restart: unless-stopped diff --git a/forms-flow-analytics/docker-compose-windows.yml b/forms-flow-analytics/docker-compose-windows.yml index f91f43318e..f0b5c46c3e 100644 --- a/forms-flow-analytics/docker-compose-windows.yml +++ b/forms-flow-analytics/docker-compose-windows.yml @@ -1,8 +1,8 @@ -# Author: Gurumoorthy Mohan +# Author: Gurumoorthy Mohan, Kurian Benoy version: "3.7" x-redash-service: &redash-service - build: https://github.com/AOT-Technologies/redash.git + image: redash/redash:10.1.0.b50633 depends_on: - postgres - redis @@ -12,32 +12,32 @@ x-redash-service: &redash-service services: server: <<: *redash-service - command: dev_server + command: server ports: - '7000:5000' environment: REDASH_WEB_WORKERS: 4 scheduler: <<: *redash-service - command: dev_scheduler + command: scheduler depends_on: - server worker: <<: *redash-service - command: dev_worker + command: worker environment: QUEUES: "periodic emails default" WORKERS_COUNT: 1 depends_on: - server + scheduled_worker: + <<: *redash-service + command: worker adhoc_worker: <<: *redash-service command: worker - environment: - QUEUES: "queries" - WORKERS_COUNT: 2 redis: - image: redis:3-alpine + image: redis:6-alpine restart: always postgres: image: postgres:9.6-alpine @@ -47,3 +47,9 @@ services: env_file: .env volumes: - ./postgres/analytics:/data/postgres + # Uncomment the following to enable redash mail server + # email: + # image: djfarrelly/maildev + # ports: + # - "1080:80" + # restart: unless-stopped diff --git a/forms-flow-analytics/sample.env b/forms-flow-analytics/sample.env index faedb753c8..9d33d6330e 100644 --- a/forms-flow-analytics/sample.env +++ b/forms-flow-analytics/sample.env @@ -10,11 +10,21 @@ REDASH_HOST=http://{your-ip-address}:7000 PYTHONUNBUFFERED=0 REDASH_LOG_LEVEL=INFO REDASH_REDIS_URL=redis://redis:6379/0 +POSTGRES_USER=postgres POSTGRES_PASSWORD=changeme -POSTGRES_HOST_AUTH_METHOD=trust +POSTGRES_DB=postgres REDASH_COOKIE_SECRET=redash-selfhosted REDASH_SECRET_KEY=redash-selfhosted -REDASH_DATABASE_URL=postgresql://postgres@postgres/postgres +REDASH_DATABASE_URL=postgresql://postgres:changeme@postgres/postgres REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN=* REDASH_REFERRER_POLICY=no-referrer-when-downgrade REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS=Content-Type, Authorization + +# Redash Mail Server settings +# REDASH_MAIL_SERVER= +# REDASH_MAIL_PORT= +# REDASH_MAIL_USE_TLS= +# REDASH_MAIL_USE_SSL= +# REDASH_MAIL_USERNAME= +# REDASH_MAIL_PASSWORD= +# REDASH_MAIL_DEFAULT_SENDER= diff --git a/forms-flow-api/Dockerfile b/forms-flow-api/Dockerfile index 7b3f4ee88e..56282aff50 100644 --- a/forms-flow-api/Dockerfile +++ b/forms-flow-api/Dockerfile @@ -11,7 +11,7 @@ RUN : \ && pip install -r requirements.txt ADD . /forms-flow-api/app -RUN pip install . +RUN pip install -e . EXPOSE 5000 RUN chmod u+x ./entrypoint diff --git a/forms-flow-api/LICENSE b/forms-flow-api/LICENSE new file mode 100644 index 0000000000..cc235ca76b --- /dev/null +++ b/forms-flow-api/LICENSE @@ -0,0 +1,203 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + Copyright 2020 AppsOnTime Technologies Ltd. + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/forms-flow-api/Makefile b/forms-flow-api/Makefile index 6a6415c23a..8cb5576bf5 100644 --- a/forms-flow-api/Makefile +++ b/forms-flow-api/Makefile @@ -6,7 +6,7 @@ MKFILE_PATH:=$(abspath $(lastword $(MAKEFILE_LIST))) CURRENT_ABS_DIR:=$(patsubst %/,%,$(dir $(MKFILE_PATH))) -PROJECT_NAME:=api +PROJECT_NAME:=formsflow_api ################################################################################# # COMMANDS -- Setup # @@ -52,8 +52,8 @@ install-dev: ## Install local application ################################################################################# ci: lint test ## CI flow -pylint: ## Linting with pylint - . venv/bin/activate && black -t py38 src/$(PROJECT_NAME) && pylint --rcfile=setup.cfg src/$(PROJECT_NAME) +pylint: ## Lint python code with black and pylint + . venv/bin/activate && black -t py39 src/$(PROJECT_NAME) && pylint --rcfile=setup.cfg src/$(PROJECT_NAME) flake8: ## Linting with flake8 . venv/bin/activate && flake8 src/$(PROJECT_NAME) tests @@ -63,6 +63,8 @@ lint: pylint flake8 ## run all lint type scripts test: ## Unit testing . venv/bin/activate && pytest +test-verbose: ## Unit testing with detailed error messages + . venv/bin/activate && pytest -vv ################################################################################# # COMMANDS - Local # diff --git a/forms-flow-api/README.md b/forms-flow-api/README.md index 3d98336b37..b74cff22c6 100644 --- a/forms-flow-api/README.md +++ b/forms-flow-api/README.md @@ -1,19 +1,20 @@ -# formsflow.ai API +# formsflow.ai API ![Python](https://img.shields.io/badge/python-3.9-blue) ![Flask](https://img.shields.io/badge/Flask-1.1.4-blue) ![postgres](https://img.shields.io/badge/postgres-11.0-blue) **formsflow.ai** has built this adaptive tier for correlating form management, BPM and analytics together. -The goal of the REST API is to provide access to all relevant interfaces of +The goal of the REST API is to provide access to all relevant interfaces of the system. It is built using Python :snake: . ## Table of Content + 1. [Prerequisites](#prerequisites) 2. [Solution Setup](#solution-setup) * [Step 1 : Installation](#installation) * [Step 2 : Environment Configuration](#environment-configuration) * [Step 3 : Running the Application](#running-the-application) - * [Step 4 : Verify the Application Status](#verify-the-application-status) + * [Step 4 : Verify the Application Status](#verify-the-application-status) 3. [API Documentation](#api-documentation) ## Prerequisites @@ -34,27 +35,31 @@ You installing dev-packages using pip as follows: ### Keycloak Setup -No specific client creation is required. Audience has been added for clients +No specific client creation is required. Audience has been added for clients **forms-flow-web** and **forms-flow-bpm**. ### Environment Configuration - * Make sure you have a Docker machine up and running. - * Make sure your current working directory is "forms-flow-ai/forms-flow-api". - * Rename the file [sample.env](./sample.env) to **.env**. - * Modify the environment variables in the newly created **.env** file if needed. Environment variables are given in the table below, - * **NOTE : {your-ip-address} given inside the .env file should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards** +* Make sure you have a Docker machine up and running. +* Make sure your current working directory is "forms-flow-ai/forms-flow-api". +* Rename the file [sample.env](./sample.env) to **.env**. +* Modify the environment variables in the newly created **.env** file if needed. Environment variables are given in the table below, +* **NOTE : {your-ip-address} given inside the .env file should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards** > :information_source: Variables with trailing :triangular_flag_on_post: in below table should be updated in the .env file - + Variable name | Meaning | Possible values | Default value | --- | --- | --- | --- +`INSIGHT_API_URL`:triangular_flag_on_post: | The forms-flow-analytics Api base end-point | | | +`INSIGHT_API_KEY` :triangular_flag_on_post: | The forms-flow-analytics admin API key | | `Get the api key from forms-flow-analytics (REDASH) by following the 'Get the Redash API Key' steps from [here](../forms-flow-analytics/README.md#get-the-redash-api-key)` `FORMSFLOW_API_DB_USER`|formsflow database postgres user|Used on installation to create the database.Choose your own|`postgres` `FORMSFLOW_API_DB_PASSWORD`|formsflow database postgres password|Used on installation to create the database.Choose your own|`changeme` `FORMSFLOW_API_DB_NAME`|formsflow database name|Used on installation to create the database.Choose your own|`FORMSFLOW_API_DB` `FORMSFLOW_API_DB_URL`|JDBC DB Connection URL for formsflow||`postgresql://postgres:changeme@forms-flow-webapi-db:5432/webapi` `KEYCLOAK_URL`:triangular_flag_on_post:| URL to your Keycloak server || `http://{your-ip-address}:8080` `KEYCLOAK_URL_REALM`|The Keycloak realm to use|eg. forms-flow-ai | `forms-flow-ai` +`KEYCLOAK_ADMIN_USERNAME` :triangular_flag_on_post: | The admin username for Keycloak. This is used for using Keycloak internal APIs | | +`KEYCLOAK_ADMIN_PASSWORD` :triangular_flag_on_post: | The admin password for Keycloak. | | `KEYCLOAK_BPM_CLIENT_ID`|Client ID for Camunda to register with Keycloak|eg. forms-flow-bpm|`forms-flow-bpm` `KEYCLOAK_BPM_CLIENT_SECRET`:triangular_flag_on_post:|Client Secret of Camunda client in realm|eg. 22ce6557-6b86-4cf4-ac3b-42338c7b1ac12|must be set to your Keycloak client secret. Follow the steps from [Here](../forms-flow-idm/keycloak/README.md#getting-the-client-secret) `KEYCLOAK_WEB_CLIENT_ID`|Client ID for formsflow to register with Keycloak|eg. forms-flow-web|`forms-flow-web` @@ -70,24 +75,26 @@ Variable name | Meaning | Possible values | Default value | * `cd {Your Directory}/forms-flow-ai/forms-flow-api` * For Linux, - * Run `docker-compose -f docker-compose-linux.yml up -d` to start. + * Run `docker-compose -f docker-compose-linux.yml up -d` to start. * For Windows, - * Run `docker-compose -f docker-compose-windows.yml up -d` to start. - + * Run `docker-compose -f docker-compose-windows.yml up -d` to start. + *NOTE: Use --build command with the start command to reflect any future **.env** changes eg : `docker-compose -f docker-compose-windows.yml up --build -d`* #### To Stop the Application + * For Linux, * Run `docker-compose -f docker-compose-linux.yml stop` to stop. * For Windows, * Run `docker-compose -f docker-compose-windows.yml stop` to stop. - + ### Verify the Application Status - The application should be up and available for use at port defaulted to 5000 in http://localhost:5000/ + The application should be up and available for use at port defaulted to 5000 in - * Access the **/checkpoint** endpoint for a Health Check on API to see it's up and running. -``` +* Access the **/checkpoint** endpoint for a Health Check on API to see it's up and running. + +``` GET http://localhost:5000/checkpoint RESPONSE @@ -96,7 +103,9 @@ RESPONSE "message": "Welcome to formsflow.ai API" } ``` - * Get the access token + +* Get the access token + ``` POST {Keycloak URL}/auth/realms//protocol/openid-connect/token @@ -108,19 +117,21 @@ client_id: forms-flow-bpm Headers: Content-Type : application/x-www-form-urlencoded -``` - * Access the **/task** endpoint and verify response. Ensure Bearer token is passed along -``` +``` + +* Access the **/task** endpoint and verify response. Ensure Bearer token is passed along + +``` GET http://localhost:5000/task Headers: Content-Type : application/json Authorization: Bearer {access token} -``` - +``` + ## API Documentation -The API docs can be accessed by checking the **/docs** endpoint. +The API docs can be accessed by checking the **/** root endpoint. ![image](https://user-images.githubusercontent.com/70306694/130730233-cf443a84-7716-4be6-b196-cb340509c495.png) diff --git a/forms-flow-api/docker-compose-linux.yml b/forms-flow-api/docker-compose-linux.yml index 4f692d9134..dd35723cef 100644 --- a/forms-flow-api/docker-compose-linux.yml +++ b/forms-flow-api/docker-compose-linux.yml @@ -27,6 +27,8 @@ services: volumes: - ./:/app:rw environment: + INSIGHT_API_KEY: ${INSIGHT_API_KEY} + INSIGHT_API_URL: ${INSIGHT_API_URL} DATABASE_URL: ${FORMSFLOW_API_DB_URL:-postgresql://postgres:changeme@forms-flow-webapi-db:5432/webapi} BPM_TOKEN_API: ${KEYCLOAK_URL}/auth/realms/${KEYCLOAK_URL_REALM:-forms-flow-ai}/protocol/openid-connect/token BPM_CLIENT_ID: ${KEYCLOAK_BPM_CLIENT_ID:-forms-flow-bpm} @@ -34,12 +36,14 @@ services: BPM_API_BASE: ${CAMUNDA_API_URL} FORMSFLOW_API_CORS_ORIGINS: ${FORMSFLOW_API_CORS_ORIGINS:-*} JWT_OIDC_WELL_KNOWN_CONFIG: ${KEYCLOAK_URL}/auth/realms/${KEYCLOAK_URL_REALM:-forms-flow-ai}/.well-known/openid-configuration - JWT_OIDC_ALGORITHMS: 'RS256' JWT_OIDC_JWKS_URI: ${KEYCLOAK_URL}/auth/realms/${KEYCLOAK_URL_REALM:-forms-flow-ai}/protocol/openid-connect/certs JWT_OIDC_ISSUER: ${KEYCLOAK_URL}/auth/realms/${KEYCLOAK_URL_REALM:-forms-flow-ai} JWT_OIDC_AUDIENCE: ${KEYCLOAK_WEB_CLIENT_ID:-forms-flow-web} JWT_OIDC_CACHING_ENABLED: 'True' - JWT_OIDC_JWKS_CACHE_TIMEOUT: 300 + KEYCLOAK_URL: ${KEYCLOAK_URL} + KEYCLOAK_URL_REALM: ${KEYCLOAK_URL_REALM:-forms-flow-ai} + KEYCLOAK_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USERNAME} + KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} WEB_API_BASE_URL: ${FORMSFLOW_API_URL} stdin_open: true # -i tty: true # -t diff --git a/forms-flow-api/docker-compose-windows.yml b/forms-flow-api/docker-compose-windows.yml index 0d3201fb27..bd587ad728 100644 --- a/forms-flow-api/docker-compose-windows.yml +++ b/forms-flow-api/docker-compose-windows.yml @@ -27,6 +27,8 @@ services: volumes: - ./:/app:rw environment: + INSIGHT_API_KEY: ${INSIGHT_API_KEY} + INSIGHT_API_URL: ${INSIGHT_API_URL} DATABASE_URL: ${FORMSFLOW_API_DB_URL:-postgresql://postgres:changeme@forms-flow-webapi-db:5432/webapi} BPM_TOKEN_API: ${KEYCLOAK_URL}/auth/realms/${KEYCLOAK_URL_REALM:-forms-flow-ai}/protocol/openid-connect/token BPM_CLIENT_ID: ${KEYCLOAK_BPM_CLIENT_ID:-forms-flow-bpm} @@ -40,6 +42,10 @@ services: JWT_OIDC_AUDIENCE: ${KEYCLOAK_WEB_CLIENT_ID:-forms-flow-web} JWT_OIDC_CACHING_ENABLED: 'True' JWT_OIDC_JWKS_CACHE_TIMEOUT: 300 + KEYCLOAK_URL: ${KEYCLOAK_URL} + KEYCLOAK_URL_REALM: ${KEYCLOAK_URL_REALM:-forms-flow-ai} + KEYCLOAK_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USERNAME} + KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} WEB_API_BASE_URL: ${FORMSFLOW_API_URL} stdin_open: true # -i tty: true # -t diff --git a/forms-flow-api/entrypoint b/forms-flow-api/entrypoint index c7cf1ef826..387a2a9ca6 100644 --- a/forms-flow-api/entrypoint +++ b/forms-flow-api/entrypoint @@ -1,2 +1,2 @@ #!/bin/bash -python manage.py db upgrade && gunicorn -b :5000 'api:create_app()' --timeout 120 --worker-class=gthread --workers=5 --threads=10 +python manage.py db upgrade && gunicorn -b :5000 'formsflow_api:create_app()' --timeout 120 --worker-class=gthread --workers=5 --threads=10 diff --git a/forms-flow-api/gunicorn_config.py b/forms-flow-api/gunicorn_config.py index b2d0a0c310..a9d9f20987 100644 --- a/forms-flow-api/gunicorn_config.py +++ b/forms-flow-api/gunicorn_config.py @@ -3,8 +3,8 @@ import os -workers = int(os.environ.get('GUNICORN_PROCESSES', '1')) -threads = int(os.environ.get('GUNICORN_THREADS', '1')) +workers = int(os.environ.get("GUNICORN_PROCESSES", "1")) +threads = int(os.environ.get("GUNICORN_THREADS", "1")) -forwarded_allow_ips = '*' -secure_scheme_headers = {'X-Forwarded-Proto': 'https'} +forwarded_allow_ips = "*" +secure_scheme_headers = {"X-Forwarded-Proto": "https"} diff --git a/forms-flow-api/manage.py b/forms-flow-api/manage.py index 335e59635c..2c0ecc6b60 100644 --- a/forms-flow-api/manage.py +++ b/forms-flow-api/manage.py @@ -6,9 +6,9 @@ from flask_script import Manager # models included so that migrate can build the database migrations -from api import models # noqa: F401 # pylint: disable=unused-import -from api import create_app -from api.models import db +from formsflow_api import models # noqa: F401 # pylint: disable=unused-import +from formsflow_api import create_app +from formsflow_api.models import db APP = create_app() diff --git a/forms-flow-api/requirements.txt b/forms-flow-api/requirements.txt index cc4b2ee4d4..82e5b8c0f6 100644 --- a/forms-flow-api/requirements.txt +++ b/forms-flow-api/requirements.txt @@ -4,38 +4,39 @@ Flask-SQLAlchemy==2.5.1 Flask-Script==2.0.6 Flask==1.1.4 Jinja2==2.11.3 -Mako==1.1.5 +Mako==1.1.6 MarkupSafe==2.0.1 -SQLAlchemy-Utils==0.37.8 -SQLAlchemy==1.4.23 +SQLAlchemy-Utils==0.37.9 +SQLAlchemy==1.4.28 Werkzeug==1.0.1 -alembic==1.7.1 +alembic==1.7.5 aniso8601==9.0.1 attrs==21.2.0 -cachelib==0.3.0 -certifi==2021.5.30 -charset-normalizer==2.0.4 +cachelib==0.4.1 +certifi==2021.10.8 +charset-normalizer==2.0.9 click==7.1.2 ecdsa==0.17.0 flask-jwt-oidc==0.3.0 flask-marshmallow==0.14.0 flask-restx==0.5.1 -greenlet==1.1.1 +greenlet==1.1.2 gunicorn==20.1.0 -idna==3.2 -importlib-resources==5.2.2 +idna==3.3 +importlib-metadata==4.8.2 +importlib-resources==5.4.0 itsdangerous==1.1.0 -jsonschema==3.2.0 +jsonschema==4.2.1 marshmallow-sqlalchemy==0.26.1 -marshmallow==3.13.0 -psycopg2-binary==2.9.1 +marshmallow==3.14.1 +psycopg2-binary==2.9.2 pyasn1==0.4.8 pyrsistent==0.18.0 -python-dotenv==0.19.0 +python-dotenv==0.19.2 python-jose==3.3.0 -pytz==2021.1 +pytz==2021.3 requests==2.26.0 -rsa==4.7.2 +rsa==4.8 six==1.16.0 -urllib3==1.26.6 -zipp==3.5.0 +urllib3==1.26.7 +zipp==3.6.0 diff --git a/forms-flow-api/requirements/dev.txt b/forms-flow-api/requirements/dev.txt index c4893f8a6d..c40acae317 100644 --- a/forms-flow-api/requirements/dev.txt +++ b/forms-flow-api/requirements/dev.txt @@ -10,5 +10,8 @@ flake8-polyfill flake8-quotes pycodestyle pytest +pytest-cov +pytest-it pyflakes pylint + diff --git a/forms-flow-api/sample.env b/forms-flow-api/sample.env index 4d2cb9520d..3ad2a56765 100644 --- a/forms-flow-api/sample.env +++ b/forms-flow-api/sample.env @@ -3,14 +3,19 @@ # rename this file to .env # # Uncomment the variables if any changes from the default values # ############################################################################### +# ===== formsflow.ai Python Webapi ENV Variables - START ===================== ##Environment variables for WEB_API/FORMSFLOW_API in the adaptive tier. +##DB Connection URL for formsflow.ai #FORMSFLOW_API_DB_URL=postgresql://postgres:changeme@forms-flow-webapi-db:5432/webapi +##formsflow.ai database postgres user #FORMSFLOW_API_DB_USER=postgres +##formsflow.ai database postgres password #FORMSFLOW_API_DB_PASSWORD=changeme -# FORMSFLOW_API_DB_NAME=webapi +##formsflow.ai database name +#FORMSFLOW_API_DB_NAME=webapi ##URL to your Keycloak server KEYCLOAK_URL=http://{your-ip-address}:8080 @@ -19,9 +24,25 @@ KEYCLOAK_URL=http://{your-ip-address}:8080 #KEYCLOAK_BPM_CLIENT_ID=forms-flow-bpm #KEYCLOAK_WEB_CLIENT_ID=forms-flow-web KEYCLOAK_BPM_CLIENT_SECRET={Keycloak client secret for forms-flow-bpm} +KEYCLOAK_ADMIN_USERNAME={Keycloak admin username} +KEYCLOAK_ADMIN_PASSWORD={Keycloak admin password} - +##Camunda Rest API URI CAMUNDA_API_URL=http://{your-ip-address}:8000/camunda +##web Api End point FORMSFLOW_API_URL=http://{your-ip-address}:5000 +##web API CORS origins FORMSFLOW_API_CORS_ORIGINS=* +##Env For Unit Testing +# TEST_REVIEWER_USERID= +# TEST_REVIEWER_PASSWORD= +# DATABASE_URL_TEST= + + + #----Insight Api Variables--------# +##Insight Api base end-point +INSIGHT_API_URL=http://{your-ip-address}:7000 +##API_KEY from REDASH +INSIGHT_API_KEY={API Key from Redash} + diff --git a/forms-flow-api/setup.cfg b/forms-flow-api/setup.cfg index ade0682e31..1764b2449c 100644 --- a/forms-flow-api/setup.cfg +++ b/forms-flow-api/setup.cfg @@ -1,12 +1,13 @@ [metadata] -name = api +name = formsflow_api +version = 4.0.4 author = aot-technologies classifiers = Development Status :: Beta Intended Audience :: Developers / QA License :: OSI Approved :: Apache Software License Natural Language :: English - Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.9 license = Apache Software License Version 2.0 description = forms flow api long_description = file: README.md @@ -42,7 +43,7 @@ max_line_length = 120 ignore = E501 docstring-min-length=10 notes=FIXME,XXX # TODO is ignored -match_dir = src/api +match_dir = src/formsflow_api ignored-modules=flask_sqlalchemy sqlalchemy per-file-ignores = diff --git a/forms-flow-api/setup.py b/forms-flow-api/setup.py index 9457466a31..c27ec72f81 100644 --- a/forms-flow-api/setup.py +++ b/forms-flow-api/setup.py @@ -11,9 +11,9 @@ def read_requirements(filename): :return: Python requirements :rtype: list """ - with open(filename, 'r') as req: + with open(filename, "r") as req: requirements = req.readlines() - install_requires = [r.strip() for r in requirements if r.find('git+') != 0] + install_requires = [r.strip() for r in requirements if r.find("git+") != 0] return install_requires @@ -23,22 +23,26 @@ def read(filepath): :return: file contents :rtype: str """ - with open(filepath, 'r') as file_handle: + with open(filepath, "r") as file_handle: content = file_handle.read() return content -REQUIREMENTS = read_requirements('requirements.txt') +REQUIREMENTS = read_requirements("requirements.txt") setup( - name='api', - packages=find_packages('src'), - package_dir={'': 'src'}, - py_modules=[splitext(basename(path))[0] for path in glob('src/*.py')], + name="formsflow_api", + packages=find_packages("src"), + package_dir={"": "src"}, + py_modules=[splitext(basename(path))[0] for path in glob("src/*.py")], include_package_data=True, - long_description=read('README.md'), + long_description=read("README.md"), zip_safe=False, install_requires=REQUIREMENTS, - setup_requires=['pytest-runner', ], - tests_require=['pytest', ], + setup_requires=[ + "pytest-runner", + ], + tests_require=[ + "pytest", + ], ) diff --git a/forms-flow-api/src/api/models/__init__.py b/forms-flow-api/src/api/models/__init__.py deleted file mode 100644 index 4a76a905dc..0000000000 --- a/forms-flow-api/src/api/models/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -"""This exports all of the models used by the application.""" - -from .db import db, ma -from .form_process_mapper import FormProcessMapper -from .application import Application - -# from .application_communication import ApplicationCommunication -from .application_history import ApplicationHistory - -# from .formio_token import FormIOToken -# from .tenant import Tenant - -__all__ = ["db", "ma", "FormProcessMapper", "Application", "ApplicationHistory"] diff --git a/forms-flow-api/src/api/models/application.py b/forms-flow-api/src/api/models/application.py deleted file mode 100644 index 8e58ffd418..0000000000 --- a/forms-flow-api/src/api/models/application.py +++ /dev/null @@ -1,303 +0,0 @@ -"""This manages Application submission Data.""" - -from __future__ import annotations - -from sqlalchemy import or_, and_, func - -from .audit_mixin import AuditDateTimeMixin, AuditUserMixin -from .base_model import BaseModel -from .db import db -from .form_process_mapper import FormProcessMapper - - -class Application(AuditDateTimeMixin, AuditUserMixin, BaseModel, db.Model): - """This class manages application against each form.""" - - id = db.Column(db.Integer, primary_key=True) - application_name = db.Column(db.String(100), nullable=False) - application_status = db.Column(db.String(100), nullable=False) - form_process_mapper_id = db.Column( - db.Integer, db.ForeignKey("form_process_mapper.id"), nullable=False - ) - form_url = db.Column(db.String(500), nullable=True) - process_instance_id = db.Column(db.String(100), nullable=True) - revision_no = db.Column(db.Integer, nullable=False) # set 1 now - - @classmethod - def create_from_dict(cls, application_info: dict) -> Application: - """Create new application.""" - if application_info: - application = Application() - application.application_name = application_info["application_name"] - application.application_status = application_info["application_status"] - application.form_process_mapper_id = application_info[ - "form_process_mapper_id" - ] - application.form_url = application_info["form_url"] - application.revision_no = 1 # application_info['revision_no'] - application.created_by = application_info["created_by"] - application.save() - return application - return None - - def update(self, mapper_info: dict): - """Update application.""" - self.update_from_dict( - [ - "application_name", - "application_status", - "form_url", - "form_process_mapper_id", - "process_instance_id", - "revision_no", - "modified_by", - ], - mapper_info, - ) - self.commit() - - @classmethod - def find_by_id(cls, application_id: int) -> Application: - """Find application that matches the provided id.""" - return cls.query.filter_by(id=application_id).first() - - @classmethod - def find_by_ids(cls, application_ids) -> Application: - """Find application that matches the provided id.""" - return cls.query.filter(cls.id.in_(application_ids)).order_by( - Application.id.desc() - ) - - @classmethod - def find_all(cls, page_no: int, limit: int) -> Application: - """Fetch all application.""" - if page_no == 0: - return cls.query.order_by(Application.id.desc()).all() - else: - return ( - cls.query.order_by(Application.id.desc()) - .paginate(page_no, limit, False) - .items - ) - - @classmethod - def find_all_by_user(cls, user_id: str, page_no: int, limit: int) -> Application: - if page_no == 0: - return cls.query.filter(Application.created_by == user_id).order_by( - Application.id.desc() - ) - else: - return ( - cls.query.filter(Application.created_by == user_id) - .order_by(Application.id.desc()) - .paginate(page_no, limit, False) - .items - ) - - @classmethod - def find_id_by_user(cls, application_id: int, user_id: str) -> Application: - """Find application that matches the provided id.""" - return cls.query.filter( - and_(Application.id == application_id, Application.created_by == user_id) - ).one_or_none() - - @classmethod - def find_all_by_user_count(cls, user_id: str) -> Application: - """Fetch all application.""" - return cls.query.filter(Application.created_by == user_id).count() - - @classmethod - def find_by_form_id(cls, form_id, page_no: int, limit: int): - if page_no == 0: - return cls.query.filter( - Application.form_url.like("%" + form_id + "%") - ).order_by(Application.id.desc()) - else: - return ( - cls.query.filter(Application.form_url.like("%" + form_id + "%")) - .order_by(Application.id.desc()) - .paginate(page_no, limit, False) - .items - ) - - @classmethod - def find_by_form_names(cls, form_names, page_no: int, limit: int): - """Fetch application based on multiple form ids.""" - if page_no == 0: - return cls.query.filter( - Application.application_name.in_(form_names) - ).order_by(Application.id.desc()) - else: - return ( - cls.query.filter(Application.application_name.in_(form_names)) - .order_by(Application.id.desc()) - .paginate(page_no, limit, False) - .items - ) - - @classmethod - def find_id_by_form_names(cls, application_id: int, form_names): - return cls.query.filter( - and_( - Application.application_name.in_(form_names), - Application.id == application_id, - ) - ).one_or_none() - - @classmethod - def find_by_form_id_user(cls, form_id, user_id: str, page_no: int, limit: int): - if page_no == 0: - return ( - cls.query.filter(Application.form_url.like("%" + form_id + "%")) - .filter(Application.created_by == user_id) - .order_by(Application.id.desc()) - ) - else: - return ( - cls.query.filter(Application.form_url.like("%" + form_id + "%")) - .filter(Application.created_by == user_id) - .order_by(Application.id.desc()) - .paginate(page_no, limit, False) - .items - ) - - @classmethod - def find_by_form_ids(cls, form_ids, page_no: int, limit: int): - """Fetch application based on multiple form ids.""" - if page_no == 0: - return cls.query.filter( - or_( - Application.form_url.like("%" + form_id + "%") - for form_id in form_ids - ) - ).order_by(Application.id.desc()) - else: - return ( - cls.query.filter( - or_( - Application.form_url.like("%" + form_id + "%") - for form_id in form_ids - ) - ) - .order_by(Application.id.desc()) - .paginate(page_no, limit, False) - .items - ) - - @classmethod - def find_all_by_form_id_count(cls, form_id): - """Fetch all application.""" - return cls.query.filter(Application.form_url.like("%" + form_id + "%")).count() - - @classmethod - def find_all_by_form_id_user_count(cls, form_id, user_id: str): - """Fetch all application.""" - return ( - cls.query.filter(Application.form_url.like("%" + form_id + "%")) - .filter(Application.created_by == user_id) - .count() - ) - - @classmethod - def find_aggregated_applications(cls, from_date: str, to_date: str): - """Fetch aggregated applications.""" - result_proxy = ( - db.session.query( - Application.form_process_mapper_id, - FormProcessMapper.form_name, - func.count(Application.form_process_mapper_id).label("count"), - ) - .join( - FormProcessMapper, - FormProcessMapper.id == Application.form_process_mapper_id, - ) - .filter( - func.date(Application.created) >= from_date, - func.date(Application.created) <= to_date, - ) - .group_by(Application.form_process_mapper_id, FormProcessMapper.form_name) - ) - - result = [] - for row in result_proxy: - info = dict(row) - result.append(info) - - return result - - @classmethod - def find_aggregated_applications_modified(cls, from_date: str, to_date: str): - """Fetch aggregated applications.""" - result_proxy = ( - db.session.query( - Application.form_process_mapper_id, - FormProcessMapper.form_name, - func.count(Application.form_process_mapper_id).label("count"), - ) - .join( - FormProcessMapper, - FormProcessMapper.id == Application.form_process_mapper_id, - ) - .filter( - func.date(Application.modified) >= from_date, - func.date(Application.modified) <= to_date, - ) - .group_by(Application.form_process_mapper_id, FormProcessMapper.form_name) - ) - - result = [] - for row in result_proxy: - info = dict(row) - result.append(info) - - return result - - @classmethod - def find_aggregated_application_status( - cls, mapper_id: int, from_date: str, to_date: str - ): - """Fetch aggregated application status.""" - result_proxy = ( - db.session.query( - Application.application_status, - Application.application_name, - func.count(Application.application_name).label("count"), - ) - .join( - FormProcessMapper, - FormProcessMapper.id == Application.form_process_mapper_id, - ) - .filter( - and_( - func.date(Application.created) >= from_date, - func.date(Application.created) <= to_date, - Application.form_process_mapper_id == mapper_id, - ) - ) - .group_by(Application.application_status, Application.application_name) - ) - - return result_proxy - - @classmethod - def find_aggregated_application_status_modified( - cls, mapper_id: int, from_date: str, to_date: str - ): - """Fetch aggregated application status.""" - result_proxy = ( - db.session.query( - Application.application_name, - Application.application_status, - func.count(Application.application_name).label("count"), - ) - .filter( - and_( - func.date(Application.modified) >= from_date, - func.date(Application.modified) <= to_date, - Application.form_process_mapper_id == mapper_id, - ) - ) - .group_by(Application.application_name, Application.application_status) - ) - - return result_proxy diff --git a/forms-flow-api/src/api/models/application_communication.py b/forms-flow-api/src/api/models/application_communication.py deleted file mode 100644 index 4477be9e85..0000000000 --- a/forms-flow-api/src/api/models/application_communication.py +++ /dev/null @@ -1,16 +0,0 @@ -"""This manages Application Communication Data.""" - -# from .base_model import BaseModel -# from .db import db - - -# class ApplicationCommunication(BaseModel, db.Model): -# """This class manages ApplicationCommunication.""" - -# id = db.Column(db.Integer, primary_key=True) -# application_id = db.Column( -# db.Integer, db.ForeignKey("application.id"), nullable=False -# ) -# message = db.Column(db.String(3000), nullable=False) -# created_by = db.Column(db.String(), nullable=False) -# created = db.Column(db.DateTime, nullable=False) diff --git a/forms-flow-api/src/api/models/enums/__init__.py b/forms-flow-api/src/api/models/enums/__init__.py deleted file mode 100644 index 34253b0ec1..0000000000 --- a/forms-flow-api/src/api/models/enums/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""This exports all of the enums used by this application.""" - -from .base_enum import ExtendedEnum, ExtendedIntEnum -from .form_process_mapper import FormProcessMapperStatus diff --git a/forms-flow-api/src/api/models/enums/base_enum.py b/forms-flow-api/src/api/models/enums/base_enum.py deleted file mode 100644 index 3380c4f2a6..0000000000 --- a/forms-flow-api/src/api/models/enums/base_enum.py +++ /dev/null @@ -1,29 +0,0 @@ -"""This exports all of the base enums used by the application.""" - -from enum import Enum, IntEnum - - -class ExtendedEnum(Enum): - """Extended Enum.""" - - @classmethod - def list(cls): - """Get list of values.""" - return list(map(lambda c: c.value, cls)) - - -class ExtendedIntEnum(IntEnum): - """Extended Int Enum.""" - - def __new__(cls, value, phrase=""): - """Customize the value to include phrase.""" - obj = int.__new__(cls, value) - obj._value_ = value - - obj.phrase = phrase - return obj - - @classmethod - def get_phrase(cls, value): - """Get phrase by value.""" - return cls(value).phrase diff --git a/forms-flow-api/src/api/models/enums/form_process_mapper.py b/forms-flow-api/src/api/models/enums/form_process_mapper.py deleted file mode 100644 index 52a5fa117e..0000000000 --- a/forms-flow-api/src/api/models/enums/form_process_mapper.py +++ /dev/null @@ -1,10 +0,0 @@ -"""This manages form process mapper enums.""" - -from .base_enum import ExtendedEnum - - -class FormProcessMapperStatus(ExtendedEnum): - """This enum provides the list of FormProcessMapper Status.""" - - Active = "active" - Inactive = "inactive" diff --git a/forms-flow-api/src/api/models/formio_token.py b/forms-flow-api/src/api/models/formio_token.py deleted file mode 100644 index 45bc7f4453..0000000000 --- a/forms-flow-api/src/api/models/formio_token.py +++ /dev/null @@ -1,14 +0,0 @@ -"""This manages FormIO Token Data.""" - -# from .base_model import BaseModel -# from .db import db - - -# class FormIOToken(BaseModel, db.Model): -# """FormIOToken Model for storing formio token.""" - -# id = db.Column(db.Integer, primary_key=True) -# keycloak_role = db.Column(db.String(50), nullable=False) -# formio_token = db.Column(db.String(500), nullable=False) -# formio_role = db.Column(db.String(50), nullable=False) -# created = db.Column(db.DateTime, nullable=False) diff --git a/forms-flow-api/src/api/models/tenant.py b/forms-flow-api/src/api/models/tenant.py deleted file mode 100644 index 1d1702363f..0000000000 --- a/forms-flow-api/src/api/models/tenant.py +++ /dev/null @@ -1,25 +0,0 @@ -"""This manages Tenant Data.""" - -# from __future__ import annotations - -# from .base_model import BaseModel -# from .db import db - - -# class Tenant(BaseModel, db.Model): # pylint: disable=too-few-public-methods -# """This class manages tenant.""" - -# id = db.Column(db.Integer, primary_key=True) -# tenant_name = db.Column("tenant_name", db.String(), nullable=False) -# relam = db.Column("relam", db.String(), nullable=False) -# audience = db.Column("audience", db.String(), nullable=False) - -# @classmethod -# def find_all(cls): -# """Fetch all tenant.""" -# return cls.query.all() - -# @classmethod -# def find_by_id(cls, tenant_id) -> Tenant: -# """Find tenant that matches the provided id.""" -# return cls.query.filter(Tenant.id == tenant_id).first() diff --git a/forms-flow-api/src/api/resources/formiotoken.py b/forms-flow-api/src/api/resources/formiotoken.py deleted file mode 100644 index e91891cc83..0000000000 --- a/forms-flow-api/src/api/resources/formiotoken.py +++ /dev/null @@ -1,26 +0,0 @@ -"""API endpoints for generating formio token.""" - -# from http import HTTPStatus - -# from flask import jsonify -# from flask_restx import Namespace, Resource - -# from ..services import FormIOTokenService -# from ..utils.util import cors_preflight - - -# API = Namespace("FormIOToken", description="FormIOToken") - - -# @cors_preflight("GET,OPTIONS") -# @API.route("", methods=["GET", "OPTIONS"]) -# class ApplicationList(Resource): -# """Resource for generatiing formiotoken.""" - -# @staticmethod -# def get(): -# """Get formio token.""" -# return ( -# jsonify({"formioToken": FormIOTokenService.get_formio_token()}), -# HTTPStatus.OK, -# ) diff --git a/forms-flow-api/src/api/resources/task.py b/forms-flow-api/src/api/resources/task.py deleted file mode 100644 index 3ce5b61096..0000000000 --- a/forms-flow-api/src/api/resources/task.py +++ /dev/null @@ -1,197 +0,0 @@ -"""API endpoints for managing task resource.""" - -from http import HTTPStatus - -from flask import current_app, request -from flask_restx import Namespace, Resource - -from api.services import TaskService -from api.utils.auth import auth -from api.utils.util import cors_preflight - - -API = Namespace("Task", description="Task") - - -@cors_preflight("GET,OPTIONS") -@API.route("", methods=["GET", "OPTIONS"]) -class TaskList(Resource): - """Resource for managing tasks.""" - - @staticmethod - @auth.require - def get(): - """List all tasks.""" - return ( - ( - { - "tasks": TaskService.get_all_tasks( - token=request.headers["Authorization"] - ) - } - ), - HTTPStatus.OK, - ) - - -@cors_preflight("GET,OPTIONS") -@API.route("/", methods=["GET", "OPTIONS"]) -class Task(Resource): - """Resource for managing tasks.""" - - @staticmethod - @auth.require - def get(task_id): - """List specific tasks.""" - return ( - ( - { - "task": TaskService.get_task( - task_id=task_id, token=request.headers["Authorization"] - ) - } - ), - HTTPStatus.OK, - ) - - -@cors_preflight("POST,OPTIONS") -@API.route("//claim", methods=["POST", "OPTIONS"]) -class TaskClaim(Resource): - """Resource for claim task.""" - - @staticmethod - @auth.require - def post(task_id): - """Claim a task.""" - request_json = request.get_json() - try: - return ( - ( - { - "tasks": TaskService.claim_task( - task_id=task_id, - data=request_json, - token=request.headers["Authorization"], - ) - } - ), - HTTPStatus.OK, - ) - except KeyError as err: - response, status = ( - { - "type": "Invalid Request Object", - "message": "Required fields are not passed", - "errors": err.messages, - }, - HTTPStatus.BAD_REQUEST, - ) - - current_app.logger.critical(response) - current_app.logger.critical(err) - return response, status - - except BaseException as err: - response, status = { - "type": "Bad request error", - "message": "Invalid request data object", - }, HTTPStatus.BAD_REQUEST - - current_app.logger.warning(response) - current_app.logger.warning(err) - return response, status - - -@cors_preflight("POST,OPTIONS") -@API.route("//unclaim", methods=["POST", "OPTIONS"]) -class TaskUnClaim(Resource): - """Resource for claim task.""" - - @staticmethod - @auth.require - def post(task_id): - """Unclaim a task.""" - request_json = request.get_json() - try: - return ( - ( - { - "tasks": TaskService.unclaim_task( - task_id=task_id, - data=request_json, - token=request.headers["Authorization"], - ) - } - ), - HTTPStatus.OK, - ) - except KeyError as err: - response, status = ( - { - "type": "Invalid Request Object", - "message": "Required fields are not passed", - "errors": err.messages, - }, - HTTPStatus.BAD_REQUEST, - ) - - current_app.logger.critical(response) - current_app.logger.critical(err) - - except BaseException as err: - response, status = { - "type": "Bad request error", - "message": "Invalid request data object", - }, HTTPStatus.BAD_REQUEST - - current_app.logger.warning(response) - current_app.logger.warning(err) - return response, status - - -@cors_preflight("POST,OPTIONS") -@API.route("//complete", methods=["POST", "OPTIONS"]) -class TaskComplete(Resource): - """Resource for claim task.""" - - @staticmethod - @auth.require - def post(task_id): - """Complete a task.""" - request_json = request.get_json() - try: - return ( - ( - { - "tasks": TaskService.complete_task( - task_id=task_id, - data=request_json, - token=request.headers["Authorization"], - ) - } - ), - HTTPStatus.OK, - ) - except KeyError as err: - response, status = ( - { - "type": "Invalid Request Object", - "message": "Required fields are not passed", - "errors": err.messages, - }, - HTTPStatus.BAD_REQUEST, - ) - - current_app.logger.critical(response) - current_app.logger.critical(err) - return response, status - except BaseException as err: - response, status = { - "type": "Bad request error", - "message": "Invalid request data object", - }, HTTPStatus.BAD_REQUEST - - current_app.logger.warning(response) - current_app.logger.warning(err) - return response, status diff --git a/forms-flow-api/src/api/resources/tenant.py b/forms-flow-api/src/api/resources/tenant.py deleted file mode 100644 index 2d75520f2d..0000000000 --- a/forms-flow-api/src/api/resources/tenant.py +++ /dev/null @@ -1,38 +0,0 @@ -# """API endpoints for managing tenant resource.""" - -# from http import HTTPStatus - -# from flask import jsonify -# from flask_restx import Namespace, Resource - -# from ..exceptions import BusinessException -# from ..services import TenantService -# from ..utils.util import cors_preflight - - -# API = Namespace("Tenant", description="Tenant") - - -# @cors_preflight("GET,OPTIONS") -# @API.route("", methods=["GET", "OPTIONS"]) -# class TenantsResource(Resource): -# """Resource for managing tenants.""" - -# @staticmethod -# def get(): -# """Get tenants.""" -# return jsonify({"tenants": TenantService.get_all()}), HTTPStatus.OK - - -# @cors_preflight("GET,OPTIONS") -# @API.route("/", methods=["GET", "OPTIONS"]) -# class TenantResource(Resource): -# """Resource for managing tenant.""" - -# @staticmethod -# def get(tenant_id): -# """Get tenant by id.""" -# try: -# return TenantService.get_by_id(tenant_id), HTTPStatus.OK -# except BusinessException as err: -# return err.error, err.status_code diff --git a/forms-flow-api/src/api/schemas/__init__.py b/forms-flow-api/src/api/schemas/__init__.py deleted file mode 100644 index 4a3fa992ce..0000000000 --- a/forms-flow-api/src/api/schemas/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -"""This exports all of the schemas used by the application.""" - -from .aggregated_application import ( - ApplicationMetricsRequestSchema, - AggregatedApplicationSchema, -) -from .application import ( - ApplicationSchema, - ApplicationListReqSchema, - ApplicationUpdateSchema, -) -from .application_history import ApplicationHistorySchema -from .form_process_mapper import FormProcessMapperSchema -from .process import ( - ProcessListSchema, - ProcessDefinitionSchema, - ProcessActionListSchema, - ProcessDefinitionXMLSchema, - ProcessMessageSchema, - ProcessActivityInstanceSchema, -) -from .task import TaskSchema, TaskVariableSchema -from .tenant import TenantSchema diff --git a/forms-flow-api/src/api/schemas/task.py b/forms-flow-api/src/api/schemas/task.py deleted file mode 100644 index 5756bdadb4..0000000000 --- a/forms-flow-api/src/api/schemas/task.py +++ /dev/null @@ -1,40 +0,0 @@ -"""This manages task Response Schema.""" - -from marshmallow import EXCLUDE, Schema, fields - - -class TaskVariableSchema(Schema): - """This class manages task varaibles response schema.""" - - class Meta: # pylint: disable=too-few-public-methods - """Exclude unknown fields in the deserialized output.""" - - unknown = EXCLUDE - - name = fields.Str() - value = fields.Str() - - -class TaskSchema(Schema): - """This class manages task response schema.""" - - class Meta: # pylint: disable=too-few-public-methods - """Exclude unknown fields in the deserialized output.""" - - unknown = EXCLUDE - - id = fields.Str() - name = fields.Str() - assignee = fields.Str() - process_instance_id = fields.Str( - data_key="processInstanceId", attribute="processInstanceId" - ) - process_definition_key = fields.Str( - data_key="processDefinitionKey", attribute="processDefinitionKey" - ) - task_definition_key = fields.Str( - data_key="taskDefinitionKey", attribute="taskDefinitionKey" - ) - groupName = fields.Str(data_key="groupName", attribute="groupName") - status = fields.Str(data_key="status", attribute="status") - variables = fields.List(fields.Nested(TaskVariableSchema)) diff --git a/forms-flow-api/src/api/schemas/tenant.py b/forms-flow-api/src/api/schemas/tenant.py deleted file mode 100644 index 2d9dcfc53b..0000000000 --- a/forms-flow-api/src/api/schemas/tenant.py +++ /dev/null @@ -1,17 +0,0 @@ -"""This manages tenant Response Schema.""" - -from marshmallow import EXCLUDE, Schema, fields - - -class TenantSchema(Schema): - """This class manages tenant response schema.""" - - class Meta: # pylint: disable=too-few-public-methods - """Exclude unknown fields in the deserialized output.""" - - unknown = EXCLUDE - - id = fields.Int() - tenant_name = fields.Str(data_key="tenantName") - relam = fields.Str() - audience = fields.Str() diff --git a/forms-flow-api/src/api/services/__init__.py b/forms-flow-api/src/api/services/__init__.py deleted file mode 100644 index 8e6079b043..0000000000 --- a/forms-flow-api/src/api/services/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -"""This exports all of the services used by the application.""" - -from .application import ApplicationService -from .application_history import ApplicationHistoryService -from .form_process_mapper import FormProcessMapperService - -# from .formio_token import FormIOTokenService -from .process import ProcessService -from .task import TaskService - -# from .tenant import TenantService - -__all__ = [ - "ApplicationService", - "ApplicationHistoryService", - "FormProcessMapperService", - "ProcessService", - "TaskService", -] diff --git a/forms-flow-api/src/api/services/process.py b/forms-flow-api/src/api/services/process.py deleted file mode 100644 index 6130c5b21c..0000000000 --- a/forms-flow-api/src/api/services/process.py +++ /dev/null @@ -1,117 +0,0 @@ -"""This exposes process service.""" - -import json -from http import HTTPStatus - -from ..exceptions import BusinessException -from ..schemas import ( - ProcessActionListSchema, - ProcessActivityInstanceSchema, - ProcessDefinitionSchema, - ProcessDefinitionXMLSchema, - ProcessListSchema, -) -from .external import BPMService -from flask import current_app - - -class ProcessService: - """This class manages process service.""" - - @staticmethod - def get_all_processes(token): - """Get all processes.""" - process = BPMService.get_all_process(token=token) - if process: - result = ProcessListSchema().dump(process, many=True) - seen = set() - new_result = [] - for data in result: - if data["key"] not in seen: - seen.add(data["key"]) - new_result.append(data) - return new_result - - return process - - @staticmethod - def get_process(process_key, token): - """Get process details.""" - process_details = BPMService.get_process_details( - process_key=process_key, token=token - ) - if process_details: - return ProcessDefinitionSchema().dump(process_details) - - raise BusinessException("Invalid process", HTTPStatus.BAD_REQUEST) - - @staticmethod - def get_process_definition_xml(process_key, token): - """Get process details.""" - process_definition_xml = BPMService.get_process_definition_xml( - process_key=process_key, token=token - ) - if process_definition_xml: - return ProcessDefinitionXMLSchema().dump(process_definition_xml) - - raise BusinessException("Invalid process", HTTPStatus.BAD_REQUEST) - - @staticmethod - def get_process_action(process_key, token): - """Get process actions.""" - process_details = BPMService.get_process_actions( - process_key=process_key, token=token - ) - if process_details: - return ProcessActionListSchema().dump(process_details) - - raise BusinessException("Invalid process", HTTPStatus.BAD_REQUEST) - - @staticmethod - def get_states(process_key, task_key, token): - """Get states.""" - payload = { - "variables": { - "process": {"value": process_key}, - "task": {"value": task_key}, - } - } - data = BPMService.post_process_evaluate(payload=payload, token=token) - if data: - value = data[0].get("state", {}).get("value") - # Since we are receiving a string instead of json and the string contain single quote - # instead of double quote. - value = value.replace("'", '"') - return json.loads(value) - - raise BusinessException("error", HTTPStatus.BAD_REQUEST) - - @staticmethod - def post_message(data, token): - """Get process details.""" - return BPMService.send_message(data=data, token=token) - - @staticmethod - def get_process_activity_instances(process_instace_id, token): - """Get process actions.""" - current_app.logger.debug("get_process_activity_instances " + process_instace_id) - activity_instances = BPMService.get_process_activity_instances( - process_instace_id=process_instace_id, token=token - ) - current_app.logger.debug(activity_instances) - try: - if activity_instances: - return ProcessActivityInstanceSchema().dump(activity_instances) - except TypeError as err: - response, status = { - "type": "Invalid request", - "message": "Invalid request object passed", - "errors": err.messages, - }, HTTPStatus.BAD_REQUEST - current_app.logger.critical(response) - current_app.logger.critical(err) - return response, status - - # raise BusinessException( - # "No activity instances available for process", HTTPStatus.BAD_REQUEST - # ) diff --git a/forms-flow-api/src/api/services/task.py b/forms-flow-api/src/api/services/task.py deleted file mode 100644 index 0794266796..0000000000 --- a/forms-flow-api/src/api/services/task.py +++ /dev/null @@ -1,60 +0,0 @@ -"""This exposes task service.""" - -from http import HTTPStatus - -from ..exceptions import BusinessException -from ..schemas import TaskSchema -from .external import BPMService - - -class TaskService: - """This class manages task service.""" - - @staticmethod - def get_all_tasks(token): - """Get all tasks.""" - tasks = BPMService.get_all_tasks(token=token) - task_list = None - if tasks: - task_schema = TaskSchema() - task_list = task_schema.dump(tasks, many=True) - return task_list - - @staticmethod - def get_task(task_id, token): - """Get task.""" - task = BPMService.get_task(task_id=task_id, token=token) - task_list = None - if task: - task_schema = TaskSchema() - task_list = task_schema.dump(task) - return task_list - - @staticmethod - def claim_task(task_id, data, token): - """Claim a task.""" - task_claim = BPMService.claim_task(task_id=task_id, data=data, token=token) - if task_claim: - return "success" - - raise BusinessException("error", HTTPStatus.BAD_REQUEST) - - @staticmethod - def unclaim_task(task_id, data, token): - """Unclaim a task.""" - task_unclaim = BPMService.unclaim_task(task_id=task_id, data=data, token=token) - if task_unclaim: - return "success" - - raise BusinessException("error", HTTPStatus.BAD_REQUEST) - - @staticmethod - def complete_task(task_id, data, token): - """Complete a task.""" - task_complete = BPMService.complete_task( - task_id=task_id, data=data, token=token - ) - if task_complete: - return "success" - - raise BusinessException("error", HTTPStatus.BAD_REQUEST) diff --git a/forms-flow-api/src/api/utils/__init__.py b/forms-flow-api/src/api/utils/__init__.py deleted file mode 100644 index 42e23a0f28..0000000000 --- a/forms-flow-api/src/api/utils/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -"""This module holds general utility functions and helpers for the main package.""" - -from .auth import auth -from .constants import ( - ALLOW_ALL_APPLICATIONS, - ALLOW_ALL_ORIGINS, - CORS_ORIGINS, - METRIC_CREATED, - METRICS_MODIFIED, - NEW_APPLICATION_STATUS, - REVIEWER_GROUP, -) -from .util import cors_preflight -from .profiler import profiletime diff --git a/forms-flow-api/src/api/utils/roles.py b/forms-flow-api/src/api/utils/roles.py deleted file mode 100644 index fa7d3675da..0000000000 --- a/forms-flow-api/src/api/utils/roles.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Role definitions.""" - - -class Role: # pylint: disable=too-few-public-methods - """User Role.""" - - rpas_designer = "rpas-designer" - rpas_reviewer = "rpas-reviewer" - rpas_client = "rpas-client" diff --git a/forms-flow-api/src/formsflow_api/__init__.py b/forms-flow-api/src/formsflow_api/__init__.py new file mode 100644 index 0000000000..bf7f744ef2 --- /dev/null +++ b/forms-flow-api/src/formsflow_api/__init__.py @@ -0,0 +1,5 @@ +"""The forms flow API service.""" + +from formsflow_api.app import create_app, setup_jwt_manager + +__version__ = "4.0.4-alpha" diff --git a/forms-flow-api/src/api/__init__.py b/forms-flow-api/src/formsflow_api/app.py similarity index 84% rename from forms-flow-api/src/api/__init__.py rename to forms-flow-api/src/formsflow_api/app.py index fa3f893af6..4b8cfd877e 100644 --- a/forms-flow-api/src/api/__init__.py +++ b/forms-flow-api/src/formsflow_api/app.py @@ -1,25 +1,21 @@ -"""The forms flow API service.""" - import logging -import logging.config import os - -# import logging.handlers -from flask import Flask -from flask import request +from flask import Flask, request +from flask.logging import default_handler from werkzeug.middleware.proxy_fix import ProxyFix -from . import config, models -from .models import db, ma -from .resources import API -from api.utils.auth import jwt -from api.utils.constants import ( - CORS_ORIGINS, + +from formsflow_api import models, config +from formsflow_api.resources import API +from formsflow_api.models import db, ma + +from formsflow_api.utils import ( ALLOW_ALL_ORIGINS, + CORS_ORIGINS, + CustomFormatter, FORMSFLOW_API_CORS_ORIGINS, + jwt, + setup_logging, ) -from api.utils.logging import setup_logging -from api.utils.format import CustomFormatter -from flask.logging import default_handler def create_app(run_mode=os.getenv("FLASK_ENV", "production")): @@ -47,9 +43,6 @@ def create_app(run_mode=os.getenv("FLASK_ENV", "production")): contents = f.read() print(contents) app.logger.info("Welcome to formsflow-API server...!") - API_URL = app.config.get("FORMSFLOW_API_URL") - FORMSFLOW_API_URL = API_URL + "/checkpoint" - app.logger.info("Go to :" + FORMSFLOW_API_URL) db.init_app(app) ma.init_app(app) diff --git a/forms-flow-api/src/api/config.py b/forms-flow-api/src/formsflow_api/config.py similarity index 70% rename from forms-flow-api/src/api/config.py rename to forms-flow-api/src/formsflow_api/config.py index 5041c23b5f..ba93b8d1c0 100644 --- a/forms-flow-api/src/api/config.py +++ b/forms-flow-api/src/formsflow_api/config.py @@ -16,10 +16,10 @@ load_dotenv(find_dotenv()) CONFIGURATION = { - "development": "api.config.DevConfig", - "testing": "api.config.TestConfig", - "production": "api.config.ProdConfig", - "default": "api.config.ProdConfig", + "development": "formsflow_api.config.DevConfig", + "testing": "formsflow_api.config.TestConfig", + "production": "formsflow_api.config.ProdConfig", + "default": "formsflow_api.config.ProdConfig", } @@ -55,15 +55,11 @@ class _Config: # pylint: disable=too-few-public-methods # POSTGRESQL SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL", "") - # SQLALCHEMY_ECHO = True SQLALCHEMY_ENGINE_OPTIONS = { "pool_pre_ping": True, "pool_recycle": 300, } - # MONGODB - MONGO_URI = os.getenv("MONGODB_URI") - TESTING = False DEBUG = False @@ -80,13 +76,22 @@ class _Config: # pylint: disable=too-few-public-methods BPM_TOKEN_API = os.getenv("BPM_TOKEN_API") BPM_CLIENT_ID = os.getenv("BPM_CLIENT_ID") BPM_CLIENT_SECRET = os.getenv("BPM_CLIENT_SECRET") - BPM_GRANT_TYPE = os.getenv("BPM_GRANT_TYPE") + BPM_GRANT_TYPE = os.getenv("BPM_GRANT_TYPE", "client_credentials") # BPM Camunda Details BPM_API_BASE = os.getenv("BPM_API_BASE") # API Base URL (Self) FORMSFLOW_API_URL = os.getenv("WEB_API_BASE_URL") + ## Analytics API End points + ANALYTICS_API_URL = os.getenv("INSIGHT_API_URL") + ANALYTICS_API_KEY = os.getenv("INSIGHT_API_KEY") + + # Keycloak Admin Service username + KEYCLOAK_ADMIN_USERNAME = os.getenv("KEYCLOAK_ADMIN_USERNAME") + KEYCLOAK_ADMIN_PASSWORD = os.getenv("KEYCLOAK_ADMIN_PASSWORD") + KEYCLOAK_URL = os.getenv("KEYCLOAK_URL") + KEYCLOAK_URL_REALM = os.getenv("KEYCLOAK_URL_REALM") class DevConfig(_Config): # pylint: disable=too-few-public-methods @@ -102,8 +107,21 @@ class TestConfig(_Config): # pylint: disable=too-few-public-methods DEBUG = True TESTING = True + FORMSFLOW_API_URL = os.getenv("WEB_API_BASE_URL") # POSTGRESQL - SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL_TEST", "") + SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL_TEST") + + # JWT_OIDC_TEST_MODE = True + # USE_TEST_KEYCLOAK_DOCKER = os.getenv("USE_TEST_KEYCLOAK_DOCKER") + + # JWT_OIDC Settings + JWT_OIDC_TEST_AUDIENCE = os.getenv("JWT_OIDC_AUDIENCE") + JWT_OIDC_TEST_ISSUER = os.getenv("JWT_OIDC_ISSUER") + JWT_OIDC_TEST_WELL_KNOWN_CONFIG = os.getenv("JWT_OIDC_WELL_KNOWN_CONFIG") + JWT_OIDC_TEST_ALGORITHMS = os.getenv("JWT_OIDC_ALGORITHMS") + JWT_OIDC_TEST_JWKS_URI = os.getenv("JWT_OIDC_JWKS_URI") + JWT_OIDC_TEST_JWKS_CACHE_TIMEOUT = 6000 + class ProdConfig(_Config): # pylint: disable=too-few-public-methods diff --git a/forms-flow-api/src/api/exceptions/__init__.py b/forms-flow-api/src/formsflow_api/exceptions/__init__.py similarity index 97% rename from forms-flow-api/src/api/exceptions/__init__.py rename to forms-flow-api/src/formsflow_api/exceptions/__init__.py index c95a00464b..ee3fd6093b 100644 --- a/forms-flow-api/src/api/exceptions/__init__.py +++ b/forms-flow-api/src/formsflow_api/exceptions/__init__.py @@ -4,7 +4,6 @@ error - a description of the error {code / description: classname / full text} status_code - where possible use HTTP Error Codes """ -import functools class BusinessException(Exception): diff --git a/forms-flow-api/src/api/logging.conf b/forms-flow-api/src/formsflow_api/logging.conf similarity index 100% rename from forms-flow-api/src/api/logging.conf rename to forms-flow-api/src/formsflow_api/logging.conf diff --git a/forms-flow-api/src/formsflow_api/models/__init__.py b/forms-flow-api/src/formsflow_api/models/__init__.py new file mode 100644 index 0000000000..6a5a858a4f --- /dev/null +++ b/forms-flow-api/src/formsflow_api/models/__init__.py @@ -0,0 +1,10 @@ +"""This exports all of the models used by the formsflow_api.""" + +from formsflow_api.models.base_model import BaseModel +from formsflow_api.models.db import db, ma +from formsflow_api.models.form_process_mapper import FormProcessMapper +from formsflow_api.models.application import Application +from formsflow_api.models.application_history import ApplicationHistory + + +__all__ = ["db", "ma", "FormProcessMapper", "Application", "ApplicationHistory"] diff --git a/forms-flow-api/src/formsflow_api/models/application.py b/forms-flow-api/src/formsflow_api/models/application.py new file mode 100644 index 0000000000..0b0eb11f8a --- /dev/null +++ b/forms-flow-api/src/formsflow_api/models/application.py @@ -0,0 +1,568 @@ +"""This manages Application submission Data.""" + +from __future__ import annotations +from datetime import datetime +from flask import current_app +from sqlalchemy import and_, func, or_ +from sqlalchemy.sql.expression import text + +from formsflow_api.models.audit_mixin import AuditDateTimeMixin, AuditUserMixin +from formsflow_api.models import BaseModel, db, FormProcessMapper +from formsflow_api.utils import validate_sort_order_and_order_by + + +class Application(AuditDateTimeMixin, AuditUserMixin, BaseModel, db.Model): + """This class manages application against each form.""" + + id = db.Column(db.Integer, primary_key=True) + application_name = db.Column(db.String(100), nullable=False) + application_status = db.Column(db.String(100), nullable=False) + form_process_mapper_id = db.Column( + db.Integer, db.ForeignKey("form_process_mapper.id"), nullable=False + ) + form_url = db.Column(db.String(500), nullable=True) + process_instance_id = db.Column(db.String(100), nullable=True) + revision_no = db.Column(db.Integer, nullable=False) # set 1 now + + @classmethod + def create_from_dict(cls, application_info: dict) -> Application: + """Create new application.""" + if application_info: + application = Application() + application.application_name = application_info["application_name"] + application.application_status = application_info["application_status"] + application.form_process_mapper_id = application_info[ + "form_process_mapper_id" + ] + application.form_url = application_info["form_url"] + application.revision_no = 1 # application_info['revision_no'] + application.created_by = application_info["created_by"] + application.save() + return application + return None + + def update(self, mapper_info: dict): + """Update application.""" + self.update_from_dict( + [ + "application_name", + "application_status", + "form_url", + "form_process_mapper_id", + "process_instance_id", + "revision_no", + "modified_by", + ], + mapper_info, + ) + self.commit() + + @classmethod + def find_by_id(cls, application_id: int) -> Application: + """Find application that matches the provided id.""" + return cls.query.filter_by(id=application_id).first() + + @classmethod + def find_all_application_status(cls): + """Find all application status""" + return cls.query.distinct(Application.application_status).all() + + @classmethod + def find_by_ids(cls, application_ids) -> Application: + """Find application that matches the provided id.""" + return cls.query.filter(cls.id.in_(application_ids)).order_by( + Application.id.desc() + ) + + @classmethod + def find_all(cls, page_no: int, limit: int) -> Application: + """Fetch all application.""" + if page_no == 0: + return cls.query.order_by(Application.id.desc()).all() + else: + return ( + cls.query.order_by(Application.id.desc()) + .paginate(page_no, limit, False) + .items + ) + + @classmethod + def find_all_by_user( + cls, + user_id: str, + page_no: int, + limit: int, + order_by: str, + application_id: int, + application_name: str, + application_status: str, + created_by: str, + modified_from: datetime, + modified_to: datetime, + sort_order: str, + created_from: datetime, + created_to: datetime, + ) -> Application: + """Fetch applications list based on searching parameters for Non-reviewer""" + + if ( + application_id + and application_name + and application_status + and modified_from + and modified_to + ): + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id and application_name and application_status: + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + ) + elif application_id and application_name and modified_from and modified_to: + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id and application_status and modified_from and modified_to: + query = cls.query.filter( + Application.id == application_id, + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_name and application_status and modified_from and modified_to: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id and application_name: + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + ) + elif application_id and application_status: + query = cls.query.filter( + Application.id == application_id, + Application.application_status == application_status, + ) + elif application_id and modified_from and modified_to: + query = query = cls.query.filter( + Application.id == application_id, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_name and application_status: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + ) + elif application_name and modified_from and modified_to: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_status and modified_from and modified_to: + query = cls.query.filter( + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id: + query = cls.query.filter( + Application.id == application_id, + ) + elif application_name: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + ) + elif application_status: + query = cls.query.filter( + Application.application_status == application_status, + ) + elif created_by: + query = cls.query.filter(Application.created_by.like(f"{created_by}%")) + elif modified_from and modified_to: + query = cls.query.filter( + and_( + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + ) + elif created_from and created_to: + query = cls.query.filter( + and_( + Application.created >= created_from, + Application.created <= created_to, + ) + ) + else: + query = cls.query + query = query.filter(Application.created_by == user_id) + + order_by, sort_order = validate_sort_order_and_order_by(order_by, sort_order) + if order_by and sort_order: + query = query.order_by(text(f"Application.{order_by} {sort_order}")) + + total_count = query.count() + pagination = query.paginate(page_no, limit) + return pagination.items, total_count + + @classmethod + def find_all_by_user_group(cls, user_id: str, page_no: int, limit: int): + if page_no == 0: + return cls.query.filter(Application.created_by == user_id).order_by( + Application.id.desc() + ) + else: + return ( + cls.query.filter(Application.created_by == user_id) + .order_by(Application.id.desc()) + .paginate(page_no, limit, False) + .items + ) + + @classmethod + def find_id_by_user(cls, application_id: int, user_id: str) -> Application: + """Find application that matches the provided id.""" + return cls.query.filter( + and_(Application.id == application_id, Application.created_by == user_id) + ).one_or_none() + + @classmethod + def find_all_by_user_count(cls, user_id: str) -> Application: + """Fetch all application.""" + return cls.query.filter(Application.created_by == user_id).count() + + @classmethod + def find_by_form_id(cls, form_id, page_no: int, limit: int): + if page_no == 0: + return cls.query.filter( + Application.form_url.like("%" + form_id + "%") + ).order_by(Application.id.desc()) + else: + return ( + cls.query.filter(Application.form_url.like("%" + form_id + "%")) + .order_by(Application.id.desc()) + .paginate(page_no, limit, False) + .items + ) + + @classmethod + def find_by_form_names( + cls, + form_names: str, + application_id: int, + modified_from: datetime, + modified_to: datetime, + application_name: str, + application_status: str, + created_by: str, + page_no: int, + limit: int, + order_by: str, + sort_order: str, + created_from: datetime, + created_to: datetime, + ): + """Fetch applications list based on searching parameters for Reviewer""" + if ( + application_id + and application_name + and application_status + and modified_from + and modified_to + ): + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id and application_name and application_status: + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + ) + elif application_id and application_name and modified_from and modified_to: + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id and application_status and modified_from and modified_to: + query = cls.query.filter( + Application.id == application_id, + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_name and application_status and modified_from and modified_to: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id and application_name: + query = cls.query.filter( + Application.id == application_id, + Application.application_name.like(f"{application_name}%"), + ) + elif application_id and application_status: + query = cls.query.filter( + Application.id == application_id, + Application.application_status == application_status, + ) + elif application_id and modified_from and modified_to: + query = query = cls.query.filter( + Application.id == application_id, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_name and application_status: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + Application.application_status == application_status, + ) + elif application_name and modified_from and modified_to: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_status and modified_from and modified_to: + query = cls.query.filter( + Application.application_status == application_status, + Application.modified >= modified_from, + Application.modified <= modified_to, + ) + elif application_id: + query = cls.query.filter( + Application.id == application_id, + ) + elif application_name: + query = cls.query.filter( + Application.application_name.like(f"{application_name}%"), + ) + elif application_status: + query = cls.query.filter( + Application.application_status == application_status, + ) + elif created_by: + query = cls.query.filter(Application.created_by.like(f"{created_by}%")) + elif modified_from and modified_to: + current_app.logger.debug((modified_from, modified_to)) + query = cls.query.filter( + and_( + Application.modified <= modified_to, + Application.modified >= modified_from, + ) + ) + elif created_from and created_to: + query = cls.query.filter( + and_( + Application.created >= created_from, + Application.created <= created_to, + ) + ) + else: + query = cls.query + query = query.filter(Application.application_name.in_(form_names)) + order_by, sort_order = validate_sort_order_and_order_by(order_by, sort_order) + if order_by and sort_order: + query = query.order_by(text(f"Application.{order_by} {sort_order}")) + total_count = query.count() + pagination = query.paginate(page_no, limit) + return pagination.items, total_count + + @classmethod + def find_all_applications(cls, page_no: int, limit: int, form_names: str): + if page_no == 0: + return cls.query.filter( + Application.application_name.in_(form_names) + ).order_by(Application.id.desc()) + else: + return ( + cls.query.filter(Application.application_name.in_(form_names)) + .order_by(Application.id.desc()) + .paginate(page_no, limit, False) + .items + ) + + @classmethod + def find_id_by_form_names(cls, application_id: int, form_names): + return cls.query.filter( + and_( + Application.application_name.in_(form_names), + Application.id == application_id, + ) + ).one_or_none() + + @classmethod + def find_by_form_id_user(cls, form_id, user_id: str, page_no: int, limit: int): + if page_no == 0: + return ( + cls.query.filter(Application.form_url.like("%" + form_id + "%")) + .filter(Application.created_by == user_id) + .order_by(Application.id.desc()) + ) + else: + return ( + cls.query.filter(Application.form_url.like("%" + form_id + "%")) + .filter(Application.created_by == user_id) + .order_by(Application.id.desc()) + .paginate(page_no, limit, False) + .items + ) + + @classmethod + def find_by_form_ids(cls, form_ids, page_no: int, limit: int): + """Fetch application based on multiple form ids.""" + if page_no == 0: + return cls.query.filter( + or_( + Application.form_url.like("%" + form_id + "%") + for form_id in form_ids + ) + ).order_by(Application.id.desc()) + else: + return ( + cls.query.filter( + or_( + Application.form_url.like("%" + form_id + "%") + for form_id in form_ids + ) + ) + .order_by(Application.id.desc()) + .paginate(page_no, limit, False) + .items + ) + + @classmethod + def find_all_by_form_id_count(cls, form_id): + """Fetch all application.""" + return cls.query.filter(Application.form_url.like("%" + form_id + "%")).count() + + @classmethod + def find_all_by_form_id_user_count(cls, form_id, user_id: str): + """Fetch all application.""" + return ( + cls.query.filter(Application.form_url.like("%" + form_id + "%")) + .filter(Application.created_by == user_id) + .count() + ) + + @classmethod + def find_aggregated_applications(cls, from_date: str, to_date: str): + """Fetch aggregated applications ordered by created date.""" + result_proxy = ( + db.session.query( + Application.form_process_mapper_id, + FormProcessMapper.form_name, + func.count(Application.form_process_mapper_id).label("count"), + ) + .join( + FormProcessMapper, + FormProcessMapper.id == Application.form_process_mapper_id, + ) + .filter( + and_( + Application.created >= from_date, + Application.created <= to_date, + ) + ) + .group_by(Application.form_process_mapper_id, FormProcessMapper.form_name) + ) + + return [dict(row) for row in result_proxy] + + @classmethod + def find_aggregated_applications_modified( + cls, from_date: datetime, to_date: datetime + ): + """Fetch aggregated applications ordered by created date.""" + result_proxy = ( + db.session.query( + Application.form_process_mapper_id, + FormProcessMapper.form_name, + func.count(Application.form_process_mapper_id).label("count"), + ) + .join( + FormProcessMapper, + FormProcessMapper.id == Application.form_process_mapper_id, + ) + .filter( + and_( + Application.modified >= from_date, + Application.modified <= to_date, + ) + ) + .group_by(Application.form_process_mapper_id, FormProcessMapper.form_name) + ) + + return [dict(row) for row in result_proxy] + + @classmethod + def find_aggregated_application_status( + cls, mapper_id: int, from_date: str, to_date: str + ): + """Fetch aggregated application status corresponding to mapper_id ordered by created date.""" + result_proxy = ( + db.session.query( + Application.application_status, + Application.application_name, + func.count(Application.application_name).label("count"), + ) + .join( + FormProcessMapper, + FormProcessMapper.id == Application.form_process_mapper_id, + ) + .filter( + and_( + Application.created >= from_date, + Application.created <= to_date, + Application.form_process_mapper_id == mapper_id, + ) + ) + .group_by(Application.application_status, Application.application_name) + ) + + return result_proxy + + @classmethod + def find_aggregated_application_status_modified( + cls, mapper_id: int, from_date: str, to_date: str + ): + """Fetch aggregated application status corresponding to mapper_id ordered by modified date..""" + result_proxy = ( + db.session.query( + Application.application_name, + Application.application_status, + func.count(Application.application_name).label("count"), + ) + .filter( + and_( + Application.modified >= from_date, + Application.modified <= to_date, + Application.form_process_mapper_id == mapper_id, + ) + ) + .group_by(Application.application_name, Application.application_status) + ) + + return result_proxy diff --git a/forms-flow-api/src/api/models/application_history.py b/forms-flow-api/src/formsflow_api/models/application_history.py similarity index 91% rename from forms-flow-api/src/api/models/application_history.py rename to forms-flow-api/src/formsflow_api/models/application_history.py index 43caa35da0..5750228a91 100644 --- a/forms-flow-api/src/api/models/application_history.py +++ b/forms-flow-api/src/formsflow_api/models/application_history.py @@ -1,14 +1,13 @@ """This manages Application audit data.""" from __future__ import annotations -from .audit_mixin import ApplicationAuditDateTimeMixin -from .base_model import BaseModel -from .db import db +from formsflow_api.models.audit_mixin import ApplicationAuditDateTimeMixin +from formsflow_api.models.base_model import BaseModel +from formsflow_api.models.db import db class ApplicationHistory(ApplicationAuditDateTimeMixin, BaseModel, db.Model): """This class manages application audit against each form.""" - __tablename__ = "application_audit" id = db.Column(db.Integer, primary_key=True) application_id = db.Column(db.Integer, nullable=False) diff --git a/forms-flow-api/src/api/models/audit_mixin.py b/forms-flow-api/src/formsflow_api/models/audit_mixin.py similarity index 96% rename from forms-flow-api/src/api/models/audit_mixin.py rename to forms-flow-api/src/formsflow_api/models/audit_mixin.py index c26b237e2f..496054a5bc 100644 --- a/forms-flow-api/src/api/models/audit_mixin.py +++ b/forms-flow-api/src/formsflow_api/models/audit_mixin.py @@ -2,7 +2,7 @@ import datetime -from .db import db +from formsflow_api.models.db import db class AuditDateTimeMixin: # pylint: disable=too-few-public-methods diff --git a/forms-flow-api/src/api/models/base_model.py b/forms-flow-api/src/formsflow_api/models/base_model.py similarity index 96% rename from forms-flow-api/src/api/models/base_model.py rename to forms-flow-api/src/formsflow_api/models/base_model.py index 1727cc5097..8bad010326 100644 --- a/forms-flow-api/src/api/models/base_model.py +++ b/forms-flow-api/src/formsflow_api/models/base_model.py @@ -1,6 +1,6 @@ """This manages Base Model functions.""" -from .db import db +from formsflow_api.models.db import db class BaseModel: diff --git a/forms-flow-api/src/api/models/db.py b/forms-flow-api/src/formsflow_api/models/db.py similarity index 100% rename from forms-flow-api/src/api/models/db.py rename to forms-flow-api/src/formsflow_api/models/db.py diff --git a/forms-flow-api/src/api/models/form_process_mapper.py b/forms-flow-api/src/formsflow_api/models/form_process_mapper.py similarity index 93% rename from forms-flow-api/src/api/models/form_process_mapper.py rename to forms-flow-api/src/formsflow_api/models/form_process_mapper.py index f418a60318..507e672693 100644 --- a/forms-flow-api/src/api/models/form_process_mapper.py +++ b/forms-flow-api/src/formsflow_api/models/form_process_mapper.py @@ -1,19 +1,19 @@ -"""This manages appication Data.""" +"""This manages Form ProcessMapper Database Models.""" from __future__ import annotations from http import HTTPStatus from sqlalchemy import and_ -from ..exceptions import BusinessException -from .audit_mixin import AuditDateTimeMixin, AuditUserMixin -from .base_model import BaseModel -from .db import db -from .enums import FormProcessMapperStatus +from formsflow_api.exceptions import BusinessException +from formsflow_api.models.audit_mixin import AuditDateTimeMixin, AuditUserMixin +from formsflow_api.models.base_model import BaseModel +from formsflow_api.models.db import db +from formsflow_api.utils.enums import FormProcessMapperStatus class FormProcessMapper(AuditDateTimeMixin, AuditUserMixin, BaseModel, db.Model): - """This class manages form process mapper imformation.""" + """This class manages form process mapper information.""" id = db.Column(db.Integer, primary_key=True) form_id = db.Column(db.String(50), nullable=False) @@ -45,7 +45,7 @@ def create_from_dict(cls, mapper_info: dict) -> FormProcessMapper: mapper.tenant_id = mapper_info.get("tenant_id") mapper.save() return mapper - except BaseException as form_err: + except BaseException: response, status = { "type": "Bad Request Error", "message": "Invalid application request passed", diff --git a/forms-flow-api/src/api/resources/__init__.py b/forms-flow-api/src/formsflow_api/resources/__init__.py similarity index 61% rename from forms-flow-api/src/api/resources/__init__.py rename to forms-flow-api/src/formsflow_api/resources/__init__.py index 21f26364a6..35fa0ffdce 100644 --- a/forms-flow-api/src/api/resources/__init__.py +++ b/forms-flow-api/src/formsflow_api/resources/__init__.py @@ -6,18 +6,16 @@ from flask_jwt_oidc import AuthError from flask_restx import Api -from ..exceptions import BusinessException -from .application import API as APPLICATION_API -from .application_history import API as APPLICATION_HISTORY_API -from .metrics import API as APPLICATION_METRICS_API -from .checkpoint import API as CHECKPOINT_API -from .form_process_mapper import API as FORM_API -from .process import API as PROCESS_API -from .task import API as TASK_API -from api.utils.constants import ALLOW_ALL_ORIGINS - -# from .formiotoken import API as FORMIOTOKEN_API -# from .tenant import API as TENANT_API +from formsflow_api.exceptions import BusinessException +from formsflow_api.resources.application import API as APPLICATION_API +from formsflow_api.resources.application_history import API as APPLICATION_HISTORY_API +from formsflow_api.resources.metrics import API as APPLICATION_METRICS_API +from formsflow_api.resources.checkpoint import API as CHECKPOINT_API +from formsflow_api.resources.dashboards import API as DASHBOARDS_API +from formsflow_api.resources.form_process_mapper import API as FORM_API +from formsflow_api.resources.groups import API as KEYCLOAK_GROUPS_API +from formsflow_api.resources.process import API as PROCESS_API +from formsflow_api.utils.constants import ALLOW_ALL_ORIGINS # This will add the Authorize button to the swagger docs @@ -30,7 +28,7 @@ description="The API for formsflow.ai. Checkout: formsflow.ai to know more", security=["apikey"], authorizations=AUTHORIZATIONS, - doc="/docs", + doc="/", ) @@ -50,8 +48,7 @@ def handle_auth_error(error: AuthError): return ( { "type": "Invalid Token Error", - "message": """Access to formsflow.ai API Denied. Check if the bearer - token is passed for Authorization or has expired.""", + "message": "Access to formsflow.ai API Denied. Check if the bearer token is passed for Authorization or has expired.", }, error.status_code, {"Access-Control-Allow-Origin": ALLOW_ALL_ORIGINS}, @@ -62,8 +59,7 @@ def handle_auth_error(error: AuthError): API.add_namespace(APPLICATION_HISTORY_API, path="/application") API.add_namespace(APPLICATION_METRICS_API, path="/metrics") API.add_namespace(CHECKPOINT_API, path="/checkpoint") +API.add_namespace(DASHBOARDS_API, path="/dashboards") API.add_namespace(FORM_API, path="/form") -# API.add_namespace(FORMIOTOKEN_API, path="/getformiotoken") +API.add_namespace(KEYCLOAK_GROUPS_API, path="/groups") API.add_namespace(PROCESS_API, path="/process") -API.add_namespace(TASK_API, path="/task") -# API.add_namespace(TENANT_API, path="/tenant") diff --git a/forms-flow-api/src/api/resources/application.py b/forms-flow-api/src/formsflow_api/resources/application.py similarity index 63% rename from forms-flow-api/src/api/resources/application.py rename to forms-flow-api/src/formsflow_api/resources/application.py index e5e2bef4a3..7e4ba7fc8b 100644 --- a/forms-flow-api/src/api/resources/application.py +++ b/forms-flow-api/src/formsflow_api/resources/application.py @@ -5,14 +5,15 @@ from flask import current_app, g, request from flask_restx import Namespace, Resource -from api.exceptions import BusinessException -from api.schemas.application import ( +from formsflow_api.exceptions import BusinessException +from formsflow_api.schemas import ( + ApplicationListRequestSchema, ApplicationListReqSchema, ApplicationSchema, ApplicationUpdateSchema, ) -from api.services import ApplicationService -from api.utils import REVIEWER_GROUP, auth, cors_preflight, profiletime +from formsflow_api.services import ApplicationService +from formsflow_api.utils import REVIEWER_GROUP, auth, cors_preflight, profiletime API = Namespace("Application", description="Application") @@ -27,36 +28,73 @@ class ApplicationsResource(Resource): @auth.require @profiletime def get(): - """Get applications.""" - if request.args: - dict_data = ApplicationListReqSchema().load(request.args) - page_no = dict_data["page_no"] - limit = dict_data["limit"] - else: - page_no = 0 - limit = 0 - if auth.has_role([REVIEWER_GROUP]): - ( - application_schema_dump, - application_count, - ) = ApplicationService.get_auth_applications_and_count( - page_no=page_no, limit=limit, token=request.headers["Authorization"] - ) - application_schema = ApplicationService.apply_custom_attributes( - application_schema=application_schema_dump - ) - else: - application_schema = ApplicationService.apply_custom_attributes( - ApplicationService.get_all_applications_by_user( + """Get applications + Fetch applications list based on parameters + :params Id: list the application for particular id + :params applicationName: retrieve application list based on application name + :params applicationStatus: list all applications based on status + :params createdBy: to retrieve applications based on createdby + :params created: retrieve the applications based on date and time + :params modified: retrieve the applications based on modified date and time + :params pageNo: to retrieve page number + :params limit: to retrieve limit for each page + :params orderBy: Name of column to order by (default: created) + """ + try: + dict_data = ApplicationListRequestSchema().load(request.args) or {} + page_no = dict_data.get("page_no") + limit = dict_data.get("limit") + order_by = dict_data.get("order_by") or "id" + application_id = dict_data.get("application_id") + application_name = dict_data.get("application_name") + application_status = dict_data.get("application_status") + created_by = dict_data.get("created_by") + created_from_date = dict_data.get("created_from_date") + created_to_date = dict_data.get("created_to_date") + modified_from_date = dict_data.get("modified_from_date") + modified_to_date = dict_data.get("modified_to_date") + sort_order = dict_data.get("sort_order") or "desc" + if auth.has_role([REVIEWER_GROUP]): + ( + application_schema_dump, + application_count, + ) = ApplicationService.get_auth_applications_and_count( + created_from=created_from_date, + created_to=created_to_date, + modified_from=modified_from_date, + modified_to=modified_to_date, + order_by=order_by, + sort_order=sort_order, + created_by=created_by, + application_id=application_id, + application_name=application_name, + application_status=application_status, + token=request.headers["Authorization"], + page_no=page_no, + limit=limit, + ) + else: + ( + application_schema_dump, + application_count, + ) = ApplicationService.get_all_applications_by_user( user_id=g.token_info.get("preferred_username"), page_no=page_no, limit=limit, + order_by=order_by, + sort_order=sort_order, + created_from=created_from_date, + created_to=created_to_date, + modified_from=modified_from_date, + modified_to=modified_to_date, + created_by=created_by, + application_id=application_id, + application_name=application_name, + application_status=application_status, + ) + application_schema = ApplicationService.apply_custom_attributes( + application_schema=application_schema_dump ) - ) - application_count = ApplicationService.get_all_application_by_user_count( - user_id=g.token_info.get("preferred_username") - ) - if page_no > 0: return ( ( { @@ -68,38 +106,18 @@ def get(): ), HTTPStatus.OK, ) - else: - return ( - ( - { - "applications": application_schema, - "totalCount": application_count, - } - ), - HTTPStatus.OK, + except KeyError as err: + response, status = ( + { + "type": "Invalid Request Object", + "message": "Required fields are not passed", + }, + HTTPStatus.BAD_REQUEST, ) - # @staticmethod - # @auth.require - # def post(): - # """Post a new application using the request body.""" - # application_json = request.get_json() - # """Get applications.""" - # try: - # return ( - # jsonify( - # { - # "applications": ApplicationService.apply_custom_attributes( - # ApplicationService.get_all_applications_ids( - # application_json["applicationIds"] - # ) - # ) - # } - # ), - # HTTPStatus.OK, - # ) - # except BusinessException as err: - # return err.error, err.status_code + current_app.logger.critical(response) + current_app.logger.critical(err) + return response, status @cors_preflight("GET,PUT,OPTIONS") @@ -247,7 +265,6 @@ def post(): application = ApplicationService.create_application( data=dict_data, token=request.headers["Authorization"] ) - response, status = application_schema.dump(application), HTTPStatus.CREATED return response, status except BaseException as application_err: @@ -277,3 +294,22 @@ def get(application_id): ) except BusinessException as err: return err.error, err.status_code + + +@cors_preflight("GET,OPTIONS") +@API.route("/status/list", methods=["GET", "OPTIONS"]) +class ApplicationResourceByApplicationStatus(Resource): + """Get application status.""" + + @staticmethod + @auth.require + @profiletime + def get(): + + try: + return ( + ApplicationService.get_all_application_status(), + HTTPStatus.OK, + ) + except BusinessException as err: + return err.error, err.status_code diff --git a/forms-flow-api/src/api/resources/application_history.py b/forms-flow-api/src/formsflow_api/resources/application_history.py similarity index 84% rename from forms-flow-api/src/api/resources/application_history.py rename to forms-flow-api/src/formsflow_api/resources/application_history.py index d72e3d74cd..613e97eed5 100644 --- a/forms-flow-api/src/api/resources/application_history.py +++ b/forms-flow-api/src/formsflow_api/resources/application_history.py @@ -5,9 +5,9 @@ from flask import current_app, request from flask_restx import Namespace, Resource -from api.schemas import ApplicationHistorySchema -from api.services import ApplicationHistoryService -from api.utils import auth, cors_preflight, profiletime +from formsflow_api.schemas import ApplicationHistorySchema +from formsflow_api.services import ApplicationHistoryService +from formsflow_api.utils import auth, cors_preflight, profiletime # keeping the base path same for application history and application/ @@ -69,10 +69,10 @@ def post(application_id): except BaseException as application_err: response, status = { - "type": "Invalid Request Object", - "message": "Invalid Request Object Passed ", - "errors": application_err, - }, HTTPStatus.BAD_REQUEST + "type": "Invalid Request Object", + "message": "Invalid Request Object Passed ", + "errors": application_err, + }, HTTPStatus.BAD_REQUEST current_app.logger.warning(response) current_app.logger.warning(application_err) diff --git a/forms-flow-api/src/api/resources/checkpoint.py b/forms-flow-api/src/formsflow_api/resources/checkpoint.py similarity index 90% rename from forms-flow-api/src/api/resources/checkpoint.py rename to forms-flow-api/src/formsflow_api/resources/checkpoint.py index bc9034a393..ee4d42836b 100644 --- a/forms-flow-api/src/api/resources/checkpoint.py +++ b/forms-flow-api/src/formsflow_api/resources/checkpoint.py @@ -2,7 +2,7 @@ from http import HTTPStatus from flask_restx import Namespace, Resource -from api.utils import cors_preflight, profiletime +from formsflow_api.utils import cors_preflight, profiletime API = Namespace("Checkpoint", description="Checkpoint") diff --git a/forms-flow-api/src/formsflow_api/resources/dashboards.py b/forms-flow-api/src/formsflow_api/resources/dashboards.py new file mode 100644 index 0000000000..e710cfbe4b --- /dev/null +++ b/forms-flow-api/src/formsflow_api/resources/dashboards.py @@ -0,0 +1,80 @@ +"""Resource to get Dashboard APIs from redash""" +import re +from http import HTTPStatus +from flask import request, g +from flask_restx import Namespace, Resource +from formsflow_api.schemas import ApplicationListReqSchema +from formsflow_api.services import RedashAPIService +from formsflow_api.utils import ( + auth, + profiletime, + cors_preflight, +) + +API = Namespace("dashboards", description="Dashboard APIs") +analytics_service = RedashAPIService() + + +@cors_preflight("GET, OPTIONS") +@API.route("", methods=["GET", "OPTIONS"]) +class DashboardList(Resource): + """Resource to fetch Dashboard List + :params int pageNo: page number which starts from number 1 (optional) + :params int limit: number of items per page (optional) + """ + + @API.doc("list_dashboards") + @auth.require + @profiletime + def get(self): + """List all dashboards""" + if request.args: + dict_data = ApplicationListReqSchema().load(request.args) + page_no = dict_data["page_no"] + limit = dict_data["limit"] + else: + page_no = None + limit = None + response = analytics_service.get_request( + url_path="dashboards", page_no=page_no, limit=limit + ) + if response == "unauthorized": + return {"message": "Dashboards not available"}, HTTPStatus.NOT_FOUND + elif response is None: + return {"message": "Error"}, HTTPStatus.SERVICE_UNAVAILABLE + else: + assert response != None + return response, HTTPStatus.OK + + +@cors_preflight("GET,OPTIONS") +@API.route("/", methods=["GET", "OPTIONS"]) +class DashboardDetail(Resource): + """Resource to fetch Dashboard Detail""" + + @API.doc("get_dashboard") + @auth.require + @profiletime + def get(self, dashboard_id): + """Get a dashboard with given dashboard_id""" + try: + available_dashboards = re.findall( + r"\d+", str(g.token_info.get("dashboards")) + ) + available_dashboards.index(str(dashboard_id)) + except ValueError: + return { + "message": f"Dashboard - {dashboard_id} not accessible" + }, HTTPStatus.FORBIDDEN + else: + # code run in case of no exception + response = analytics_service.get_request( + url_path=f"dashboards/{dashboard_id}" + ) + if response == "unauthorized": + return {"message": "Dashboard not found"}, HTTPStatus.NOT_FOUND + elif response is None: + return {"message": "Error"}, HTTPStatus.SERVICE_UNAVAILABLE + else: + assert response != None + return response, HTTPStatus.OK diff --git a/forms-flow-api/src/api/resources/form_process_mapper.py b/forms-flow-api/src/formsflow_api/resources/form_process_mapper.py similarity index 96% rename from forms-flow-api/src/api/resources/form_process_mapper.py rename to forms-flow-api/src/formsflow_api/resources/form_process_mapper.py index 3d1fff2dca..acd641c77b 100644 --- a/forms-flow-api/src/api/resources/form_process_mapper.py +++ b/forms-flow-api/src/formsflow_api/resources/form_process_mapper.py @@ -5,11 +5,11 @@ from flask import current_app, g, request from flask_restx import Namespace, Resource -from ..exceptions import BusinessException -from ..schemas import ApplicationListReqSchema, FormProcessMapperSchema -from ..services import FormProcessMapperService +from formsflow_api.exceptions import BusinessException +from formsflow_api.schemas import ApplicationListReqSchema, FormProcessMapperSchema +from formsflow_api.services import FormProcessMapperService -from api.utils import auth, cors_preflight, profiletime +from formsflow_api.utils import auth, cors_preflight, profiletime API = Namespace("Form", description="Form") diff --git a/forms-flow-api/src/formsflow_api/resources/groups.py b/forms-flow-api/src/formsflow_api/resources/groups.py new file mode 100644 index 0000000000..7840cdab05 --- /dev/null +++ b/forms-flow-api/src/formsflow_api/resources/groups.py @@ -0,0 +1,112 @@ +"""Resource to call Keycloak Service API calls and filter responses""" +from http import HTTPStatus +from pprint import pprint +from flask import request +from flask_restx import Namespace, Resource +from marshmallow import ValidationError + +from formsflow_api.services import KeycloakAdminAPIService +from formsflow_api.schemas import ApplicationListReqSchema, KeycloakDashboardGroupSchema +from formsflow_api.utils import ( + KEYCLOAK_DASHBOARD_BASE_GROUP, + auth, + cors_preflight, + profiletime, +) + +API = Namespace("groups", description="Keycloak wrapper APIs") + + +@cors_preflight("GET, OPTIONS") +@API.route("", methods=["GET", "OPTIONS"]) +class KeycloakDashboardGroupList(Resource): + """Resource to fetch Dashboard List""" + + @staticmethod + @auth.require + @profiletime + def get(): + """GET request to fetch all dashboard groups from Keycloak + :params int pageNo: page number (optional) + :params int limit: number of items per page (optional) + """ + client = KeycloakAdminAPIService() + if request.args: + dict_data = ApplicationListReqSchema().load(request.args) + page_no = dict_data["page_no"] + limit = dict_data["limit"] + else: + page_no = 0 + limit = 0 + + if page_no == 0 and limit == 0: + group_list_response = client.get_request(url_path="groups") + else: + group_list_response = client.get_paginated_request( + url_path="groups", first=page_no, max=limit + ) + + for group in group_list_response: + if group["name"] == KEYCLOAK_DASHBOARD_BASE_GROUP: + dashboard_group_list = [x for x in group["subGroups"]] + if dashboard_group_list == []: + return { + "message": "No Dashboard authorized Group found" + }, HTTPStatus.NOT_FOUND + else: + for group in dashboard_group_list: + group["dashboards"] = ( + client.get_request(url_path=f"groups/{group['id']}") + .get("attributes") + .get("dashboards") + ) + return dashboard_group_list, HTTPStatus.OK + + +@cors_preflight("GET,PUT,OPTIONS") +@API.route("/", methods=["GET", "PUT", "OPTIONS"]) +class KeycloakDashboardGroupDetail(Resource): + @staticmethod + @auth.require + @profiletime + def get(id): + """GET request to fetch groups details API + :params str id: group-id of Keycloak Dashboard Authorized groups + """ + client = KeycloakAdminAPIService() + response = client.get_request(url_path=f"groups/{id}") + if response is None: + return {"message": f"Group - {id} not found"}, HTTPStatus.NOT_FOUND + return response + + @staticmethod + @auth.require + @profiletime + def put(id): + """Update request to update dashboard details + :params str id: group-id of Keycloak Dashboard Authorized groups + """ + client = KeycloakAdminAPIService() + group_json = request.get_json() + try: + dict_data = KeycloakDashboardGroupSchema().load(group_json) + + dashboard_id_details = client.get_request(url_path=f"groups/{id}") + if dashboard_id_details == None: + return {"message": f"Group - {id} not found"}, HTTPStatus.NOT_FOUND + else: + dashboard_id_details["attributes"]["dashboards"] = [ + str(dict_data["dashboards"]) + ] + response = client.update_request( + url_path=f"groups/{id}", data=dashboard_id_details + ) + if response is None: + return { + "message": f"Group - {id} not updated successfully" + }, HTTPStatus.SERVICE_UNAVAILABLE + else: + return response + except ValidationError as err: + pprint(err.messages) + return {"message": "Invalid Request Object format"}, HTTPStatus.BAD_REQUEST diff --git a/forms-flow-api/src/api/resources/metrics.py b/forms-flow-api/src/formsflow_api/resources/metrics.py similarity index 92% rename from forms-flow-api/src/api/resources/metrics.py rename to forms-flow-api/src/formsflow_api/resources/metrics.py index 7e47778ccb..98ba18a1aa 100644 --- a/forms-flow-api/src/api/resources/metrics.py +++ b/forms-flow-api/src/formsflow_api/resources/metrics.py @@ -5,9 +5,10 @@ from flask_restx import Namespace, Resource from marshmallow.exceptions import ValidationError -from api.schemas.aggregated_application import ApplicationMetricsRequestSchema -from api.services import ApplicationService -from api.utils import auth, cors_preflight, profiletime, METRICS_MODIFIED +from formsflow_api.schemas.aggregated_application import ApplicationMetricsRequestSchema +from formsflow_api.services import ApplicationService +from formsflow_api.utils import auth, cors_preflight, profiletime +from formsflow_api.utils.enums import MetricsState API = Namespace("Metrics", description="Application Metrics endpoint") @@ -30,7 +31,7 @@ def get(): to_date = dict_data["to_date"] order_by = dict_data.get("order_by") - if order_by == METRICS_MODIFIED: + if order_by == MetricsState.MODIFIED.value: return ( ( { @@ -92,7 +93,7 @@ def get(mapper_id): to_date = dict_data["to_date"] order_by = dict_data.get("order_by") - if order_by == METRICS_MODIFIED: + if order_by == MetricsState.MODIFIED.value: return ( ( { diff --git a/forms-flow-api/src/api/resources/process.py b/forms-flow-api/src/formsflow_api/resources/process.py similarity index 67% rename from forms-flow-api/src/api/resources/process.py rename to forms-flow-api/src/formsflow_api/resources/process.py index 42eef7d968..35bb4811fd 100644 --- a/forms-flow-api/src/api/resources/process.py +++ b/forms-flow-api/src/formsflow_api/resources/process.py @@ -4,48 +4,14 @@ from flask import current_app, request from flask_restx import Namespace, Resource - -from ..services import ProcessService - -from api.schemas.process import ProcessMessageSchema -from api.utils import auth, cors_preflight, profiletime +from formsflow_api.schemas import ProcessMessageSchema +from formsflow_api.services import ProcessService +from formsflow_api.utils import auth, cors_preflight, profiletime API = Namespace("Process", description="Process") -@cors_preflight("GET,OPTIONS") -@API.route( - "//task//state", methods=["GET", "OPTIONS"] -) -class ProcessStateResource(Resource): - """Resource for managing state.""" - - @staticmethod - @auth.require - @profiletime - def get(process_key, task_key): - """Get states by process and task key.""" - try: - return ( - ( - ProcessService.get_states( - process_key, task_key, request.headers["Authorization"] - ) - ), - HTTPStatus.OK, - ) - except BaseException as err: - response, status = { - "type": "Bad request error", - "message": "Invalid request data object", - }, HTTPStatus.BAD_REQUEST - - current_app.logger.warning(response) - current_app.logger.warning(err) - return response, status - - @cors_preflight("GET,OPTIONS") @API.route("", methods=["GET", "OPTIONS"]) class ProcessResource(Resource): @@ -173,7 +139,7 @@ def get(process_InstanceId): ), HTTPStatus.OK, ) - except BaseException as err: + except BaseException: response, status = { "type": "Bad request error", "message": "Invalid request data object", @@ -181,31 +147,3 @@ def get(process_InstanceId): current_app.logger.warning(response) return response, status - - -# @cors_preflight('GET,OPTIONS') -# @API.route('/', methods=['GET', 'OPTIONS']) -# class ProcessDetailsResource(Resource): -# """Resource for managing process details.""" - -# @staticmethod -# def get(process_key): -# """Get process details.""" -# try: -# return ProcessService.get_process(process_key), HTTPStatus.OK -# except BusinessException as err: -# return err.error, err.status_code - - -# @cors_preflight('GET,OPTIONS') -# @API.route('//action', methods=['GET', 'OPTIONS']) -# class ProcessActionsResource(Resource): -# """Resource for managing process ations.""" - -# @staticmethod -# def get(process_key): -# """Get process action details.""" -# try: -# return ProcessService.get_process_action(process_key), HTTPStatus.OK -# except BusinessException as err: -# return err.error, err.status_code diff --git a/forms-flow-api/src/formsflow_api/schemas/__init__.py b/forms-flow-api/src/formsflow_api/schemas/__init__.py new file mode 100644 index 0000000000..d86f93894f --- /dev/null +++ b/forms-flow-api/src/formsflow_api/schemas/__init__.py @@ -0,0 +1,21 @@ +"""This exports all of the schemas used by the application.""" + +from formsflow_api.schemas.aggregated_application import ( + ApplicationMetricsRequestSchema, + AggregatedApplicationSchema, +) +from formsflow_api.schemas.application import ( + ApplicationSchema, + ApplicationListReqSchema, + ApplicationListRequestSchema, + ApplicationUpdateSchema, +) +from formsflow_api.schemas.application_history import ApplicationHistorySchema +from formsflow_api.schemas.form_process_mapper import FormProcessMapperSchema +from .process import ( + ProcessActivityInstanceSchema, + ProcessListSchema, + ProcessDefinitionXMLSchema, + ProcessMessageSchema, +) +from formsflow_api.schemas.keycloak_groups import KeycloakDashboardGroupSchema diff --git a/forms-flow-api/src/api/schemas/aggregated_application.py b/forms-flow-api/src/formsflow_api/schemas/aggregated_application.py similarity index 81% rename from forms-flow-api/src/api/schemas/aggregated_application.py rename to forms-flow-api/src/formsflow_api/schemas/aggregated_application.py index 733b29e117..25de43dccf 100644 --- a/forms-flow-api/src/api/schemas/aggregated_application.py +++ b/forms-flow-api/src/formsflow_api/schemas/aggregated_application.py @@ -11,8 +11,12 @@ class Meta: # pylint: disable=too-few-public-methods unknown = EXCLUDE - from_date = fields.Date(format="%Y-%m-%d", data_key="from", required=True) - to_date = fields.Date(format="%Y-%m-%d", data_key="to", required=True) + from_date = fields.DateTime( + format="%Y-%m-%dT%H:%M:%S+00:00", data_key="from", required=True + ) + to_date = fields.DateTime( + format="%Y-%m-%dT%H:%M:%S+00:00", data_key="to", required=True + ) order_by = fields.Str(data_key="orderBy", required=False) diff --git a/forms-flow-api/src/api/schemas/application.py b/forms-flow-api/src/formsflow_api/schemas/application.py similarity index 63% rename from forms-flow-api/src/api/schemas/application.py rename to forms-flow-api/src/formsflow_api/schemas/application.py index 6f8049cff7..3503361cf5 100644 --- a/forms-flow-api/src/api/schemas/application.py +++ b/forms-flow-api/src/formsflow_api/schemas/application.py @@ -4,7 +4,7 @@ class ApplicationListReqSchema(Schema): - """This class manages application list request schema.""" + """This is a general class for paginated request schema.""" class Meta: # pylint: disable=too-few-public-methods """Exclude unknown fields in the deserialized output.""" @@ -15,6 +15,30 @@ class Meta: # pylint: disable=too-few-public-methods limit = fields.Int(required=False, allow_none=True) +class ApplicationListRequestSchema(ApplicationListReqSchema): + + """This class manages application list request schema.""" + + order_by = fields.Str(data_key="sortBy", required=False) + application_id = fields.Int(data_key="Id", required=False) + application_name = fields.Str(data_key="applicationName", required=False) + application_status = fields.Str(data_key="applicationStatus", required=False) + created_by = fields.Str(data_key="createdBy", required=False) + created_from_date = fields.DateTime( + data_key="createdFrom", format="%Y-%m-%dT%H:%M:%S+00:00" + ) + created_to_date = fields.DateTime( + data_key="createdTo", format="%Y-%m-%dT%H:%M:%S+00:00" + ) + modified_from_date = fields.DateTime( + data_key="modifiedFrom", format="%Y-%m-%dT%H:%M:%S+00:00" + ) + modified_to_date = fields.DateTime( + data_key="modifiedTo", format="%Y-%m-%dT%H:%M:%S+00:00" + ) + sort_order = fields.Str(data_key="sortOrder", required=False) + + class ApplicationSchema(Schema): """This class manages application request and response schema.""" @@ -23,7 +47,7 @@ class Meta: # pylint: disable=too-few-public-methods unknown = EXCLUDE - id = fields.Int() + id = fields.Int(data_key="id") application_name = fields.Str(data_key="applicationName") application_status = fields.Str(data_key="applicationStatus") form_process_mapper_id = fields.Str(data_key="formProcessMapperId") diff --git a/forms-flow-api/src/api/schemas/application_history.py b/forms-flow-api/src/formsflow_api/schemas/application_history.py similarity index 100% rename from forms-flow-api/src/api/schemas/application_history.py rename to forms-flow-api/src/formsflow_api/schemas/application_history.py diff --git a/forms-flow-api/src/api/schemas/form_process_mapper.py b/forms-flow-api/src/formsflow_api/schemas/form_process_mapper.py similarity index 100% rename from forms-flow-api/src/api/schemas/form_process_mapper.py rename to forms-flow-api/src/formsflow_api/schemas/form_process_mapper.py diff --git a/forms-flow-api/src/formsflow_api/schemas/keycloak_groups.py b/forms-flow-api/src/formsflow_api/schemas/keycloak_groups.py new file mode 100644 index 0000000000..c52edf93af --- /dev/null +++ b/forms-flow-api/src/formsflow_api/schemas/keycloak_groups.py @@ -0,0 +1,13 @@ +"""This is for marshmallowing Keycloak groups field""" +from marshmallow import EXCLUDE, Schema, fields + + +class KeycloakDashboardGroupSchema(Schema): + """This class manages Keycloak Group Schema""" + + class Meta: # pylint: disable=too-few-public-methods + unknown = EXCLUDE + + dashboards = fields.List( + fields.Dict(keys=fields.Str(), values=fields.Str(), required=True) + ) diff --git a/forms-flow-api/src/api/schemas/process.py b/forms-flow-api/src/formsflow_api/schemas/process.py similarity index 70% rename from forms-flow-api/src/api/schemas/process.py rename to forms-flow-api/src/formsflow_api/schemas/process.py index fe848abf83..6e7bf6877e 100644 --- a/forms-flow-api/src/api/schemas/process.py +++ b/forms-flow-api/src/formsflow_api/schemas/process.py @@ -15,41 +15,32 @@ class Meta: # pylint: disable=too-few-public-methods name = fields.Str() -class ProcessDefinitionSchema(Schema): +class ProcessDefinitionXMLSchema(Schema): """This class manages process definition response schema.""" - class Meta: # pylint: disable=too-few-public-methods - """Exclude unknown fields in the deserialized output.""" - - unknown = EXCLUDE - - key = fields.Str() - name = fields.Str() - variables = fields.Str() - - -class ProcessActionListSchema(Schema): - """This class manages process action list response schema.""" - class Meta: # pylint: disable=too-few-public-methods """Exclude unknown fields in the deserialized output.""" unknown = EXCLUDE id = fields.Str() - actiontype = fields.Str() + processXml = fields.Str(data_key="bpmn20Xml", attribute="bpmn20Xml") -class ProcessDefinitionXMLSchema(Schema): - """This class manages process definition response schema.""" +class ProcessActivityInstanceSchema(Schema): + """This class manages task response schema.""" class Meta: # pylint: disable=too-few-public-methods """Exclude unknown fields in the deserialized output.""" unknown = EXCLUDE - id = fields.Str() - processXml = fields.Str(data_key="bpmn20Xml", attribute="bpmn20Xml") + process_instance_id = fields.Str( + data_key="processInstanceId", attribute="processInstanceId" + ) + childActivityInstances = fields.Str( + data_key="childActivityInstances", attribute="childActivityInstances" + ) class ProcessMessageSchema(Schema): @@ -62,19 +53,3 @@ class Meta: # pylint: disable=too-few-public-methods messageName = fields.Str() processInstanceId = fields.Str() - - -class ProcessActivityInstanceSchema(Schema): - """This class manages task response schema.""" - - class Meta: # pylint: disable=too-few-public-methods - """Exclude unknown fields in the deserialized output.""" - - unknown = EXCLUDE - - process_instance_id = fields.Str( - data_key="processInstanceId", attribute="processInstanceId" - ) - childActivityInstances = fields.Str( - data_key="childActivityInstances", attribute="childActivityInstances" - ) diff --git a/forms-flow-api/src/formsflow_api/schemas/tenant.py b/forms-flow-api/src/formsflow_api/schemas/tenant.py new file mode 100644 index 0000000000..2a7272c4cd --- /dev/null +++ b/forms-flow-api/src/formsflow_api/schemas/tenant.py @@ -0,0 +1,17 @@ +# """This manages tenant Response Schema.""" + +# from marshmallow import EXCLUDE, Schema, fields + + +# class TenantSchema(Schema): +# """This class manages tenant response schema.""" + +# class Meta: # pylint: disable=too-few-public-methods +# """Exclude unknown fields in the deserialized output.""" + +# unknown = EXCLUDE + +# id = fields.Int() +# tenant_name = fields.Str(data_key="tenantName") +# relam = fields.Str() +# audience = fields.Str() diff --git a/forms-flow-api/src/formsflow_api/services/__init__.py b/forms-flow-api/src/formsflow_api/services/__init__.py new file mode 100644 index 0000000000..f4a675fcaf --- /dev/null +++ b/forms-flow-api/src/formsflow_api/services/__init__.py @@ -0,0 +1,18 @@ +"""This exports all of the services used by the application.""" + +from formsflow_api.services.application import ApplicationService +from formsflow_api.services.application_history import ApplicationHistoryService +from formsflow_api.services.form_process_mapper import FormProcessMapperService +from formsflow_api.services.process import ProcessService +from formsflow_api.services.external.analytics_api import RedashAPIService +from formsflow_api.services.external.keycloak import KeycloakAdminAPIService + + +__all__ = [ + "ApplicationService", + "ApplicationHistoryService", + "FormProcessMapperService", + "KeycloakAdminAPIService", + "ProcessService", + "RedashAPIService", +] diff --git a/forms-flow-api/src/api/services/application.py b/forms-flow-api/src/formsflow_api/services/application.py similarity index 68% rename from forms-flow-api/src/api/services/application.py rename to forms-flow-api/src/formsflow_api/services/application.py index 95ad767268..eaa3be182a 100644 --- a/forms-flow-api/src/api/services/application.py +++ b/forms-flow-api/src/formsflow_api/services/application.py @@ -1,18 +1,22 @@ """This exposes application service.""" -from http import HTTPStatus +from datetime import datetime from functools import lru_cache +from http import HTTPStatus + +from flask import current_app + +from formsflow_api.exceptions import BusinessException +from formsflow_api.models import Application, FormProcessMapper -from ..exceptions import BusinessException -from ..models import Application, FormProcessMapper -from ..schemas import ( +from formsflow_api.schemas import ( AggregatedApplicationSchema, ApplicationSchema, FormProcessMapperSchema, ) -from .external import BPMService -from api.utils import NEW_APPLICATION_STATUS -from flask import current_app + +from formsflow_api.services.external import BPMService +from formsflow_api.utils import NEW_APPLICATION_STATUS class ApplicationService: @@ -70,12 +74,39 @@ def get_authorised_form_list(token): return response @staticmethod - def get_auth_applications_and_count(page_no: int, limit: int, token: str): + def get_auth_applications_and_count( + token: str, + page_no: int, + limit: int, + order_by: str, + created_from: datetime, + created_to: datetime, + modified_from: datetime, + modified_to: datetime, + application_id: int, + application_name: str, + application_status: str, + created_by: str, + sort_order: str, + ): """Get applications only from authorized groups.""" if page_no: page_no = int(page_no) if limit: limit = int(limit) + if order_by: + order_by = str(order_by) + if application_id: + application_id = int(application_id) + if application_name: + application_name = str(application_name) + if application_status: + application_status = str(application_status) + if created_by: + created_by = str(created_by) + + if sort_order: + sort_order = str(sort_order) auth_form_details = ApplicationService.get_authorised_form_list(token=token) form_names = [] @@ -83,12 +114,25 @@ def get_auth_applications_and_count(page_no: int, limit: int, token: str): if auth_form_details: for auth_form_detail in auth_form_details: form_names.append(auth_form_detail["formName"]) - applications = Application.find_by_form_names( - form_names=form_names, page_no=page_no, limit=limit + applications, get_all_applications_count = Application.find_by_form_names( + form_names=form_names, + application_id=application_id, + application_name=application_name, + application_status=application_status, + created_by=created_by, + page_no=page_no, + limit=limit, + order_by=order_by, + modified_from=modified_from, + modified_to=modified_to, + sort_order=sort_order, + created_from=created_from, + created_to=created_to, ) + return ( application_schema.dump(applications, many=True), - applications.count(), + get_all_applications_count, ) else: return (application_schema.dump([], many=True), 0) @@ -123,14 +167,68 @@ def get_all_applications(page_no: int, limit: int): return application_schema.dump(applications, many=True) @staticmethod - def get_all_applications_by_user(user_id: str, page_no: int, limit: int): + def get_all_applications_by_user( + user_id: str, + page_no: int, + limit: int, + order_by: str, + sort_order: str, + created_from: datetime, + created_to: datetime, + modified_from: datetime, + modified_to: datetime, + created_by: str, + application_status: str, + application_name: str, + application_id: int, + ): """Get all applications based on user.""" if page_no: page_no = int(page_no) if limit: limit = int(limit) + if order_by: + order_by = str(order_by) + if sort_order: + sort_order = str(sort_order) + if application_id: + application_id = int(application_id) + if application_name: + application_name = str(application_name) + if application_status: + application_status = str(application_status) + if created_by: + created_by = str(created_by) + + applications, get_all_applications_count = Application.find_all_by_user( + user_id=user_id, + page_no=page_no, + limit=limit, + order_by=order_by, + sort_order=sort_order, + application_id=application_id, + application_name=application_name, + application_status=application_status, + created_by=created_by, + modified_from=modified_from, + modified_to=modified_to, + created_from=created_from, + created_to=created_to, + ) + application_schema = ApplicationSchema() - applications = Application.find_all_by_user( + return ( + application_schema.dump(applications, many=True), + get_all_applications_count, + ) + + @staticmethod + def get_all_application_by_user_group(page_no: int, limit: int, user_id: str): + if page_no: + page_no = int(page_no) + if limit: + limit = int(limit) + applications = Application.find_all_by_user_group( user_id=user_id, page_no=page_no, limit=limit ) application_schema = ApplicationSchema() @@ -143,14 +241,44 @@ def get_all_applications_ids(application_ids): return application_schema.dump(applications, many=True) @staticmethod - def get_all_application_count(): + def get_all_application_count( + token: str, + page_no: int, + limit: int, + ): """Get application count.""" - return Application.query.count() + if page_no: + page_no = int(page_no) + if limit: + limit = int(limit) + auth_form_details = ApplicationService.get_authorised_form_list(token=token) + form_names = [] + application_schema = ApplicationSchema() + if auth_form_details: + for auth_form_detail in auth_form_details: + form_names.append(auth_form_detail["formName"]) + applications = Application.find_all_applications( + form_names=form_names, page_no=page_no, limit=limit + ) + return ( + application_schema.dump(applications, many=True), + applications.count(), + ) + else: + return (application_schema.dump([], many=True), 0) @staticmethod def get_all_application_by_user_count(user_id: str): """Get application count.""" - return Application.find_all_by_user_count(user_id) + return Application.find_all_by_user_count(user_id=user_id) + + @staticmethod + def get_all_application_status(): + """Get all application status""" + status_list = Application.find_all_application_status() + status_list = [x.application_status for x in status_list] + current_app.logger.debug(status_list) + return {"applicationStatus": status_list} @staticmethod def get_all_applications_form_id(form_id, page_no: int, limit: int): @@ -231,7 +359,7 @@ def get_aggregated_applications(from_date: str, to_date: str): return schema.dump(applications, many=True) @staticmethod - def get_current_aggregated_applications(from_date: str, to_date: str): + def get_current_aggregated_applications(from_date: datetime, to_date: datetime): """Get aggregated applications.""" applications = Application.find_aggregated_applications_modified( from_date=from_date, to_date=to_date @@ -240,7 +368,9 @@ def get_current_aggregated_applications(from_date: str, to_date: str): return schema.dump(applications, many=True) @staticmethod - def get_aggregated_application_status(mapper_id: int, from_date: str, to_date: str): + def get_aggregated_application_status( + mapper_id: int, from_date: datetime, to_date: datetime + ): """Get aggregated application status.""" application_status = Application.find_aggregated_application_status( mapper_id=mapper_id, from_date=from_date, to_date=to_date diff --git a/forms-flow-api/src/api/services/application_history.py b/forms-flow-api/src/formsflow_api/services/application_history.py similarity index 84% rename from forms-flow-api/src/api/services/application_history.py rename to forms-flow-api/src/formsflow_api/services/application_history.py index ee3ed87cff..61f1dea24a 100644 --- a/forms-flow-api/src/api/services/application_history.py +++ b/forms-flow-api/src/formsflow_api/services/application_history.py @@ -1,6 +1,6 @@ """This exposes application audit service.""" -from ..models import ApplicationHistory -from ..schemas import ApplicationHistorySchema +from formsflow_api.models import ApplicationHistory +from formsflow_api.schemas import ApplicationHistorySchema class ApplicationHistoryService: diff --git a/forms-flow-api/src/api/services/external/__init__.py b/forms-flow-api/src/formsflow_api/services/external/__init__.py similarity index 100% rename from forms-flow-api/src/api/services/external/__init__.py rename to forms-flow-api/src/formsflow_api/services/external/__init__.py diff --git a/forms-flow-api/src/formsflow_api/services/external/analytics_api.py b/forms-flow-api/src/formsflow_api/services/external/analytics_api.py new file mode 100644 index 0000000000..ba2f3e9e50 --- /dev/null +++ b/forms-flow-api/src/formsflow_api/services/external/analytics_api.py @@ -0,0 +1,25 @@ +"""This exposes the analytics API""" +from http import HTTPStatus +import requests +from flask import current_app + + +class RedashAPIService: + """This class manages all the Redash analytics service API calls""" + + def get_request(self, url_path, page_no=None, limit=None): + """This method makes the GET request to Redash API""" + if page_no is None: + url = f"{current_app.config.get('ANALYTICS_API_URL')}/api/{url_path}" + else: + url = f"{current_app.config.get('ANALYTICS_API_URL')}/api/{url_path}?page={page_no}&page_size={limit}" + analytics_admin_token = current_app.config.get("ANALYTICS_API_KEY") + headers = {"Authorization": analytics_admin_token} + response = requests.get(url, headers=headers) + + if response.ok: + return response.json() + elif response.status_code == HTTPStatus.NOT_FOUND: + return "unauthorized" + else: + return None diff --git a/forms-flow-api/src/api/services/external/base_bpm.py b/forms-flow-api/src/formsflow_api/services/external/base_bpm.py similarity index 97% rename from forms-flow-api/src/api/services/external/base_bpm.py rename to forms-flow-api/src/formsflow_api/services/external/base_bpm.py index 99c522697d..afdf97c17b 100644 --- a/forms-flow-api/src/api/services/external/base_bpm.py +++ b/forms-flow-api/src/formsflow_api/services/external/base_bpm.py @@ -5,7 +5,7 @@ import requests from flask import current_app -from api.utils.logging import log_bpm_error +from formsflow_api.utils.logging import log_bpm_error class BaseBPMService: diff --git a/forms-flow-api/src/api/services/external/bpm.py b/forms-flow-api/src/formsflow_api/services/external/bpm.py similarity index 100% rename from forms-flow-api/src/api/services/external/bpm.py rename to forms-flow-api/src/formsflow_api/services/external/bpm.py diff --git a/forms-flow-api/src/formsflow_api/services/external/keycloak.py b/forms-flow-api/src/formsflow_api/services/external/keycloak.py new file mode 100644 index 0000000000..e2aad9872c --- /dev/null +++ b/forms-flow-api/src/formsflow_api/services/external/keycloak.py @@ -0,0 +1,81 @@ +"""This exposes the Keycloak Admin APIs""" +import json +import requests +from flask import current_app +from formsflow_api.utils import profiletime + + +class KeycloakAdminAPIService(object): + """This class manages all the Keycloak service API calls""" + + def __init__(self): + self.session = requests.Session() + username = current_app.config.get("KEYCLOAK_ADMIN_USERNAME") + password = current_app.config.get("KEYCLOAK_ADMIN_PASSWORD") + + headers = {"Content-Type": "application/x-www-form-urlencoded"} + payload = { + "client_id": "admin-cli", + "username": username, + "password": password, + "grant_type": "password", + } + + token_api = f"{current_app.config.get('KEYCLOAK_URL')}/auth/realms/master/protocol/openid-connect/token" + response = requests.post(token_api, headers=headers, data=payload) + data = json.loads(response.text) + self.session.headers.update( + { + "Authorization": "Bearer " + data["access_token"], + "Content-Type": "application/json", + } + ) + self.base_url = f"{current_app.config.get('KEYCLOAK_URL')}/auth/admin/realms/{current_app.config.get('KEYCLOAK_URL_REALM')}" + + @profiletime + def get_request(self, url_path): + """Method to fetch get request of Keycloak Admin APIs + :param url_path: The relative path of the API + """ + url = f"{self.base_url}/{url_path}" + response = self.session.request("GET", url) + response.raise_for_status() + + if response.ok: + return response.json() + else: + return None + + def get_paginated_request(self, url_path, first, max): + """Method to fetch GET paginated request of Keycloak Admin APIs + :param url_path: The relative path of the API + :param first: The page_number + :param max: The max number of items per page + """ + url = f"{self.base_url}/{url_path}?first={first}&max={max}" + response = self.session.request("GET", url) + response.raise_for_status() + + if response.ok: + return response.json() + else: + return None + + @profiletime + def update_request(self, url_path, data=None): + """Method to fetch get request of Keycloak Admin APIs + :param url_path: The relative path of the API + :param data: The request data object + """ + url = f"{self.base_url}/{url_path}" + try: + response = self.session.request( + "PUT", + url, + data=json.dumps(data), + ) + except Exception as e: + raise f"Request to Keycloak Admin APIs failed., {e}" + else: + if response.status_code == 204: + return f"Updated - {url_path}" diff --git a/forms-flow-api/src/api/services/form_process_mapper.py b/forms-flow-api/src/formsflow_api/services/form_process_mapper.py similarity index 95% rename from forms-flow-api/src/api/services/form_process_mapper.py rename to forms-flow-api/src/formsflow_api/services/form_process_mapper.py index 210c4a7f15..0a47f1fb13 100644 --- a/forms-flow-api/src/api/services/form_process_mapper.py +++ b/forms-flow-api/src/formsflow_api/services/form_process_mapper.py @@ -2,9 +2,9 @@ from http import HTTPStatus -from ..exceptions import BusinessException -from ..models import FormProcessMapper -from ..schemas import FormProcessMapperSchema +from formsflow_api.exceptions import BusinessException +from formsflow_api.models import FormProcessMapper +from formsflow_api.schemas import FormProcessMapperSchema class FormProcessMapperService: diff --git a/forms-flow-api/src/api/services/formio_token.py b/forms-flow-api/src/formsflow_api/services/formio_token.py similarity index 100% rename from forms-flow-api/src/api/services/formio_token.py rename to forms-flow-api/src/formsflow_api/services/formio_token.py diff --git a/forms-flow-api/src/formsflow_api/services/process.py b/forms-flow-api/src/formsflow_api/services/process.py new file mode 100644 index 0000000000..39b0190d29 --- /dev/null +++ b/forms-flow-api/src/formsflow_api/services/process.py @@ -0,0 +1,65 @@ +"""This exposes process service.""" + +from flask import current_app +from http import HTTPStatus + +from formsflow_api.exceptions import BusinessException +from formsflow_api.schemas import ( + ProcessActivityInstanceSchema, + ProcessDefinitionXMLSchema, + ProcessListSchema, +) +from formsflow_api.services.external import BPMService + + +class ProcessService: + """This class manages process service.""" + + @staticmethod + def get_all_processes(token): + """Get all processes.""" + process = BPMService.get_all_process(token=token) + if process: + result = ProcessListSchema().dump(process, many=True) + seen = set() + new_result = [] + for data in result: + if data["key"] not in seen: + seen.add(data["key"]) + new_result.append(data) + return new_result + + return process + + @staticmethod + def get_process_definition_xml(process_key, token): + """Get process details.""" + process_definition_xml = BPMService.get_process_definition_xml( + process_key=process_key, token=token + ) + if process_definition_xml: + return ProcessDefinitionXMLSchema().dump(process_definition_xml) + + raise BusinessException("Invalid process", HTTPStatus.BAD_REQUEST) + + @staticmethod + def get_process_activity_instances(process_instace_id, token): + """Get process actions.""" + current_app.logger.debug("get_process_activity_instances " + process_instace_id) + activity_instances = BPMService.get_process_activity_instances( + process_instace_id=process_instace_id, token=token + ) + current_app.logger.debug(activity_instances) + try: + if activity_instances: + return ProcessActivityInstanceSchema().dump(activity_instances) + except TypeError as err: + current_app.logger.critical(err) + raise BusinessException( + "No activity instances available for process", HTTPStatus.BAD_REQUEST + ) + + @staticmethod + def post_message(data, token): + """Get process details.""" + return BPMService.send_message(data=data, token=token) diff --git a/forms-flow-api/src/api/services/tenant.py b/forms-flow-api/src/formsflow_api/services/tenant.py similarity index 100% rename from forms-flow-api/src/api/services/tenant.py rename to forms-flow-api/src/formsflow_api/services/tenant.py diff --git a/forms-flow-api/src/formsflow_api/utils/__init__.py b/forms-flow-api/src/formsflow_api/utils/__init__.py new file mode 100644 index 0000000000..8ab0784427 --- /dev/null +++ b/forms-flow-api/src/formsflow_api/utils/__init__.py @@ -0,0 +1,19 @@ +"""This module holds general utility functions and helpers for the main package.""" + +from .auth import auth +from .auth import jwt +from .constants import ( + ALLOW_ALL_APPLICATIONS, + ALLOW_ALL_ORIGINS, + CORS_ORIGINS, + DESIGNER_GROUP, + FORMSFLOW_API_CORS_ORIGINS, + KEYCLOAK_DASHBOARD_BASE_GROUP, + NEW_APPLICATION_STATUS, + REVIEWER_GROUP, +) +from .enums import ApplicationSortingParameters +from .format import CustomFormatter +from .logging import setup_logging +from .util import cors_preflight, validate_sort_order_and_order_by +from .profiler import profiletime diff --git a/forms-flow-api/src/api/utils/auth.py b/forms-flow-api/src/formsflow_api/utils/auth.py similarity index 92% rename from forms-flow-api/src/api/utils/auth.py rename to forms-flow-api/src/formsflow_api/utils/auth.py index 19d7d605e2..dba2af9fc1 100644 --- a/forms-flow-api/src/api/utils/auth.py +++ b/forms-flow-api/src/formsflow_api/utils/auth.py @@ -9,9 +9,7 @@ from ..exceptions import BusinessException -jwt = ( - JwtManager() -) # pylint: disable=invalid-name; lower case name as used by convention in most Flask apps +jwt = JwtManager() # pylint: disable=invalid-name class Auth: diff --git a/forms-flow-api/src/api/utils/constants.py b/forms-flow-api/src/formsflow_api/utils/constants.py similarity index 59% rename from forms-flow-api/src/api/utils/constants.py rename to forms-flow-api/src/formsflow_api/utils/constants.py index 88405a0d85..c6de82c55f 100644 --- a/forms-flow-api/src/api/utils/constants.py +++ b/forms-flow-api/src/formsflow_api/utils/constants.py @@ -1,13 +1,17 @@ import os +from dotenv import find_dotenv, load_dotenv + +# this will load all the envars from a .env file located in the project root (api) +load_dotenv(find_dotenv()) FORMSFLOW_API_CORS_ORIGINS = os.getenv("FORMSFLOW_API_CORS_ORIGINS") ALLOW_ALL_ORIGINS = "*" CORS_ORIGINS = [] if FORMSFLOW_API_CORS_ORIGINS != "*": CORS_ORIGINS = FORMSFLOW_API_CORS_ORIGINS.split(",") +DESIGNER_GROUP = "formsflow-designer" REVIEWER_GROUP = "formsflow-reviewer" ALLOW_ALL_APPLICATIONS = "/formsflow/formsflow-reviewer/access-allow-applications" -METRICS_MODIFIED = "modified" -METRIC_CREATED = "created" NEW_APPLICATION_STATUS = "New" +KEYCLOAK_DASHBOARD_BASE_GROUP = "formsflow-analytics" diff --git a/forms-flow-api/src/formsflow_api/utils/enums.py b/forms-flow-api/src/formsflow_api/utils/enums.py new file mode 100644 index 0000000000..eb25473d15 --- /dev/null +++ b/forms-flow-api/src/formsflow_api/utils/enums.py @@ -0,0 +1,26 @@ +"""Enum User Definition""" +from enum import Enum + + +class FormProcessMapperStatus(Enum): + """This enum provides the list of FormProcessMapper Status.""" + + Active = "active" + Inactive = "inactive" + + +class MetricsState(Enum): + """This enum provides the list of states of Metrics""" + + CREATED = "created" + MODIFIED = "modified" + + +class ApplicationSortingParameters: + """This enum provides the list of Sorting Parameters.""" + + Id = "id" + Created = "created" + Name = "applicationName" + Status = "applicationStatus" + Modified = "modified" diff --git a/forms-flow-api/src/api/utils/format.py b/forms-flow-api/src/formsflow_api/utils/format.py similarity index 100% rename from forms-flow-api/src/api/utils/format.py rename to forms-flow-api/src/formsflow_api/utils/format.py diff --git a/forms-flow-api/src/api/utils/logging.py b/forms-flow-api/src/formsflow_api/utils/logging.py similarity index 100% rename from forms-flow-api/src/api/utils/logging.py rename to forms-flow-api/src/formsflow_api/utils/logging.py diff --git a/forms-flow-api/src/api/utils/profiler.py b/forms-flow-api/src/formsflow_api/utils/profiler.py similarity index 100% rename from forms-flow-api/src/api/utils/profiler.py rename to forms-flow-api/src/formsflow_api/utils/profiler.py diff --git a/forms-flow-api/src/formsflow_api/utils/roles.py b/forms-flow-api/src/formsflow_api/utils/roles.py new file mode 100644 index 0000000000..9050703b9e --- /dev/null +++ b/forms-flow-api/src/formsflow_api/utils/roles.py @@ -0,0 +1,9 @@ +# """Role definitions.""" + + +# class Role: # pylint: disable=too-few-public-methods +# """User Role.""" + +# rpas_designer = "rpas-designer" +# rpas_reviewer = "rpas-reviewer" +# rpas_client = "rpas-client" diff --git a/forms-flow-api/src/api/utils/util.py b/forms-flow-api/src/formsflow_api/utils/util.py similarity index 51% rename from forms-flow-api/src/api/utils/util.py rename to forms-flow-api/src/formsflow_api/utils/util.py index 61c0a34abe..be1cbc98a4 100644 --- a/forms-flow-api/src/api/utils/util.py +++ b/forms-flow-api/src/formsflow_api/utils/util.py @@ -2,7 +2,9 @@ * CORS pre-flight decorator. A simple decorator to add the options method to a Request Class. """ +import re from .constants import ALLOW_ALL_ORIGINS +from .enums import ApplicationSortingParameters def cors_preflight(methods: str = "GET"): @@ -24,3 +26,25 @@ def options(self, *args, **kwargs): # pylint: disable=unused-argument return f return wrapper + + +def camel_to_snake(name: str) -> str: + """Convert camel case to snake case.""" + s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) + return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() + + +def validate_sort_order_and_order_by(order_by: str, sort_order: str) -> bool: + """Validate sort order and order by.""" + if order_by not in [ + ApplicationSortingParameters.Id, + ApplicationSortingParameters.Name, + ApplicationSortingParameters.Status, + ApplicationSortingParameters.Modified, + ]: + order_by = None + else: + order_by = camel_to_snake(order_by) + if sort_order not in ["asc", "desc"]: + sort_order = None + return order_by, sort_order diff --git a/forms-flow-api/tests/conftest.py b/forms-flow-api/tests/conftest.py index e8cbcb881b..bf28a0275e 100644 --- a/forms-flow-api/tests/conftest.py +++ b/forms-flow-api/tests/conftest.py @@ -1,67 +1,53 @@ """Common setup and fixtures for the pytest suite used by this service.""" +from pathlib import Path import pytest from flask_migrate import Migrate, upgrade from sqlalchemy import event, text from sqlalchemy.schema import DropConstraint, MetaData -from api import create_app -from api import jwt as _jwt -from api.models import db as _db +from formsflow_api import create_app, setup_jwt_manager +from formsflow_api.models import db as _db +from formsflow_api.utils import jwt as _jwt -@pytest.fixture(scope='session') +@pytest.fixture(scope="session", autouse=True) def app(): """Return a session-wide application configured in TEST mode.""" - _app = create_app('testing') + _app = create_app("testing") return _app -@pytest.fixture(scope='function') -def app_ctx(event_loop): # pylint: disable=unused-argument - # def app_ctx(): - """Return a session-wide application configured in TEST mode.""" - _app = create_app('testing') - with _app.app_context(): - yield _app - - -@pytest.fixture -def config(app): # pylint: disable=redefined-outer-name - """Return the application config.""" - return app.config - - -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def app_request(): """Return a session-wide application configured in TEST mode.""" - _app = create_app('testing') + _app = create_app("testing") return _app -@pytest.fixture(scope='session') +@pytest.fixture def client(app): # pylint: disable=redefined-outer-name """Return a session-wide Flask test client.""" return app.test_client() -@pytest.fixture(scope='session') -def jwt(): - """Return a session-wide jwt manager.""" +@pytest.fixture(scope="session") +def jwt(app): + """Return session-wide jwt manager.""" return _jwt -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def client_ctx(app): # pylint: disable=redefined-outer-name """Return session-wide Flask test client.""" with app.test_client() as _client: yield _client -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def db(app): # pylint: disable=redefined-outer-name, invalid-name """Return a session-wide initialised database. @@ -84,10 +70,10 @@ def db(app): # pylint: disable=redefined-outer-name, invalid-name sess = _db.session() for seq in [name for (name,) in sess.execute(text(sequence_sql))]: try: - sess.execute(text('DROP SEQUENCE public.%s ;' % seq)) - print('DROP SEQUENCE public.%s ' % seq) + sess.execute(text("DROP SEQUENCE public.%s ;" % seq)) + print("DROP SEQUENCE public.%s " % seq) except Exception as err: # pylint: disable=broad-except - print(f'Error: {err}') + print(f"Error: {err}") sess.commit() # ############################################ @@ -106,7 +92,7 @@ def db(app): # pylint: disable=redefined-outer-name, invalid-name return _db -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def session(app, db): # pylint: disable=redefined-outer-name, invalid-name """Return a function-scoped session.""" with app.app_context(): @@ -120,17 +106,19 @@ def session(app, db): # pylint: disable=redefined-outer-name, invalid-name # (http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html#using-savepoint) sess.begin_nested() - @event.listens_for(sess(), 'after_transaction_end') + @event.listens_for(sess(), "after_transaction_end") def restart_savepoint(sess2, trans): # pylint: disable=unused-variable # Detecting whether this is indeed the nested transaction of the test - if trans.nested and not trans._parent.nested: # pylint: disable=protected-access + if ( + trans.nested and not trans._parent.nested + ): # pylint: disable=protected-access # Handle where test DOESN'T session.commit(), sess2.expire_all() sess.begin_nested() db.session = sess - sql = text('select 1') + sql = text("select 1") sess.execute(sql) yield sess diff --git a/forms-flow-api/tests/docker/docker-compose.yml b/forms-flow-api/tests/docker/docker-compose.yml new file mode 100644 index 0000000000..1555c1baeb --- /dev/null +++ b/forms-flow-api/tests/docker/docker-compose.yml @@ -0,0 +1,69 @@ +version: "3.7" + +volumes: + postgres: + +networks: + keycloak-server-network: + driver: 'bridge' + +services: + keycloak-db: + image: postgres:latest + restart: always + container_name: keycloak_db + volumes: + - ./postgres/keycloak:/data/postgres + environment: + POSTGRES_DB: ${KEYCLOAK_JDBC_DB:-keycloak} + POSTGRES_USER: ${KEYCLOAK_JDBC_USER:-admin} + POSTGRES_PASSWORD: ${KEYCLOAK_JDBC_PASSWORD:-changeme} + ports: + - 5431:5431 + networks: + - keycloak-server-network + + keycloak: + image: jboss/keycloak:14.0.0 + restart: unless-stopped + container_name: keycloak + volumes: + - ./imports:/opt/jboss/keycloak/imports + command: + - "-b 0.0.0.0 -Dkeycloak.import=/opt/jboss/keycloak/imports/formsflow-ai-realm.json -Dkeycloak.migration.strategy=OVERWRITE_EXISTING" + environment: + - DB_VENDOR=POSTGRES + - DB_ADDR=keycloak-db + - DB_DATABASE=${KEYCLOAK_JDBC_DB:-keycloak} + - DB_USER=${KEYCLOAK_JDBC_USER-admin} + - DB_PASSWORD=${KEYCLOAK_JDBC_PASSWORD:-changeme} + - KEYCLOAK_USER=${KEYCLOAK_ADMIN_USER:-admin} + - KEYCLOAK_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD:-changeme} + ports: + - 8080:8080 + depends_on: + - keycloak-db + networks: + - keycloak-server-network + + healthcheck: + test: [ + "CMD", + "curl", + "--fail", + "http://localhost:8080/auth/realms/forms-flow-ai || exit 1", + ] + interval: 30s + timeout: 10s + retries: 3 + postgres: + image: postgres:13 + restart: always + environment: + POSTGRES_DB: ${KEYCLOAK_JDBC_DB:-webapi} + POSTGRES_USER: ${KEYCLOAK_JDBC_USER:-postgres} + POSTGRES_PASSWORD: ${KEYCLOAK_JDBC_PASSWORD:-changeme} + ports: + - 6432:6432 + + diff --git a/forms-flow-api/tests/docker/imports/formsflow-ai-realm.json b/forms-flow-api/tests/docker/imports/formsflow-ai-realm.json new file mode 100644 index 0000000000..5cbe78e2cf --- /dev/null +++ b/forms-flow-api/tests/docker/imports/formsflow-ai-realm.json @@ -0,0 +1,2476 @@ +{ + "id": "forms-flow-ai", + "realm": "forms-flow-ai", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "forms-flow-ai", + "attributes": {} + }, + { + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "forms-flow-ai", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + + "attributes": {} + }, + { + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-groups", + "query-clients", + "view-events", + "impersonation", + "manage-events", + "query-realms", + "query-users", + "create-client", + "view-clients", + "manage-authorization", + "view-identity-providers", + "view-users", + "view-realm", + "view-authorization", + "manage-identity-providers", + "manage-users", + "manage-realm", + "manage-clients" + ] + } + }, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "attributes": {} + }, + { + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + + "attributes": {} + } + ], + "forms-flow-web": [ + { + "name": "formsflow-client", + "description": "Provides access to use the formsflow.ai solution. Required to access and submit forms.", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "formsflow-designer", + "description": "Provides access to use the formsflow.ai solution. Access to wok on form designer studio.", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "formsflow-reviewer", + "description": "Provides access to use the formsflow.ai solution. Identifies the staff to work on applications and forms submissions.", + "composite": false, + "clientRole": true, + + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "forms-flow-bpm": [], + "account-console": [], + "broker": [ + { + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + + "attributes": {} + } + ], + "forms-flow-analytics": [], + "account": [ + { + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + + "attributes": {} + }, + { + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + + "attributes": {} + }, + { + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + + "attributes": {} + } + ] + } + }, + "groups": [ + { + "name": "camunda-admin", + "path": "/camunda-admin", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + }, + { + "name": "formsflow", + "path": "/formsflow", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "name": "formsflow-client", + "path": "/formsflow/formsflow-client", + "attributes": {}, + "realmRoles": [], + "clientRoles": { + "forms-flow-web": [ + "formsflow-client" + ] + }, + "subGroups": [] + }, + { + "name": "formsflow-designer", + "path": "/formsflow/formsflow-designer", + "attributes": {}, + "realmRoles": [], + "clientRoles": { + "forms-flow-web": [ + "formsflow-designer" + ] + }, + "subGroups": [] + }, + { + "name": "formsflow-reviewer", + "path": "/formsflow/formsflow-reviewer", + "attributes": {}, + "realmRoles": [], + "clientRoles": { + "forms-flow-web": [ + "formsflow-reviewer" + ] + }, + "subGroups": [ + { + "name": "clerk", + "path": "/formsflow/formsflow-reviewer/clerk", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + }, + { + "name": "approver", + "path": "/formsflow/formsflow-reviewer/approver", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + } + ] + } + ] + } + ], + "defaultRoles": [ + "offline_access", + "uma_authorization" + ], + "defaultGroups": [ + "/camunda-admin", + "/formsflow" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "users" : [ { + "createdTimestamp" : 1621862607660, + "username" : "formsflow-client", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "Client", + "lastName" : "FFA", + "email" : "formsflow-client@example.com", + "credentials" : [ { + "type" : "password", + "createdDate" : 1621863987325, + "secretData" : "{\"value\":\"9R9a8Onha7JcZt59SIq8ngfqwDJwPKiKb8mJ2WO6p2eI3S9qhzR1GPDFtKjOWq8qpm8vsGfp/a/DyHWQuIvmlA==\",\"salt\":\"R/OTBeSXHzsKtJOV/bufEA==\"}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ "UPDATE_PASSWORD" ], + "realmRoles" : [ "uma_authorization", "offline_access" ], + "clientRoles" : { + "account" : [ "view-profile", "manage-account" ] + }, + "notBefore" : 0, + "groups" : [ "/camunda-admin", "/formsflow/formsflow-client" ] + }, { + "createdTimestamp" : 1621862546931, + "username" : "formsflow-designer", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "Designer", + "lastName" : "FFA", + "email" : "formsflow-designer@example.com", + "credentials" : [ { + "type" : "password", + "createdDate" : 1621864001408, + "secretData" : "{\"value\":\"XlcFXNSJAfv5YzTh5vd4NtyEjWm4B47CS9MA3aHmEjLNjdRMbnGFVFZwlZx3alXYBCg4Evs3md25DQ6Xvl+nZg==\",\"salt\":\"TefHE1L0xpqlAMg/h6w6BA==\"}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ "UPDATE_PASSWORD" ], + "realmRoles" : [ "uma_authorization", "offline_access" ], + "clientRoles" : { + "account" : [ "view-profile", "manage-account" ] + }, + "notBefore" : 0, + "groups" : [ "/camunda-admin", "/formsflow/formsflow-designer" ] + }, { + "createdTimestamp" : 1625009614956, + "username" : "formsflow-approver", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "Approver", + "lastName" : "FFA", + "email" : "formsflow-approver@aot-technologies.com", + "credentials" : [ { + "type" : "password", + "createdDate" : 1625009625540, + "secretData" : "{\"value\":\"Ej6BGTe5D+jLChY9zmoty3Jzt8i+KoV+UTPK6+1Vi+GaUpVfdJ0RFJ/7M4+1Y1jNGBcvMgc8knQT2AJDtixxRQ==\",\"salt\":\"MDP6nouKEx0l7hdJA+lIJw==\"}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ "UPDATE_PASSWORD" ], + "notBefore" : 0, + "groups" : [ "/formsflow/formsflow-reviewer/approver", "/camunda-admin", "/formsflow" ] + }, { + "createdTimestamp" : 1625009564217, + "username" : "formsflow-clerk", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "Clerk", + "lastName" : "FFA", + "email" : "formsflow-clerk@aot-technologies.com", + "credentials" : [ { + "type" : "password", + "createdDate" : 1625009575561, + "secretData" : "{\"value\":\"iWFPywh7ck8FesufjXu81lxpJ0XKSvPd9ladBcJrE4TTXLeQOhvqBOC5e+bwVg20Y61EwtkTta0L9MWtGpSraw==\",\"salt\":\"noE1kDJ7Lo20VYuTOHOBTw==\"}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ "UPDATE_PASSWORD" ], + "notBefore" : 0, + "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer/clerk", "/formsflow" ] + }, { + "createdTimestamp" : 1621862578318, + "username" : "formsflow-reviewer", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "Reviewer", + "lastName" : "FFA", + "email" : "formsflow-reviewer@example.com", + "credentials" : [ { + "type" : "password", + "createdDate" : 1621864014317, + "secretData" : "{\"value\":\"bXzhJ0BrMJBWMzRRjO2khWgCRgDAA6vfTrE0UNNO1DNRzp1aMrGCz5kF20H76PjyuqNDZaKF1nKApEjccg+KRA==\",\"salt\":\"gmoZwO3i7Y6B+jpgnsnixw==\"}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ "UPDATE_PASSWORD" ], + "realmRoles" : [ "uma_authorization", "offline_access" ], + "clientRoles" : { + "account" : [ "view-profile", "manage-account" ] + }, + "notBefore" : 0, + "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer" ] + }, { + "createdTimestamp" : 1621585233480, + "username" : "service-account-forms-flow-bpm", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "serviceAccountClientId" : "forms-flow-bpm", + "credentials" : [ ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "uma_authorization", "offline_access" ], + "clientRoles" : { + "realm-management" : [ "query-users", "query-groups", "view-users" ], + "account" : [ "view-profile", "manage-account" ] + }, + "notBefore" : 0, + "groups" : [ "/camunda-admin" ] + } ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account" ] + } ] + }, + "clients": [ + { + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/forms-flow-ai/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": [ + "view-profile", + "manage-account" + ], + "redirectUris": [ + "/realms/forms-flow-ai/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/forms-flow-ai/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/realms/forms-flow-ai/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "forms-flow-analytics", + "description": "Redash-Analytics", + "adminUrl": "http://localhost:7000/saml/callback?org_slug=default", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://localhost:7000/*", + "*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "saml", + "attributes": { + "saml.assertion.signature": "true", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml.signature.algorithm": "RSA_SHA256", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "true", + "display.on.consent.screen": "false", + "saml_name_id_format": "email", + "saml.onetimeuse.condition": "false", + "saml_signature_canonicalization_method": "http://www.w3.org/2001/10/xml-exc-c14n#WithComments" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "name": "X500 surname", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "user.attribute": "lastName", + "friendly.name": "LastName", + "attribute.name": "urn:oid:2.5.4.4" + } + }, + { + "name": "X500 givenName", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "user.attribute": "firstName", + "friendly.name": "FirstName", + "attribute.name": "urn:oid:2.5.4.42" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "forms-flow-bpm", + "description": "Camunda Process Engine Components", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://localhost:8000/camunda/*", + "*" + ], + "webOrigins": [ + "*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "name": "formsflow-web-mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "forms-flow-web", + "id.token.claim": "false", + "access.token.claim": "true", + "userinfo.token.claim": "false" + } + }, + { + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "name": "camunda-rest-api", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "false", + "access.token.claim": "true", + "included.custom.audience": "camunda-rest-api" + } + }, + { + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-group-membership-mapper", + "consentRequired": false, + "config": { + "full.path": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "userinfo.token.claim": "true" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "camunda-rest-api", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "forms-flow-web", + "description": "React based FormIO web components", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://localhost:3000/*", + "*" + ], + "webOrigins": [ + "*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "name": "formsflow-web-mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "forms-flow-web", + "id.token.claim": "false", + "access.token.claim": "true", + "userinfo.token.claim": "false" + } + }, + { + "name": "camunda-rest-api", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "false", + "access.token.claim": "true", + "included.custom.audience": "camunda-rest-api" + } + }, + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-group-membership-mapper", + "consentRequired": false, + "config": { + "full.path": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "userinfo.token.claim": "true" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "camunda-rest-api", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/forms-flow-ai/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/admin/forms-flow-ai/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "name": "Role", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "role", + "usermodel.clientRoleMapping.clientId": "forms-flow-web" + } + }, + { + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "camunda-rest-api", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "camunda-rest-api", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "false", + "access.token.claim": "true", + "included.custom.audience": "camunda-rest-api", + "userinfo.token.claim": "false" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "camunda-rest-api" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + }, + { + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "clientOfflineSessionMaxLifespan": "0", + "clientSessionIdleTimeout": "0", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0" + }, + "keycloakVersion": "11.0.0", + "userManagedAccessAllowed": false +} \ No newline at end of file diff --git a/forms-flow-api/tests/unit/api/__init__.py b/forms-flow-api/tests/unit/api/__init__.py new file mode 100644 index 0000000000..d4c2f9822e --- /dev/null +++ b/forms-flow-api/tests/unit/api/__init__.py @@ -0,0 +1 @@ +"""Test suite for API""" diff --git a/forms-flow-api/tests/unit/api/test_application.py b/forms-flow-api/tests/unit/api/test_application.py new file mode 100644 index 0000000000..3746a62fb1 --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_application.py @@ -0,0 +1,211 @@ +"""Test suite for application API endpoint""" +from pytest import mark +from tests.utilities.base_test import ( + get_token_header, + get_token_body, + get_application_create_payload, + get_form_request_payload, + factory_auth_header, +) + + +@mark.describe("Initialize application API") +class TestApplicationResource: + def test_application_no_auth_api(self, client): + """Assert that API /application when passed with no token returns 401 status code""" + response = client.get("/application") + assert response.status_code == 401 + assert response.json == { + "type": "Invalid Token Error", + "message": "Access to formsflow.ai API Denied. Check if the bearer token is passed for Authorization or has expired.", + } + + def test_application_list(self, session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + + response = client.get("/application", headers=headers) + assert response.status_code == 200 + + def test_application_paginated_list(self, session, client, jwt, pageNo, limit): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + response = client.get( + f"/application?pageNo={pageNo}&limit={limit}", headers=headers + ) + assert response.status_code == 200 + + def test_application_paginated_sorted_list( + self, session, client, jwt, pageNo, limit, sortBy, sortOrder + ): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + response = client.get( + f"/application?pageNo={pageNo}&limit={limit}&sortBy={sortBy}&sortOrder={sortOrder}", + headers=headers, + ) + assert response.status_code == 200 + + +class TestApplicationDetailView: + def test_application_no_auth_api(self, session, client, jwt): + response = client.get("/application/1") + assert response.status_code == 401 + assert response.json == { + "type": "Invalid Token Error", + "message": "Access to formsflow.ai API Denied. Check if the bearer token is passed for Authorization or has expired.", + } + + def test_application_detailed_view(self, session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + response = client.get("/application/1", headers=headers) + assert response.status_code == 403 + + +class TestApplicationResourceByFormId: + def test_application_submission(self, session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + response = client.get( + "/application/formid/61b81b6f85589c44f62865c7", headers=headers + ) + assert response.status_code == 200 + + +class TestProcessMapperResourceByApplicationId: + def test_application_process_details(session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + response = client.get("/application/1/process", headers=headers) + assert response.status_code == 200 + + +class TestApplicationResourceByApplicationStatus: + def test_application_status_list(session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + response = client.get("/application/status/list", headers=headers) + assert response.status_code == 200 + assert response.json["applicationStatus"] + + +def test_application_status_list(session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + response = client.get("/application/status/list", headers=headers) + assert response.status_code == 200 + assert response.json["applicationStatus"] + + +def test_application_create_method(session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + + +def test_application_update_details_api(session, client, jwt): + token = factory_auth_header() + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + application_id = rv.json.get("id") + rv = client.get(f"/application/{application_id}", headers=headers) + payload = rv.json() + payload["applicationStatus"] = "New" + rv = client.put(f"/application/{application_id}", headers=headers, json=payload) + assert rv.status_code == 200 + assert rv.json() == "Updated successfully" diff --git a/forms-flow-api/tests/unit/api/test_application_history.py b/forms-flow-api/tests/unit/api/test_application_history.py new file mode 100644 index 0000000000..8177518a57 --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_application_history.py @@ -0,0 +1,66 @@ +"""Test suite for application History API endpoint""" +from tests.utilities.base_test import ( + token_header, + get_application_create_payload, + get_claims, + get_form_request_payload, + factory_auth_header, +) + + +def test_get_application_history(client, jwt): + """Get the json request for application /application/{application_id}/history""" + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + + ## This application create fails because of pessimistic DB management + + application_id = rv.json.get("applicationId") + + rv = client.get(f"/application/{application_id}/history", headers=headers) + assert rv.status_code == 200 + + +def test_get_application_history_unauthorized(client): + """Testing the response of unauthorized application /application/{application_id}/history""" + rv = client.get("/application/1/history") + assert rv.status_code == 401 + + +def test_post_application_history_create_method(client, jwt): + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + application_id = rv.json.get("applicationId") + new_application = client.post( + f"/application/{application_id}/history", + headers=headers, + json={ + "applicationId": 1, + "applicationStatus": "New", + "formUrl": "http://testsample.com/form/23/submission/3423", + }, + ) + assert new_application.status_code == 201 diff --git a/forms-flow-api/tests/unit/api/test_checkpoint.py b/forms-flow-api/tests/unit/api/test_checkpoint.py new file mode 100644 index 0000000000..bb6720f810 --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_checkpoint.py @@ -0,0 +1,20 @@ +"""Test suite for Checkpoint API endpoint""" +from pytest import mark +from formsflow_api import create_app + + +@mark.describe("Initialize Checkpoint API") +def test_checkpoint_api(): + """Assert that checkpoint API resonse""" + flask_app = create_app(run_mode="testing") + + with flask_app.test_client() as client: + response = client.get("/checkpoint") + assert response.status_code == 200 + assert response.json == {"message": "Welcome to formsflow.ai API"} + + +def test_checkpoint_test_api(session, client): + """Assert that checkpoint API status code""" + response = client.get("/checkpoint") + assert response.status_code == 200 diff --git a/forms-flow-api/tests/unit/api/test_dashboards.py b/forms-flow-api/tests/unit/api/test_dashboards.py new file mode 100644 index 0000000000..63fc7ec679 --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_dashboards.py @@ -0,0 +1,32 @@ +"""Unit test for APIs of Dashboards""" +from tests.utilities.base_test import factory_auth_header + + +def test_get_dashboards(client): + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + rv = client.get("/dashboards", headers=headers) + assert rv.status_code == 200 + assert len(rv.json) >= 1 + + +def test_get_dashboard_details(client): + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + rv = client.get("/dashboards/1", headers=headers) + assert rv.json() is not None + assert rv.status_code == 200 + + +def test_no_auth_get_dashboards(client): + rv = client.get("/dashboards") + assert rv.status_code == 401 + + +def test_get_dashboard_error_details(client): + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + rv = client.get("/dashboards/10000", headers=headers) + assert rv.json == {"message": "Dashboard not found"} diff --git a/forms-flow-api/tests/unit/api/test_form_process_mapper.py b/forms-flow-api/tests/unit/api/test_form_process_mapper.py new file mode 100644 index 0000000000..f09a372baf --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_form_process_mapper.py @@ -0,0 +1,50 @@ +"""Test suite for FormProcessMapper API endpoint""" +from tests.utilities.base_test import ( + get_token_header, + get_token_body, + get_form_request_payload, +) + + +def test_form_process_mapper_list(session, client, jwt, app): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + response = client.get("/form", headers=headers) + assert response.status_code == 200 + + +def test_form_process_mapper_creation(session, client, jwt, app): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + response = client.post("/form", headers=headers, json=get_form_request_payload()) + assert response.status_code == 201 + assert response.json.get("id") != None + + +def test_form_process_mapper_detail_view(session, client, jwt, app): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + response = client.post( + "/form", + headers=headers, + json=get_form_request_payload(), + ) + assert response.status_code == 201 + mapper_id = response.json.get("id") + rv = client.get(f"/form/{mapper_id}", headers=headers) + assert rv.status_code == 200 + assert rv.json.get("id") == mapper_id + + +def test_form_process_mapper_by_formid(client, jwt): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + response = client.post( + "/form", + headers=headers, + json=get_form_request_payload(), + ) + assert response.status_code == 201 + form_id = response.json.get("formId") + rv = client.get(f"/form/formid/{form_id}", headers=headers) + assert rv.status_code == 200 diff --git a/forms-flow-api/tests/unit/api/test_keycloak_groups.py b/forms-flow-api/tests/unit/api/test_keycloak_groups.py new file mode 100644 index 0000000000..eb1f513619 --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_keycloak_groups.py @@ -0,0 +1,86 @@ +"""Unit test for APIs of Keycloak Group""" +from tests.utilities.base_test import factory_auth_header + + +def test_group_list(client): + """Passing case of Group List API""" + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + response = client.get("/groups", headers=headers) + assert response.status_code == 200 + + +def test_group_list_wrongmethod(client): + """Instead of Get Request, what if POST request comes""" + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + response = client.post("/groups", headers=headers) + assert response.status_code == 405 + assert response.json() == { + "message": "The method is not allowed for the requested URL." + } + + +def test_group_list_wrong_auth_header(client): + """Wrong Authorization header""" + response = client.get("/groups") + assert response.status_code == 401 + assert response.json() == { + "type": "Invalid Token Error", + "message": "Access to formsflow.ai API Denied. Check if the bearer token is passed for Authorization or has expired.", + } + + +def test_group_details(client): + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + response = client.get("/groups", headers=headers) + assert len(response.json()) > 0 + + id = response.json()[0]["id"] + response = client.get(f"/groups/{id}", headers=headers) + assert response.status_code == 200 + assert len(response.json()) > 0 + + +def test_non_existential_group_id(client): + """non-existential group id""" + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + response = client.get("/groups/123", headers=headers) + assert response.status_code == 404 + + +def test_groups_put_details(client): + """good cases""" + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + response = client.get("/groups", headers=headers) + assert len(response.json()) > 0 + id = response.json()[0]["id"] + + response = client.put( + f"/groups/{id}", headers=headers, data={"dashboards": [{100: "Test Dashboard"}]} + ) + assert response.status_code == 204 + + +def test_groups_put_wrong_details(client): + """wrong request object""" + token = factory_auth_header() + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + response = client.get("/groups", headers=headers) + assert len(response.json()) > 0 + id = response.json()[0]["id"] + + response = client.put( + f"/groups/{id}", headers=headers, data={"dashboard": [{100: "Test Dashboard"}]} + ) + assert response.status_code == 400 + assert response.json() == {"message": "Invalid Request Object format"} diff --git a/forms-flow-api/tests/unit/api/test_metrics.py b/forms-flow-api/tests/unit/api/test_metrics.py new file mode 100644 index 0000000000..a151ac044c --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_metrics.py @@ -0,0 +1,86 @@ +"""Test suite for metrics API endpoint""" +import pytest +from datetime import date +from tests.utilities.base_test import ( + get_application_create_payload, + get_token_header, + get_token_body, + get_form_request_payload, +) + +METRICS_ORDER_BY_VALUES = ["created", "modified"] + + +@pytest.mark.parametrize("orderBy", METRICS_ORDER_BY_VALUES) +def test_metrics_get_200(orderBy, session, client, jwt, app): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + today = date.today().strftime("%Y-%m-%d") + rv = client.get( + f"/metrics?from={today}&to={today}&orderBy={orderBy}", headers=headers + ) + assert rv.status_code == 200 + assert rv.status_code == 200 + + +@pytest.mark.parametrize("orderBy", METRICS_ORDER_BY_VALUES) +def test_metrics_get_401(orderBy, session, client, jwt, app): + rv = client.get(f"/metrics?from=2021-10-10&to=2021-10-31&orderBy={orderBy}") + assert rv.status_code == 401 + + +@pytest.mark.parametrize("orderBy", METRICS_ORDER_BY_VALUES) +def test_metrics_list_view(orderBy, session, client, jwt, app): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + form_id = rv.json.get("formId") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + + today = date.today().strftime("%Y-%m-%d") + rv = client.get( + f"/metrics?from={today}&to={today}&orderBy={orderBy}", headers=headers + ) + assert rv.status_code == 200 + assert len(rv.json.get("applications")) == 1 + + +@pytest.mark.parametrize("orderBy", METRICS_ORDER_BY_VALUES) +def test_metrics_detailed_get_401(orderBy, session, client, jwt, app): + rv = client.get(f"/metrics/1?from=2021-10-10&to=2021-10-31&orderBy={orderBy}") + assert rv.status_code == 401 + + +@pytest.mark.parametrize("orderBy", METRICS_ORDER_BY_VALUES) +def test_metrics_detailed_view(orderBy, session, client, jwt, app): + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + + rv = client.post("/form", headers=headers, json=get_form_request_payload()) + assert rv.status_code == 201 + form_id = rv.json.get("formId") + mapper_id = rv.json.get("id") + + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + assert rv.status_code == 201 + + today = date.today().strftime("%Y-%m-%d") + rv = client.get( + f"/metrics/{mapper_id}?from={today}&to={today}&orderBy={orderBy}", + headers=headers, + ) + assert rv.status_code == 200 + assert rv.json.get("applications") diff --git a/forms-flow-api/tests/unit/api/test_process.py b/forms-flow-api/tests/unit/api/test_process.py new file mode 100644 index 0000000000..aedf48bba5 --- /dev/null +++ b/forms-flow-api/tests/unit/api/test_process.py @@ -0,0 +1,19 @@ +"""Test suite for process API endpoint""" +from tests.utilities.base_test import get_token_header, get_token_body + + +def test_process_get_all_processes(client, session, jwt): + """Test process get all processes""" + token = jwt.create_jwt(get_token_body(), get_token_header()) + headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"} + response = client.get("/application", headers=headers) + assert response.status_code == 200 + + +# TODO: Add integration test using BPM Mock APIs +# def test_process_xml_details(client, session, jwt): +# headers = { +# "Authorization": "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJrYTFKalB6Vy1EaHNFSE9vd2NZVHRJdW9sR3FqT0NhN1NYV0RFcDI1dGZBIn0.eyJqdGkiOiJjZjBlYjVmZS0zMGE2LTRiY2QtOTM1OS03ZTVjMzg4ZWZjZjAiLCJleHAiOjE2MzYzNTY0MDMsIm5iZiI6MCwiaWF0IjoxNjM1NDkyNDAzLCJpc3MiOiJodHRwczovL2lhbS5hb3QtdGVjaG5vbG9naWVzLmNvbS9hdXRoL3JlYWxtcy9mb3Jtc2Zsb3ctYWktd2lsbG93IiwiYXVkIjpbImNhbXVuZGEtcmVzdC1hcGkiLCJmb3Jtcy1mbG93LXdlYiIsImFjY291bnQiXSwic3ViIjoiMmYzMThhMDktNDY3YS00MTUxLTliMzAtY2Y3NTg4MTlmMDU1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiZm9ybXMtZmxvdy13ZWIiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiIwOGEzZTVlMi1lYTZlLTRkYTUtYjQzZi05MTIyYjgwOWNhNDkiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJmb3Jtcy1mbG93LXdlYiI6eyJyb2xlcyI6WyJmb3Jtc2Zsb3ctZGVzaWduZXIiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiY2FtdW5kYS1yZXN0LWFwaSBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJyb2xlIjpbImZvcm1zZmxvdy1kZXNpZ25lciJdLCJuYW1lIjoiUGV0ZXIgV2F0dHMiLCJncm91cHMiOlsiL2NhbXVuZGEtYWRtaW4iLCIvZm9ybXNmbG93L2Zvcm1zZmxvdy1kZXNpZ25lciJdLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJwZXRlci13YXR0cyIsImdpdmVuX25hbWUiOiJQZXRlciIsImZhbWlseV9uYW1lIjoiV2F0dHMiLCJlbWFpbCI6InBldGVyLndhdHRzQGFvdC5jb20ifQ.ioYSAO9hgbNl2w7vET9vBFL1DDi1YqX6x0N0HokGZsntNRWLkrh8sawmTnJ3z4ambMmI2Swy9jRiV_GhNjaXy-DzQa8WkHsFZixuiYhNM6KuUypwo49H9JhW9xs9Dyo0ejlL3IkS20yKDHFx69ee0YxFiVtNv8_zdFEn2OOj2zQAVPmfzzcD0GyaAEVKdBhelENYDF4BDNWNO77YfrlYURMcRhtC3ptAm_SbbL05hkGKHVVMWoukgEJ2iH0Y40qEYg8MOGrrDscl2eywpNNqvoxpFPGHjGfM_5wvNnVzhnHc_JBt9mIyNFFuPDzoS9OBVEXuS7DxxiKf8sYrx0LzIQ" +# } +# response = client.get("/process/one-step-approval/xml", headers=headers) +# assert response.status_code == response diff --git a/forms-flow-api/tests/unit/conf/test_configuration.py b/forms-flow-api/tests/unit/conf/test_configuration.py index 9f046b5171..868ed65b2d 100644 --- a/forms-flow-api/tests/unit/conf/test_configuration.py +++ b/forms-flow-api/tests/unit/conf/test_configuration.py @@ -6,26 +6,26 @@ from importlib import reload import pytest -from api import config +from formsflow_api import config # testdata pattern is ({str: environment}, {expected return value}) TEST_ENVIRONMENT_DATA = [ - ('valid', 'development', config.DevConfig), - ('valid', 'testing', config.TestConfig), - ('valid', 'default', config.ProdConfig), - ('valid', 'production', config.ProdConfig), - ('error', None, KeyError) + ("valid", "development", config.DevConfig), + ("valid", "testing", config.TestConfig), + ("valid", "default", config.ProdConfig), + ("valid", "production", config.ProdConfig), + ("error", None, KeyError), ] -@pytest.mark.parametrize('test_type,environment,expected', TEST_ENVIRONMENT_DATA) +@pytest.mark.parametrize("test_type,environment,expected", TEST_ENVIRONMENT_DATA) def test_get_named_config(test_type, environment, expected): """Assert that the named configurations can be loaded. Or that a KeyError is returned for missing config types. """ - if test_type == 'valid': + if test_type == "valid": assert isinstance(config.get_named_config(environment), expected) else: with pytest.raises(KeyError): @@ -38,7 +38,7 @@ def test_prod_config_secret_key(monkeypatch): The object either uses the SECRET_KEY from the environment, or creates the SECRET_KEY on the fly. """ - key = 'SECRET_KEY' + key = "SECRET_KEY" # Assert that secret key will default to some value # even if missed in the environment setup @@ -47,6 +47,6 @@ def test_prod_config_secret_key(monkeypatch): assert config.ProdConfig().SECRET_KEY is not None # Assert that the secret_key is set to the assigned environment value - monkeypatch.setenv(key, 'SECRET_KEY') + monkeypatch.setenv(key, "SECRET_KEY") reload(config) - assert config.ProdConfig().SECRET_KEY == 'SECRET_KEY' + assert config.ProdConfig().SECRET_KEY == "SECRET_KEY" diff --git a/forms-flow-api/tests/unit/models/test_application.py b/forms-flow-api/tests/unit/models/test_application.py index 5187148513..3e763752ea 100644 --- a/forms-flow-api/tests/unit/models/test_application.py +++ b/forms-flow-api/tests/unit/models/test_application.py @@ -1,20 +1,32 @@ """Unit tests for application Model""" -from api.models import Application, FormProcessMapper +from formsflow_api.models import Application, FormProcessMapper + def test_application_model_can_create_application(): """Test application model can create application.""" - form = FormProcessMapper(id=1, form_id=12324, form_name='One Step Approval', - form_revision_number=1, process_key=121312, - process_name='test', status='Pending', - comments='test',tenant_id=12) + form = FormProcessMapper( + id=1, + form_id=12324, + form_name="One Step Approval", + form_revision_number=1, + process_key=121312, + process_name="test", + status="Pending", + comments="test", + tenant_id=12, + ) assert form.id == 1 - application1 = Application(application_name='Test Form Application', - application_status='Approved', - form_url="https://testsample.com/api/form/123/submission/2313", - process_instance_id="213123", - revision_no=1, - form_process_mapper_id=1) - - assert application1.application_name == 'Test Form Application' - assert application1.application_status == 'Approved' - assert application1.form_url == "https://testsample.com/api/form/123/submission/2313" + application1 = Application( + application_name="Test Form Application", + application_status="Approved", + form_url="https://testsample.com/api/form/123/submission/2313", + process_instance_id="213123", + revision_no=1, + form_process_mapper_id=1, + ) + + assert application1.application_name == "Test Form Application" + assert application1.application_status == "Approved" + assert ( + application1.form_url == "https://testsample.com/api/form/123/submission/2313" + ) diff --git a/forms-flow-api/tests/unit/models/test_application_audit.py b/forms-flow-api/tests/unit/models/test_application_audit.py index bc03ce1404..e4cb27601f 100644 --- a/forms-flow-api/tests/unit/models/test_application_audit.py +++ b/forms-flow-api/tests/unit/models/test_application_audit.py @@ -1,10 +1,17 @@ """Unit tests for Application Audit Model""" -from api.models import ApplicationHistory +from formsflow_api.models import ApplicationHistory + def test_application_audit_creation(): """Test Application History Model creation""" - instance1 = ApplicationHistory(id=1, application_id=10, application_status="New", - form_url="https://testsample.com/api/form/6100fae7ba5ac0627e9eefe6/submission/6101131fc325d44c1d846c13") + instance1 = ApplicationHistory( + id=1, + application_id=10, + application_status="New", + form_url="https://testsample.com/api/form/6100fae7ba5ac0627e9eefe6/submission/6101131fc325d44c1d846c13", + ) assert instance1.id == 1 - assert instance1.form_url == "https://testsample.com/api/form/6100fae7ba5ac0627e9eefe6/submission/6101131fc325d44c1d846c13" - + assert ( + instance1.form_url + == "https://testsample.com/api/form/6100fae7ba5ac0627e9eefe6/submission/6101131fc325d44c1d846c13" + ) diff --git a/forms-flow-api/tests/unit/models/test_form_process_mapper.py b/forms-flow-api/tests/unit/models/test_form_process_mapper.py index 45d548ddde..713e77ac16 100644 --- a/forms-flow-api/tests/unit/models/test_form_process_mapper.py +++ b/forms-flow-api/tests/unit/models/test_form_process_mapper.py @@ -1,11 +1,19 @@ """Unit tests for FormProcessMapper Model""" -from api.models import FormProcessMapper +from formsflow_api.models import FormProcessMapper + def test_formprocessmapper_creation(): """Test FormProcessMapper can create""" - form = FormProcessMapper(id=1, form_id=12324, form_name='One Step Approval', - form_revision_number=1, process_key=121312, - process_name='test', status='Pending', - comments='test',tenant_id=12) + form = FormProcessMapper( + id=1, + form_id=12324, + form_name="One Step Approval", + form_revision_number=1, + process_key=121312, + process_name="test", + status="Pending", + comments="test", + tenant_id=12, + ) assert form.id == 1 assert form.form_id == 12324 diff --git a/forms-flow-api/tests/unit/services/test_application.py b/forms-flow-api/tests/unit/services/test_application.py new file mode 100644 index 0000000000..56c4e0195e --- /dev/null +++ b/forms-flow-api/tests/unit/services/test_application.py @@ -0,0 +1,4 @@ +"""Tests to assure the Application Service""" +from formsflow_api.services import ApplicationService + +application_service = ApplicationService() diff --git a/forms-flow-api/tests/unit/services/test_application_history.py b/forms-flow-api/tests/unit/services/test_application_history.py new file mode 100644 index 0000000000..463e65b88e --- /dev/null +++ b/forms-flow-api/tests/unit/services/test_application_history.py @@ -0,0 +1,28 @@ +"""Tests to assure the Application History Service""" +from formsflow_api.services import ApplicationHistoryService + +application_history_service = ApplicationHistoryService() + + +def test_create_application_history(session): + payload = { + "application_status": "Pending", + "form_url": "http://sample.com/form/23232/submission/2342", + } + payload["application_id"] = 1222 # sample value + application_history = application_history_service.create_application_history( + data=payload + ) + assert application_history.application_id == 1222 + assert application_history.application_status == "Pending" + assert ( + application_history.form_url == "http://sample.com/form/23232/submission/2342" + ) + + +def test_get_application_history(session): + # Need to have at least one application before running this test + application_history = application_history_service.get_application_history( + application_id=1 + ) + assert not application_history diff --git a/forms-flow-api/tests/unit/services/test_form_process_mapper.py b/forms-flow-api/tests/unit/services/test_form_process_mapper.py new file mode 100644 index 0000000000..2c7fdd2025 --- /dev/null +++ b/forms-flow-api/tests/unit/services/test_form_process_mapper.py @@ -0,0 +1,45 @@ +"""Tests to assure the FormProcessMapper Service""" +from formsflow_api.services import FormProcessMapperService +from tests.utilities.base_test import get_form_service_payload + +form_service = FormProcessMapperService() + + +def test_form_get_all_mappers(session): + rv = form_service.get_all_mappers(page_number=0, limit=0) + assert not rv + + +def test_get_form_mapper_count(session): + rv = form_service.get_mapper_count() + assert not rv + assert type(rv) == int + + +def test_get_form_mapper(session): + rv = form_service.get_mapper(1) + assert not rv + assert type(rv) == dict + + +def test_get_form_mapper_by_formid(session): + rv = form_service.get_mapper_by_formid(1) + assert not rv + assert type(rv) == dict + + +def test_create_form_mapper(session): + rv = form_service.create_mapper(data=get_form_service_payload()) + assert rv.form_id == "1234" + assert rv.form_name == "Sample form" + + +def test_update_form_mapper(session, client): + rv = form_service.update_mapper(1, data=get_form_service_payload()) + assert rv.form_id == "1234" + assert rv.form_name == "Sample form" + + +def test_mark_inactive(session): + rv = form_service.mark_inactive(form_process_mapper_id=1) + assert rv.status_code == 200 diff --git a/forms-flow-api/tests/unit/utils/logging.conf b/forms-flow-api/tests/unit/utils/logging.conf index 0806a8a2c0..985f6dcfdf 100644 --- a/forms-flow-api/tests/unit/utils/logging.conf +++ b/forms-flow-api/tests/unit/utils/logging.conf @@ -14,7 +14,7 @@ handlers=console [logger_api] level=DEBUG handlers=console -qualname=api +qualname=formsflow_api propagate=0 [handler_console] diff --git a/forms-flow-api/tests/unit/utils/test_logging.py b/forms-flow-api/tests/unit/utils/test_logging.py index 617a204662..cc508ff02c 100644 --- a/forms-flow-api/tests/unit/utils/test_logging.py +++ b/forms-flow-api/tests/unit/utils/test_logging.py @@ -5,7 +5,7 @@ import os -from api.utils.logging import log_error, log_info, setup_logging +from formsflow_api.utils.logging import setup_logging def test_logging_with_missing_file(capsys): @@ -15,4 +15,4 @@ def test_logging_with_missing_file(capsys): captured = capsys.readouterr() - assert captured.err.startswith('Unable to configure logging') + assert captured.err.startswith("Unable to configure logging") diff --git a/forms-flow-api/tests/unit/utils/test_util_cors.py b/forms-flow-api/tests/unit/utils/test_util_cors.py index e5d89981cd..e44d5c0891 100644 --- a/forms-flow-api/tests/unit/utils/test_util_cors.py +++ b/forms-flow-api/tests/unit/utils/test_util_cors.py @@ -4,29 +4,30 @@ """ import pytest -from api.utils.util import cors_preflight +from formsflow_api.utils.util import cors_preflight TEST_CORS_METHODS_DATA = [ - ('GET'), - ('PUT'), - ('POST'), - ('GET,PUT'), - ('GET,POST'), - ('PUT,POST'), - ('GET,PUT,POST'), + ("GET"), + ("PUT"), + ("POST"), + ("GET,PUT"), + ("GET,POST"), + ("PUT,POST"), + ("GET,PUT,POST"), ] -@pytest.mark.parametrize('methods', TEST_CORS_METHODS_DATA) +@pytest.mark.parametrize("methods", TEST_CORS_METHODS_DATA) def test_cors_preflight_post(methods): """Assert that the options methos is added to the class and \ that the correct access controls are set.""" + @cors_preflight(methods) - class TestCors(): + class TestCors: pass rv = TestCors().options() - assert rv[2]['Access-Control-Allow-Origin'] == '*' - assert rv[2]['Access-Control-Allow-Methods'] == methods + assert rv[2]["Access-Control-Allow-Origin"] == "*" + assert rv[2]["Access-Control-Allow-Methods"] == methods diff --git a/forms-flow-api/tests/utilities/base_test.py b/forms-flow-api/tests/utilities/base_test.py new file mode 100644 index 0000000000..e9def78efb --- /dev/null +++ b/forms-flow-api/tests/utilities/base_test.py @@ -0,0 +1,130 @@ +"""Base Test Class to be used by test suites. Used for getting JWT token purpose""" +import os +import ast +import requests +from dotenv import find_dotenv, load_dotenv + +load_dotenv(find_dotenv()) + +# token_header = {"alg": "RS256", "typ": "JWT", "kid": "forms-flow-web"} + + +# def get_token_header(): +# """Get the token header json.""" +# return { +# "alg": "RS256", +# "typ": "JWT", +# "kid": "ka1JjPzW-DhsEHOowcYTtIuolGqjOCa7SXWDEp25tfA", +# } + + +# def get_token_body(): +# """Get the token body json.""" +# return { +# "jti": "1d8c24bd-a1a7-4251-b769-b7bd6ecd51213215", +# "exp": 1636263332, +# "nbf": 0, +# "iat": 1635399332, +# "iss": "http://localhost:8081/auth/realms/demo", +# "aud": ["camunda-rest-api", "forms-flow-web", "account"], +# "sub": "47b46f22-45ec-4cfb-825b-ed10ba8bed01", +# "typ": "Bearer", +# "azp": "forms-flow-web", +# "auth_time": 0, +# "session_state": "6f50e760-cd96-4934-86dc-e0e667f1a407", +# "acr": "1", +# "allowed-origins": ["*"], +# "realm_access": {"roles": ["offline_access", "uma_authorization"]}, +# "resource_access": { +# "forms-flow-web": {"roles": ["formsflow-client"]}, +# "account": { +# "roles": ["manage-account", "manage-account-links", "view-profile"] +# }, +# }, +# "scope": "camunda-rest-api email profile", +# "role": ["formsflow-client"], +# "name": "John Smith", +# "groups": ["/camunda-admin", "/formsflow/formsflow-client"], +# "preferred_username": "john-smith", +# "given_name": "John", +# "family_name": "Smith", +# "email": "john.smith@aot.com", +# } + + +# def get_claims( +# app_request=None, +# role: str = "edit", +# username: str = "CP0001234", +# login_source: str = None, +# roles: list = [], +# ): +# """Return the claim with the role param.""" +# claim = { +# "jti": "a50fafa4-c4d6-4a9b-9e51-1e5e0d102878", +# "exp": 31531718745, +# "iat": 1531718745, +# "iss": "http://localhost:8081/auth/realms/demo", +# "aud": "sbc-auth-web", +# "sub": "15099883-3c3f-4b4c-a124-a1824d6cba84", +# "typ": "Bearer", +# "realm_access": {"roles": ["{}".format(role), *roles]}, +# "preferred_username": username, +# "name": username, +# "username": username, +# "loginSource": login_source, +# "roles": ["{}".format(role), *roles], +# } +# return claim + + +TEST_USER_PAYLOAD = { + "client_id": "forms-flow-web", + "grant_type": "password", + "username": os.getenv("TEST_REVIEWER_USERID"), + "password": os.getenv("TEST_REVIEWER_PASSWORD"), +} + + +def factory_auth_header(): + url = f"{os.getenv('KEYCLOAK_URL')}/auth/realms/{os.getenv('KEYCLOAK_URL_REALM')}/protocol/openid-connect/token" + x = requests.post(url, TEST_USER_PAYLOAD, verify=True).content.decode("utf-8") + print(x) + return str(ast.literal_eval(x)["access_token"]) + + +def get_form_request_payload(): + """Return a form request payload object""" + return { + "formId": "1234", + "formName": "Sample form", + "formRevisionNumber": "v1", + "processKey": "121312", + "processName": "OneStep Approval", + "status": "active", + "commeIs": "test", + "tenantId": 12, + } + + +def get_application_create_payload(form_id: str = "1234"): + return { + "formId": form_id, + "submissionId": "1233432", + "formUrl": f"http://sample.com/formid/{form_id}/submissionid/1233432", + } + + +def get_form_service_payload(): + """Return a form Service payload object""" + return { + "form_id": "1234", + "form_name": "Sample form", + "form_revision_number": "v1", + "process_key": "121312", + "process_name": "OneStep Approval", + "status": "active", + "comments": "test", + "tenant_id": 12, + "created_by": "test-user", + } diff --git a/forms-flow-api/wsgi.py b/forms-flow-api/wsgi.py index 8113df3ba2..a2e8cf238d 100644 --- a/forms-flow-api/wsgi.py +++ b/forms-flow-api/wsgi.py @@ -1,9 +1,9 @@ """Provides the WSGI entry point for running the application.""" -from api import create_app +from formsflow_api import create_app application = create_app() # pylint: disable=invalid-name -if __name__ == '__main__': +if __name__ == "__main__": application.run() diff --git a/forms-flow-bpm/.DS_Store b/forms-flow-bpm/.DS_Store deleted file mode 100644 index a2911781d42afccd7c1c215d46322f383bf2c703..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKO^ee&7=CA4HLa*ch24|nA_(r5F0C#oLbrAg3kqUH1(n^V>9)Z%Q<8M+S}VQy zAJl)~5AZJDJn7B5f59K1&wQv!tKvaK%Dgc1%*^{W@6#reAtKfodh0|bBC^l~=8Ncl zB0?|PoGj^;6F??nYzMsU2HeG51Tf*mH`gll5WGW_(VP2fH>sM23jgFyhpw0s0s#Wjeqt$i|?{h;c5Hx0#BuhwQ;@ zUJ`pv`y7`!`pB5hU#3U%`PlM|Z-H*o7Hv|Kt^>>P@UlCURi?9@lGP-VnGoE>f0Xz0 zOx_&)B5G%INjB2Ig0^x;@j$<8-?@XpkCRH}BU{Sl4;?;YSw*XOtoXp`@sX3Xl40Cv zMfb$)Ml0#LdVGuX;QP4c-u64Aozm&6JWN`C*omaG?{#2u|BfGeeAM8>(2HdpM=30; zU=?;sE93EnT4mL)R%?@0d%UrMajklBGAUTgXVyx;Q17N(=*rfxpCnct6-^0_z&53gxQiiCGb4`9%=8U~>5B)mr8%*> zLem=t3s)c-thLd0(S!)QsY2<3 kP9Mi|Adcb{G%3*8VgRgboGQc$#C!-y8cb&x_@@kf1wiuQQUCw| diff --git a/forms-flow-bpm/.gitignore b/forms-flow-bpm/.gitignore index 3c7004da6f..b345e51ffd 100644 --- a/forms-flow-bpm/.gitignore +++ b/forms-flow-bpm/.gitignore @@ -1,3 +1,28 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +##forms-flow-bpm .settings/ .project .classpath diff --git a/forms-flow-bpm/Dockerfile b/forms-flow-bpm/Dockerfile index 4d031f520c..1261f7f1f7 100644 --- a/forms-flow-bpm/Dockerfile +++ b/forms-flow-bpm/Dockerfile @@ -22,8 +22,8 @@ EXPOSE 8080 RUN test ! -d /app && mkdir /app || : # Add spring boot application RUN mkdir -p /app -COPY --from=MAVEN_TOOL_CHAIN /tmp/target/camunda-bpm-identity-keycloak-examples-sso-kubernetes*.jar ./app +COPY --from=MAVEN_TOOL_CHAIN /tmp/target/forms-flow-bpm.jar ./app RUN chmod a+rwx -R /app WORKDIR /app VOLUME /tmp -ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/camunda-bpm-identity-keycloak-examples-sso-kubernetes.jar"] +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/forms-flow-bpm.jar"] diff --git a/forms-flow-bpm/LICENSE b/forms-flow-bpm/LICENSE new file mode 100644 index 0000000000..cc235ca76b --- /dev/null +++ b/forms-flow-bpm/LICENSE @@ -0,0 +1,203 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + Copyright 2020 AppsOnTime Technologies Ltd. + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/forms-flow-bpm/README.md b/forms-flow-bpm/README.md index 75701d72d5..239847d2e4 100644 --- a/forms-flow-bpm/README.md +++ b/forms-flow-bpm/README.md @@ -1,5 +1,5 @@ # Workflow Engine -![Camunda](https://img.shields.io/badge/Camunda-7.13.0-blue) ![Spring Boot](https://img.shields.io/badge/Spring_Boot-2.2.7.RELEASE-blue) ![postgres](https://img.shields.io/badge/postgres-latest-blue) +![Camunda](https://img.shields.io/badge/Camunda-7.15.0-blue) ![Spring Boot](https://img.shields.io/badge/Spring_Boot-2.4.8.RELEASE-blue) ![postgres](https://img.shields.io/badge/postgres-latest-blue) **formsflow.ai** leverages Camunda for workflow and decision automation. To know more about Camunda, visit https://camunda.com/. @@ -101,6 +101,8 @@ To know more about Camunda, visit https://camunda.com/. --- | --- | --- | --- `APP_SECURITY_ORIGIN`|CORS setup, for multiple origins you can separate them using a comma |eg:`host1, host2`| `*` `CAMUNDA_APP_ROOT_LOG_FLAG`|Log level setting||`error` + `DATA_BUFFER_SIZE`|Configure a limit on the number of bytes that can be buffered for webclient||`2 (In MB)` + `IDENTITY_PROVIDER_MAX_RESULT_SIZE`|Maximum result size for Keycloak user queries||`250` **Additionally, you may want to change these** * The value of Datastore credentials (especially if this instance is not just for testing purposes) diff --git a/forms-flow-bpm/docker-compose-linux.yml b/forms-flow-bpm/docker-compose-linux.yml index 5598e15bc8..c55152c8fa 100644 --- a/forms-flow-bpm/docker-compose-linux.yml +++ b/forms-flow-bpm/docker-compose-linux.yml @@ -59,6 +59,8 @@ services: - WEBSOCKET_SECURITY_ORIGIN=${WEBSOCKET_SECURITY_ORIGIN} - WEBSOCKET_MESSAGE_TYPE=${WEBSOCKET_MESSAGE_TYPE:-TASK_EVENT} - WEBSOCKET_ENCRYPT_KEY=${WEBSOCKET_ENCRYPT_KEY:-giert989jkwrgb@DR55} + - DATA_BUFFER_SIZE=${DATA_BUFFER_SIZE:-2} + - IDENTITY_PROVIDER_MAX_RESULT_SIZE=${IDENTITY_PROVIDER_MAX_RESULT_SIZE:-250} networks: - forms-flow-bpm-network diff --git a/forms-flow-bpm/docker-compose-windows.yml b/forms-flow-bpm/docker-compose-windows.yml index 7dda664dcd..15a98567bb 100644 --- a/forms-flow-bpm/docker-compose-windows.yml +++ b/forms-flow-bpm/docker-compose-windows.yml @@ -57,6 +57,8 @@ services: - WEBSOCKET_SECURITY_ORIGIN=${WEBSOCKET_SECURITY_ORIGIN} - WEBSOCKET_MESSAGE_TYPE=${WEBSOCKET_MESSAGE_TYPE:-TASK_EVENT} - WEBSOCKET_ENCRYPT_KEY=${WEBSOCKET_ENCRYPT_KEY:-giert989jkwrgb@DR55} + - DATA_BUFFER_SIZE=${DATA_BUFFER_SIZE:-2} + - IDENTITY_PROVIDER_MAX_RESULT_SIZE=${IDENTITY_PROVIDER_MAX_RESULT_SIZE:-250} networks: - forms-flow-bpm-network diff --git a/forms-flow-bpm/downgrade/README.md b/forms-flow-bpm/downgrade/README.md new file mode 100644 index 0000000000..c82ae0b905 --- /dev/null +++ b/forms-flow-bpm/downgrade/README.md @@ -0,0 +1,10 @@ +# forms-flow-bpm downgrade + +Camunda downgrade `7.15.0` to `7.13.0` includes db changes. Please run the [downgrade file](./process-engine_7.15_to_7.13.sql) after the `forms-flow-bpm-db` service is up. + + ### Steps to run the downgrade file + +* Open a postgres client installed on your machine `eg: pgAdmin, Dbeaver etc`. +* Open the `Query Editor` to run `.sql` file. +* Copy and paste the [downgrade file](./process-engine_7.15_to_7.13.sql). +* Click on `Run` icon to execute the script. diff --git a/forms-flow-bpm/downgrade/process-engine_7.15_to_7.13.sql b/forms-flow-bpm/downgrade/process-engine_7.15_to_7.13.sql new file mode 100644 index 0000000000..d2aaf95b6d --- /dev/null +++ b/forms-flow-bpm/downgrade/process-engine_7.15_to_7.13.sql @@ -0,0 +1,13 @@ +delete from ACT_GE_SCHEMA_LOG where id_ = '400'; + +DROP INDEX ACT_IDX_BATCH_ID; +ALTER TABLE ACT_RU_VARIABLE DROP CONSTRAINT ACT_FK_VAR_BATCH; +ALTER TABLE ACT_RU_VARIABLE DROP COLUMN BATCH_ID_; + +DROP INDEX ACT_IDX_VARIABLE_TASK_NAME_TYPE; + +DROP INDEX ACT_IDX_TASK_METER_LOG_TIME; +DROP TABLE ACT_RU_TASK_METER_LOG; + +ALTER TABLE ACT_RU_INCIDENT DROP COLUMN ANNOTATION_; +ALTER TABLE ACT_HI_INCIDENT DROP COLUMN ANNOTATION_; \ No newline at end of file diff --git a/forms-flow-bpm/pom-docker.xml b/forms-flow-bpm/pom-docker.xml index 7cb2e61b73..a247f93aea 100644 --- a/forms-flow-bpm/pom-docker.xml +++ b/forms-flow-bpm/pom-docker.xml @@ -4,12 +4,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.camunda.bpm.extension.examples - camunda-bpm-identity-keycloak-examples-sso-kubernetes + org.camunda.bpm + extension 2.0.0 - camunda BPM - engine plugins - identity - keycloak - examples - showcase - Showcase for using Camunda Keycloak Identity Provider + Forms flow BPM Extension + Forms flow BPM Extension 11 @@ -21,11 +21,14 @@ false - 7.13.0 - 7.13.0 - 2.4.2 - 2.4.2 2.2.1 + 7.15.0 + 7.15.0 + 1.2.2 + 1.2.0 + 2.4.8 + 2.4.8 + 2.12.2 @@ -56,19 +59,16 @@ - org.springframework - spring-web - 5.3.4 + org.springframework.boot + spring-boot-starter-webflux org.camunda.bpm.springboot camunda-bpm-spring-boot-starter-webapp - ${version.camundaSpringBoot} - org.camunda.bpm.springboot camunda-bpm-spring-boot-starter-rest @@ -106,56 +106,12 @@ org.springframework.security spring-security-oauth2-resource-server + org.springframework.security spring-security-oauth2-jose - - - - - - - - - - - - - org.camunda.bpm.extension @@ -163,7 +119,6 @@ - org.camunda.connect camunda-connect-connectors-all @@ -172,13 +127,13 @@ org.camunda.bpm.extension camunda-bpm-mail-core - 1.2.0 + ${version.camundaMail} org.camunda.connect camunda-connect-core - 1.2.2 + ${version.camundaConnect} @@ -216,6 +171,7 @@ org.springframework.boot spring-boot-starter-jdbc + org.postgresql postgresql @@ -256,19 +212,16 @@ spring-boot-starter-test test - org.camunda.bpm.assert camunda-bpm-assert - 5.0.0 + 12.0.0 test org.assertj assertj-core - 1.7.1 + 3.21.0 test @@ -297,25 +250,25 @@ com.fasterxml.jackson.core jackson-databind - 2.12.2 + ${version.jackson} com.fasterxml.jackson.core jackson-core - 2.12.2 + ${version.jackson} com.fasterxml.jackson.dataformat jackson-dataformat-xml - 2.12.2 + ${version.jackson} com.fasterxml.jackson.core jackson-annotations - 2.12.2 + ${version.jackson} @@ -355,18 +308,47 @@ https://app.camunda.com/nexus/repository/camunda-bpm-community-extensions-snapshots - - ${project.artifactId} + forms-flow-bpm + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + org.jacoco + jacoco-maven-plugin + 0.8.7 + + target/jacoco-ut + + org/camunda/bpm/extension/keycloak/sso/*.class + org/camunda/bpm/extension/keycloak/rest/*.class + org/camunda/bpm/extension/keycloak/rest/oauth2client/*.class + org/camunda/bpm/extension/keycloak/plugin/*.class + org/camunda/bpm/extension/hooks/controllers/mapper/*.class + org/camunda/bpm/extension/hooks/controllers/data/*.class + org/camunda/bpm/extension/hooks/listeners/data/*.class + org/camunda/bpm/extension/hooks/services/IUser.class + org/camunda/bpm/extension/hooks/delegates/data/*.class + org/camunda/bpm/extension/commons/io/socket/message/*.class + org/camunda/bpm/extension/commons/io/socket/*.class + org/camunda/bpm/extension/commons/connector/*.class + org/camunda/bpm/extension/CamundaApplication.class + + + + + + prepare-agent + report + + + + org.springframework.boot spring-boot-maven-plugin @@ -387,7 +369,7 @@ exec-maven-plugin 3.0.0 - org.camunda.bpm.extension.keycloak.showcase.CamundaApplication + org.camunda.bpm.extension.CamundaApplication @@ -406,8 +388,23 @@ org.apache.maven.plugins maven-surefire-plugin + 3.0.0-M5 + + + org.jacoco + jacoco-maven-plugin + 0.8.7 + target/jacoco-ut + + + + prepare-agent + report + + + diff --git a/forms-flow-bpm/sample.env b/forms-flow-bpm/sample.env index 8e309d2129..9e25fa66b2 100644 --- a/forms-flow-bpm/sample.env +++ b/forms-flow-bpm/sample.env @@ -56,4 +56,8 @@ FORMSFLOW_API_URL=http://{your-ip-address}:5000 WEBSOCKET_SECURITY_ORIGIN=http://{your-ip-address}:3000 ##Allowed Options: TASK_EVENT, TASK_EVENT_DETAILS. To send multiple seperate by comma. #WEBSOCKET_MESSAGE_TYPE=TASK_EVENT -#WEBSOCKET_ENCRYPT_KEY=giert989jkwrgb@DR55 \ No newline at end of file +#WEBSOCKET_ENCRYPT_KEY=giert989jkwrgb@DR55 + +#Camunda - General variable settings +#DATA_BUFFER_SIZE=2 +#IDENTITY_PROVIDER_MAX_RESULT_SIZE=250 diff --git a/forms-flow-bpm/src/.DS_Store b/forms-flow-bpm/src/.DS_Store deleted file mode 100644 index 041ea5d521cc68692260a0c6f4456d1ef8ec27ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKL2DC16n@jLb`lkH5bR0zA_!JUNVEqL))6;H_Xls0Eq55Y5_C=Kw{D8)Ui57 zv|X1Yvcx@S5rvMik*M7;Q6aWqSwC0b@&{_-7eO)3yTRzOZru-xLCE?8rINWGgb(BX zWV>?K4&iW&Aj-x&fdGaXEA~or%aTeti$2SHkYqGZ8Se;ImVrOOfc`$XSTuT! zr9t|1U`0;=L_HL6716i~eqsoIISAv9c8|xG28}xini=Ep z%z|Gif*&5jrQskvgSNH|SO%&LESqLS-~V^<4FBT&Uv;uA%YbFzzhXc*J-^q*CGp*Q zWO4egb+PPV(W1wd2FV30zK%)JSMe$q612HmLG&0)gV=*&e*}mITUiGFDg!?NK}?|e diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/CamundaApplication.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/CamundaApplication.java new file mode 100644 index 0000000000..f963be495e --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/CamundaApplication.java @@ -0,0 +1,96 @@ +package org.camunda.bpm.extension; + +import org.camunda.bpm.engine.AuthorizationService; +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.ProcessEngines; +import org.camunda.bpm.engine.authorization.Authorization; +import org.camunda.bpm.engine.authorization.Resource; +import org.camunda.bpm.engine.authorization.Resources; +import org.camunda.bpm.extension.commons.connector.AccessHandlerFactory; +import org.camunda.bpm.spring.boot.starter.annotation.EnableProcessApplication; +import org.camunda.bpm.spring.boot.starter.event.PostDeployEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.ServiceLocatorFactoryBean; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.event.EventListener; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.scheduling.annotation.EnableScheduling; + +import javax.sql.DataSource; +import java.util.Properties; + +import static org.camunda.bpm.engine.authorization.Permissions.ALL; +import static org.camunda.bpm.engine.authorization.Authorization.ANY; +import static org.camunda.bpm.engine.authorization.Authorization.AUTH_TYPE_GRANT; +import static org.camunda.bpm.engine.authorization.Authorization.AUTH_TYPE_GLOBAL; + +/** + * The Camunda Showcase Spring Boot application. + */ +@EnableConfigurationProperties +@PropertySource("classpath:application.yaml") +@SpringBootApplication(scanBasePackages = {"org.camunda.bpm.extension"}, exclude = ReactiveOAuth2ClientAutoConfiguration.class) +@EnableProcessApplication("camunda.showcase") +public class CamundaApplication { + + /** This class' logger. */ + private static final Logger LOG = LoggerFactory.getLogger(CamundaApplication.class); + + + /** + * Starts this application. + * @param args arguments + */ + public static void main(String... args) { + SpringApplication.run(CamundaApplication.class, args); + } + + /** + * Primary datasource. + * This is owned by Camunda. + * Note: Bean name should not be changed. + * @return + */ + @Bean(name="camundaBpmDataSource") + @ConfigurationProperties("spring.datasource") + @Primary + public DataSource camundaBpmDataSource(){ + return DataSourceBuilder.create().build(); + } + + + @Bean("bpmJdbcTemplate") + public NamedParameterJdbcTemplate bpmJdbcTemplate(@Qualifier("camundaBpmDataSource") DataSource camundaBpmDataSource) { + return new NamedParameterJdbcTemplate(camundaBpmDataSource); + } + + @Bean + @ConfigurationProperties(prefix = "spring.security.oauth2.client") + public Properties clientCredentialProperties() { + return new Properties(); + } + + @Bean + @ConfigurationProperties(prefix = "formsflow.ai") + public Properties integrationCredentialProperties() { + return new Properties(); + } + + @Bean("accessHandlerFactory") + public FactoryBean accessHandlerFactory() { + ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean(); + factoryBean.setServiceLocatorInterface(AccessHandlerFactory.class); + return factoryBean; + } +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandler.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandler.java index c3f6757828..a3b3d0921f 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandler.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandler.java @@ -1,14 +1,16 @@ package org.camunda.bpm.extension.commons.connector.support; +import com.google.gson.JsonObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; import org.springframework.http.*; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; -import java.util.Properties; -import java.util.logging.Logger; /** * This class serves as gateway for all application service interactions. @@ -18,21 +20,25 @@ @Service("applicationAccessHandler") public class ApplicationAccessHandler implements IAccessHandler { - private final Logger LOGGER = Logger.getLogger(ApplicationAccessHandler.class.getName()); + private final Logger LOGGER = LoggerFactory.getLogger(ApplicationAccessHandler.class); @Autowired - private OAuth2RestTemplate oAuth2RestTemplate; + private WebClient webClient; public ResponseEntity exchange(String url, HttpMethod method, String payload) { - //HTTP Headers - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.set("Authorization", "Bearer " + oAuth2RestTemplate.getAccessToken().getValue()); - HttpEntity reqObj = - new HttpEntity(payload, headers); - - ResponseEntity wrsp = oAuth2RestTemplate.exchange(url, method, reqObj, String.class); - LOGGER.info("Response code for service invocation: " + wrsp.getStatusCode()); - return wrsp; + + payload = (payload == null) ? new JsonObject().toString() : payload; + + Mono> entityMono = webClient.method(method).uri(url) + .attributes(clientRegistrationId("keycloak-client")) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .body(Mono.just(payload), String.class) + .retrieve() + .toEntity(String.class); + + ResponseEntity response = entityMono.block(); + return new ResponseEntity<>(response.getBody(), response.getStatusCode()); } + } diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandler.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandler.java index 2956214b14..4026172a3b 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandler.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandler.java @@ -1,23 +1,23 @@ package org.camunda.bpm.extension.commons.connector.support; +import com.google.gson.JsonObject; import org.apache.commons.lang3.StringUtils; import org.camunda.bpm.engine.ProcessEngines; import org.camunda.bpm.engine.repository.ProcessDefinition; +import org.camunda.bpm.extension.hooks.exceptions.FormioServiceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.HttpStatus; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; /** @@ -30,9 +30,16 @@ public class FormAccessHandler extends FormTokenAccessHandler implements IAccess private final Logger logger = LoggerFactory.getLogger(FormAccessHandler.class.getName()); + static final String TOKEN_NAME = "formio_access_token"; + static final String TOKEN_PROCESS_NAME = "formio-access-token"; + static final int TOKEN_EXPIRY_CODE = 404; + @Autowired private NamedParameterJdbcTemplate bpmJdbcTemplate; + @Autowired + private WebClient unauthenticatedWebClient; + public ResponseEntity exchange(String url, HttpMethod method, String payload) { String accessToken = getToken(); @@ -49,26 +56,42 @@ public ResponseEntity exchange(String url, HttpMethod method, String pay } public ResponseEntity exchange(String url, HttpMethod method, String payload, String accessToken) { - //HTTP Headers - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.set("x-jwt-token", accessToken); - HttpEntity reqObj = - new HttpEntity<>(payload, headers); + + payload = (payload == null) ? new JsonObject().toString() : payload; + if(HttpMethod.PATCH.name().equals(method.name())) { - HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); - RestTemplate restTemplate = new RestTemplate(requestFactory); - String response = restTemplate.patchForObject(getDecoratedServerUrl(url), reqObj, String.class); - if("Token Expired".equalsIgnoreCase(response)) { - return new ResponseEntity<>(response, HttpStatus.valueOf(TOKEN_EXPIRY_CODE)); + logger.info("payload="+payload); + Mono> entityMono = unauthenticatedWebClient.patch() + .uri(getDecoratedServerUrl(url)) + .bodyValue(payload) + .header("x-jwt-token", accessToken) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .retrieve() + .onStatus(HttpStatus::is4xxClientError, + response -> Mono.error(new FormioServiceException(response.toString()))) + .toEntity(String.class); + + ResponseEntity response = entityMono.block(); + if(response !=null && "Token Expired".equalsIgnoreCase(response.getBody())) { + return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(TOKEN_EXPIRY_CODE)); } - return new ResponseEntity<>(response, HttpStatus.OK); + return response; + } else { + return unauthenticatedWebClient.method(method) + .uri(getDecoratedServerUrl(url)) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .header("x-jwt-token", accessToken) + .body(Mono.just(payload), String.class) + .retrieve() + .onStatus(HttpStatus::is4xxClientError, + response -> Mono.error(new FormioServiceException(response.toString()))) + .toEntity(String.class) + .block(); } - return getRestTemplate().exchange(getDecoratedServerUrl(url), method, reqObj, String.class); } - - private String getDecoratedServerUrl(String url) { if(StringUtils.contains(url,"/form/")) { return getIntegrationCredentialProperties().getProperty("formio.url") + "/form/" + StringUtils.substringAfter(url, "/form/"); @@ -101,9 +124,4 @@ private String getTokenFromDBStore(String processDefinitionId) { parameters.addValue("processDefinitionId", processDefinitionId); return bpmJdbcTemplate.queryForObject(query,parameters, String.class); } - - static final String TOKEN_NAME = "formio_access_token"; - static final String TOKEN_PROCESS_NAME = "formio-access-token"; - static final int TOKEN_EXPIRY_CODE = 440; - -} \ No newline at end of file +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandler.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandler.java index 6c8edfc958..af7cd3d989 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandler.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandler.java @@ -1,33 +1,34 @@ package org.camunda.bpm.extension.commons.connector.support; -import com.fasterxml.jackson.databind.ObjectMapper; import org.camunda.bpm.extension.hooks.exceptions.FormioServiceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; -import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; -import java.util.logging.Logger; + /** * This class abstracts formio token generation logic with the intent to cached & refreshed accordingly. * @author sumathi.thirumani@aot-technologies.com + * @author shibin.thoma@aot-technologies.com */ @Service("formTokenAccessHandler") public class FormTokenAccessHandler { - private final Logger LOGGER = Logger.getLogger(FormTokenAccessHandler.class.getName()); + private final Logger LOGGER = LoggerFactory.getLogger(FormTokenAccessHandler.class); @Autowired private Properties integrationCredentialProperties; - protected RestTemplate getRestTemplate() { - return new RestTemplate(); - } + @Autowired + private WebClient unauthenticatedWebClient; public String getAccessToken(){ Map paramMap = new HashMap<>(); @@ -35,18 +36,25 @@ public String getAccessToken(){ paramMap.put("password",getIntegrationCredentialProperties().getProperty("formio.security.password")); HashMap dataMap = new HashMap<>(); dataMap.put("data", paramMap); - try { - //HTTP Headers - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity reqObj = - new HttpEntity(new ObjectMapper().writeValueAsString(dataMap), headers); - ResponseEntity response = getRestTemplate().exchange(getIntegrationCredentialProperties().getProperty("formio.security.accessTokenUri"), HttpMethod.POST, reqObj, String.class); - return response.getHeaders().get("x-jwt-token").get(0); - } catch (IOException e) { - throw new FormioServiceException("Exception occurred in getting x-jwt-token"+ ". Message Body: " + - e.getMessage()); - } + + String token = unauthenticatedWebClient.post().uri(getIntegrationCredentialProperties().getProperty("formio.security.accessTokenUri")) + .bodyValue(dataMap) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .exchangeToMono(data -> { + if(data.statusCode().is2xxSuccessful()){ + return Mono.just(data.headers().header("x-jwt-token").get(0)); + } else{ + return Mono.error(new FormioServiceException("Exception occurred in getting x-jwt-token"+ ". Message Body: " + + data)); + } + }) + .log() + .block(); + + LOGGER.debug("Fetched the x-jwt-token = "+token); + + return token; } protected Properties getIntegrationCredentialProperties() { @@ -55,3 +63,4 @@ protected Properties getIntegrationCredentialProperties() { } + diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListener.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListener.java index 259c4b2453..55f8d5e195 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListener.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListener.java @@ -40,7 +40,6 @@ public class CamundaEventListener { private String messageEvents; - @EventListener public void onTaskEventListener(DelegateTask taskDelegate) { try { @@ -89,7 +88,8 @@ private List getRegisteredEvents() { if ("DEFAULT".equalsIgnoreCase(messageEvents)) { return getDefaultRegisteredEvents(); } - return Arrays.asList(StringUtils.split(messageEvents,",")); + String events = messageEvents != null?messageEvents: ""; + return Arrays.asList(StringUtils.split(events,",")); } private Map getVariables(DelegateTask taskDelegate) { diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/AdminController.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/AdminController.java index 57d7ffcbbc..fcaed8c235 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/AdminController.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/AdminController.java @@ -4,6 +4,9 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.nimbusds.oauth2.sdk.util.CollectionUtils; +import lombok.Data; +import lombok.NoArgsConstructor; +import net.minidev.json.JSONArray; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; @@ -21,7 +24,9 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -29,6 +34,9 @@ import org.camunda.bpm.engine.authorization.ProcessDefinitionPermissions; import org.camunda.bpm.engine.authorization.Resources; +import javax.servlet.ServletException; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -56,7 +64,7 @@ public class AdminController { private String adminGroupName; @RequestMapping(value = "/engine-rest-ext/form", method = RequestMethod.GET, produces = "application/json") - private @ResponseBody List getForms() { + private @ResponseBody List getForms() throws ServletException { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); List groups = getGroups(authentication); List authorizationList = getAuthorization(groups); @@ -82,7 +90,7 @@ public class AdminController { } if(CollectionUtils.isNotEmpty(groups) && groups.contains(adminGroupName)) { for(AuthorizedAction formObj : formList) { - if(isExists(filteredList, formObj.getFormId()) == false) { + if(!isExists(filteredList, formObj.getFormId())) { filteredList.add(formObj); } @@ -90,7 +98,7 @@ public class AdminController { } else { for (Authorization authObj : authorizationList) { for (AuthorizedAction formObj : formList) { - if (authObj.getResourceId().equals(formObj.getProcessKey()) && isExists(filteredList, formObj.getFormId()) == false) { + if (authObj.getResourceId().equals(formObj.getProcessKey()) && !isExists(filteredList, formObj.getFormId())) { filteredList.add(formObj); } } @@ -125,27 +133,30 @@ private boolean isExists(List filteredList, String formId) { * @param authentication * @return */ - private List getGroups(Authentication authentication) { - OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails(); - String accessToken = details.getTokenValue(); - String claims = JwtHelper.decode(accessToken).getClaims(); - List groups = new ArrayList<>(); - ObjectMapper mapper = new ObjectMapper(); - try { - JsonNode dataNode = mapper.readTree(claims); - for (final JsonNode objNode : dataNode.get("groups")) { - System.out.println(objNode); - String groupName = StringEscapeUtils.unescapeJava(objNode.asText()); + private List getGroups(Authentication authentication) throws ServletException { + + Map claims; + if (authentication instanceof JwtAuthenticationToken) { + claims = ((JwtAuthenticationToken)authentication).getToken().getClaims(); + } else if (authentication.getPrincipal() instanceof OidcUser) { + claims = ((OidcUser)authentication.getPrincipal()).getClaims(); + } else { + throw new ServletException("Invalid authentication request token"); + } + + List groupIds = new ArrayList<>(); + if(claims != null && claims.containsKey("groups")) { + JSONArray groups = (JSONArray)claims.get("groups"); + for (Object group1 : groups) { + String groupName = group1.toString(); if(StringUtils.startsWith(groupName,"/")) { - groups.add(StringUtils.substring(groupName,1)); + groupIds.add(StringUtils.substring(groupName,1)); } else { - groups.add(groupName); + groupIds.add(groupName); } } - } catch (JsonProcessingException e) { - e.printStackTrace(); } - return groups; + return groupIds; } /** diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/TaskController.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/TaskController.java index 8571c71308..0d1a1b6388 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/TaskController.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/TaskController.java @@ -1,21 +1,27 @@ package org.camunda.bpm.extension.hooks.controllers; import com.nimbusds.oauth2.sdk.util.CollectionUtils; -import lombok.Data; +import net.minidev.json.JSONArray; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; -import org.camunda.bpm.engine.rest.dto.task.TaskDto; +import org.camunda.bpm.extension.hooks.controllers.data.Task; +import org.camunda.bpm.extension.hooks.controllers.data.Variable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.security.core.Authentication; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; +import javax.servlet.ServletException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -37,8 +43,9 @@ public class TaskController { private NamedParameterJdbcTemplate bpmJdbcTemplate; @RequestMapping(value = "/engine-rest-ext/task", method = RequestMethod.GET, produces = "application/json") - private @ResponseBody List getTasks(@AuthenticationPrincipal Jwt principal) { - List groups = getGroups(principal); + private @ResponseBody List getTasks() throws ServletException { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + List groups = getGroups(authentication); Map taskMap = new HashMap<>(); MapSqlParameterSource parameters = new MapSqlParameterSource(); parameters.addValue("groups", groups); @@ -69,8 +76,10 @@ public class TaskController { @RequestMapping(value = "/engine-rest-ext/task/{taskid}", method = RequestMethod.GET, produces = "application/json") - private @ResponseBody Task getTask(@PathVariable("taskid") String taskid,@AuthenticationPrincipal Jwt principal) { - List groups = getGroups(principal); + private @ResponseBody Task getTask(@PathVariable("taskid") String taskid) throws ServletException { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + List groups = getGroups(authentication); MapSqlParameterSource parameters = new MapSqlParameterSource(); parameters.addValue("groups", groups); parameters.addValue("taskid", taskid); @@ -94,42 +103,29 @@ public class TaskController { return task; } - private List getGroups(Jwt principal) { - List rawgroups = principal.getClaim("groups"); - List groups = new ArrayList<>(); - if(CollectionUtils.isNotEmpty(rawgroups)) { - for(String entry: rawgroups) { - String groupName = StringEscapeUtils.unescapeJava(entry); + private List getGroups(Authentication authentication) throws ServletException { + + Map claims; + if (authentication instanceof JwtAuthenticationToken) { + claims = ((JwtAuthenticationToken)authentication).getToken().getClaims(); + } else if (authentication.getPrincipal() instanceof OidcUser) { + claims = ((OidcUser)authentication.getPrincipal()).getClaims(); + } else { + throw new ServletException("Invalid authentication request token"); + } + List groupIds = new ArrayList<>(); + if(claims != null && claims.containsKey("groups")) { + JSONArray groups = (JSONArray)claims.get("groups"); + for (Object group1 : groups) { + String groupName = group1.toString(); if(StringUtils.startsWith(groupName,"/")) { - groups.add(StringUtils.substring(groupName,1)); + groupIds.add(StringUtils.substring(groupName,1)); } else { - groups.add(groupName); + groupIds.add(groupName); } - } } - return groups; - } - - @Data - class Task extends TaskDto { - private String processInstanceId; - private String processDefinitionKey; - private String taskDefinitionKey; - private String groupName; - private String status; - private List variables; - } - - @Data - class Variable { - private String name; - private String value; - - Variable(String name, String value) { - this.name = name; - this.value = value; - } + return groupIds; } enum TaskQuery { diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Authorization.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Authorization.java index 558bf240bd..b0b27a0dca 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Authorization.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Authorization.java @@ -1,13 +1,15 @@ package org.camunda.bpm.extension.hooks.controllers.data; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * Mapper associated with querying authorization. */ -@NoArgsConstructor @Data +@NoArgsConstructor +@AllArgsConstructor public class Authorization { private String groupId; private String userId; diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Task.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Task.java new file mode 100644 index 0000000000..80502c84fc --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Task.java @@ -0,0 +1,16 @@ +package org.camunda.bpm.extension.hooks.controllers.data; + +import lombok.Data; +import org.camunda.bpm.engine.rest.dto.task.TaskDto; + +import java.util.List; + +@Data +public class Task extends TaskDto { + private String processInstanceId; + private String processDefinitionKey; + private String taskDefinitionKey; + private String groupName; + private String status; + private List variables; +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Variable.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Variable.java new file mode 100644 index 0000000000..bc1c48c66d --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/data/Variable.java @@ -0,0 +1,13 @@ +package org.camunda.bpm.extension.hooks.controllers.data; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Variable { + private String name; + private String value; +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/mapper/TaskResultSetExtractor.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/mapper/TaskResultSetExtractor.java new file mode 100644 index 0000000000..52684bfbf6 --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/controllers/mapper/TaskResultSetExtractor.java @@ -0,0 +1,45 @@ +package org.camunda.bpm.extension.hooks.controllers.mapper; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.camunda.bpm.extension.hooks.controllers.data.Task; +import org.camunda.bpm.extension.hooks.controllers.data.Variable; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.ResultSetExtractor; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Data +@NoArgsConstructor +public class TaskResultSetExtractor implements ResultSetExtractor { + + private Map taskMap; + + @Override + public Task extractData(ResultSet rs) throws SQLException, DataAccessException { + String taskId = rs.getString("taskid"); + Task task = null; + if(!taskMap.containsKey(taskId)) { + taskMap.put(rs.getString("taskid"), new Task()); + task = taskMap.get(taskId); + task.setId(rs.getString("taskid")); + task.setName(rs.getString("taskname")); + task.setAssignee(rs.getString("assignee")); + task.setStatus(rs.getString("status")); + task.setProcessInstanceId(rs.getString("pid")); + task.setProcessDefinitionKey(rs.getString("processdefkey")); + task.setTaskDefinitionKey(rs.getString("taskDefinitionKey")); + task.setGroupName(rs.getString("groupname")); + List variables = new ArrayList<>(); + task.setVariables(variables); + } else { + task = taskMap.get(taskId); + } + task.getVariables().add(new Variable(rs.getString("variablename"), rs.getString("variablevalue"))); + return task; + } +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegate.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegate.java index cce8f81d60..0c220406ea 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegate.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegate.java @@ -8,6 +8,8 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.camunda.bpm.engine.delegate.JavaDelegate; import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.camunda.bpm.extension.hooks.delegates.data.TextSentimentData; +import org.camunda.bpm.extension.hooks.delegates.data.TextSentimentRequest; import org.camunda.bpm.extension.hooks.services.FormSubmissionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; @@ -48,18 +50,18 @@ public void execute(DelegateExecution execution) throws Exception { private TextSentimentRequest prepareRequest(DelegateExecution execution) throws JsonProcessingException { List txtRecords = new ArrayList<>(); - String submission = formSubmissionService.readSubmission(String.valueOf(execution.getVariables().get("formUrl"))); - if(submission.isEmpty()) { - throw new RuntimeException("Unable to retrieve submission"); + String submission = formSubmissionService.readSubmission(String.valueOf(execution.getVariables().get("formUrl"))); + if(submission.isEmpty()) { + throw new RuntimeException("Unable to retrieve submission"); + } + JsonNode dataNode = getObjectMapper().readTree(submission); + Iterator> dataElements = dataNode.findPath("data").fields(); + while (dataElements.hasNext()) { + Map.Entry entry = dataElements.next(); + if(entry.getValue().has("type") && getSentimentCategory().equals(entry.getValue().get("type").asText())) { + txtRecords.add(CreateTextSentimentData(entry.getKey(), + getObjectMapper().readValue(entry.getValue().get("topics").toString(), List.class), entry.getValue().get("text").asText())); } - JsonNode dataNode = getObjectMapper().readTree(submission); - Iterator> dataElements = dataNode.findPath("data").fields(); - while (dataElements.hasNext()) { - Map.Entry entry = dataElements.next(); - if(entry.getValue().has("type") && getSentimentCategory().equals(entry.getValue().get("type").asText())) { - txtRecords.add(CreateTextSentimentData(entry.getKey(), - getObjectMapper().readValue(entry.getValue().get("topics").toString(), List.class), entry.getValue().get("text").asText())); - } } if(CollectionUtils.isNotEmpty(txtRecords)) { return CreateTextSentimentRequest((Integer) execution.getVariable("applicationId"), @@ -90,25 +92,6 @@ private String getSentimentCategory() { } -@Scope("prototype") -@Data -@NoArgsConstructor -@AllArgsConstructor -class TextSentimentRequest{ - private Integer applicationId; - private String formUrl; - private List data; -} - -@Scope("prototype") -@Data -@NoArgsConstructor -@AllArgsConstructor -class TextSentimentData{ - private String elementId; - private List topics; - private String text; -} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentData.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentData.java new file mode 100644 index 0000000000..602ed1865b --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentData.java @@ -0,0 +1,16 @@ +package org.camunda.bpm.extension.hooks.delegates.data; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TextSentimentData{ + private String elementId; + private List topics; + private String text; +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentRequest.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentRequest.java new file mode 100644 index 0000000000..7b16888969 --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/delegates/data/TextSentimentRequest.java @@ -0,0 +1,16 @@ +package org.camunda.bpm.extension.hooks.delegates.data; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TextSentimentRequest{ + private Integer applicationId; + private String formUrl; + private List data; +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListener.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListener.java index c67d7aef42..f3caf0b917 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListener.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListener.java @@ -39,7 +39,6 @@ public void notify(DelegateExecution execution) { } catch (IOException e) { handleException(execution, ExceptionSource.EXECUTION, e); } - } @Override diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListener.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListener.java index ccfc5409c5..6538bff02f 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListener.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListener.java @@ -37,7 +37,7 @@ @Named("BPMFormDataPipelineListener") public class BPMFormDataPipelineListener extends BaseListener implements TaskListener, ExecutionListener { - private static final Logger LOGGER = Logger.getLogger(BPMFormDataPipelineListener.class.getName()); + private Logger LOGGER = Logger.getLogger(BPMFormDataPipelineListener.class.getName()); private Expression fields; diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListener.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListener.java index 35e0f18b07..14173e0918 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListener.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListener.java @@ -52,7 +52,4 @@ private void createRevision(DelegateExecution execution) throws IOException { private String getUrl(DelegateExecution execution){ return StringUtils.substringBeforeLast(String.valueOf(execution.getVariables().get("formUrl")),"/"); } - - - } diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListener.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListener.java index 4e1af9a596..efe93320e2 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListener.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListener.java @@ -28,7 +28,11 @@ public void notify(DelegateExecution execution) { String groupName = String.valueOf(execution.getVariable("groupName")); List emailgroup = getEmailsForGroup(execution,groupName); if(CollectionUtils.isNotEmpty(emailgroup)) { - emailto = emailto.concat(",").concat(String.join(",",emailgroup)); + if(emailto.length() > 0) { + emailto = emailto.concat(",").concat(String.join(",", emailgroup)); + } else { + emailto = String.join(",", emailgroup); + } } tranformEmailContent(execution,dmnMap); execution.setVariable("email_cc", getAddressValue(execution,dmnMap,"cc")); diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListener.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListener.java index 241721c1f9..5043a707de 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListener.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListener.java @@ -86,7 +86,7 @@ private void createApplication(DelegateExecution execution, boolean retryOnce) t execution.setVariable("applicationId", applicationId); } else { if(retryOnce) { - LOGGER.error("Retrying the application create once more due to previous failure"); + LOGGER.warn("Retrying the application create once more due to previous failure"); createApplication(execution, false); } else { throw new ApplicationServiceException("Unable to create application " + ". Message Body: " + diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListener.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListener.java index 7063236270..166857f111 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListener.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListener.java @@ -14,10 +14,7 @@ import org.springframework.stereotype.Component; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.logging.Logger; /** @@ -43,7 +40,7 @@ public class NotifyListener extends BaseListener implements TaskListener, IMessa * @param delegateTask: The task which sends the message */ public void notify(DelegateTask delegateTask) { - List toEmails = new ArrayList<>(); + Set toEmails = new HashSet<>(); if(!"Y".equals(getGroupsOnly(delegateTask.getExecution()))) { toEmails.addAll(getEmailsOfUnassignedTask(delegateTask)); } @@ -59,9 +56,6 @@ public void notify(DelegateTask delegateTask) { } } sendEmailNotification(delegateTask, toEmails ,delegateTask.getId()); - - - } /** @@ -70,7 +64,7 @@ public void notify(DelegateTask delegateTask) { * @param toEmails * @param taskId */ - private void sendEmailNotification(DelegateTask delegateTask,List toEmails,String taskId) { + private void sendEmailNotification(DelegateTask delegateTask,Set toEmails,String taskId) { String toAddress = CollectionUtils.isNotEmpty(toEmails) ? StringUtils.join(toEmails,",") : null; if(StringUtils.isNotEmpty(toAddress)) { Map emailAttributes = new HashMap<>(); diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/services/FormSubmissionService.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/services/FormSubmissionService.java index 06a8f5c758..76e23001fe 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/services/FormSubmissionService.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/hooks/services/FormSubmissionService.java @@ -53,42 +53,41 @@ public String createRevision(String formUrl) throws IOException { return null; } ObjectMapper objectMapper = new ObjectMapper(); - ResponseEntity response = httpServiceInvoker.execute(getSubmissionUrl(formUrl), HttpMethod.POST, submission); - if(response.getStatusCode().value() == HttpStatus.CREATED.value()) { - JsonNode jsonNode = objectMapper.readTree(response.getBody()); - String submissionId = jsonNode.get("_id").asText(); - return submissionId; - } else { - throw new FormioServiceException("Unable to create revision for: "+ formUrl+ ". Message Body: " + - response.getBody()); - } + ResponseEntity response = httpServiceInvoker.execute(getSubmissionUrl(formUrl), HttpMethod.POST, submission); + if(response.getStatusCode().value() == HttpStatus.CREATED.value()) { + JsonNode jsonNode = objectMapper.readTree(response.getBody()); + String submissionId = jsonNode.get("_id").asText(); + return submissionId; + } else { + throw new FormioServiceException("Unable to create revision for: "+ formUrl+ ". Message Body: " + + response.getBody()); + } } public String createSubmission(String formUrl, String submission) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); - ResponseEntity response = httpServiceInvoker.execute(getSubmissionUrl(formUrl), HttpMethod.POST, submission); - if(response.getStatusCode().value() == HttpStatus.CREATED.value()) { - JsonNode jsonNode = objectMapper.readTree(response.getBody()); - String submissionId = jsonNode.get("_id").asText(); - return submissionId; - } else { - throw new FormioServiceException("Unable to create submission for: "+ formUrl+ ". Message Body: " + - response.getBody()); - } + ResponseEntity response = httpServiceInvoker.execute(getSubmissionUrl(formUrl), HttpMethod.POST, submission); + if(response.getStatusCode().value() == HttpStatus.CREATED.value()) { + JsonNode jsonNode = objectMapper.readTree(response.getBody()); + String submissionId = jsonNode.get("_id").asText(); + return submissionId; + } else { + throw new FormioServiceException("Unable to create submission for: "+ formUrl+ ". Message Body: " + + response.getBody()); + } } public String getFormIdByName(String formUrl) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); - ResponseEntity response = httpServiceInvoker.execute(formUrl, HttpMethod.GET, null); - if(response.getStatusCode().value() == HttpStatus.OK.value()) { - JsonNode jsonNode = objectMapper.readTree(response.getBody()); - String formId = jsonNode.get("_id").asText(); - return formId; - } else { - throw new FormioServiceException("Unable to get name for: "+ formUrl+ ". Message Body: " + - response.getBody()); - } - + ResponseEntity response = httpServiceInvoker.execute(formUrl, HttpMethod.GET, null); + if(response.getStatusCode().value() == HttpStatus.OK.value()) { + JsonNode jsonNode = objectMapper.readTree(response.getBody()); + String formId = jsonNode.get("_id").asText(); + return formId; + } else { + throw new FormioServiceException("Unable to get name for: "+ formUrl+ ". Message Body: " + + response.getBody()); + } } private String getSubmissionUrl(String formUrl){ @@ -102,31 +101,31 @@ public Map retrieveFormValues(String formUrl) throws IOException Map fieldValues = new HashMap(); String submission = readSubmission(formUrl); if(StringUtils.isNotEmpty(submission)) { - JsonNode dataNode = getObjectMapper().readTree(submission); - Iterator> dataElements = dataNode.findPath("data").fields(); - while (dataElements.hasNext()) { - Map.Entry entry = dataElements.next(); - if(StringUtils.endsWithIgnoreCase(entry.getKey(),"_file")) { - List fileNames = new ArrayList(); - if(entry.getValue().isArray()) { - for (JsonNode fileNode : entry.getValue()) { - byte[] bytes = Base64.getDecoder().decode(StringUtils.substringAfterLast(fileNode.get("url").asText(), "base64,")); - FileValue fileValue = Variables.fileValue(fileNode.get("originalName").asText()) - .file(bytes) - .mimeType(fileNode.get("type").asText()) - .create(); - fileNames.add(fileNode.get("originalName").asText()); - fieldValues.put(StringUtils.substringBeforeLast(fileNode.get("originalName").asText(),".")+entry.getKey(), fileValue); - if(fileNames.size() > 0) { - fieldValues.put(entry.getKey()+"_uploadname", StringUtils.join(fileNames, ",")); + JsonNode dataNode = getObjectMapper().readTree(submission); + Iterator> dataElements = dataNode.findPath("data").fields(); + while (dataElements.hasNext()) { + Map.Entry entry = dataElements.next(); + if(StringUtils.endsWithIgnoreCase(entry.getKey(),"_file")) { + List fileNames = new ArrayList(); + if(entry.getValue().isArray()) { + for (JsonNode fileNode : entry.getValue()) { + byte[] bytes = Base64.getDecoder().decode(StringUtils.substringAfterLast(fileNode.get("url").asText(), "base64,")); + FileValue fileValue = Variables.fileValue(fileNode.get("originalName").asText()) + .file(bytes) + .mimeType(fileNode.get("type").asText()) + .create(); + fileNames.add(fileNode.get("originalName").asText()); + fieldValues.put(StringUtils.substringBeforeLast(fileNode.get("originalName").asText(),".")+entry.getKey(), fileValue); + if(fileNames.size() > 0) { + fieldValues.put(entry.getKey()+"_uploadname", StringUtils.join(fileNames, ",")); + } } } + } else{ + fieldValues.put(entry.getKey(), convertToOriginType(entry.getValue())); } - } else{ - fieldValues.put(entry.getKey(), convertToOriginType(entry.getValue())); } } - } return fieldValues; } @@ -160,9 +159,9 @@ private Object convertToOriginType(JsonNode value) throws IOException { } public String createFormSubmissionData(Map bpmVariables) throws IOException { - Map> data = new HashMap<>(); - data.put("data",bpmVariables); - return getObjectMapper().writeValueAsString(data); + Map> data = new HashMap<>(); + data.put("data",bpmVariables); + return getObjectMapper().writeValueAsString(data); } diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/ProcessConstants.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/ProcessConstants.java similarity index 75% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/ProcessConstants.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/ProcessConstants.java index a0ae3c4d2b..c58749f463 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/ProcessConstants.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/ProcessConstants.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase; +package org.camunda.bpm.extension.keycloak; public interface ProcessConstants { diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/plugin/KeycloakIdentityProvider.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakIdentityProvider.java similarity index 85% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/plugin/KeycloakIdentityProvider.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakIdentityProvider.java index a188bbde4e..a1e23ff0b5 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/plugin/KeycloakIdentityProvider.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/plugin/KeycloakIdentityProvider.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.plugin; +package org.camunda.bpm.extension.keycloak.plugin; import org.camunda.bpm.extension.keycloak.plugin.KeycloakIdentityProviderPlugin; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/AudienceValidator.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/AudienceValidator.java new file mode 100644 index 0000000000..b0bf77acf6 --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/AudienceValidator.java @@ -0,0 +1,34 @@ +package org.camunda.bpm.extension.keycloak.rest; + +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.OAuth2TokenValidator; +import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; +import org.springframework.security.oauth2.jwt.Jwt; +/** + * Token validator for audience claims. + */ +public class AudienceValidator implements OAuth2TokenValidator { + + /** The required audience. */ + private final String audience; + + /** + * Creates a new audience validator + * @param audience the required audience + */ + public AudienceValidator(String audience) { + this.audience = audience; + } + + /** + * {@inheritDoc} + */ + @Override + public OAuth2TokenValidatorResult validate(Jwt jwt) { + if (jwt.getAudience().contains(audience)) { + return OAuth2TokenValidatorResult.success(); + } + return OAuth2TokenValidatorResult.failure( + new OAuth2Error("invalid_token", "The required audience is missing", null)); + } +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/KeycloakAuthenticationConverter.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationConverter.java similarity index 97% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/KeycloakAuthenticationConverter.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationConverter.java index 6be2e3a8ed..7bda4f1ccf 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/KeycloakAuthenticationConverter.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationConverter.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.rest; +package org.camunda.bpm.extension.keycloak.rest; import java.util.Arrays; import java.util.Collection; diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java new file mode 100644 index 0000000000..e96a3b9249 --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilter.java @@ -0,0 +1,100 @@ +package org.camunda.bpm.extension.keycloak.rest; + + +import net.minidev.json.JSONArray; +import org.apache.commons.lang3.StringUtils; +import org.camunda.bpm.engine.IdentityService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; + +import javax.servlet.*; +import java.io.IOException; +import java.util.*; + +/** + * Keycloak Authentication Filter - used for REST API Security. + */ +public class KeycloakAuthenticationFilter implements Filter { + + /** This class' logger. */ + private static final Logger LOG = LoggerFactory.getLogger(KeycloakAuthenticationFilter.class); + + /** Access to Camunda's IdentityService. */ + private IdentityService identityService; + + /** Access to the OAuth2 client service. */ + private OAuth2AuthorizedClientService clientService; + + /** + * Creates a new KeycloakAuthenticationFilter. + * @param identityService access to Camunda's IdentityService + */ + public KeycloakAuthenticationFilter(IdentityService identityService, OAuth2AuthorizedClientService clientService) { + this.identityService = identityService; + this.clientService = clientService; + } + + /** + * {@inheritDoc} + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + // Extract user-name-attribute of the JWT / OAuth2 token + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String userId = null; + Map claims; + if (authentication instanceof JwtAuthenticationToken) { + userId = ((JwtAuthenticationToken)authentication).getName(); + claims = ((JwtAuthenticationToken)authentication).getToken().getClaims(); + } else if (authentication.getPrincipal() instanceof OidcUser) { + userId = ((OidcUser)authentication.getPrincipal()).getName(); + claims = ((OidcUser)authentication.getPrincipal()).getClaims(); + } else { + throw new ServletException("Invalid authentication request token"); + } + if (StringUtils.isEmpty(userId)) { + throw new ServletException("Unable to extract user-name-attribute from token"); + } + + LOG.debug("Extracted userId from bearer token: {}", userId); + + try { + identityService.setAuthentication(userId, getUserGroups(userId, claims)); + chain.doFilter(request, response); + } finally { + identityService.clearAuthentication(); + } + } + + + /** + * Retrieves groups for given userId + * @param userId + * @param claims + * @return + */ + private List getUserGroups(String userId, Map claims){ + List groupIds = new ArrayList<>(); + if(claims != null && claims.containsKey("groups")) { + JSONArray groups = (JSONArray)claims.get("groups"); + for (Object group1 : groups) { + String group = group1.toString(); + String groupName = StringUtils.contains(group, "/") ? StringUtils.substringAfter(group, "/") : group; + groupIds.add(groupName); + } + } else { + identityService.createGroupQuery().groupMember(userId).list() + .forEach( g -> groupIds.add(g.getId())); + } + return groupIds; + } + + +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/RestApiSecurityConfig.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfig.java similarity index 52% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/RestApiSecurityConfig.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfig.java index 059d3b6bc1..0962fa5e45 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/RestApiSecurityConfig.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfig.java @@ -1,39 +1,36 @@ -package org.camunda.bpm.extension.keycloak.showcase.rest; +package org.camunda.bpm.extension.keycloak.rest; import org.camunda.bpm.engine.IdentityService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; -import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; -import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore; +import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; +import org.springframework.security.oauth2.core.OAuth2TokenValidator; +import org.springframework.security.oauth2.jwt.*; import javax.inject.Inject; import javax.ws.rs.HttpMethod; import java.util.Properties; + /** * Optional Security Configuration for Camunda REST Api. */ @Configuration -@EnableResourceServer @EnableWebSecurity @Order(SecurityProperties.BASIC_AUTH_ORDER - 20) @ConditionalOnProperty(name = "rest.security.enabled", havingValue = "true", matchIfMissing = true) -public class RestApiSecurityConfig extends ResourceServerConfigurerAdapter { +public class RestApiSecurityConfig extends WebSecurityConfigurerAdapter { /** Configuration for REST Api security. */ @Inject @@ -43,8 +40,12 @@ public class RestApiSecurityConfig extends ResourceServerConfigurerAdapter { @Inject private IdentityService identityService; - @Autowired - private Properties clientCredentialProperties; + @Inject + private ApplicationContext applicationContext; + + /** Access to Spring Security OAuth2 client service. */ + @Inject + private OAuth2AuthorizedClientService clientService; /** * {@inheritDoc} @@ -52,43 +53,45 @@ public class RestApiSecurityConfig extends ResourceServerConfigurerAdapter { @Override public void configure(final HttpSecurity http) throws Exception { + String jwkSetUri = applicationContext.getEnvironment().getRequiredProperty( + "spring.security.oauth2.client.provider." + configProps.getProvider() + ".jwk-set-uri"); + http.requestMatchers().antMatchers("/engine-rest/**","/engine-rest-ext/**","/forms-flow-bpm-socket/**", "/actuator/**"). and().authorizeRequests().antMatchers(HttpMethod.OPTIONS,"/engine-rest/**").permitAll() .and().authorizeRequests().antMatchers(HttpMethod.OPTIONS,"/engine-rest-ext/**").permitAll() .and().authorizeRequests().antMatchers(HttpMethod.OPTIONS,"/forms-flow-bpm-socket/**").permitAll() .antMatchers("/engine-rest/**","/engine-rest-ext/**") .authenticated().and().csrf().disable() - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .oauth2ResourceServer() + .jwt() + .jwkSetUri(jwkSetUri); } - /** - * {@inheritDoc} - */ - @Override - public void configure(final ResourceServerSecurityConfigurer config) { - config - .tokenServices(tokenServices()) - .resourceId(configProps.getRequiredAudience()); - } /** - * Configures the JWKS bases TokenStore. + * Create a JWT decoder with issuer and audience claim validation. + * @return the JWT decoder */ @Bean - public TokenStore tokenStore() { - return new JwkTokenStore(configProps.getJwkSetUrl()); - } + public JwtDecoder jwtDecoder() { + String issuerUri = applicationContext.getEnvironment().getRequiredProperty( + "spring.security.oauth2.client.provider." + configProps.getProvider() + ".issuer-uri"); - /** - * Creates JWKS based TokenServices. - * @return DefaultTokenServices - */ - public ResourceServerTokenServices tokenServices() { - DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); - defaultTokenServices.setTokenStore(tokenStore()); - return defaultTokenServices; + NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) + JwtDecoders.fromOidcIssuerLocation(issuerUri); + + OAuth2TokenValidator audienceValidator = new AudienceValidator(configProps.getRequiredAudience()); + OAuth2TokenValidator withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri); + OAuth2TokenValidator withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator); + + jwtDecoder.setJwtValidator(withAudience); + + return jwtDecoder; } + /** * Registers the REST Api Keycloak Authentication Filter. * @return filter registration @@ -97,20 +100,9 @@ public ResourceServerTokenServices tokenServices() { @Bean public FilterRegistrationBean keycloakAuthenticationFilter(){ FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); - filterRegistration.setFilter(new KeycloakAuthenticationFilter(identityService)); + filterRegistration.setFilter(new KeycloakAuthenticationFilter(identityService, clientService)); filterRegistration.setOrder(102); // make sure the filter is registered after the Spring Security Filter Chain - filterRegistration.addUrlPatterns("/engine-rest/*","/engine-rest-ext/*"); + filterRegistration.addUrlPatterns("/engine-rest/*"); return filterRegistration; } - - @Bean - public OAuth2RestTemplate getOAuth2RestTemplate() { - ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails (); - resourceDetails.setClientId(clientCredentialProperties.getProperty("client-id")); - resourceDetails.setClientSecret(clientCredentialProperties.getProperty("client-secret")); - resourceDetails.setAccessTokenUri(clientCredentialProperties.getProperty("accessTokenUri")); - resourceDetails.setGrantType("client_credentials"); - return new OAuth2RestTemplate(resourceDetails); - } - } diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigurationProperties.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigurationProperties.java new file mode 100644 index 0000000000..df4b5822ba --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigurationProperties.java @@ -0,0 +1,44 @@ +package org.camunda.bpm.extension.keycloak.rest; + +import javax.validation.constraints.NotEmpty; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; +import org.springframework.validation.annotation.Validated; + +/** + * Complete Security Configuration Properties for Camunda REST Api. + */ +@Data +@Component +@Validated +@NoArgsConstructor +@ConfigurationProperties(prefix = "rest.security") +public class RestApiSecurityConfigurationProperties { + + /** + * rest.security.enabled: + * + * Rest Security is enabled by default. Switch off by setting this flag to {@code false}. + */ + @SuppressWarnings("unused") + private Boolean enabled = true; + + /** + * rest.security.provider: + * + * Client provider eg : Keycloak. + */ + @NotEmpty + private String provider; + + /** + * rest.security.required-audience: + * + * Required Audience. + */ + @NotEmpty + private String requiredAudience; +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/client/WebClientOauth2Config.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/client/WebClientOauth2Config.java new file mode 100644 index 0000000000..64027793c7 --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/rest/client/WebClientOauth2Config.java @@ -0,0 +1,86 @@ +package org.camunda.bpm.extension.keycloak.rest.client; + +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ClientHttpConnector; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; +import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.http.client.HttpClient; + +import java.time.Duration; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + + +/** + * Created by shibin.thomas on 21-09-2021. + */ +@Configuration +public class WebClientOauth2Config { + + private static final Logger LOGGER = LoggerFactory.getLogger(WebClientOauth2Config.class); + + @Autowired + private Properties integrationCredentialProperties; + + public ClientHttpConnector clientHttpConnector(){ + + int connectionTimeout = Integer.parseInt(integrationCredentialProperties.getProperty("camunda.spring.webclient.connectionTimeout")); + + HttpClient httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionTimeout) + .responseTimeout(Duration.ofMillis(connectionTimeout)) + .doOnConnected(conn -> + conn.addHandlerLast(new ReadTimeoutHandler(connectionTimeout, TimeUnit.MILLISECONDS)) + .addHandlerLast(new WriteTimeoutHandler(connectionTimeout, TimeUnit.MILLISECONDS))); + return new ReactorClientHttpConnector(httpClient); + } + + @Bean + public WebClient unauthenticatedWebClient(){ + + int maxInMemorySize = Integer.parseInt(integrationCredentialProperties.getProperty("camunda.spring.webclient.maxInMemorySize")) * 1024 * 1024; + + return WebClient.builder() + .exchangeStrategies(ExchangeStrategies.builder() + .codecs(configurer -> configurer + .defaultCodecs() + .maxInMemorySize(maxInMemorySize)) + .build()) + .clientConnector(clientHttpConnector()) + .build(); + } + + + @Bean + WebClient webClient(ClientRegistrationRepository webClientClientRegistrationRepository, + OAuth2AuthorizedClientRepository authorizedClients) { + ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = + new ServletOAuth2AuthorizedClientExchangeFilterFunction( + webClientClientRegistrationRepository, authorizedClients); + oauth2.setDefaultClientRegistrationId ("keycloak-client"); + + int maxInMemorySize = Integer.parseInt(integrationCredentialProperties.getProperty("camunda.spring.webclient.maxInMemorySize")) * 1024 * 1024; + + return WebClient.builder() + .exchangeStrategies(ExchangeStrategies.builder() + .codecs(configurer -> configurer + .defaultCodecs() + .maxInMemorySize(maxInMemorySize)) + .build()) + .apply(oauth2.oauth2Configuration()) + .clientConnector(clientHttpConnector()) + .build(); + } +} + diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/CamundaApplication.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/CamundaApplication.java deleted file mode 100644 index 17f1bdf9f1..0000000000 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/CamundaApplication.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.camunda.bpm.extension.keycloak.showcase; - -import org.camunda.bpm.engine.AuthorizationService; -import org.camunda.bpm.engine.ProcessEngine; -import org.camunda.bpm.engine.ProcessEngines; -import org.camunda.bpm.engine.authorization.Authorization; -import org.camunda.bpm.engine.authorization.Resource; -import org.camunda.bpm.engine.authorization.Resources; -import org.camunda.bpm.extension.commons.connector.AccessHandlerFactory; -import org.camunda.bpm.spring.boot.starter.annotation.EnableProcessApplication; -import org.camunda.bpm.spring.boot.starter.event.PostDeployEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.config.ServiceLocatorFactoryBean; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.PropertySource; -import org.springframework.context.event.EventListener; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; -//import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource; - -import javax.sql.DataSource; -import java.util.Properties; - -import static org.camunda.bpm.engine.authorization.Permissions.ALL; -import static org.camunda.bpm.engine.authorization.Authorization.ANY; -import static org.camunda.bpm.engine.authorization.Authorization.AUTH_TYPE_GRANT; -import static org.camunda.bpm.engine.authorization.Authorization.AUTH_TYPE_GLOBAL; - -/** - * The Camunda Showcase Spring Boot application. - */ -@EnableOAuth2Client -@EnableConfigurationProperties -@PropertySource("application.yaml") -@SpringBootApplication(scanBasePackages = {"org.camunda.bpm.extension"}) -@EnableProcessApplication("camunda.showcase") -public class CamundaApplication { - - /** This class' logger. */ - private static final Logger LOG = LoggerFactory.getLogger(CamundaApplication.class); - - /** - * Post deployment work. - * @param event - */ - @EventListener - public void onPostDeploy(PostDeployEvent event) { - LOG.info("========================================"); - LOG.info("Successfully started Camunda Showcase"); - LOG.info("========================================\n"); - //authorizeServiceAccount(); - } - - /** - * Starts this application. - * @param args arguments - */ - public static void main(String... args) { - SpringApplication.run(CamundaApplication.class, args); - } - - /** - * Primary datasource. - * This is owned by Camunda. - * Note: Bean name should not be changed. - * @return - */ - @Bean(name="camundaBpmDataSource") - @ConfigurationProperties("spring.datasource") - @Primary - public DataSource camundaBpmDataSource(){ - return DataSourceBuilder.create().build(); - } - - /** - * Uncomment this method to enable session management in JDBC. - * - * Session datasource. - * Note: Bean name should not be changed. - * @return - */ - /*@Bean(name="springSessionDataSource") - @ConfigurationProperties("session.datasource") - @SpringSessionDataSource - public DataSource springSessionDataSource(){ - return DataSourceBuilder.create().build(); - }*/ - - - @Bean("bpmJdbcTemplate") - public NamedParameterJdbcTemplate bpmJdbcTemplate(@Qualifier("camundaBpmDataSource") DataSource camundaBpmDataSource) { - return new NamedParameterJdbcTemplate(camundaBpmDataSource); - } - - @Bean - @ConfigurationProperties(prefix = "security.oauth2.client") - public Properties clientCredentialProperties() { - return new Properties(); - } - - @Bean - @ConfigurationProperties(prefix = "formsflow.ai") - public Properties integrationCredentialProperties() { - return new Properties(); - } - - @Bean("accessHandlerFactory") - public FactoryBean accessHandlerFactory() { - ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean(); - factoryBean.setServiceLocatorInterface(AccessHandlerFactory.class); - return factoryBean; - } - - - private static void authorizeServiceAccount() { - LOG.info("Setting authorization for service account..."); - ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); - - for (int resourceType = 0; resourceType<=17; resourceType++){ - LOG.info(String.format("==> Setting resource type %d", resourceType)); - Resource resource = null; - if (resourceType==0) resource = Resources.APPLICATION; - else if (resourceType==1) resource = Resources.USER; - else if (resourceType==2) resource = Resources.GROUP; - else if (resourceType==3) resource = Resources.GROUP_MEMBERSHIP; - else if (resourceType==4) resource = Resources.AUTHORIZATION; - else if (resourceType==5) resource = Resources.FILTER; - else if (resourceType==6) resource = Resources.PROCESS_DEFINITION; - else if (resourceType==7) resource = Resources.TASK; - else if (resourceType==8) resource = Resources.PROCESS_INSTANCE; - else if (resourceType==9) resource = Resources.DEPLOYMENT; - else if (resourceType==10) resource = Resources.DECISION_DEFINITION; - else if (resourceType==11) resource = Resources.TENANT; - else if (resourceType==12) resource = Resources.TENANT_MEMBERSHIP; - else if (resourceType==13) resource = Resources.BATCH; - else if (resourceType==14) resource = Resources.DECISION_REQUIREMENTS_DEFINITION; - else if (resourceType==15) resource = Resources.REPORT; - else if (resourceType==16) resource = Resources.DASHBOARD; - else if (resourceType==17) resource = Resources.OPERATION_LOG_CATEGORY; - - AuthorizationService authorizationService = processEngine.getAuthorizationService(); - Authorization auth; - // If resource is process definition or instance, set GLOBAL; Else, ALLOW - if (resourceType == 6 || resourceType == 8 || resourceType == 10 || resourceType == 1 || resourceType == 2 || resourceType == 3) { - if (authorizationService.isUserAuthorized("*", null, ALL, resource, ANY)) continue; - auth = authorizationService.createNewAuthorization(AUTH_TYPE_GLOBAL); - auth.setUserId("*"); - } else { - String userId = "service-account-"+System.getenv("KEYCLOAK_CLIENTID"); - if (authorizationService.isUserAuthorized(userId, null, ALL, resource, ANY)) continue; - auth = authorizationService.createNewAuthorization(AUTH_TYPE_GRANT); - auth.setUserId(userId); - } - auth.setResourceType(resourceType); - auth.setResourceId(ANY); - auth.addPermission(ALL); - authorizationService.saveAuthorization(auth); - } - LOG.info("Authorization set!\n"); - } -} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/KeycloakAuthenticationFilter.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/KeycloakAuthenticationFilter.java deleted file mode 100644 index 8e0b60276d..0000000000 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/KeycloakAuthenticationFilter.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.camunda.bpm.extension.keycloak.showcase.rest; - - -import org.apache.commons.lang3.StringUtils; -import org.camunda.bpm.engine.IdentityService; -import org.camunda.spin.Spin; -import org.camunda.spin.SpinList; -import org.camunda.spin.json.SpinJsonNode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.jwt.JwtHelper; -import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; - -import javax.servlet.*; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Keycloak Authentication Filter - used for REST API Security. - */ -public class KeycloakAuthenticationFilter implements Filter { - - /** This class' logger. */ - private static final Logger LOG = LoggerFactory.getLogger(KeycloakAuthenticationFilter.class); - - /** Access to Camunda's IdentityService. */ - private IdentityService identityService; - - /** - * Creates a new KeycloakAuthenticationFilter. - * @param identityService access to Camunda's IdentityService - */ - public KeycloakAuthenticationFilter(IdentityService identityService) { - this.identityService = identityService; - } - - /** - * {@inheritDoc} - */ - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - - // Get the Bearer Token and extract claims - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails(); - String accessToken = details.getTokenValue(); - String claims = JwtHelper.decode(accessToken).getClaims(); - - // Extract user ID from Token claims -depending on Keycloak Identity Provider configuration - // String userId = Spin.JSON(claims).prop("sub").stringValue(); - //String userId = Spin.JSON(claims).prop("email").stringValue(); // useEmailAsCamundaUserId = true - String userId = Spin.JSON(claims).prop("preferred_username").stringValue(); // useUsernameAsCamundaUserId = true - LOG.debug("Extracted userId from bearer token: {}", userId); - - try { - identityService.setAuthentication(userId, getUserGroups(userId , claims)); - chain.doFilter(request, response); - } finally { - identityService.clearAuthentication(); - } - } - - - /** - * Retrieves groups for given userId - * @param userId - * @param claims - * @return - */ - private List getUserGroups(String userId, String claims){ - List groupIds = new ArrayList<>(); - if(Spin.JSON(claims).hasProp("groups")) { - SpinList groups = Spin.JSON(claims).prop("groups").elements(); - for(SpinJsonNode entry : groups) { - String groupName = StringUtils.contains(entry.stringValue(),"/") ? StringUtils.substringAfter(entry.stringValue(), "/") : entry.stringValue(); - groupIds.add(groupName); - } - } else { - identityService.createGroupQuery().groupMember(userId).list() - .forEach( g -> groupIds.add(g.getId())); - } - return groupIds; - } - - -} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/RestApiSecurityConfigurationProperties.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/RestApiSecurityConfigurationProperties.java deleted file mode 100644 index b5204ed858..0000000000 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/rest/RestApiSecurityConfigurationProperties.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.camunda.bpm.extension.keycloak.showcase.rest; - -import javax.validation.constraints.NotEmpty; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; -import org.springframework.validation.annotation.Validated; - -/** - * Complete Security Configuration Properties for Camunda REST Api. - */ -@Component -@ConfigurationProperties(prefix = "rest.security") -@Validated -public class RestApiSecurityConfigurationProperties { - - /** - * rest.security.enabled: - * - * Rest Security is enabled by default. Switch off by setting this flag to {@code false}. - */ - @SuppressWarnings("unused") - private Boolean enabled = true; - - /** - * rest.security.jwk-set-url: - * - * JWK Set URL (e.g. https:///auth/realms/camunda/protocol/openid-connect/certs). - */ - @NotEmpty - private String jwkSetUrl; - - /** - * rest.security.required-audience: - * - * Required Audience. - */ - @NotEmpty - private String requiredAudience; - - // ------------------------------------------------------------------------ - - /** - * @return the jwkSetUrl - */ - public String getJwkSetUrl() { - return jwkSetUrl; - } - - /** - * @param jwkSetUrl the jwkSetUrl to set - */ - public void setJwkSetUrl(String jwkSetUrl) { - this.jwkSetUrl = jwkSetUrl; - } - - /** - * @return the requiredAudience - */ - public String getRequiredAudience() { - return requiredAudience; - } - - /** - * @param requiredAudience the requiredAudience to set - */ - public void setRequiredAudience(String requiredAudience) { - this.requiredAudience = requiredAudience; - } - -} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/WebAppSecurityConfig.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/WebAppSecurityConfig.java deleted file mode 100644 index 3750983a5d..0000000000 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/WebAppSecurityConfig.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.camunda.bpm.extension.keycloak.showcase.sso; - -import java.util.Collections; - -import javax.inject.Inject; - -import org.camunda.bpm.webapp.impl.security.auth.ContainerBasedAuthenticationFilter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; -import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; -import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import org.springframework.web.context.request.RequestContextListener; - -/** - * Camunda Web application SSO configuration for usage with - * Auth0IdentityProviderPlugin. - */ -@ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringJUnit4ClassRunner") -@Configuration -@EnableOAuth2Sso -@Order(SecurityProperties.BASIC_AUTH_ORDER - 15) -public class WebAppSecurityConfig extends WebSecurityConfigurerAdapter { - - @Inject - private KeycloakLogoutHandler keycloakLogoutHandler; - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .csrf().ignoringAntMatchers("/api/**","/forms-flow-bpm-socket/**","/engine-rest/**","/engine-rest-ext/**","/camunda/engine-rest/**", "/camunda/engine-rest-ext/**", "/camunda/form-builder/**", "/actuator/**") - .and() - .antMatcher("/**") - .authorizeRequests() - .antMatchers("/app/**") - .authenticated() - .anyRequest() - .permitAll() - .and() - .logout() - .logoutRequestMatcher(new AntPathRequestMatcher("/app/**/logout")) - .logoutSuccessHandler(keycloakLogoutHandler) - ; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - public FilterRegistrationBean containerBasedAuthenticationFilter() { - - FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); - filterRegistration.setFilter(new ContainerBasedAuthenticationFilter()); - - filterRegistration.setInitParameters(Collections.singletonMap("authentication-provider", - "org.camunda.bpm.extension.keycloak.showcase.sso.KeycloakAuthenticationProvider")); - filterRegistration.setOrder(101); // make sure the filter is registered after the Spring Security Filter Chain - filterRegistration.addUrlPatterns("/app/*"); - return filterRegistration; - } - - - @Bean - @Order(0) - public RequestContextListener requestContextListener() { - return new RequestContextListener(); - } - - /** - * Configures the OAuth2 TokenStore for Redis Cache usage. - * - * @param redisConnectionFactory the Redis Connection Factoryf - * @return Redis prepared TokenStore - */ - /* - * Redis Session Cache not yet in use - * - * @Bean - * - * @Primary public TokenStore tokenStore(RedisConnectionFactory - * redisConnectionFactory) { return new RedisTokenStore(redisConnectionFactory); - * } - */ -} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/AESUtils.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/AESUtils.java similarity index 98% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/AESUtils.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/AESUtils.java index e355fa3485..bb42b87881 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/AESUtils.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/AESUtils.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.sso; +package org.camunda.bpm.extension.keycloak.sso; import org.springframework.stereotype.Component; diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/CustomCorsFilter.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/CustomCorsFilter.java similarity index 95% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/CustomCorsFilter.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/CustomCorsFilter.java index 36963be459..57165d13b8 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/CustomCorsFilter.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/CustomCorsFilter.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.sso; +package org.camunda.bpm.extension.keycloak.sso; import java.io.IOException; import java.util.Arrays; @@ -63,18 +63,18 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) response.setHeader("Access-Control-Allow-Headers", "*"); response.setHeader("Access-Control-Max-Age", "3600"); - if ("OPTIONS".equalsIgnoreCase(requestMethod) && isEngineRestRequest(request) == true) { + if ("OPTIONS".equalsIgnoreCase(requestMethod) && isEngineRestRequest(request)) { if(isWebSocketRequest(request)) { response.setHeader("Access-Control-Allow-Credentials", "true"); } response.setStatus(HttpServletResponse.SC_OK); } else { - if (isWebSocketRequest(request) == true) { + if (isWebSocketRequest(request)) { response.setHeader("Access-Control-Allow-Credentials", "true"); CustomHttpRequestWrapper customHttpRequestWrapper = new CustomHttpRequestWrapper(request); if (StringUtils.isNotBlank(request.getQueryString())) { - List queryParams = Arrays.asList(request.getQueryString().split("&")); + String[] queryParams = request.getQueryString().split("&"); for (String param : queryParams) { if ("accesstoken".equals(StringUtils.substringBefore(param, "="))) { String decryptedToken = aesUtils.decryptText(StringUtils.substringAfter(param, "="), socketSecretKey); diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/CustomHttpRequestWrapper.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/CustomHttpRequestWrapper.java similarity index 96% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/CustomHttpRequestWrapper.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/CustomHttpRequestWrapper.java index 01f14214d9..efd004b846 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/CustomHttpRequestWrapper.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/CustomHttpRequestWrapper.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.sso; +package org.camunda.bpm.extension.keycloak.sso; import org.springframework.stereotype.Component; diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/KeycloakAuthenticationProvider.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java similarity index 52% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/KeycloakAuthenticationProvider.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java index a2c70b17ee..3287607a6a 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/KeycloakAuthenticationProvider.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakAuthenticationProvider.java @@ -1,7 +1,6 @@ -package org.camunda.bpm.extension.keycloak.showcase.sso; +package org.camunda.bpm.extension.keycloak.sso; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import org.springframework.security.core.context.SecurityContextHolder; @@ -11,8 +10,9 @@ import org.camunda.bpm.engine.rest.security.auth.AuthenticationResult; import org.camunda.bpm.engine.rest.security.auth.impl.ContainerBasedAuthenticationProvider; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.util.StringUtils; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.util.ObjectUtils; /** * OAuth2 Authentication Provider for usage with Keycloak and @@ -24,29 +24,14 @@ public class KeycloakAuthenticationProvider extends ContainerBasedAuthentication public AuthenticationResult extractAuthenticatedUser(HttpServletRequest request, ProcessEngine engine) { // Extract authentication details - OAuth2Authentication authentication = (OAuth2Authentication) SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication == null) { - return AuthenticationResult.unsuccessful(); - } - Authentication userAuthentication = authentication.getUserAuthentication(); - if (userAuthentication == null || userAuthentication.getDetails() == null) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof OAuth2AuthenticationToken) || !(authentication.getPrincipal() instanceof OidcUser)) { return AuthenticationResult.unsuccessful(); } - // Extract user ID from Keycloak authentication result - which is part of the - // requested user info - @SuppressWarnings("unchecked") - // String userId = ((HashMap) - // userAuthentication.getDetails()).get("sub"); - // String userId = ((HashMap) - // userAuthentication.getDetails()).get("email"); // useEmailAsCamundaUserId = - // true - // String userId = ((HashMap) - // userAuthentication.getDetails()).get("email"); - String userId = ((HashMap) userAuthentication.getDetails()).get("preferred_username"); - // useUsernameAsCamundaUserId = true - if (StringUtils.isEmpty(userId)) { + String userId = ((OidcUser)authentication.getPrincipal()).getName(); + + if (ObjectUtils.isEmpty(userId)) { return AuthenticationResult.unsuccessful(); } diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/KeycloakLogoutHandler.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakLogoutHandler.java similarity index 84% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/KeycloakLogoutHandler.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakLogoutHandler.java index 0eff28330a..2020ae3737 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/sso/KeycloakLogoutHandler.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/KeycloakLogoutHandler.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.sso; +package org.camunda.bpm.extension.keycloak.sso; import java.io.IOException; @@ -15,7 +15,7 @@ import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.springframework.util.ObjectUtils; /** * Keycloak Logout Handler. @@ -31,13 +31,13 @@ public class KeycloakLogoutHandler implements LogoutSuccessHandler { /** Keycloak's logout URI. */ private String oauth2UserLogoutUri; - + /** * Default constructor. * @param oauth2UserAuthorizationUri configured keycloak authorization URI */ - public KeycloakLogoutHandler(@Value("${security.oauth2.client.user-authorization-uri:}") String oauth2UserAuthorizationUri) { - if (!StringUtils.isEmpty(oauth2UserAuthorizationUri)) { + public KeycloakLogoutHandler(@Value("${spring.security.oauth2.client.provider.keycloak.authorization-uri:}") String oauth2UserAuthorizationUri) { + if (!ObjectUtils.isEmpty(oauth2UserAuthorizationUri)) { // in order to get the valid logout uri: simply replace "/auth" at the end of the user authorization uri with "/logout" this.oauth2UserLogoutUri = oauth2UserAuthorizationUri.replace("openid-connect/auth", "openid-connect/logout"); } @@ -49,21 +49,22 @@ public KeycloakLogoutHandler(@Value("${security.oauth2.client.user-authorization @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - if (!StringUtils.isEmpty(oauth2UserLogoutUri)) { + + if (!ObjectUtils.isEmpty(oauth2UserLogoutUri)) { // Calculate redirect URI for Keycloak, something like http:///camunda/login String requestUrl = request.getRequestURL().toString(); - String redirectUri = requestUrl.substring(0, requestUrl.indexOf("/app")) + "/login"; + String redirectUri = requestUrl.substring(0, requestUrl.indexOf("/app")); // Complete logout URL String logoutUrl = oauth2UserLogoutUri + "?redirect_uri=" + redirectUri; Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { - LOG.error("-------cookie---------->"+cookie.getName()); + LOG.debug("-------cookie---------->"+cookie.getName()); cookie.setMaxAge(0); cookie.setValue(null); cookie.setPath("/camunda"); response.addCookie(cookie); } - LOG.error("-------context path---------->"+request.getContextPath()); + LOG.debug("-------context path---------->"+request.getContextPath()); //To remove JSESSIONID Cookie cookieWithSlash = new Cookie("JSESSIONID", null); //Tomcat adds extra slash at the end of context path (e.g. "/foo/") @@ -79,7 +80,7 @@ public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse resp response.addCookie(cookieWithSlash); //For Tomcat response.addCookie(cookieWithoutSlash); //For JBoss // Do logout by redirecting to Keycloak logout - LOG.error("Redirecting to logout URL {}", logoutUrl); + LOG.debug("Redirecting to logout URL {}", logoutUrl); redirectStrategy.sendRedirect(request, response, logoutUrl); } } diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java new file mode 100644 index 0000000000..04cd8656ad --- /dev/null +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/sso/OAuth2LoginSecurityConfig.java @@ -0,0 +1,96 @@ +package org.camunda.bpm.extension.keycloak.sso; + +import java.util.Collections; +import java.util.List; + +import javax.inject.Inject; + +import org.camunda.bpm.engine.IdentityService; +import org.camunda.bpm.extension.keycloak.rest.RestApiSecurityConfigurationProperties; +import org.camunda.bpm.webapp.impl.security.auth.ContainerBasedAuthenticationFilter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.web.context.request.RequestContextListener; +import org.springframework.web.filter.ForwardedHeaderFilter; + +import static org.springframework.security.config.Customizer.withDefaults; + +/** + * Camunda Web application SSO configuration for usage with + * Auth0IdentityProviderPlugin. + */ +@Configuration +@ConditionalOnMissingClass("org.springframework.test.context.junit.jupiter.SpringExtension") +@Order(SecurityProperties.BASIC_AUTH_ORDER - 10) +public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter { + + @Inject + private KeycloakLogoutHandler keycloakLogoutHandler; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().ignoringAntMatchers("/api/**","/forms-flow-bpm-socket/**","/engine-rest/**","/engine-rest-ext/**","/camunda/engine-rest/**", "/camunda/engine-rest-ext/**", "/camunda/form-builder/**", "/actuator/**") + .and() + .antMatcher("/**") + .authorizeRequests( + authorizeRequests -> + authorizeRequests + .antMatchers("/app/**") + .authenticated() + .anyRequest() + .permitAll() + ) + .oauth2Login(withDefaults()) + .oauth2Client(withDefaults()) + .logout() + .logoutRequestMatcher(new AntPathRequestMatcher("/app/**/logout")) + .logoutSuccessHandler(keycloakLogoutHandler); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + public FilterRegistrationBean containerBasedAuthenticationFilter() { + + FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); + filterRegistration.setFilter(new ContainerBasedAuthenticationFilter()); + + filterRegistration.setInitParameters(Collections.singletonMap("authentication-provider", + "org.camunda.bpm.extension.keycloak.sso.KeycloakAuthenticationProvider")); + filterRegistration.setOrder(101); // make sure the filter is registered after the Spring Security Filter Chain + filterRegistration.addUrlPatterns("/app/*"); + return filterRegistration; + } + + @Bean + public FilterRegistrationBean forwardedHeaderFilter() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); + filterRegistrationBean.setFilter(new ForwardedHeaderFilter()); + filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); + return filterRegistrationBean; + } + + + @Bean + @Order(0) + public RequestContextListener requestContextListener() { + return new RequestContextListener(); + } +} diff --git a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/task/LoggerDelegate.java b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/task/LoggerDelegate.java similarity index 94% rename from forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/task/LoggerDelegate.java rename to forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/task/LoggerDelegate.java index a85b7df0dc..f6ae3c1854 100644 --- a/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/showcase/task/LoggerDelegate.java +++ b/forms-flow-bpm/src/main/java/org/camunda/bpm/extension/keycloak/task/LoggerDelegate.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.task; +package org.camunda.bpm.extension.keycloak.task; import java.util.logging.Logger; diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/custom/logout.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/custom/logout.js index 9915dd9260..2d023ae1ba 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/custom/logout.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/custom/logout.js @@ -1,22 +1,22 @@ -'use strict'; -define('custom-logout', ['angular'], function (angular) { - var customLogoutModule = angular.module('custom-logout', []).run( - ['$rootScope', function ($rootScope) { +let observer = new MutationObserver(() => { + // find the logout button + const logoutButton = document.querySelectorAll(".logout > a")[0]; +// once the button is present replace it with new functionality +if (logoutButton) { + var parent = logoutButton.parentElement; + parent.removeChild(logoutButton); + var newLogout = document.createElement('a'); + newLogout.setAttribute('className', 'ng-binding'); + newLogout.innerText = logoutButton.innerText.replaceAll('\n', ''); + newLogout.setAttribute('href', 'logout'); // call server side logout handler + parent.appendChild(newLogout); + observer.disconnect(); +} +}); - $rootScope.$on('$viewContentLoaded', function (event) { - // Get the HTML element of the header widget. - var div = document.querySelector("[cam-widget-header]"); - - // Get the only property on it, its key is jQuery and its value - // contains the controller ($camWidgetHeaderController) and the isolated - // Scope ($isolateScope). The logout function is defined in this scope. - var jQueryKey = Object.getOwnPropertyNames(div)[0]; - var $isolateScope = div[jQueryKey]['$isolateScope']; - $isolateScope.logout = function () { - // Do whatever you want to do on logout. - window.location.href = "logout" - } - - }) - }]); +observer.observe(document.body, { + childList: true, + subtree: true, + attributes: false, + characterData: false }); \ No newline at end of file diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/scripts/config.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/scripts/config.js index 5f82571b9c..1f015d4e68 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/scripts/config.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/admin/scripts/config.js @@ -23,3 +23,9 @@ window.camAdminConf = { vendor: ' ' } }; + +export default { + customScripts: [ + 'custom/logout' + ] +}; \ No newline at end of file diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/custom/logout.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/custom/logout.js index 9915dd9260..423c2cbf74 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/custom/logout.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/custom/logout.js @@ -1,22 +1,22 @@ -'use strict'; -define('custom-logout', ['angular'], function (angular) { - var customLogoutModule = angular.module('custom-logout', []).run( - ['$rootScope', function ($rootScope) { +let observer = new MutationObserver(() => { + // find the logout button + const logoutButton = document.querySelectorAll(".logout > a")[0]; +// once the button is present replace it with new functionality +if (logoutButton) { + var parent = logoutButton.parentElement + parent.removeChild(logoutButton) + var newLogout = document.createElement('a'); + newLogout.setAttribute('className', 'ng-binding') + newLogout.innerText = logoutButton.innerText.replaceAll('\n', ''); + newLogout.setAttribute('href', 'logout'); // call server side logout handler + parent.appendChild(newLogout) + observer.disconnect(); +} +}); - $rootScope.$on('$viewContentLoaded', function (event) { - // Get the HTML element of the header widget. - var div = document.querySelector("[cam-widget-header]"); - - // Get the only property on it, its key is jQuery and its value - // contains the controller ($camWidgetHeaderController) and the isolated - // Scope ($isolateScope). The logout function is defined in this scope. - var jQueryKey = Object.getOwnPropertyNames(div)[0]; - var $isolateScope = div[jQueryKey]['$isolateScope']; - $isolateScope.logout = function () { - // Do whatever you want to do on logout. - window.location.href = "logout" - } - - }) - }]); +observer.observe(document.body, { + childList: true, + subtree: true, + attributes: false, + characterData: false }); \ No newline at end of file diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/scripts/config.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/scripts/config.js index 5d0f0b5403..b26aa0caec 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/scripts/config.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/cockpit/scripts/config.js @@ -23,3 +23,10 @@ window.camCockpitConf = { vendor: ' ' } }; + +export default { + bpmnJs: {}, + customScripts: [ + 'custom/logout' + ] +} diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/custom/logout.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/custom/logout.js index 9915dd9260..423c2cbf74 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/custom/logout.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/custom/logout.js @@ -1,22 +1,22 @@ -'use strict'; -define('custom-logout', ['angular'], function (angular) { - var customLogoutModule = angular.module('custom-logout', []).run( - ['$rootScope', function ($rootScope) { +let observer = new MutationObserver(() => { + // find the logout button + const logoutButton = document.querySelectorAll(".logout > a")[0]; +// once the button is present replace it with new functionality +if (logoutButton) { + var parent = logoutButton.parentElement + parent.removeChild(logoutButton) + var newLogout = document.createElement('a'); + newLogout.setAttribute('className', 'ng-binding') + newLogout.innerText = logoutButton.innerText.replaceAll('\n', ''); + newLogout.setAttribute('href', 'logout'); // call server side logout handler + parent.appendChild(newLogout) + observer.disconnect(); +} +}); - $rootScope.$on('$viewContentLoaded', function (event) { - // Get the HTML element of the header widget. - var div = document.querySelector("[cam-widget-header]"); - - // Get the only property on it, its key is jQuery and its value - // contains the controller ($camWidgetHeaderController) and the isolated - // Scope ($isolateScope). The logout function is defined in this scope. - var jQueryKey = Object.getOwnPropertyNames(div)[0]; - var $isolateScope = div[jQueryKey]['$isolateScope']; - $isolateScope.logout = function () { - // Do whatever you want to do on logout. - window.location.href = "logout" - } - - }) - }]); +observer.observe(document.body, { + childList: true, + subtree: true, + attributes: false, + characterData: false }); \ No newline at end of file diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/scripts/config.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/scripts/config.js index 24ba306e7e..a61953e4b8 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/scripts/config.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/tasklist/scripts/config.js @@ -24,3 +24,9 @@ window.camTasklistConf = { } }; +export default { + customScripts: [ + 'custom/logout' + ] +}; + diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/custom/logout.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/custom/logout.js index 9915dd9260..423c2cbf74 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/custom/logout.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/custom/logout.js @@ -1,22 +1,22 @@ -'use strict'; -define('custom-logout', ['angular'], function (angular) { - var customLogoutModule = angular.module('custom-logout', []).run( - ['$rootScope', function ($rootScope) { +let observer = new MutationObserver(() => { + // find the logout button + const logoutButton = document.querySelectorAll(".logout > a")[0]; +// once the button is present replace it with new functionality +if (logoutButton) { + var parent = logoutButton.parentElement + parent.removeChild(logoutButton) + var newLogout = document.createElement('a'); + newLogout.setAttribute('className', 'ng-binding') + newLogout.innerText = logoutButton.innerText.replaceAll('\n', ''); + newLogout.setAttribute('href', 'logout'); // call server side logout handler + parent.appendChild(newLogout) + observer.disconnect(); +} +}); - $rootScope.$on('$viewContentLoaded', function (event) { - // Get the HTML element of the header widget. - var div = document.querySelector("[cam-widget-header]"); - - // Get the only property on it, its key is jQuery and its value - // contains the controller ($camWidgetHeaderController) and the isolated - // Scope ($isolateScope). The logout function is defined in this scope. - var jQueryKey = Object.getOwnPropertyNames(div)[0]; - var $isolateScope = div[jQueryKey]['$isolateScope']; - $isolateScope.logout = function () { - // Do whatever you want to do on logout. - window.location.href = "logout" - } - - }) - }]); +observer.observe(document.body, { + childList: true, + subtree: true, + attributes: false, + characterData: false }); \ No newline at end of file diff --git a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/scripts/config.js b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/scripts/config.js index a1827d8781..8e31434038 100644 --- a/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/scripts/config.js +++ b/forms-flow-bpm/src/main/resources/META-INF/resources/webjars/camunda/app/welcome/scripts/config.js @@ -23,3 +23,9 @@ window.camWelcomeConf = { vendor: ' ' } }; + +export default { + customScripts: [ + 'custom/logout' + ] +}; \ No newline at end of file diff --git a/forms-flow-bpm/src/main/resources/application.yaml b/forms-flow-bpm/src/main/resources/application.yaml index a5e2f09da6..89c3d1dfa7 100644 --- a/forms-flow-bpm/src/main/resources/application.yaml +++ b/forms-flow-bpm/src/main/resources/application.yaml @@ -37,18 +37,14 @@ formsflow.ai: accessTokenUri: ${FORMIO_URL}/user/login username: ${FORMIO_ROOT_EMAIL} password: ${FORMIO_ROOT_PASSWORD} + camunda: + spring: + webclient: + maxInMemorySize: ${DATA_BUFFER_SIZE:2} + connectionTimeout: 5000 + -spring: - jersey: - application-path: /engine-rest - security: - oauth2: - resourceserver: - jwt: - issuer-uri: ${keycloak.url}/auth/realms/${keycloak.url.realm} - main: - allow-bean-definition-overriding: true # session: # jdbc.initialize-schema: always # store-type: ${CAMUNDA_SESSION_STORE_TYPE:none} @@ -70,7 +66,7 @@ info: app: name: "Camunda" description: "formsflow.ai Engine" - version: "7.13" + version: "7.15" java: version: "11" @@ -110,19 +106,47 @@ server: cookie: secure: true -security: - oauth2: - client: - client-id: ${keycloak.clientId} - client-secret: ${keycloak.clientSecret} - accessTokenUri: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/token - userAuthorizationUri: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/auth - scope: openid profile email - grant-type: authorization_code implicit refresh_token password client_credentials - resource: - userInfoUri: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/userinfo - headers: - hsts: domain +# Camunda Rest API +rest.security: + enabled: true + provider: keycloak + required-audience: camunda-rest-api + +spring: + jersey: + application-path: /engine-rest + security: + oauth2: + client: + registration: + keycloak: + provider: keycloak + client-id: ${keycloak.clientId} + client-secret: ${keycloak.clientSecret} + redirect-uri: "{baseUrl}/{action}/oauth2/code/{registrationId}" + scope: + - openid + - profile + - email + authorizationGrantType: authorization_code + keycloak-client: + provider: keycloak + client-id: ${keycloak.clientId} + client-secret: ${keycloak.clientSecret} + authorizationGrantType: client_credentials + provider: + keycloak: + authorization-uri: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/auth + token-uri: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/token + user-info-uri: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/userinfo + user-name-attribute: preferred_username + jwk-set-uri: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/certs + issuer-uri: ${keycloak.url}/auth/realms/${keycloak.url.realm} + resourceserver: + jwt: + issuer-uri: ${keycloak.url}/auth/realms/${keycloak.url.realm} + main: + allow-bean-definition-overriding: true logging: @@ -133,13 +157,6 @@ logging: org.camunda.bpm: ${CAMUNDA_APP_ROOT_LOG_FLAG} -# Camunda Rest API -rest.security: - enabled: true - jwk-set-url: ${keycloak.url}/auth/realms/${keycloak.url.realm}/protocol/openid-connect/certs - required-audience: camunda-rest-api - - plugin.identity.keycloak.rest: userNameClaim: preferred_username authorityPrefix: "ROLE_" @@ -155,6 +172,7 @@ plugin.identity.keycloak: useGroupPathAsCamundaGroupId: true administratorGroupName: camunda-admin disableSSLCertificateValidation: true + maxResultSize: ${IDENTITY_PROVIDER_MAX_RESULT_SIZE:250} app.security.origin: ${APP_SECURITY_ORIGIN} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/CamundaApplicationTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/CamundaApplicationTest.java new file mode 100644 index 0000000000..63bce5a45c --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/CamundaApplicationTest.java @@ -0,0 +1,23 @@ +package org.camunda.bpm.extension; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.camunda.bpm.engine.IdentityService; +import org.camunda.bpm.extension.keycloak.rest.RestApiSecurityConfigurationProperties; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest +public class CamundaApplicationTest { + +/* @Test + public void contextLoads() { + }*/ +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandlerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandlerTest.java new file mode 100644 index 0000000000..84d0bd48d8 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/ApplicationAccessHandlerTest.java @@ -0,0 +1,71 @@ +package org.camunda.bpm.extension.commons.connector.support; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.function.Consumer; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; + +/** + * Test class for ApplicationAccessHandler + */ +@ExtendWith(SpringExtension.class) +class ApplicationAccessHandlerTest { + + @InjectMocks + private ApplicationAccessHandler applicationAccessHandler; + + @Mock + private WebClient webClient; + + /** + * This test perform a positive test over ApplicationAccessHandler + * This will validate the response entity is Success + */ + @Test + public void testExchangeSuccess() { + final String apiUrl = "http://localhost:5000/api/application/123"; + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + when(webClient.method(any(HttpMethod.class))) + .thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri(anyString())) + .thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.accept(any(MediaType.class))) + .thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())) + .thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.attributes(any(Consumer.class))) + .thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.headers(any(Consumer.class))) + .thenReturn(requestBodyUriSpec); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(requestBodyUriSpec.body(any(Mono.class), any(Class.class))) + .thenReturn(requestHeadersSpec); + WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + when(requestHeadersSpec.retrieve()).thenReturn(responseSpec); + Mono> response = Mono.just(ResponseEntity.ok("Success")); + when(responseSpec.toEntity(String.class)) + .thenReturn(response); + + ResponseEntity data = applicationAccessHandler.exchange(apiUrl, HttpMethod.GET, "{}"); + assertEquals(data.getBody(), "Success"); + } + +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandlerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandlerTest.java new file mode 100644 index 0000000000..9f3bff1635 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormAccessHandlerTest.java @@ -0,0 +1,297 @@ +package org.camunda.bpm.extension.commons.connector.support; + +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.ProcessEngines; +import org.camunda.bpm.engine.RepositoryService; +import org.camunda.bpm.engine.repository.ProcessDefinition; +import org.camunda.bpm.engine.repository.ProcessDefinitionQuery; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.function.Function; +import java.util.function.Predicate; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Test class for FormAccessHandler + */ +@ExtendWith(SpringExtension.class) +class FormAccessHandlerTest { + + @InjectMocks + private FormAccessHandler formAccessHandler; + + @Mock + private NamedParameterJdbcTemplate bpmJdbcTemplate; + + @Mock + private WebClient webClient; + + @Mock + private Properties integrationCredentialProperties; + + /** + * This test perform a positive test over FormAccessHandler + * This will validate the response entity is Success + */ + @Test + public void exchange_happyFlow_withPatch() { + ProcessEngines processEngines = mock(ProcessEngines.class); + Map processEngineMap = new HashMap(); + ProcessEngine processEngine = mock(ProcessEngine.class); + processEngineMap.put("default", processEngine); + ReflectionTestUtils.setField(processEngines, "processEngines", processEngineMap); + ReflectionTestUtils.setField(processEngines, "isInitialized", true); + RepositoryService repositoryService = mock(RepositoryService.class); + when(processEngine.getRepositoryService()).thenReturn(repositoryService); + ProcessDefinitionQuery processDefinitionQuery = mock(ProcessDefinitionQuery.class); + when(repositoryService.createProcessDefinitionQuery()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.latestVersion()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.processDefinitionKey(anyString())).thenReturn(processDefinitionQuery); + ProcessDefinition processDefinition = mock(ProcessDefinition.class); + when(processDefinitionQuery.singleResult()).thenReturn(processDefinition); + when(processDefinition.getId()).thenReturn("abcd123"); + when(bpmJdbcTemplate.queryForObject(anyString(), any(MapSqlParameterSource.class), any(Class.class))) + .thenReturn("adhjsadhajyuyuxyuxyvxucvyxcuvtyatd"); + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + when(webClient.patch()).thenReturn(requestBodyUriSpec); + when(integrationCredentialProperties.getProperty(anyString())).thenReturn("http://localhost:3001"); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(requestBodyUriSpec.bodyValue(anyString())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.onStatus(any(Predicate.class), any(Function.class))).thenReturn(responseSpec); + when(responseSpec.toEntity(any(Class.class))).thenReturn(Mono.just(new ResponseEntity("", HttpStatus.OK))); + + ResponseEntity expected = new ResponseEntity("", HttpStatus.OK); + ResponseEntity actual = formAccessHandler.exchange("http://localhost:3001", HttpMethod.PATCH, "{}"); + assertEquals(expected, actual); + } + + /** + * This test perform with expired token over FormAccessHandler + * This will validate the response entity 404 status + */ + @Test + public void exchange_withPatch_with_tokenExpired() { + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(integrationCredentialProperties.getProperty("formio.security.username")).thenReturn("admin@example.com"); + when(integrationCredentialProperties.getProperty("formio.security.password")).thenReturn("changeme"); + when(integrationCredentialProperties.getProperty("formio.security.accessTokenUri")) + .thenReturn("http://localhost:3001/login"); + when(webClient.post()).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.bodyValue(any(Map.class))).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.exchangeToMono(any(Function.class))) + .thenReturn(Mono.just("adhjsadhajyuyuxyuxyvxucvyxcuvtyatd")); + + when(webClient.patch()).thenReturn(requestBodyUriSpec); + when(integrationCredentialProperties.getProperty(anyString())).thenReturn("http://localhost:3001"); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.bodyValue(anyString())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.onStatus(any(Predicate.class), any(Function.class))).thenReturn(responseSpec); + when(responseSpec.toEntity(any(Class.class))) + .thenReturn(Mono.just(new ResponseEntity("Token Expired", HttpStatus.OK))); + + ResponseEntity expected = new ResponseEntity("Token Expired", HttpStatus.valueOf(404)); + ResponseEntity actual = formAccessHandler.exchange("http://localhost:3001", HttpMethod.PATCH, "{}"); + assertEquals(expected, actual); + } + + /** + * This test perform a happy flow with any method + * This will validate the response entity status is OK + */ + @Test + public void exchange_happyFlow_withAnyMethod() { + ProcessEngines processEngines = mock(ProcessEngines.class); + Map processEngineMap = new HashMap(); + ProcessEngine processEngine = mock(ProcessEngine.class); + processEngineMap.put("default", processEngine); + ReflectionTestUtils.setField(processEngines, "processEngines", processEngineMap); + ReflectionTestUtils.setField(processEngines, "isInitialized", true); + RepositoryService repositoryService = mock(RepositoryService.class); + when(processEngine.getRepositoryService()).thenReturn(repositoryService); + ProcessDefinitionQuery processDefinitionQuery = mock(ProcessDefinitionQuery.class); + when(repositoryService.createProcessDefinitionQuery()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.latestVersion()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.processDefinitionKey(anyString())).thenReturn(processDefinitionQuery); + ProcessDefinition processDefinition = mock(ProcessDefinition.class); + when(processDefinitionQuery.singleResult()).thenReturn(processDefinition); + when(processDefinition.getId()).thenReturn("abcd123"); + when(bpmJdbcTemplate.queryForObject(anyString(), any(MapSqlParameterSource.class), any(Class.class))) + .thenReturn("adhjsadhajyuyuxyuxyvxucvyxcuvtyatd"); + + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + when(webClient.method(any(HttpMethod.class))).thenReturn(requestBodyUriSpec); + when(integrationCredentialProperties.getProperty(anyString())).thenReturn("http://localhost:3001"); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(requestBodyUriSpec.body(any(Mono.class), any(Class.class))).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + when(requestHeadersSpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.onStatus(any(Predicate.class), any(Function.class))).thenReturn(responseSpec); + when(responseSpec.toEntity(any(Class.class))).thenReturn(Mono.just(new ResponseEntity("", HttpStatus.OK))); + + ResponseEntity expected = new ResponseEntity("", HttpStatus.OK); + ResponseEntity actual = formAccessHandler.exchange("http://localhost:3001", HttpMethod.GET, "{}"); + assertEquals(expected, actual); + } + + /** + * This test perform with no Access Token in DB + * This will validate the response entity status is OK + */ + @Test + public void exchange_withPatch_with_noAccessTokenInDB() { + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(integrationCredentialProperties.getProperty("formio.security.username")).thenReturn("admin@example.com"); + when(integrationCredentialProperties.getProperty("formio.security.password")).thenReturn("changeme"); + when(integrationCredentialProperties.getProperty("formio.security.accessTokenUri")) + .thenReturn("http://localhost:3001/login"); + when(webClient.post()).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.bodyValue(any(Map.class))).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.exchangeToMono(any(Function.class))) + .thenReturn(Mono.just("adhjsadhajyuyuxyuxyvxucvyxcuvtyatd")); + + when(webClient.patch()).thenReturn(requestBodyUriSpec); + when(integrationCredentialProperties.getProperty(anyString())).thenReturn("http://localhost:3001"); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.bodyValue(anyString())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.onStatus(any(Predicate.class), any(Function.class))).thenReturn(responseSpec); + when(responseSpec.toEntity(any(Class.class))).thenReturn(Mono.just(new ResponseEntity("", HttpStatus.OK))); + + ResponseEntity expected = new ResponseEntity("", HttpStatus.OK); + ResponseEntity actual = formAccessHandler.exchange("http://localhost:3001", HttpMethod.PATCH, "{}"); + assertEquals(expected, actual); + } + + /** + * This test perform with Blank Access Token + * This will validate the response entity is null + */ + @Test + public void exchange_withPatch_andBlankAccessToken() { + ProcessEngines processEngines = mock(ProcessEngines.class); + Map processEngineMap = new HashMap(); + ProcessEngine processEngine = mock(ProcessEngine.class); + processEngineMap.put("default", processEngine); + ReflectionTestUtils.setField(processEngines, "processEngines", processEngineMap); + ReflectionTestUtils.setField(processEngines, "isInitialized", true); + RepositoryService repositoryService = mock(RepositoryService.class); + when(processEngine.getRepositoryService()).thenReturn(repositoryService); + ProcessDefinitionQuery processDefinitionQuery = mock(ProcessDefinitionQuery.class); + when(repositoryService.createProcessDefinitionQuery()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.latestVersion()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.processDefinitionKey(anyString())).thenReturn(processDefinitionQuery); + ProcessDefinition processDefinition = mock(ProcessDefinition.class); + when(processDefinitionQuery.singleResult()).thenReturn(processDefinition); + when(processDefinition.getId()).thenReturn("abcd123"); + when(bpmJdbcTemplate.queryForObject(anyString(), any(MapSqlParameterSource.class), any(Class.class))) + .thenReturn(""); + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + when(webClient.patch()).thenReturn(requestBodyUriSpec); + when(integrationCredentialProperties.getProperty(anyString())).thenReturn("http://localhost:3001"); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(requestBodyUriSpec.bodyValue(anyString())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.onStatus(any(Predicate.class), any(Function.class))).thenReturn(responseSpec); + when(responseSpec.toEntity(any(Class.class))).thenReturn(Mono.just(new ResponseEntity("", HttpStatus.OK))); + + ResponseEntity expected = null; + ResponseEntity actual = formAccessHandler.exchange("http://localhost:3001", HttpMethod.PATCH, "{}"); + assertEquals(expected, actual); + } + + /** + * This test perform with formUrl ends with form + * This will validate the response entity status is OK + */ + @Test + public void exchange_happyFlow_withUrlEndsWithForm() { + ProcessEngines processEngines = mock(ProcessEngines.class); + Map processEngineMap = new HashMap(); + ProcessEngine processEngine = mock(ProcessEngine.class); + processEngineMap.put("default", processEngine); + ReflectionTestUtils.setField(processEngines, "processEngines", processEngineMap); + ReflectionTestUtils.setField(processEngines, "isInitialized", true); + RepositoryService repositoryService = mock(RepositoryService.class); + when(processEngine.getRepositoryService()).thenReturn(repositoryService); + ProcessDefinitionQuery processDefinitionQuery = mock(ProcessDefinitionQuery.class); + when(repositoryService.createProcessDefinitionQuery()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.latestVersion()).thenReturn(processDefinitionQuery); + when(processDefinitionQuery.processDefinitionKey(anyString())).thenReturn(processDefinitionQuery); + ProcessDefinition processDefinition = mock(ProcessDefinition.class); + when(processDefinitionQuery.singleResult()).thenReturn(processDefinition); + when(processDefinition.getId()).thenReturn("abcd123"); + when(bpmJdbcTemplate.queryForObject(anyString(), any(MapSqlParameterSource.class), any(Class.class))) + .thenReturn("adhjsadhajyuyuxyuxyvxucvyxcuvtyatd"); + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + when(webClient.patch()).thenReturn(requestBodyUriSpec); + when(integrationCredentialProperties.getProperty(anyString())).thenReturn("http://localhost:3001"); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(requestBodyUriSpec.bodyValue(anyString())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.accept(any(MediaType.class))).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec); + WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.onStatus(any(Predicate.class), any(Function.class))).thenReturn(responseSpec); + when(responseSpec.toEntity(any(Class.class))).thenReturn(Mono.just(new ResponseEntity("", HttpStatus.OK))); + + ResponseEntity expected = new ResponseEntity("", HttpStatus.OK); + ResponseEntity actual = formAccessHandler.exchange("http://localhost:3001/form/", HttpMethod.PATCH, + "{}"); + assertEquals(expected, actual); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandlerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandlerTest.java new file mode 100644 index 0000000000..c80536edb1 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/connector/support/FormTokenAccessHandlerTest.java @@ -0,0 +1,65 @@ +package org.camunda.bpm.extension.commons.connector.support; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Map; +import java.util.Properties; +import java.util.function.Function; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Test class for FormTokenAccessHandler + */ +@ExtendWith(SpringExtension.class) +class FormTokenAccessHandlerTest { + + @InjectMocks + private FormTokenAccessHandler formTokenAccessHandler; + + @Mock + private Properties integrationCredentialProperties; + + @Mock + private WebClient webClient; + + /** + * This test will validate the Access Token + */ + @Test + public void getAccessToken_happyFlow1(){ + when(integrationCredentialProperties.getProperty("formio.security.username")) + .thenReturn("admin@example.com"); + when(integrationCredentialProperties.getProperty("formio.security.password")) + .thenReturn("changeme"); + when(integrationCredentialProperties.getProperty("formio.security.accessTokenUri")) + .thenReturn("http://localhost:3001/login"); + WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + when(webClient.post()) + .thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri(anyString())) + .thenReturn(requestBodyUriSpec); + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(requestBodyUriSpec.bodyValue(any(Map.class))) + .thenReturn(requestHeadersSpec); + when(requestHeadersSpec.accept(any(MediaType.class))) + .thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.header(anyString(), anyString())) + .thenReturn(requestBodyUriSpec); + String expected = "abcdeff"; + when(requestBodyUriSpec.exchangeToMono(any(Function.class))) + .thenReturn(Mono.just("abcdeff")); + String actual = formTokenAccessHandler.getAccessToken(); + assertEquals(expected, actual); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListenerTest.java new file mode 100644 index 0000000000..542e406ed6 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/commons/io/event/CamundaEventListenerTest.java @@ -0,0 +1,125 @@ +package org.camunda.bpm.extension.commons.io.event; + +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +/** + * Test class for CamundaEventListener + */ +@ExtendWith(SpringExtension.class) +public class CamundaEventListenerTest { + + @InjectMocks + public CamundaEventListener camundaEventListener; + + @Mock + private SimpMessagingTemplate template; + + /** + * Test perform a positive test over onTaskEventListener + * This test will validate the template + */ + @Test + public void onTaskEventListener_with_defaultEvents(){ + DelegateTask delegateTask = mock(DelegateTask.class); + when(delegateTask.getEventName()) + .thenReturn("create"); + + ReflectionTestUtils.setField(camundaEventListener, "messageCategory", "TASK_EVENT_DETAILS,TASK_EVENT"); + ReflectionTestUtils.setField(camundaEventListener, "messageEvents", "ALL"); + Map variables = new HashMap<>(); + variables.put("applicationId" , "id1"); + variables.put("formUrl" , "http://localhost:3001"); + variables.put("applicationStatus" , "New"); + when(delegateTask.getVariables()) + .thenReturn(variables); + camundaEventListener.onTaskEventListener(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(template, times(2)).convertAndSend(anyString(), captor.capture()); + assertEquals("{\"assignee\":null,\"createTime\":null,\"deleteReason\":null,\"description\":null,\"dueDate\":null,\"eventName\":\"create\",\"executionId\":null,\"followUpDate\":null,\"id\":null,\"name\":null,\"owner\":null,\"priority\":0,\"processDefinitionId\":null,\"processInstanceId\":null,\"taskDefinitionKey\":null,\"variables\":{\"applicationStatus\":null,\"formUrl\":null,\"applicationId\":null}}", + captor.getAllValues().get(0)); + assertEquals("{\"id\":null,\"eventName\":\"create\"}", captor.getAllValues().get(1)); + } + + /** + * Test perform a positive test with default message events + * This test will validate the template + */ + @Test + public void onTaskEventListener_with_default_messageEvents(){ + DelegateTask delegateTask = mock(DelegateTask.class); + when(delegateTask.getEventName()) + .thenReturn("create"); + + ReflectionTestUtils.setField(camundaEventListener, "messageCategory", "TASK_EVENT_DETAILS,TASK_EVENT"); + ReflectionTestUtils.setField(camundaEventListener, "messageEvents", "DEFAULT"); + Map variables = new HashMap<>(); + variables.put("applicationId" , "id1"); + variables.put("formUrl" , "http://localhost:3001"); + variables.put("applicationStatus" , "New"); + when(delegateTask.getVariables()) + .thenReturn(variables); + camundaEventListener.onTaskEventListener(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(template, times(2)).convertAndSend(anyString(), captor.capture()); + assertEquals("{\"assignee\":null,\"createTime\":null,\"deleteReason\":null,\"description\":null,\"dueDate\":null,\"eventName\":\"create\",\"executionId\":null,\"followUpDate\":null,\"id\":null,\"name\":null,\"owner\":null,\"priority\":0,\"processDefinitionId\":null,\"processInstanceId\":null,\"taskDefinitionKey\":null,\"variables\":{\"applicationStatus\":null,\"formUrl\":null,\"applicationId\":null}}", + captor.getAllValues().get(0)); + assertEquals("{\"id\":null,\"eventName\":\"create\"}", captor.getAllValues().get(1)); + } + + /** + * Test perform a positive test with custom message events + * This test will validate the template + */ + @Test + public void onTaskEventListener_with_custom_messageEvents() { + DelegateTask delegateTask = mock(DelegateTask.class); + when(delegateTask.getEventName()) + .thenReturn("create"); + + ReflectionTestUtils.setField(camundaEventListener, "messageCategory", "TASK_EVENT_DETAILS,TASK_EVENT"); + ReflectionTestUtils.setField(camundaEventListener, "messageEvents", "create"); + Map variables = new HashMap<>(); + variables.put("applicationId", "id1"); + variables.put("formUrl", "http://localhost:3001"); + variables.put("applicationStatus", "New"); + when(delegateTask.getVariables()) + .thenReturn(variables); + camundaEventListener.onTaskEventListener(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(template, times(2)).convertAndSend(anyString(), captor.capture()); + assertEquals( + "{\"assignee\":null,\"createTime\":null,\"deleteReason\":null,\"description\":null,\"dueDate\":null,\"eventName\":\"create\",\"executionId\":null,\"followUpDate\":null,\"id\":null,\"name\":null,\"owner\":null,\"priority\":0,\"processDefinitionId\":null,\"processInstanceId\":null,\"taskDefinitionKey\":null,\"variables\":{\"applicationStatus\":null,\"formUrl\":null,\"applicationId\":null}}", + captor.getAllValues().get(0)); + assertEquals("{\"id\":null,\"eventName\":\"create\"}", captor.getAllValues().get(1)); + } + + /** + * Negetive test case. + * Test perform with no events on onTaskEventListener + */ + @Test + public void onTaskEventListener_with_no_registeredEvents() { + DelegateTask delegateTask = mock(DelegateTask.class); + when(delegateTask.getEventName()) + .thenReturn("create"); + + camundaEventListener.onTaskEventListener(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(template, times(0)).convertAndSend(anyString(), captor.capture()); + } + +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/AdminControllerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/AdminControllerTest.java new file mode 100644 index 0000000000..199ddafa7b --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/AdminControllerTest.java @@ -0,0 +1,132 @@ +package org.camunda.bpm.extension.hooks.controllers; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +import net.minidev.json.JSONArray; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.camunda.bpm.extension.hooks.controllers.data.Authorization; +import org.camunda.bpm.extension.hooks.controllers.mapper.AuthorizationMapper; +import org.camunda.bpm.extension.hooks.controllers.stubs.AuthorizationStub; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Test class for AdminController + */ +@ExtendWith(SpringExtension.class) +public class AdminControllerTest { + + @InjectMocks + private AdminController adminController; + + private MockMvc mockMvc; + + @Mock + private Authentication auth; + + @Mock + private NamedParameterJdbcTemplate bpmJdbcTemplate; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + + @BeforeEach + public void setup() { + mockMvc = MockMvcBuilders.standaloneSetup(adminController).build(); + SecurityContextHolder.getContext().setAuthentication(auth); + + Map claims = new HashMap<>(); + JSONArray groups = new JSONArray(); + groups.add(new String("/camunda-admin")); + groups.add(new String("/formsflow/formsflow-reviewer")); + claims.put("groups", groups); + + OidcUser oidcUser = mock(OidcUser.class); + when(auth.getPrincipal()) + .thenReturn(oidcUser); + + when(oidcUser.getClaims()) + .thenReturn(claims); + + List authorizationList = new ArrayList<>(); + authorizationList.add(new AuthorizationStub("test-id-1","test-id-1","224233456456")); + given(bpmJdbcTemplate.query(anyString(), any(SqlParameterSource.class), any(AuthorizationMapper.class))) + .willReturn(authorizationList); + } + + /** + * This test case perform a positive test over getForms with admin group name + * Expect Status OK and content + */ + @Test + public void getFormsSuccess_with_adminGroupName() throws Exception { + final String adminGroupName = "camunda-admin"; + ReflectionTestUtils.setField(adminController, "adminGroupName", adminGroupName); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any())) + .thenReturn(ResponseEntity.ok("{\"totalCount\":\"2\",\"forms\":[" + + "{\"formId\":\"foi\",\"formName\":\"Freedom Of Information\",\"processKey\":\"224233456456\"}," + + "{\"formId\":\"nbl\",\"formName\":\"New Business Licence\",\"processKey\":\"456456456\"}]}")); + mockMvc.perform( + MockMvcRequestBuilders.get("/engine-rest-ext/form")) + .andExpect(status().isOk()) + .andExpect(content().string("[{\"formId\":\"foi\",\"formName\":\"Freedom Of Information\",\"processKey\":\"224233456456\"},{\"formId\":\"nbl\",\"formName\":\"New Business Licence\",\"processKey\":\"456456456\"}]")); + } + + /** + * This test case perform a positive test over getForms without admin group name + * Expect Status OK and content + */ + @Test + public void getFormsSuccess_without_adminGroupName() throws Exception { + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any())) + .thenReturn(ResponseEntity.ok("{\"totalCount\":\"2\",\"forms\":[" + + "{\"formId\":\"foi\",\"formName\":\"Freedom Of Information\",\"processKey\":\"224233456456\"}," + + "{\"formId\":\"nbl\",\"formName\":\"New Business Licence\",\"processKey\":\"456456456\"}]}")); + mockMvc.perform( + MockMvcRequestBuilders.get("/engine-rest-ext/form")) + .andExpect(status().isOk()) + .andExpect(content().string("[{\"formId\":\"foi\",\"formName\":\"Freedom Of Information\",\"processKey\":\"224233456456\"}]")); + } + + /** + * Expect Status OK and empty content + */ + @Test + public void getFormsFailure() throws Exception { + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any())) + .thenReturn(ResponseEntity.ok("{\"totalCount\":\"2\",\"forms\":[" + + "{\"formId\":\"foi\",\"formName\":\"Freedom Of Information\",\"processKey\":\"224233456456\"}," + + "{\"formId\":\"nbl\",\"formName\":\"New Business Licence\",\"processKey\":\"456456456\"]}")); + mockMvc.perform( + MockMvcRequestBuilders.get("/engine-rest-ext/form")) + .andExpect(status().isOk()) + .andExpect(content().string("[]")); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/TaskControllerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/TaskControllerTest.java new file mode 100644 index 0000000000..9f0e0459bd --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/TaskControllerTest.java @@ -0,0 +1,128 @@ +package org.camunda.bpm.extension.hooks.controllers; + +import net.minidev.json.JSONArray; +import org.camunda.bpm.extension.hooks.controllers.data.Task; +import org.camunda.bpm.extension.hooks.controllers.data.Variable; +import org.camunda.bpm.extension.hooks.controllers.stubs.TaskStub; +import org.camunda.bpm.extension.hooks.controllers.stubs.VariableStub; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Test class for TaskController + */ +@ExtendWith(SpringExtension.class) +public class TaskControllerTest { + + @InjectMocks + private TaskController taskController; + + private MockMvc mockMvc; + + @Mock + private Authentication auth; + + @Mock + private NamedParameterJdbcTemplate bpmJdbcTemplate; + + @BeforeEach + public void setup() { + mockMvc = MockMvcBuilders.standaloneSetup(taskController).build(); + SecurityContextHolder.getContext().setAuthentication(auth); + + Map claims = new HashMap<>(); + JSONArray groups = new JSONArray(); + groups.add(new String("/camunda-admin")); + groups.add(new String("/formsflow/formsflow-reviewer")); + claims.put("groups", groups); + + OidcUser oidcUser = mock(OidcUser.class); + when(auth.getPrincipal()) + .thenReturn(oidcUser); + + when(oidcUser.getClaims()) + .thenReturn(claims); + } + + /** + * This test case perform over getTasks method and success + * Expect Status OK + */ + @Test + public void getTasks_2xxSuccessful() throws Exception { + + List tasks = new ArrayList<>(); + List variables = new ArrayList<>(); + VariableStub variableStub = new VariableStub("applicationStatus", "New"); + variables.add(variableStub); + TaskStub taskStub = new TaskStub("pinst-1","pdef-1","task-1", "camunda-admin", "New", variables); + tasks.add(taskStub); + given(bpmJdbcTemplate.query(anyString(), any(SqlParameterSource.class), any(ResultSetExtractor.class))) + .willReturn(tasks); + mockMvc.perform( + MockMvcRequestBuilders.get("/engine-rest-ext/task")) + .andExpect(status().isOk()); + } + + /** + * This test case perform over getTasks method and success + * Expect Status OK + */ + @Test + public void getTasks_2xxSuccessful_with_param_taskId() throws Exception { + + List variables = new ArrayList<>(); + VariableStub variableStub = new VariableStub("applicationStatus", "New"); + variables.add(variableStub); + TaskStub taskStub = new TaskStub("pinst-1","pdef-1","task-1", "camunda-admin", "New", variables); + taskStub.setId("1"); + given(bpmJdbcTemplate.query(anyString(), any(SqlParameterSource.class), any(ResultSetExtractor.class))) + .willReturn(taskStub); + mockMvc.perform( + MockMvcRequestBuilders.get("/engine-rest-ext/task/{taskid}", "1")) + .andExpect(status().isOk()); + } + + /** + * This test case perform over getTasks method and success + * Expect Status 404 NOTFOUND + */ + @Test + public void getTasks_4xxNotFound_with_param_taskId() throws Exception { + + List variables = new ArrayList<>(); + VariableStub variableStub = new VariableStub("applicationStatus", "New"); + variables.add(variableStub); + TaskStub taskStub = new TaskStub("pinst-1","pdef-1","task-1", "camunda-admin", "New", variables); + given(bpmJdbcTemplate.query(anyString(), any(SqlParameterSource.class), any(ResultSetExtractor.class))) + .willReturn(taskStub); + mockMvc.perform( + MockMvcRequestBuilders.get("/engine-rest-ext/task/{taskid}", "1")) + .andExpect(status().is4xxClientError()); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/AuthorizationStub.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/AuthorizationStub.java new file mode 100644 index 0000000000..57ec52090f --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/AuthorizationStub.java @@ -0,0 +1,16 @@ +package org.camunda.bpm.extension.hooks.controllers.stubs; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.camunda.bpm.extension.hooks.controllers.data.Authorization; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AuthorizationStub extends Authorization { + + private String groupId; + private String userId; + private String resourceId; +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/TaskStub.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/TaskStub.java new file mode 100644 index 0000000000..b693fe1f44 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/TaskStub.java @@ -0,0 +1,22 @@ +package org.camunda.bpm.extension.hooks.controllers.stubs; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.camunda.bpm.extension.hooks.controllers.data.Task; +import org.camunda.bpm.extension.hooks.controllers.data.Variable; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class TaskStub extends Task { + + private String processInstanceId; + private String processDefinitionKey; + private String taskDefinitionKey; + private String groupName; + private String status; + private List variables; +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/VariableStub.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/VariableStub.java new file mode 100644 index 0000000000..4b02916ed4 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/controllers/stubs/VariableStub.java @@ -0,0 +1,15 @@ +package org.camunda.bpm.extension.hooks.controllers.stubs; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.camunda.bpm.extension.hooks.controllers.data.Variable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VariableStub extends Variable { + + private String name; + private String value; +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormDocumentTransformerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormDocumentTransformerTest.java new file mode 100644 index 0000000000..5d81e0eeb5 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormDocumentTransformerTest.java @@ -0,0 +1,55 @@ +package org.camunda.bpm.extension.hooks.delegates; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.extension.hooks.services.FormSubmissionService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Test class for FormDocumentTransformer + */ +@ExtendWith(SpringExtension.class) +public class FormDocumentTransformerTest { + + @InjectMocks + private FormDocumentTransformer formDocumentTransformer; + + @Mock + private FormSubmissionService formSubmissionService; + + /** + * This test case perform a positive test over execute method in FormDocumentTransformer + * There is a setVariable operations are happening over DelegateExecution + * By providing the variable this test will ensure it sets properly + */ + @Test + public void testFormDocumentTransformer_happyFlow() throws Exception { + Map variables = new HashMap<>(); + variables.put("formUrl", "http://localhost:3001"); + Map dataMap = new HashMap<>(); + dataMap.put("applicationStatus", "New"); + DelegateExecution execution = mock(DelegateExecution.class); + when(execution.getVariables()) + .thenReturn(variables); + when(formSubmissionService.retrieveFormValues(anyString())) + .thenReturn(dataMap); + + formDocumentTransformer.execute(execution); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(execution, times(1)).setVariable(anyString(), captor.capture()); + String expected = "New"; + String actual = captor.getValue(); + assertEquals(expected, actual); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegateTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegateTest.java new file mode 100644 index 0000000000..1ac3504b56 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/delegates/FormTextAnalysisDelegateTest.java @@ -0,0 +1,107 @@ +package org.camunda.bpm.extension.hooks.delegates; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.camunda.bpm.extension.hooks.delegates.data.TextSentimentData; +import org.camunda.bpm.extension.hooks.delegates.data.TextSentimentRequest; +import org.camunda.bpm.extension.hooks.services.FormSubmissionService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Test class for FormTextAnalysisDelegate + */ +@ExtendWith(SpringExtension.class) +public class FormTextAnalysisDelegateTest { + + @InjectMocks + private FormTextAnalysisDelegate formTextAnalysisDelegate; + + @Mock + private FormSubmissionService formSubmissionService; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + /** + * This test case perform a positive test over execute method in FormTextAnalysisDelegate + * This will verify the textSentimentRequest + */ + @Test + public void formTextAnalysisDelegate_happyFlow() throws Exception { + DelegateExecution execution = mock(DelegateExecution.class); + Map variable = new HashMap<>(); + variable.put("formUrl", "http://localhost:3001/submission/id1"); + variable.put("applicationId", 123); + when(execution.getVariables()) + .thenReturn(variable); + when(execution.getVariable("formUrl")) + .thenReturn(variable.get("formUrl")); + when(execution.getVariable("applicationId")) + .thenReturn(variable.get("applicationId")); + when(formSubmissionService.readSubmission(anyString())) + .thenReturn("{\"data\":{\"formId\":\"123\",\"formName\":\"New Business Licence\"," + + "\"description\":{\"type\":\"textAreaWithAnalytics\",\"topics\":[\"t1\",\"t2\"],\"text\":\"test\"}}}"); + List txtRecords = new ArrayList<>(); + txtRecords.add(formTextAnalysisDelegate.CreateTextSentimentData("description", + new ArrayList<>(Arrays.asList("t1","t2")), "test")); + TextSentimentRequest textSentimentRequest = new TextSentimentRequest(123, "http://localhost:3001/submission/id1",txtRecords); + ArgumentCaptor captor = ArgumentCaptor.forClass(TextSentimentRequest.class); + + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn("http://localhost:5001"); + formTextAnalysisDelegate.execute(execution); + verify(httpServiceInvoker).execute(anyString(), any(HttpMethod.class),captor.capture()); + assertEquals(textSentimentRequest, captor.getValue()); + } + + /** + * This test case perform a positive test over execute method in FormTextAnalysisDelegate + * This will handle the runtime Exception + */ + @Test + public void formTextAnalysisDelegate_with_nullSubmissionData() throws Exception { + DelegateExecution execution = mock(DelegateExecution.class); + Map variable = new HashMap<>(); + variable.put("formUrl", "http://localhost:3001/submission/id1"); + when(execution.getVariables()) + .thenReturn(variable); + when(formSubmissionService.readSubmission(anyString())) + .thenReturn(""); + assertThrows(RuntimeException.class, () -> { + formTextAnalysisDelegate.execute(execution); + }); + } + + /** + * This test case perform a test over execute method with empty submission data + * This will verify the TextSentimentRequest + */ + @Test + public void formTextAnalysisDelegate_with_emptySubmissionData() throws Exception { + DelegateExecution execution = mock(DelegateExecution.class); + Map variable = new HashMap<>(); + variable.put("formUrl", "http://localhost:3001/submission/id1"); + when(execution.getVariables()) + .thenReturn(variable); + when(formSubmissionService.readSubmission(anyString())) + .thenReturn("{}"); + formTextAnalysisDelegate.execute(execution); + verify(httpServiceInvoker, times(0)).execute(anyString(), any(HttpMethod.class),any(TextSentimentRequest.class)); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationAuditListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationAuditListenerTest.java new file mode 100644 index 0000000000..3e2d2c4dc7 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationAuditListenerTest.java @@ -0,0 +1,194 @@ +package org.camunda.bpm.extension.hooks.listeners; + +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.extension.hooks.listeners.data.Application; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.util.Properties; + +/** + * Test class for ApplicationAuditListener + */ +@ExtendWith(SpringExtension.class) +public class ApplicationAuditListenerTest { + + @InjectMocks + private ApplicationAuditListener applicationAuditListener; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + /** + * Application Audit Listener will be invoked with DelegateExecution parameter + * and success + */ + @Test + public void invokeApplicationAuditService_with_delegateExecution_with_success() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.CREATED); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + applicationAuditListener.notify(delegateExecution); + } + + /** + * Application Audit Listener will be invoked with DelegateExecution parameter + * and expecting a status code as 500 + */ + @Test + public void invokeApplicationAuditService_with_delegateExecution_with_statusCode500() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + assertThrows(RuntimeException.class, () -> { + applicationAuditListener.notify(delegateExecution); + }); + } + + /** + * Application Audit Listener will be invoked with DelegateExecution parameter + * and expecting IOException + */ + @Test + public void invokeApplicationAuditService_with_delegateExecution_with_ioException() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + doThrow(new IOException("Unable to read submission for: " +formUrl)). + when(httpServiceInvoker).execute(any(), any(HttpMethod.class), any(Application.class)); + assertThrows(RuntimeException.class, () -> { + applicationAuditListener.notify(delegateExecution); + }); + } + + /** + * Application Audit Listener will be invoked with DelegateTask parameter and + * success + */ + @Test + public void invokeApplicationAuditService_with_delegateTask_with_success() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.CREATED); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + applicationAuditListener.notify(delegateTask); + } + + /** + * Application Audit Listener will be invoked with DelegateTask parameter and + * expecting a status code as 500 + */ + @Test + public void invokeApplicationAuditService_with_delegateTask_with_statusCode500() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + assertThrows(RuntimeException.class, () -> { + applicationAuditListener.notify(delegateTask); + }); + } + + /** + * Application Audit Listener will be invoked with DelegateTask parameter and + * expecting IOException + */ + @Test + public void invokeApplicationAuditService_with_delegateTask_with_ioException() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + doThrow(new IOException("Unable to read submission for: " +formUrl)). + when(httpServiceInvoker).execute(any(), any(HttpMethod.class), any(Application.class)); + assertThrows(RuntimeException.class, () -> { + applicationAuditListener.notify(delegateTask); + }); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListenerTest.java new file mode 100644 index 0000000000..c7f41dab9a --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/ApplicationStateListenerTest.java @@ -0,0 +1,209 @@ +package org.camunda.bpm.extension.hooks.listeners; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.camunda.bpm.extension.hooks.listeners.data.Application; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.IOException; +import java.util.Properties; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * Test class for ApplicationStateListener + */ +@ExtendWith(SpringExtension.class) +public class ApplicationStateListenerTest { + + @InjectMocks + private ApplicationStateListener applicationStateListener; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + @Mock + private ApplicationAuditListener applicationAuditListener; + + /** + * This test case perform a positive test over notify method in ApplicationStateListener + * @throws IOException + */ + @Test + public void invokeApplicationService_with_delegateExecution_with_success() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.OK); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + doNothing().when(applicationAuditListener) + .invokeApplicationAuditService(delegateExecution); + applicationStateListener.notify(delegateExecution); + } + + /** + * This test case will evaluate ApplicationStateListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * Expectation will be to fail the case with Runtime Exception + * @throws IOException + */ + @Test + public void invokeApplicationService_with_delegateExecution_with_statusCode500() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + assertThrows(RuntimeException.class, () -> { + applicationStateListener.notify(delegateExecution); + }); + } + + /** + * This test case will evaluate ApplicationStateListener with a negative case + * This test case expect the formUrl to fail with ioexception + * Expectation will be to fail the case with Runtime Exception + * @throws IOException + */ + @Test + public void invokeApplicationService_with_delegateExecution_with_ioException() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + doThrow(new IOException("Unable to read submission for: " +formUrl)). + when(httpServiceInvoker).execute(any(), any(HttpMethod.class), any(Application.class)); + assertThrows(RuntimeException.class, () -> { + applicationStateListener.notify(delegateExecution); + }); + } + + /** + * This test case will evaluate ApplicationStateListener with a positive case + * @throws IOException + */ + @Test + public void invokeApplicationService_with_delegateTask_with_success() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.OK); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + doNothing().when(applicationAuditListener) + .invokeApplicationAuditService(delegateExecution); + applicationStateListener.notify(delegateTask); + } + + /** + * This test case will evaluate ApplicationStateListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * Expectation will be to fail the case with Runtime Exception + * @throws IOException + */ + @Test + public void invokeApplicationService_with_delegateTask_with_statusCode500() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + when(httpServiceInvoker.execute(any(), any(HttpMethod.class), any(Application.class))) + .thenReturn(responseEntity); + assertThrows(RuntimeException.class, () -> { + applicationStateListener.notify(delegateTask); + }); + } + + /** + * This test case will evaluate ApplicationStateListener with a negative case + * This test case expect the formUrl to fail with ioexception + * Expectation will be to fail the case with Runtime Exception + * @throws IOException + */ + @Test + public void invokeApplicationService_with_delegateTask_with_ioException() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + String apiUrl = "http://localhost:5000"; + String applicationStatus = "Success"; + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("api.url")) + .thenReturn(apiUrl); + when(delegateExecution.getVariable("formUrl")).thenReturn(formUrl); + when(delegateExecution.getVariable("applicationStatus")).thenReturn(applicationStatus); + when(delegateExecution.getVariable("applicationId")).thenReturn("id1"); + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + doThrow(new IOException("Unable to read submission for: " +formUrl)). + when(httpServiceInvoker).execute(any(), any(HttpMethod.class), any(Application.class)); + assertThrows(RuntimeException.class, () -> { + applicationStateListener.notify(delegateTask); + }); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListenerTest.java new file mode 100644 index 0000000000..abc18d39e6 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/BPMFormDataPipelineListenerTest.java @@ -0,0 +1,289 @@ +package org.camunda.bpm.extension.hooks.listeners; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.engine.delegate.Expression; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +/** + * Test class for BPMFormDataPipelineListener + */ +@ExtendWith(SpringExtension.class) +public class BPMFormDataPipelineListenerTest { + + @InjectMocks + private BPMFormDataPipelineListener bpmFormDataPipelineListener; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + private Expression fields; + + @BeforeEach + public void init(){ + this.fields = mock(Expression.class); + } + + /** + * This test case perform positive test over notify method in BPMFormDataPipelineListener + */ + @Test + public void patchFormAttributes_withInput_delegateExecution_with_statusOk() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any(List.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.OK)); + String payload = "[\"applicationStatus\",\"applicationId\"]"; + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "fields", this.fields); + when(this.fields.getValue(delegateExecution)) + .thenReturn(payload); + when(delegateExecution.getVariable("applicationStatus")) + .thenReturn("New"); + when(delegateExecution.getVariable("applicationId")) + .thenReturn(1); + bpmFormDataPipelineListener.notify(delegateExecution); + } + + /** + * This test case will evaluate BPMFormDataPipelineListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * Expectation will be to fail the case with Runtimeexception + * @throws IOException + */ + @Test + public void patchFormAttributes_withInput_delegateExecution_with_fieldValues() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any(List.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); + String payload = "[\"applicationStatus\",\"applicationId\"]"; + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "fields", this.fields); + when(this.fields.getValue(delegateExecution)) + .thenReturn(payload); + when(delegateExecution.getVariable("applicationStatus")) + .thenReturn("New"); + when(delegateExecution.getVariable("applicationId")) + .thenReturn(1); + assertThrows(RuntimeException.class, () -> { + bpmFormDataPipelineListener.notify(delegateExecution); + }); + } + + /** + * This test case will evaluate BPMFormDataPipelineListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * Expectation will be to fail the case with Runtimeexception + * @throws IOException + */ + @Test + public void patchFormAttributes_withInput_delegateExecution_with_emptyFieldValues() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any(List.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); + String payload = "[]"; + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "fields", this.fields); + when(this.fields.getValue(delegateExecution)) + .thenReturn(payload); + when(delegateExecution.getVariable("applicationStatus")) + .thenReturn("New"); + when(delegateExecution.getVariable("applicationId")) + .thenReturn(1); + assertThrows(RuntimeException.class, () -> { + bpmFormDataPipelineListener.notify(delegateExecution); + }); + } + + /** + * This test case will evaluate BPMFormDataPipelineListener with a positive case + * @throws IOException + */ + @Test + public void patchFormAttributes_withInput_delegateExecution_with_ioException() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String formUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + doThrow(new IOException("Test Failure")).when(httpServiceInvoker) + .execute(anyString(), any(HttpMethod.class), any(List.class)); + String payload = "[]"; + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "fields", this.fields); + when(this.fields.getValue(delegateExecution)) + .thenReturn(payload); + when(delegateExecution.getVariable("applicationStatus")) + .thenReturn("New"); + when(delegateExecution.getVariable("applicationId")) + .thenReturn(1); + assertThrows(RuntimeException.class, () -> { + bpmFormDataPipelineListener.notify(delegateExecution); + }); + } + + /** + * This test case will validate the behaviour with empty form Url + * @throws IOException + */ + @Test + public void patchFormAttributes_withInput_delegateExecution_with_emptyFormUrl() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + Map variables = new HashMap<>(); + when(delegateExecution.getVariables()) + .thenReturn(variables); + Logger LOGGER = mock(Logger.class); + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "LOGGER", LOGGER); + bpmFormDataPipelineListener.notify(delegateExecution); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(LOGGER).log(any(Level.class), captor.capture()); + assertEquals("Unable to read submission for null", captor.getValue()); + } + + /** + * This test case will evaluate BPMFormDataPipelineListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * Expectation will be to fail the case with Runtimeexception + * @throws IOException + */ + @Test + public void patchFormAttributes_withInput_delegateTask_with_fieldValues() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + String formUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any(List.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); + String payload = "[\"applicationStatus\",\"applicationId\"]"; + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "fields", this.fields); + when(this.fields.getValue(delegateExecution)) + .thenReturn(payload); + when(delegateExecution.getVariable("applicationStatus")) + .thenReturn("New"); + when(delegateExecution.getVariable("applicationId")) + .thenReturn(1); + assertThrows(RuntimeException.class, () -> { + bpmFormDataPipelineListener.notify(delegateTask); + }); + } + + /** + * This test case will evaluate BPMFormDataPipelineListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * Expectation will be to fail the case with Runtimeexception + * @throws IOException + */ + @Test + public void patchFormAttributes_withInput_delegateTask_with_emptyFieldValues() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + String formUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any(List.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); + String payload = "[]"; + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "fields", this.fields); + when(this.fields.getValue(delegateExecution)) + .thenReturn(payload); + when(delegateExecution.getVariable("applicationStatus")) + .thenReturn("New"); + when(delegateExecution.getVariable("applicationId")) + .thenReturn(1); + assertThrows(RuntimeException.class, () -> { + bpmFormDataPipelineListener.notify(delegateTask); + }); + } + + /** + * This test case will evaluate BPMFormDataPipelineListener with a positive case + * @throws IOException + */ + @Test + public void patchFormAttributes_withInput_delegateTask_with_ioException() throws IOException { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + String formUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + doThrow(new IOException("Test Failure")).when(httpServiceInvoker) + .execute(anyString(), any(HttpMethod.class), any(List.class)); + String payload = "[]"; + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "fields", this.fields); + when(this.fields.getValue(delegateExecution)) + .thenReturn(payload); + when(delegateExecution.getVariable("applicationStatus")) + .thenReturn("New"); + when(delegateExecution.getVariable("applicationId")) + .thenReturn(1); + assertThrows(RuntimeException.class, () -> { + bpmFormDataPipelineListener.notify(delegateTask); + }); + } + + /** + * This test case will validate the behaviour with empty form Url + */ + @Test + public void patchFormAttributes_withInput_delegateTask_with_emptyFormUrl(){ + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + Map variables = new HashMap<>(); + when(delegateExecution.getVariables()) + .thenReturn(variables); + Logger LOGGER = mock(Logger.class); + ReflectionTestUtils.setField(bpmFormDataPipelineListener, "LOGGER", LOGGER); + bpmFormDataPipelineListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(LOGGER).log(any(Level.class), captor.capture()); + assertEquals("Unable to read submission for null", captor.getValue()); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormBPMDataPipelineListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormBPMDataPipelineListenerTest.java new file mode 100644 index 0000000000..ea6dbf924c --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormBPMDataPipelineListenerTest.java @@ -0,0 +1,130 @@ +package org.camunda.bpm.extension.hooks.listeners; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.extension.hooks.services.FormSubmissionService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Test class for FormBPMDataPipelineListener + */ +@ExtendWith(SpringExtension.class) +public class FormBPMDataPipelineListenerTest { + + @InjectMocks + private FormBPMDataPipelineListener formBPMDataPipelineListener; + + @Mock + private FormSubmissionService formSubmissionService; + + /** + * This test case perform positive test over notify method in FormBPMDataPipelineListener + * There is setVariable operations are happening over DelegateExecution + * By providing the variable this test will ensure it sets properly + */ + @Test + public void syncFormVariables_with_delegateExecution_and_validFormUrl_test() throws Exception { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateExecution.setVariable("formUrl", actualFormUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + + Map dataMap = new HashMap<>(); + dataMap.put("name", "john"); + when(formSubmissionService.retrieveFormValues(actualFormUrl)) + .thenReturn(dataMap); + formBPMDataPipelineListener.notify(delegateExecution); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(delegateExecution, times(2)).setVariable(anyString(), captor.capture()); + assertEquals("john", captor.getValue()); + } + + /** + * This test case perform positive test over notify method in FormBPMDataPipelineListener + * There is setVariable operations are happening over DelegateTask + * By providing the variable this test will ensure it sets properly + */ + @Test + public void syncFormVariables_with_delegateTask_and_validFormUrl_test() throws Exception { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateTask.setVariable("formUrl", actualFormUrl); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateExecution.getVariables()) + .thenReturn(variables); + + Map dataMap = new HashMap<>(); + dataMap.put("name", "john"); + when(formSubmissionService.retrieveFormValues(actualFormUrl)) + .thenReturn(dataMap); + formBPMDataPipelineListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(delegateExecution).setVariable(anyString(), captor.capture()); + assertEquals("john", captor.getValue()); + } + + /** + * This test case perform negative test over notify method in FormBPMDataPipelineListener + * Expectation will be to fail the case with Runtime Exception + */ + @Test + public void syncFormVariables_with_delegateExecution_and_exception_test() throws Exception { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateExecution.setVariable("formUrl", actualFormUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + doThrow(new IOException("Unable to Sync Form Variables")) + .when(formSubmissionService).retrieveFormValues(actualFormUrl); + assertThrows(RuntimeException.class, () -> { + formBPMDataPipelineListener.notify(delegateExecution); + }); + + } + + /** + * This test case perform negative test over notify method in FormBPMDataPipelineListener + * Expectation will be to fail the case with Runtime Exception + */ + @Test + public void syncFormVariables_with_delegateTask_and_exception_test() throws Exception { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateTask.setVariable("formUrl", actualFormUrl); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateExecution.getVariables()) + .thenReturn(variables); + doThrow(new IOException("Unable to Sync Form Variables")) + .when(formSubmissionService).retrieveFormValues(actualFormUrl); + assertThrows(RuntimeException.class, () -> { + formBPMDataPipelineListener.notify(delegateTask); + }); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListenerTest.java new file mode 100644 index 0000000000..228ffd3f77 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/FormSubmissionListenerTest.java @@ -0,0 +1,125 @@ +package org.camunda.bpm.extension.hooks.listeners; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.extension.hooks.services.FormSubmissionService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Test class for FormSubmissionListener + */ +@ExtendWith(SpringExtension.class) +public class FormSubmissionListenerTest { + + @InjectMocks + private FormSubmissionListener formSubmissionListener; + + @Mock + private FormSubmissionService formSubmissionService; + + /** + * This test case perform positive test over notify method in FormSubmissionListener + * There is setVariable operations are happening over DelegateExecution + * By providing the variable this test will ensure it sets properly + */ + @Test + public void createRevision_with_delegateExecution_and_validFormUrl_test() throws Exception { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + String expectedFormUrl = "http://localhost:3001/form/id2"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateExecution.setVariable("formUrl", actualFormUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(formSubmissionService.createRevision(actualFormUrl)) + .thenReturn("id2"); + formSubmissionListener.notify(delegateExecution); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(delegateExecution, times(2)).setVariable(anyString(), captor.capture()); + assertEquals(expectedFormUrl, captor.getValue()); + } + + /** + * This test case perform positive test over notify method in FormSubmissionListener + * There is setVariable operations are happening over DelegateTask + * By providing the variable this test will ensure it sets properly + */ + @Test + public void createRevision_with_delegateTask_and_validFormUrl_test() throws Exception { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + String expectedFormUrl = "http://localhost:3001/form/id2"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateTask.setVariable("formUrl", actualFormUrl); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(formSubmissionService.createRevision(actualFormUrl)) + .thenReturn("id2"); + formSubmissionListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(delegateExecution).setVariable(anyString(), captor.capture()); + assertEquals(expectedFormUrl, captor.getValue()); + } + + /** + * This test case perform negative test over notify method in FormSubmissionListener + * Expectation will be to fail the case with Runtimeexception + */ + @Test + public void createRevision_with_delegateTask_and_exception_test() throws Exception { + DelegateTask delegateTask = mock(DelegateTask.class); + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateTask.setVariable("formUrl", actualFormUrl); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateExecution.getVariables()) + .thenReturn(variables); + doThrow(new IOException("Unable to read submission for: "+ actualFormUrl)) + .when(formSubmissionService).createRevision(actualFormUrl); + assertThrows(RuntimeException.class, () -> { + formSubmissionListener.notify(delegateTask); + }); + } + + /** + * This test case perform negative test over notify method in FormSubmissionListener + * Expectation will be to fail the case with Runtimeexception + */ + @Test + public void createRevision_with_delegateExecution_and_exception_test() throws Exception { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String actualFormUrl = "http://localhost:3001/form/id1"; + Map variables = new HashMap<>(); + variables.put("formUrl", actualFormUrl); + delegateExecution.setVariable("formUrl", actualFormUrl); + when(delegateExecution.getVariables()) + .thenReturn(variables); + doThrow(new IOException("Unable to read submission for: "+ actualFormUrl)) + .when(formSubmissionService).createRevision(actualFormUrl); + assertThrows(RuntimeException.class, () -> { + formSubmissionListener.notify(delegateExecution); + }); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListenerTest.java new file mode 100644 index 0000000000..48f8604c1d --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/EmailAttributesListenerTest.java @@ -0,0 +1,261 @@ +package org.camunda.bpm.extension.hooks.listeners.execution; + +import org.camunda.bpm.engine.IdentityService; +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.identity.User; +import org.camunda.bpm.engine.identity.UserQuery; +import org.camunda.bpm.engine.variable.Variables; +import org.junit.jupiter.api.Test; +import org.camunda.bpm.extension.hooks.listeners.stubs.UserStub; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Test class for EmailAttributesListener + */ +@ExtendWith(SpringExtension.class) +public class EmailAttributesListenerTest { + + @InjectMocks + private EmailAttributesListener emailAttributesListener; + + /** + * This test case perform a positive test over notify method in EmailAttributesListener + * The to field is set on template data for validation + * There are 4 setVariable operations are happening over DelegateExecution + * By providing the 4 variable this test will ensure it sets properly + */ + @Test + public void transform_emailAttributeData_mapToExecutionData_with_templateToAddressData_and_success(){ + + DelegateExecution execution = mock(DelegateExecution.class); + + Map variables = new HashMap<>(); + variables.put("receiverName", "Test User"); + variables.put("senderName", "John Honai"); + + Map dmnMap = new HashMap<>(); + dmnMap.put("to", "test@aot-technologies.com"); + dmnMap.put("body", "Hi @receiverName, This is @senderName"); + dmnMap.put("subject", "Test Subject from @senderName"); + dmnMap.put("cc", "admin@aot-technologies.com"); + variables.put("template", dmnMap); + + when(execution.getVariables()) + .thenReturn(variables); + + when(execution.getVariable("groupName")) + .thenReturn("camunda-admin"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + + ProcessEngine processEngine = mock(ProcessEngine.class); + when(execution.getProcessEngine()) + .thenReturn(processEngine); + IdentityService identityService = mock(IdentityService.class); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + emailAttributesListener.notify(execution); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Object.class); + verify(execution, times(4)).setVariable(anyString(), captor.capture()); + List allValues = captor.getAllValues(); + + //Validating for the expected 4 variables set / not + assertEquals(Variables.stringValue("Hi Test User, This is John Honai",true),allValues.get(0)); + assertEquals("Test Subject from John Honai",allValues.get(1)); + assertEquals("admin@aot-technologies.com",allValues.get(2)); + assertEquals("test@aot-technologies.com,john.honai@aot-technologies.com,peter.scots@aot-technologies.com",allValues.get(3)); + } + + /** + * This test case perform a positive test over notify method in EmailAttributesListener + * The to field is set on DelegateExecution data for validation + * There are 4 setVariable operations are happening over DelegateExecution + * By providing the 4 variable this test will ensure it sets properly + */ + @Test + public void transform_emailAttributeData_mapToExecutionData_with_executionToAddressData_and_success(){ + + DelegateExecution execution = mock(DelegateExecution.class); + + Map variables = new HashMap<>(); + variables.put("to", "test@aot-technologies.com"); + variables.put("receiverName", "Test User"); + variables.put("senderName", "John Honai"); + + Map dmnMap = new HashMap<>(); + dmnMap.put("body", "Hi @receiverName, This is @senderName"); + dmnMap.put("subject", "Test Subject from @senderName"); + dmnMap.put("cc", "admin@aot-technologies.com"); + variables.put("template", dmnMap); + + when(execution.getVariables()) + .thenReturn(variables); + + when(execution.getVariable("to")) + .thenReturn("test@aot-technologies.com"); + when(execution.getVariable("groupName")) + .thenReturn("camunda-admin"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + + ProcessEngine processEngine = mock(ProcessEngine.class); + when(execution.getProcessEngine()) + .thenReturn(processEngine); + IdentityService identityService = mock(IdentityService.class); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + emailAttributesListener.notify(execution); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Object.class); + verify(execution, times(4)).setVariable(anyString(), captor.capture()); + List allValues = captor.getAllValues(); + + //Validating for the expected 4 variables set / not + assertEquals(Variables.stringValue("Hi Test User, This is John Honai",true),allValues.get(0)); + assertEquals("Test Subject from John Honai",allValues.get(1)); + assertEquals("admin@aot-technologies.com",allValues.get(2)); + assertEquals("test@aot-technologies.com,john.honai@aot-technologies.com,peter.scots@aot-technologies.com",allValues.get(3)); + } + + /** + * This test case perform a positive test over notify method in EmailAttributesListener + * The to field is passed null in this test case + * There are 4 setVariable operations are happening over DelegateExecution + * By providing the 4 variable this test will ensure it sets properly + */ + @Test + public void transform_emailAttributeData_mapToExecutionData_with_emptyToAddressData_and_success(){ + + DelegateExecution execution = mock(DelegateExecution.class); + + Map variables = new HashMap<>(); + variables.put("receiverName", "Test User"); + variables.put("senderName", "John Honai"); + + Map dmnMap = new HashMap<>(); + dmnMap.put("body", "Hi @receiverName, This is @senderName"); + dmnMap.put("subject", "Test Subject from @senderName"); + dmnMap.put("cc", "admin@aot-technologies.com"); + variables.put("template", dmnMap); + + when(execution.getVariables()) + .thenReturn(variables); + when(execution.getVariable("groupName")) + .thenReturn("camunda-admin"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + + ProcessEngine processEngine = mock(ProcessEngine.class); + when(execution.getProcessEngine()) + .thenReturn(processEngine); + IdentityService identityService = mock(IdentityService.class); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + emailAttributesListener.notify(execution); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Object.class); + verify(execution, times(4)).setVariable(anyString(), captor.capture()); + List allValues = captor.getAllValues(); + + //Validating for the expected 4 variables set / not + assertEquals(Variables.stringValue("Hi Test User, This is John Honai",true),allValues.get(0)); + assertEquals("Test Subject from John Honai",allValues.get(1)); + assertEquals("admin@aot-technologies.com",allValues.get(2)); + assertEquals("john.honai@aot-technologies.com,peter.scots@aot-technologies.com",allValues.get(3)); + } + + /** + * This test case perform a positive test over notify method in EmailAttributesListener + * All fields are passed null in this test case + * There are only 3 setVariable operations are happening over DelegateExecution + * By providing the 3 variable this test will ensure it sets properly + */ + @Test + public void transform_emailAttributeData_mapToExecutionData_with_emptyData(){ + + DelegateExecution execution = mock(DelegateExecution.class); + + Map variables = new HashMap<>(); + Map dmnMap = new HashMap<>(); + variables.put("template", dmnMap); + + when(execution.getVariables()) + .thenReturn(variables); + when(execution.getVariable("groupName")) + .thenReturn("camunda-admin"); + List userList = new ArrayList<>(); + ProcessEngine processEngine = mock(ProcessEngine.class); + when(execution.getProcessEngine()) + .thenReturn(processEngine); + IdentityService identityService = mock(IdentityService.class); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + emailAttributesListener.notify(execution); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Object.class); + verify(execution, times(3)).setVariable(anyString(), captor.capture()); + List allValues = captor.getAllValues(); + + //Validating for the expected 3 variables set / not + assertEquals(Variables.stringValue(null,true),allValues.get(0)); + assertNull(allValues.get(1)); + assertEquals("",allValues.get(2)); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListenerTest.java new file mode 100644 index 0000000000..7defa13a96 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/ExternalSubmissionListenerTest.java @@ -0,0 +1,239 @@ +package org.camunda.bpm.extension.hooks.listeners.execution; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.Expression; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.camunda.bpm.extension.hooks.services.FormSubmissionService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Test class for ExternalSubmissionListener + */ +@ExtendWith(SpringExtension.class) +public class ExternalSubmissionListenerTest { + + @InjectMocks + private ExternalSubmissionListener externalSubmissionListener; + + @Mock + private FormSubmissionService formSubmissionService; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + private Expression formName; + + @BeforeEach + public void init(){ + formName = mock(Expression.class); + } + + /** + * This test case will evaluate ExternalSubmissionListener with a positive case + * Expectation will be to pass the scenario with submissionId validation + * @throws IOException + */ + @Test + public void notify_with_delegateExecution_with_httpStatus_created_with_success() throws IOException { + String formUrl = "http://localhost:3001"; + DelegateExecution execution = mock(DelegateExecution.class); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("formio.url")) + .thenReturn(formUrl); + String data = "TwoStepApproval"; + ReflectionTestUtils.setField(externalSubmissionListener, "formName", this.formName); + when(this.formName.getValue(execution)) + .thenReturn(data); + when(formSubmissionService.getFormIdByName(anyString())) + .thenReturn("test-id1"); + Map variables = new HashMap<>(); + when(execution.getVariables()) + .thenReturn(variables); + when(formSubmissionService.createFormSubmissionData(any())) + .thenReturn("{data:{}}"); + when(formSubmissionService.createSubmission(anyString(), anyString())) + .thenReturn("id1"); + when(execution.getVariable("formUrl")) + .thenReturn(formUrl); + when(execution.getProcessInstanceId()) + .thenReturn("instanceId-1"); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), anyString())) + .thenReturn(new ResponseEntity<>("{\"id\":\"id1\"}",HttpStatus.CREATED)); + externalSubmissionListener.notify(execution); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(execution, times(2)).setVariable(anyString(), captor.capture()); + assertEquals("id1", captor.getValue()); + } + + /** + * This test case will evaluate ExternalSubmissionListener with a negative case + * This test case expect the getformurl to fail with ioexception - positive case + * Expectation will be to fail the case with Runtimeexception + * @throws IOException + */ + @Test + public void notify_with_delegateExecution_with_getFormUrl_with_IOException() throws IOException { + + String formUrl = "http://localhost:3001"; + DelegateExecution execution = mock(DelegateExecution.class); + Properties properties = mock(Properties.class); + when(properties.getProperty("formio.url")) + .thenReturn(formUrl); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + String data = "TwoStepApproval"; + ReflectionTestUtils.setField(externalSubmissionListener, "formName", this.formName); + when(this.formName.getValue(execution)) + .thenReturn(data); + doThrow(new IOException("No form found")).when(formSubmissionService) + .getFormIdByName(anyString()); + assertThrows(RuntimeException.class, () -> { + externalSubmissionListener.notify(execution); + }); + } + + /** + * This test case will evaluate ExternalSubmissionListener with a negative case + * This test case expect the httpserviceinvoker to return created - positive case + * But while parsing the response an exception will be thrown + * Expectation will be to fail the case with Runtimeexception + * @throws IOException + */ + @Test + public void notify_with_delegateExecution_with_httpStatus_created_with_parsingException() throws IOException { + String formUrl = "http://localhost:3001"; + DelegateExecution execution = mock(DelegateExecution.class); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("formio.url")) + .thenReturn(formUrl); + String data = "TwoStepApproval"; + ReflectionTestUtils.setField(externalSubmissionListener, "formName", this.formName); + when(this.formName.getValue(execution)) + .thenReturn(data); + when(formSubmissionService.getFormIdByName(anyString())) + .thenReturn("test-id1"); + Map variables = new HashMap<>(); + when(execution.getVariables()) + .thenReturn(variables); + when(formSubmissionService.createFormSubmissionData(any())) + .thenReturn("{data:{}}"); + when(formSubmissionService.createSubmission(anyString(), anyString())) + .thenReturn("id1"); + when(execution.getVariable("formUrl")) + .thenReturn(formUrl); + when(execution.getProcessInstanceId()) + .thenReturn("instanceId-1"); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), anyString())) + .thenReturn(new ResponseEntity<>("}",HttpStatus.CREATED)); + assertThrows(RuntimeException.class, () -> { + externalSubmissionListener.notify(execution); + }); + } + + /** + * This test case will evaluate ExternalSubmissionListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * and also it will pass during the retry + * Expectation will be to pass the scenario with submissionId validation + * @throws IOException + */ + @Test + public void notify_with_delegateExecution_with_httpStatus_error_with_retryOnce_with_success() throws IOException { + String formUrl = "http://localhost:3001"; + DelegateExecution execution = mock(DelegateExecution.class); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("formio.url")) + .thenReturn(formUrl); + String data = "TwoStepApproval"; + ReflectionTestUtils.setField(externalSubmissionListener, "formName", this.formName); + when(this.formName.getValue(execution)) + .thenReturn(data); + when(formSubmissionService.getFormIdByName(anyString())) + .thenReturn("test-id1"); + Map variables = new HashMap<>(); + when(execution.getVariables()) + .thenReturn(variables); + when(formSubmissionService.createFormSubmissionData(any())) + .thenReturn("{data:{}}"); + when(formSubmissionService.createSubmission(anyString(), anyString())) + .thenReturn("id1"); + when(execution.getVariable("formUrl")) + .thenReturn(formUrl); + when(execution.getProcessInstanceId()) + .thenReturn("instanceId-1"); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), anyString())) + .thenReturn(new ResponseEntity<>("{\"id\":\"id1\"}",HttpStatus.INTERNAL_SERVER_ERROR)) + .thenReturn(new ResponseEntity<>("{\"id\":\"id1\"}",HttpStatus.CREATED)); + externalSubmissionListener.notify(execution); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(execution, times(2)).setVariable(anyString(), captor.capture()); + assertEquals("id1", captor.getValue()); + } + + /** + * This test case will evaluate ExternalSubmissionListener with a negative case + * This test case expect the httpserviceinvoker to return internal error + * and also it will continue fail during the retry as well + * Expectation will be to capture a Runtime exception + * @throws IOException + */ + @Test + public void notify_with_delegateExecution_with_httpStatus_error_with_retryOnce_with_fail() throws IOException { + String formUrl = "http://localhost:3001"; + DelegateExecution execution = mock(DelegateExecution.class); + Properties properties = mock(Properties.class); + when(httpServiceInvoker.getProperties()) + .thenReturn(properties); + when(properties.getProperty("formio.url")) + .thenReturn(formUrl); + String data = "TwoStepApproval"; + ReflectionTestUtils.setField(externalSubmissionListener, "formName", this.formName); + when(this.formName.getValue(execution)) + .thenReturn(data); + when(formSubmissionService.getFormIdByName(anyString())) + .thenReturn("test-id1"); + Map variables = new HashMap<>(); + when(execution.getVariables()) + .thenReturn(variables); + when(formSubmissionService.createFormSubmissionData(any())) + .thenReturn("{data:{}}"); + when(formSubmissionService.createSubmission(anyString(), anyString())) + .thenReturn("id1"); + when(execution.getVariable("formUrl")) + .thenReturn(formUrl); + when(execution.getProcessInstanceId()) + .thenReturn("instanceId-1"); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), anyString())) + .thenReturn(new ResponseEntity<>("{\"id\":\"id1\"}",HttpStatus.INTERNAL_SERVER_ERROR)) + .thenReturn(new ResponseEntity<>("{\"id\":\"id1\"}",HttpStatus.INTERNAL_SERVER_ERROR)); + assertThrows(RuntimeException.class, () -> { + externalSubmissionListener.notify(execution); + }); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/FormAccessTokenCacheListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/FormAccessTokenCacheListenerTest.java new file mode 100644 index 0000000000..18c96cbaca --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/execution/FormAccessTokenCacheListenerTest.java @@ -0,0 +1,57 @@ +package org.camunda.bpm.extension.hooks.listeners.execution; + +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.extension.hooks.services.FormSubmissionService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.IOException; +import java.util.List; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +/** + * Test class for FormAccessTokenCacheListener + */ +@ExtendWith(SpringExtension.class) +public class FormAccessTokenCacheListenerTest { + + @InjectMocks + private FormAccessTokenCacheListener formAccessTokenCacheListener; + + @Mock + private FormSubmissionService formSubmissionService; + + /** + * This test case perform a positive test over notify method in FormAccessTokenCacheListener + * This will validate the Test ID and Access Token + */ + @Test + public void get_Token_with_delegateExecution_test() throws IOException { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + String accessToken = "543789765427877936383638"; + when(formSubmissionService.getAccessToken()).thenReturn(accessToken); + ProcessEngine processEngine = mock(ProcessEngine.class); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + RuntimeService runtimeService = mock(RuntimeService.class); + when(processEngine.getRuntimeService()) + .thenReturn(runtimeService); + when(delegateExecution.getId()) + .thenReturn("testId"); + formAccessTokenCacheListener.notify(delegateExecution); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(runtimeService) + .setVariable(captor.capture(), anyString(), captor.capture()); + List captorValues = captor.getAllValues(); + assertEquals("testId", captorValues.get(0)); + assertEquals("543789765427877936383638", captorValues.get(1)); + } + +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/CustomUserStub.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/CustomUserStub.java new file mode 100644 index 0000000000..70a0eef487 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/CustomUserStub.java @@ -0,0 +1,7 @@ +package org.camunda.bpm.extension.hooks.listeners.stubs; + + +import org.camunda.bpm.extension.hooks.services.IUser; + +public class CustomUserStub implements IUser { +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/IdentityStub.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/IdentityStub.java new file mode 100644 index 0000000000..a9541a56bb --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/IdentityStub.java @@ -0,0 +1,22 @@ +package org.camunda.bpm.extension.hooks.listeners.stubs; + +import org.camunda.bpm.engine.task.IdentityLink; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class IdentityStub implements IdentityLink { + + private String id; + private String type; + private String groupId; + private String taskId; + private String processDefId; + private String tenantId; + private String userId; + +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/UserStub.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/UserStub.java new file mode 100644 index 0000000000..53df78240f --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/stubs/UserStub.java @@ -0,0 +1,18 @@ +package org.camunda.bpm.extension.hooks.listeners.stubs; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.camunda.bpm.engine.identity.User; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserStub implements User { + + private String id; + private String firstName; + private String lastName; + private String email; + private String password; +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/FormConnectorListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/FormConnectorListenerTest.java new file mode 100644 index 0000000000..24dc986f24 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/FormConnectorListenerTest.java @@ -0,0 +1,242 @@ +package org.camunda.bpm.extension.hooks.listeners.task; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.*; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.engine.delegate.Expression; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.camunda.bpm.extension.hooks.services.FormSubmissionService; +import org.camunda.bpm.model.bpmn.Query; +import org.camunda.bpm.model.bpmn.instance.ExtensionElements; +import org.camunda.bpm.model.bpmn.instance.FlowElement; +import org.camunda.bpm.model.bpmn.instance.camunda.CamundaProperties; +import org.camunda.bpm.model.bpmn.instance.camunda.CamundaProperty; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Test class for FormConnectorListener + */ +@ExtendWith(SpringExtension.class) +public class FormConnectorListenerTest { + + @InjectMocks + private FormConnectorListener formConnectorListener; + + @Mock + private FormSubmissionService formSubmissionService; + + @Mock + private Expression fields; + + @Mock + private Expression copyDataIndicator; + + @Mock + private DelegateTask delegateTask; + + @Mock + private DelegateExecution delegateExecution; + + @Mock + private FlowElement flowElement; + + @Mock + private ExtensionElements extensionElements; + + @Mock + private CamundaProperties camundaProperties; + + @Mock + private CamundaProperty camundaProperty; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + + /** + * This test case perform a positive test over notify method in FormConnectorListener + * Copy indicator is Y and formId is not empty + * This test will validate the new form Url with submission Id and form Id + */ + @Test + public void invokeNotify_with_createSubmission_with_copyDataIndicator_Y() throws IOException { + String formUrl = "http://localhost:3001/form/id1/submission"; + String applicationId1 = "63628738293"; + String applicationId2 = "7267864574"; + String json = "[\"applicationId1\",\"applicationId2\"]"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + variables.put("applicationId1", applicationId1); + variables.put("applicationId2", applicationId2); + when(delegateTask.getExecution()).thenReturn(delegateExecution); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(delegateExecution.getBpmnModelElementInstance()) + .thenReturn(flowElement); + when(flowElement.getExtensionElements()) + .thenReturn(extensionElements); + Query elementsQuery = mock(Query.class); + Query elementsQuery1 = mock(Query.class); + when(extensionElements.getElementsQuery()) + .thenReturn(elementsQuery); + when(elementsQuery.filterByType(CamundaProperties.class)) + .thenReturn(elementsQuery1); + when(elementsQuery1.singleResult()) + .thenReturn(camundaProperties); + when(camundaProperty.getCamundaValue()) + .thenReturn("TwoStepApproval"); + when(camundaProperty.getCamundaName()) + .thenReturn("formName"); + List camundaPropertyList = new ArrayList<>(Collections.singletonList(camundaProperty)); + when(camundaProperties.getCamundaProperties()) + .thenReturn(camundaPropertyList); + when(formSubmissionService.getFormIdByName(anyString())) + .thenReturn("id2"); + when(delegateExecution.getVariables().get("formUrl")) + .thenReturn(variables); + when(fields.getValue(delegateTask)) + .thenReturn(json); + when(copyDataIndicator.getValue(delegateTask)) + .thenReturn("Y"); + when(formSubmissionService.readSubmission(anyString())) + .thenReturn("{\"data\": {\"Form1\": \"Complete Submission\", \"Form3\": \"Review Submission\" }}"); + when(formSubmissionService.createSubmission(anyString(), anyString())) + .thenReturn("submissionid1"); + + formConnectorListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(delegateExecution).setVariable(anyString(), captor.capture()); + assertEquals("http://localhost:3001/form/id2/submission/submissionid1", captor.getValue()); + } + + /** + * This test case perform a positive test over notify method in FormConnectorListener + * Copy indicator is N and formId is not empty + * This test will validate the new form Url with submission Id and form Id + */ + @Test + public void invokeNotify_with_createSubmission_with_copyDataIndicator_N() throws IOException { + String formUrl = "http://localhost:3001/form/id1/submission"; + String applicationId1 = "63628738293"; + String applicationId2 = "7267864574"; + String json = "[\"applicationId1\",\"applicationId2\"]"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + variables.put("applicationId1", applicationId1); + variables.put("applicationId2", applicationId2); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(delegateExecution.getBpmnModelElementInstance()) + .thenReturn(flowElement); + when(flowElement.getExtensionElements()) + .thenReturn(extensionElements); + Query elementsQuery = mock(Query.class); + Query elementsQuery1 = mock(Query.class); + when(extensionElements.getElementsQuery()) + .thenReturn(elementsQuery); + when(elementsQuery.filterByType(CamundaProperties.class)) + .thenReturn(elementsQuery1); + when(elementsQuery1.singleResult()) + .thenReturn(camundaProperties); + when(camundaProperty.getCamundaValue()) + .thenReturn("TwoStepApproval"); + when(camundaProperty.getCamundaName()) + .thenReturn("formName"); + List camundaPropertyList = new ArrayList<>(Collections.singletonList(camundaProperty)); + when(camundaProperties.getCamundaProperties()) + .thenReturn(camundaPropertyList); + when(formSubmissionService.getFormIdByName(anyString())) + .thenReturn("id2"); + when(delegateExecution.getVariables().get("formUrl")) + .thenReturn(variables); + when(fields.getValue(delegateTask)).thenReturn(json); + when(copyDataIndicator.getValue(delegateTask)) + .thenReturn(""); + when(formSubmissionService.readSubmission(anyString())) + .thenReturn("{\"data\": {\"Form1\": \"Complete Submission\", \"Form3\": \"Review Submission\" }}"); + formConnectorListener.notify(delegateTask); + when(formSubmissionService.createSubmission(anyString(), anyString())) + .thenReturn("submissionid1"); + + formConnectorListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(delegateExecution).setVariable(anyString(), captor.capture()); + assertEquals("http://localhost:3001/form/id2/submission/submissionid1", captor.getValue()); + } + + /** + * This test case perform a negetive test over notify method in FormConnectorListener + * Copy indicator is Y and formId is empty + * This test will validate the behaviour with blank input + */ + @Test + public void invokeNotify_with_createSubmission_with_getFormId_empty() throws IOException { + String formUrl = "http://localhost:3001/form/id1/submission"; + String applicationId1 = "63628738293"; + String applicationId2 = "7267864574"; + String json = "[\"applicationId1\",\"applicationId2\"]"; + Map variables = new HashMap<>(); + variables.put("formUrl", formUrl); + variables.put("applicationId1", applicationId1); + variables.put("applicationId2", applicationId2); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(delegateExecution.getBpmnModelElementInstance()) + .thenReturn(flowElement); + when(flowElement.getExtensionElements()).thenReturn(extensionElements); + Query elementsQuery = mock(Query.class); + Query elementsQuery1 = mock(Query.class); + when(extensionElements.getElementsQuery()) + .thenReturn(elementsQuery); + when(elementsQuery.filterByType(CamundaProperties.class)) + .thenReturn(elementsQuery1); + when(elementsQuery1.singleResult()) + .thenReturn(camundaProperties); + when(camundaProperty.getCamundaValue()) + .thenReturn("TwoStepApproval"); + when(camundaProperty.getCamundaName()) + .thenReturn(""); + List camundaPropertyList = new ArrayList<>(Collections.singletonList(camundaProperty)); + when(camundaProperties.getCamundaProperties()) + .thenReturn(camundaPropertyList); + when(formSubmissionService.getFormIdByName(anyString())) + .thenReturn("id2"); + when(delegateExecution.getVariables().get("formUrl")) + .thenReturn(variables); + when(fields.getValue(delegateTask)) + .thenReturn(json); + when(copyDataIndicator.getValue(delegateTask)) + .thenReturn("Y"); + when(formSubmissionService.readSubmission(anyString())) + .thenReturn("{\"data\": {\"Form1\": \"Complete Submission\", \"Form3\": \"Review Submission\" }}"); + formConnectorListener.notify(delegateTask); + verify(formSubmissionService, times(0)) + .getFormIdByName(anyString()); + when(formSubmissionService.createSubmission(anyString(), anyString())) + .thenReturn("submissionid1"); + + formConnectorListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(delegateExecution).setVariable(anyString(), captor.capture()); + assertEquals("http://localhost:3001/form/null/submission/submissionid1", captor.getValue()); + } +} \ No newline at end of file diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListenerTest.java new file mode 100644 index 0000000000..af8e8edd58 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/NotifyListenerTest.java @@ -0,0 +1,355 @@ +package org.camunda.bpm.extension.hooks.listeners.task; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.camunda.bpm.engine.IdentityService; +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.ProcessEngineServices; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.engine.delegate.Expression; +import org.camunda.bpm.engine.identity.User; +import org.camunda.bpm.engine.identity.UserQuery; +import org.camunda.bpm.engine.task.IdentityLink; +import org.camunda.bpm.extension.hooks.listeners.stubs.IdentityStub; +import org.camunda.bpm.extension.hooks.listeners.stubs.UserStub; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Test class for NotifyListener + */ +@ExtendWith(SpringExtension.class) +public class NotifyListenerTest { + + @InjectMocks + private NotifyListener notifyListener; + + @Mock + private Expression messageId; + + @Mock + private Expression category; + + @Mock + private Expression emailGroups; + + @Mock + private Expression groupsOnly; + + @Mock + private DelegateTask delegateTask; + + @Mock + private DelegateExecution delegateExecution; + + @Mock + private ProcessEngine processEngine; + + @Mock + private IdentityService identityService; + + @Mock + private ProcessEngineServices processEngineServices; + + @Mock + private RuntimeService runtimeService; + + /** + * This test case perform a positive test over notify method in NotifyListener + * This test will validate the send message. + */ + @Test + public void invoke_notify_with_delegateTask_with_groupsOnly_Y_and_emailGroups() { + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(groupsOnly.getValue(delegateExecution)) + .thenReturn("Y"); + when(emailGroups.getValue(delegateExecution)) + .thenReturn("[\"forms-flow-designer\",\"forms-flow-clerk\"]"); + when(category.getValue(delegateExecution)) + .thenReturn("test-category"); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageId.getValue(delegateExecution)) + .thenReturn("id1"); + notifyListener.notify(delegateTask); + + ArgumentCaptor messageIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor messageVariableCaptor = ArgumentCaptor.forClass(Map.class); + verify(runtimeService).startProcessInstanceByMessage(messageIdCaptor.capture(), + messageVariableCaptor.capture()); + Map eMessageVariables = new HashMap<>(); + eMessageVariables.put("email_to", "john.honai@aot-technologies.com,peter.scots@aot-technologies.com"); + eMessageVariables.put("name", "Team"); + eMessageVariables.put("category", "test-category"); + eMessageVariables.put("taskid", "taskId-1"); + assertEquals("id1", messageIdCaptor.getValue()); + assertEquals(eMessageVariables, messageVariableCaptor.getValue()); + } + + /** + * This test case perform a positive test over notify method in NotifyListener + * This test will validate the send message. + */ + @Test + public void invoke_notify_with_delegateTask_with_groupsOnly_N_and_emailGroups() { + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(groupsOnly.getValue(delegateExecution)) + .thenReturn("N"); + when(emailGroups.getValue(delegateExecution)) + .thenReturn("[\"forms-flow-designer\",\"forms-flow-clerk\"]"); + when(category.getValue(delegateExecution)) + .thenReturn("test-category"); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + Set identityList = new HashSet<>(); + identityList.add(new IdentityStub("1", "CANDIDATE", "Honai", "Group1", "task1", "5678986", "tenant1")); + when(delegateTask.getCandidates()) + .thenReturn(identityList); + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageId.getValue(delegateExecution)) + .thenReturn("id1"); + notifyListener.notify(delegateTask); + ArgumentCaptor messageIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor messageVariableCaptor = ArgumentCaptor.forClass(Map.class); + verify(runtimeService).startProcessInstanceByMessage(messageIdCaptor.capture(), + messageVariableCaptor.capture()); + Map eMessageVariables = new HashMap<>(); + eMessageVariables.put("email_to", "john.honai@aot-technologies.com,peter.scots@aot-technologies.com"); + eMessageVariables.put("name", "Team"); + eMessageVariables.put("category", "test-category"); + eMessageVariables.put("taskid", "taskId-1"); + assertEquals("id1", messageIdCaptor.getValue()); + assertEquals(eMessageVariables, messageVariableCaptor.getValue()); + } + + /** + * This test case perform with empty email groups + * GroupOnly is Y + */ + @Test + public void invoke_notify_with_delegateTask_with_groupsOnly_Y_and_emailGroups_empty() { + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(groupsOnly.getValue(delegateExecution)) + .thenReturn("Y"); + when(emailGroups.getValue(delegateExecution)) + .thenReturn(""); + when(category.getValue(delegateExecution)) + .thenReturn("test-category"); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageId.getValue(delegateExecution)) + .thenReturn("id1"); + notifyListener.notify(delegateTask); + verify(runtimeService, times(0)).startProcessInstanceByMessage(anyString(), any(Map.class)); + } + + /** + * This test case perform with empty email groups + * GroupOnly is N + * This will validate the send message + */ + @Test + public void invoke_notify_with_delegateTask_with_groupsOnly_N_and_emailGroups_empty() { + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(groupsOnly.getValue(delegateExecution)) + .thenReturn("N"); + when(emailGroups.getValue(delegateExecution)) + .thenReturn(""); + when(category.getValue(delegateExecution)) + .thenReturn("test-category"); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + Set identityList = new HashSet<>(); + identityList.add(new IdentityStub("1", "CANDIDATE", "Honai", "Group1", "task1", "5678986", "tenant1")); + when(delegateTask.getCandidates()) + .thenReturn(identityList); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageId.getValue(delegateExecution)) + .thenReturn("id1"); + notifyListener.notify(delegateTask); + verify(runtimeService, times(1)).startProcessInstanceByMessage(anyString(), any(Map.class)); + + ArgumentCaptor messageIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor messageVariableCaptor = ArgumentCaptor.forClass(Map.class); + verify(runtimeService).startProcessInstanceByMessage(messageIdCaptor.capture(), + messageVariableCaptor.capture()); + Map eMessageVariables = new HashMap<>(); + eMessageVariables.put("email_to", "john.honai@aot-technologies.com,peter.scots@aot-technologies.com"); + eMessageVariables.put("name", "Team"); + eMessageVariables.put("category", "test-category"); + eMessageVariables.put("taskid", "taskId-1"); + assertEquals("id1", messageIdCaptor.getValue()); + assertEquals(eMessageVariables, messageVariableCaptor.getValue()); + + } + + /** + * Negetive test case. GroupOnly is Y and email groups is not empty + * To address is empty + */ + @Test + public void invoke_notify_with_delegateTask_with_groupsOnly_Y_and_emailGroups_with_toAddressempty() { + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(groupsOnly.getValue(delegateExecution)) + .thenReturn("Y"); + when(emailGroups.getValue(delegateExecution)) + .thenReturn("[\"forms-flow-designer\",\"forms-flow-clerk\"]"); + when(category.getValue(delegateExecution)) + .thenReturn("test-category"); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()).thenReturn(userList); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageId.getValue(delegateExecution)) + .thenReturn("id1"); + notifyListener.notify(delegateTask); + verify(runtimeService, times(0)).startProcessInstanceByMessage(anyString(), any(Map.class)); + } + +} \ No newline at end of file diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TaskDurationAttributesListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TaskDurationAttributesListenerTest.java new file mode 100644 index 0000000000..7fa235a4c7 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TaskDurationAttributesListenerTest.java @@ -0,0 +1,88 @@ +package org.camunda.bpm.extension.hooks.listeners.task; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +import java.util.Date; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.engine.delegate.Expression; +import org.camunda.bpm.extension.hooks.listeners.stubs.CustomUserStub; +import org.joda.time.DateTime; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Test class for TaskDurationAttributesListener + */ +@ExtendWith(SpringExtension.class) +public class TaskDurationAttributesListenerTest { + + @InjectMocks + TaskDurationAttributesListener taskDurationAttributesListener; + + @Mock + private Expression SLAInDays; + + @Mock + private DelegateTask delegateTask; + + @Mock + private DelegateExecution delegateExecution; + + @Captor + private ArgumentCaptor Captor; + + /** + * This test case will invoke notify method with SLA 5 days + * @throws Exception + * This will validate the due date + */ + @Test + public void notify_with_delegateTask_with_SLAIDays() throws Exception { + when(delegateTask.getExecution()).thenReturn(delegateExecution); + String startDate = new DateTime().toString(); + when(delegateTask.getExecution().getVariable(anyString())) + .thenReturn(startDate); + when(SLAInDays.getValue(delegateTask)).thenReturn(5); + taskDurationAttributesListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor dueDateCaptor = ArgumentCaptor.forClass(Date.class); + verify(delegateExecution, times(2)).setVariable(anyString(), captor.capture()); + verify(delegateTask).setDueDate(dueDateCaptor.capture()); + DateTime expected = new DateTime(captor.getAllValues().get(1)); + CustomUserStub customUserStub = new CustomUserStub(); + DateTime actual = customUserStub.addBusinessDays(new DateTime(startDate),5); + assertEquals(actual.toDate().toString(), dueDateCaptor.getValue().toString()); + assertEquals(actual, expected); + } + + /** + * This test case will invoke notify method with SLA 3 days by default + * This will validate the due date + */ + @Test + public void notify_with_delegateTask_with_SLAIDays_null() { + when(delegateTask.getExecution()).thenReturn(delegateExecution); + String startDate = new DateTime().toString(); + when(delegateTask.getExecution().getVariable(anyString())) + .thenReturn(startDate); + taskDurationAttributesListener.notify(delegateTask); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor dueDateCaptor = ArgumentCaptor.forClass(Date.class); + verify(delegateExecution, times(2)).setVariable(anyString(), captor.capture()); + verify(delegateTask).setDueDate(dueDateCaptor.capture()); + DateTime expected = new DateTime(captor.getAllValues().get(1)); + CustomUserStub customUserStub = new CustomUserStub(); + DateTime actual = customUserStub.addBusinessDays(new DateTime(startDate),3); + assertEquals(actual.toDate().toString(), dueDateCaptor.getValue().toString()); + assertEquals(actual, expected); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TimeoutNotifyListenerTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TimeoutNotifyListenerTest.java new file mode 100644 index 0000000000..81a75e744f --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/listeners/task/TimeoutNotifyListenerTest.java @@ -0,0 +1,345 @@ +package org.camunda.bpm.extension.hooks.listeners.task; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.camunda.bpm.engine.IdentityService; +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.ProcessEngineServices; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.DelegateTask; +import org.camunda.bpm.engine.delegate.Expression; +import org.camunda.bpm.engine.identity.User; +import org.camunda.bpm.engine.identity.UserQuery; +import org.camunda.bpm.engine.task.IdentityLink; +import org.camunda.bpm.extension.hooks.listeners.stubs.IdentityStub; +import org.camunda.bpm.extension.hooks.listeners.stubs.UserStub; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Test class for TimeoutNotifyListener + */ +@ExtendWith(SpringExtension.class) +public class TimeoutNotifyListenerTest { + + @InjectMocks + private TimeoutNotifyListener timeoutNotifyListener; + + @Mock + private Expression escalationGroup; + + @Mock + private Expression messageName; + + @Mock + private Expression currentDate; + + @Mock + private DelegateTask delegateTask; + + @Mock + private DelegateExecution delegateExecution; + + @Mock + private ProcessEngine processEngine; + + @Mock + private IdentityService identityService; + + @Mock + private UserQuery user; + + @Mock + private ProcessEngineServices processEngineServices; + + @Mock + private RuntimeService runtimeService; + + /** + * This test case perform a positive test over notify method in TimeoutNotifyListener + * Assignee is not blank and escalation true. + * This test will validate the send message. + */ + @Test + public void notify_with_DelegateTask_and_validateAssignee_escalation_assignee_not_blank() throws Exception { + when(currentDate.getValue(delegateTask)) + .thenReturn("2021-11-01T16:38:34.144+05:30"); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateTask.getExecution().getVariable(anyString())) + .thenReturn("2021-10-30T16:39:53.041+05:30"); + when(escalationGroup.getValue(delegateTask)) + .thenReturn("someGroup"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + User userId = userList.get(0); + when(delegateTask.getAssignee()) + .thenReturn("assigneeId1"); + when(userQuery.userId(anyString())) + .thenReturn(user); + when(userQuery.userId(anyString()).singleResult()) + .thenReturn(userId); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageName.getValue(delegateExecution)) + .thenReturn("Success"); + timeoutNotifyListener.notify(delegateTask); + + ArgumentCaptor messageNameCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor messageVariableCaptor = ArgumentCaptor.forClass(Map.class); + verify(runtimeService).startProcessInstanceByMessage(messageNameCaptor.capture(), + messageVariableCaptor.capture()); + Map eMessageVariables = new HashMap<>(); + eMessageVariables.put("cc", "john.honai@aot-technologies.com,peter.scots@aot-technologies.com"); + eMessageVariables.put("to", "john.honai@aot-technologies.com"); + eMessageVariables.put("category", "activity_escalation"); + eMessageVariables.put("taskid", "taskId-1"); + assertEquals("Success", messageNameCaptor.getValue()); + assertEquals(eMessageVariables, messageVariableCaptor.getValue()); + } + + /** + * This test case perform over notify method in TimeoutNotifyListener + * Assignee is blank and escalation true. + * This test will validate the send message. + */ + @Test + public void notify_with_DelegateTask_and_validateAssignee_escalation_and_assignee_blank() throws Exception { + when(currentDate.getValue(delegateTask)) + .thenReturn("2021-11-01T16:38:34.144+05:30"); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateTask.getExecution().getVariable(anyString())) + .thenReturn("2021-10-30T16:39:53.041+05:30"); + when(escalationGroup.getValue(delegateTask)) + .thenReturn("someGroup"); + + Set identityList = new HashSet(); + identityList.add(new IdentityStub("1", "CANDIDATE", "GROUP1", "TASK1", "PROCESS1", "TENANT-1", "Honai")); + when(delegateTask.getCandidates()) + .thenReturn(identityList); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + User userId = userList.get(0); + when(delegateTask.getAssignee()) + .thenReturn(""); + when(userQuery.userId(anyString())) + .thenReturn(user); + when(userQuery.userId(anyString()).singleResult()) + .thenReturn(userId); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageName.getValue(delegateExecution)) + .thenReturn("Success"); + timeoutNotifyListener.notify(delegateTask); + + ArgumentCaptor messageNameCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor messageVariableCaptor = ArgumentCaptor.forClass(Map.class); + verify(runtimeService).startProcessInstanceByMessage(messageNameCaptor.capture(), + messageVariableCaptor.capture()); + Map eMessageVariables = new HashMap<>(); + eMessageVariables.put("cc", "john.honai@aot-technologies.com,peter.scots@aot-technologies.com"); + eMessageVariables.put("to", "john.honai@aot-technologies.com,peter.scots@aot-technologies.com"); + eMessageVariables.put("category", "activity_escalation"); + eMessageVariables.put("taskid", "taskId-1"); + assertEquals("Success", messageNameCaptor.getValue()); + assertEquals(eMessageVariables, messageVariableCaptor.getValue()); + } + + /** + * This test case perform a positive test over notify method in TimeoutNotifyListener + * Assignee is not blank and reminder true. + * This test will validate the send message. + */ + @Test + public void notify_with_DelegateTask_and_validateAssignee_reminder_and_assignee_not_blank() throws Exception { + when(currentDate.getValue(delegateTask)) + .thenReturn("2021-10-30T16:51:29.115+05:30"); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateTask.getExecution().getVariable(anyString())) + .thenReturn("2021-10-31T16:51:29.183+05:30"); + when(escalationGroup.getValue(delegateTask)) + .thenReturn("someGroup"); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + User userId = userList.get(0); + when(delegateTask.getAssignee()) + .thenReturn("assigneeId1"); + when(userQuery.userId(anyString())) + .thenReturn(user); + when(userQuery.userId(anyString()).singleResult()) + .thenReturn(userId); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageName.getValue(delegateExecution)) + .thenReturn("Success"); + timeoutNotifyListener.notify(delegateTask); + + ArgumentCaptor messageNameCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor messageVariableCaptor = ArgumentCaptor.forClass(Map.class); + verify(runtimeService).startProcessInstanceByMessage(messageNameCaptor.capture(), + messageVariableCaptor.capture()); + Map eMessageVariables = new HashMap<>(); + eMessageVariables.put("to", "john.honai@aot-technologies.com"); + eMessageVariables.put("category", "activity_reminder"); + eMessageVariables.put("taskid", "taskId-1"); + assertEquals("Success", messageNameCaptor.getValue()); + assertEquals(eMessageVariables, messageVariableCaptor.getValue()); + } + + /** + * This test case perform over notify method in TimeoutNotifyListener + * Assignee is blank and reminder true. + * This test will validate the send message. + */ + @Test + public void notify_with_DelegateTask_and_validateAssignee_reminder_and_assignee_blank() throws Exception { + when(currentDate.getValue(delegateTask)) + .thenReturn("2021-10-30T16:51:29.115+05:30"); + when(delegateTask.getExecution()) + .thenReturn(delegateExecution); + when(delegateTask.getExecution().getVariable(anyString())) + .thenReturn("2021-10-31T16:51:29.183+05:30"); + when(escalationGroup.getValue(delegateTask)) + .thenReturn("someGroup"); + + Set identityList = new HashSet(); + identityList.add(new IdentityStub("1", "CANDIDATE", "GROUP1", "TASK1", "PROCESS1", "TENANT-1", "Honai")); + when(delegateTask.getCandidates()) + .thenReturn(identityList); + + List userList = new ArrayList<>(); + userList.add(new UserStub("1", "John", "Honai", "john.honai@aot-technologies.com", "password")); + userList.add(new UserStub("2", "Peter", "Scots", "peter.scots@aot-technologies.com", "password")); + when(delegateExecution.getProcessEngine()) + .thenReturn(processEngine); + when(processEngine.getIdentityService()) + .thenReturn(identityService); + UserQuery userQuery = mock(UserQuery.class); + UserQuery userQuery1 = mock(UserQuery.class); + when(identityService.createUserQuery()) + .thenReturn(userQuery); + when(userQuery.memberOfGroup(anyString())) + .thenReturn(userQuery1); + when(userQuery1.list()) + .thenReturn(userList); + User userId = userList.get(0); + when(delegateTask.getAssignee()) + .thenReturn(""); + when(userQuery.userId(anyString())) + .thenReturn(user); + when(userQuery.userId(anyString()).singleResult()) + .thenReturn(userId); + when(delegateTask.getId()) + .thenReturn("taskId-1"); + + when(delegateExecution.getProcessEngineServices()) + .thenReturn(processEngineServices); + when(delegateExecution.getProcessEngineServices().getRuntimeService()) + .thenReturn(runtimeService); + Map variables = new HashMap<>(); + variables.put("_file", new Object()); + when(delegateExecution.getVariables()) + .thenReturn(variables); + when(messageName.getValue(delegateExecution)) + .thenReturn("Success"); + timeoutNotifyListener.notify(delegateTask); + + ArgumentCaptor messageNameCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor messageVariableCaptor = ArgumentCaptor.forClass(Map.class); + verify(runtimeService).startProcessInstanceByMessage(messageNameCaptor.capture(), + messageVariableCaptor.capture()); + Map eMessageVariables = new HashMap<>(); + eMessageVariables.put("to", "john.honai@aot-technologies.com,peter.scots@aot-technologies.com"); + eMessageVariables.put("category", "activity_reminder"); + eMessageVariables.put("taskid", "taskId-1"); + assertEquals("Success", messageNameCaptor.getValue()); + assertEquals(eMessageVariables, messageVariableCaptor.getValue()); + } + +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/services/FormSubmissionServiceTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/services/FormSubmissionServiceTest.java new file mode 100644 index 0000000000..8c755b6ce6 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/hooks/services/FormSubmissionServiceTest.java @@ -0,0 +1,211 @@ +package org.camunda.bpm.extension.hooks.services; + +import org.camunda.bpm.engine.variable.Variables; +import org.camunda.bpm.extension.commons.connector.HTTPServiceInvoker; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +/** + * Test class for FormSubmissionService + */ +@ExtendWith(SpringExtension.class) +public class FormSubmissionServiceTest { + + @InjectMocks + private FormSubmissionService formSubmissionService; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + private static final String formUrl = "http://localhost:3001/form/615d4097163a6c58ae2e7668/submission"; + + /** + * This test case perform a positive test over read submission method + * This will validate the response + */ + @Test + public void readSubmission_happyFlow(){ + String expected = "{data:{}}"; + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>(expected, HttpStatus.OK)); + String actual = formSubmissionService.readSubmission(formUrl); + assertEquals(expected, actual); + } + + /** + * This test case perform a negative test over read submission method + * Expecting a runtime Exception + */ + @Test + public void readSubmission_with_status_notOK(){ + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR)); + assertThrows(RuntimeException.class, () -> { + formSubmissionService.readSubmission(formUrl); + }); + } + + /** + * This test case perform a positive test over createRevision method + * This will validate the response + */ + @Test + public void createRevision_happyFlow() throws IOException { + String expected = "ID1"; + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("{}", HttpStatus.OK)) + .thenReturn(new ResponseEntity<>("{\"_id\":\"ID1\"}", HttpStatus.CREATED)); + String actual = formSubmissionService.createRevision(formUrl); + assertEquals(expected, actual); + } + + /** + * This test case perform a negative test over createRevision method + * This will validate the behavior with null inputs + */ + @Test + public void createRevision_with_emptySubmissionData() throws IOException { + String expected = null; + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("", HttpStatus.OK)); + String actual = formSubmissionService.createRevision(formUrl); + assertEquals(expected, actual); + } + + /** + * This test case perform a negative test over createRevision method + * Expecting a runtime Exception + */ + @Test + public void createRevision_with_intenalServerError() { + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("{}", HttpStatus.OK)) + .thenReturn(new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR)); + assertThrows(RuntimeException.class, () -> { + formSubmissionService.createRevision(formUrl); + }); + } + + /** + * This test case perform a positive test over createSubmission method + * This will validate the response + */ + @Test + public void createSubmission_happyFlow() throws IOException { + String expected = "ID1"; + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("{\"_id\":\"ID1\"}", HttpStatus.CREATED)); + String actual = formSubmissionService.createSubmission(formUrl, "{}"); + assertEquals(expected, actual); + } + + /** + * This test case perform a negative test over createSubmission method + * This will validate the response + */ + @Test + public void createSubmission_with_internalError() { + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("{\"_id\":\"ID1\"}", HttpStatus.INTERNAL_SERVER_ERROR)); + assertThrows(RuntimeException.class, () -> { + formSubmissionService.createSubmission(formUrl, "{}"); + }); + } + + /** + * This test case perform a positive test over getFormIdByName method + * This will validate the formId + */ + @Test + public void getFormIdByName_happyFlow() throws IOException { + String expected = "ID1"; + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("{\"_id\":\"ID1\"}", HttpStatus.OK)); + String actual = formSubmissionService.getFormIdByName(formUrl); + assertEquals(expected, actual); + } + + /** + * This test case perform a negative test over getFormIdByName method + * This will validate the behavior with null input + */ + @Test + public void getFormIdByName_with_intenalServerError() { + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR)); + assertThrows(RuntimeException.class, () -> { + formSubmissionService.getFormIdByName(formUrl); + }); + } + + /** + * This test case perform a positive test over retrieveFormValues method + * This will validate the formValues + */ + @Test + public void retrieveFormValues_happyFlow_withOnlyFile() throws IOException { + Map expected = new HashMap(); + expected.put("test-filetest_file", Variables.fileValue("test-file.csv") + .file(new byte[]{}) + .mimeType("csv") + .create()); + expected.put("test_file_uploadname","test-file.csv"); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("{\"data\":{\"test_file\":[{" + + "\"url\":\"https://test-site/test-file.csv\",\"originalName\":\"test-file.csv\"," + + "\"type\":\"csv\"}]}}", HttpStatus.OK)); + Map actual = formSubmissionService.retrieveFormValues(formUrl); + assertEquals(expected.get("test_file_uploadname"), actual.get("test_file_uploadname")); + } + + /** + * This test case perform a positive test over retrieveFormValues method + * This will validate the response + */ + @Test + public void retrieveFormValues_happyFlow_withoutFile() throws IOException { + Map expected = new HashMap(); + expected.put("url", "https://test-site/test-file.csv"); + expected.put("originalName", "test-file.csv"); + expected.put("type", "csv"); + expected.put("details", null); + expected.put("isAvailable", true); + expected.put("count", 123); + expected.put("countInDouble", 123.343434343); + when(httpServiceInvoker.execute(anyString(), any(HttpMethod.class), any())) + .thenReturn(new ResponseEntity<>("{\"data\":{" + + "\"url\":\"https://test-site/test-file.csv\",\"originalName\":\"test-file.csv\"," + + "\"type\":\"csv\",\"details\":null,\"isAvailable\":true,\"count\":123,\"countInDouble\":123.343434343}}", HttpStatus.OK)); + Map actual = formSubmissionService.retrieveFormValues(formUrl); + assertEquals(expected, actual); + } + + /** + * This test case perform a positive test over createFormSubmissionData method + * This will validate the submission data + */ + @Test + public void createFormSubmissionData_happyFlow() throws IOException { + Map bpmVariables = new HashMap<>(); + String expected = "{\"data\":{\"applicationStatus\":\"New\"}}"; + bpmVariables.put("applicationStatus", "New"); + String actual = formSubmissionService.createFormSubmissionData(bpmVariables); + assertEquals(expected, actual); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/ConfigurationPropertyTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/ConfigurationPropertyTest.java new file mode 100644 index 0000000000..ed2d7c1ea3 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/ConfigurationPropertyTest.java @@ -0,0 +1,33 @@ +package org.camunda.bpm.extension.keycloak.rest; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(SpringExtension.class) +public class ConfigurationPropertyTest { + + /*@Autowired + private RestApiSecurityConfigurationProperties configProps; + + @Test + void test_restapisecurityconfig_propertybinding() { + assertEquals("keycloak", configProps.getProvider()); + assertEquals("camunda-rest-api", configProps.getRequiredAudience()); + assertEquals(true, configProps.getEnabled()); + } + + @EnableConfigurationProperties(RestApiSecurityConfigurationProperties.class) + public static class RestApiSecurityConfigurationPropertiesTest { + // nothing + }*/ +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilterTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilterTest.java new file mode 100644 index 0000000000..f16912e887 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/KeycloakAuthenticationFilterTest.java @@ -0,0 +1,91 @@ +package org.camunda.bpm.extension.keycloak.rest; + +import java.io.IOException; +import java.util.*; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import org.camunda.bpm.engine.IdentityService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import net.minidev.json.JSONArray; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Keycloak Authentication Filter Test - used for REST API Security. + * + * @author Sneha Suresh + */ +@ExtendWith(SpringExtension.class) +public class KeycloakAuthenticationFilterTest { + + @InjectMocks + private KeycloakAuthenticationFilter keycloakAuthenticationFilter; + + @Mock + private IdentityService identityService; + + @Mock + private OAuth2AuthorizedClientService clientService; + + @Mock + private Authentication auth; + + @Mock + private ServletRequest request; + + @Mock + private ServletResponse response; + + @Mock + private FilterChain chain; + + /** + * This test perform to check the groups and users + * This will validate the userId and userGroups + */ + @Test + public void doFilterTest() throws IOException, ServletException { + SecurityContextHolder.getContext().setAuthentication(auth); + + Map claims = new HashMap<>(); + String userId = "User1"; + JSONArray groups = new JSONArray(); + groups.add(new String("/camunda-admin")); + groups.add(new String("/formsflow/formsflow-reviewer")); + claims.put("groups", groups); + + OidcUser oidcUser = mock(OidcUser.class); + when(auth.getPrincipal()) + .thenReturn(oidcUser); + when(oidcUser.getName()) + .thenReturn(userId); + when(oidcUser.getClaims()) + .thenReturn(claims); + + keycloakAuthenticationFilter.doFilter(request, response, chain); + ArgumentCaptor userIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor userGroupsCaptor = ArgumentCaptor.forClass(List.class); + verify(identityService).setAuthentication(userIdCaptor.capture(), userGroupsCaptor.capture()); + List userGroups = new ArrayList<>(); + userGroups.add("camunda-admin"); + userGroups.add("formsflow/formsflow-reviewer"); + assertEquals("User1", userIdCaptor.getValue()); + assertEquals(userGroups, userGroupsCaptor.getValue()); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigTest.java new file mode 100644 index 0000000000..d163a9cbff --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/rest/RestApiSecurityConfigTest.java @@ -0,0 +1,90 @@ +package org.camunda.bpm.extension.keycloak.rest; + +import static org.camunda.bpm.engine.test.assertions.bpmn.AbstractAssertions.init; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.lang.reflect.Field; +import java.util.Properties; + +import javax.inject.Inject; + +import org.apache.ibatis.logging.LogFactory; +import org.camunda.bpm.engine.IdentityService; +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.camunda.bpm.extension.commons.connector.support.FormAccessHandler; +import org.camunda.bpm.extension.keycloak.KeycloakContext; +import org.camunda.bpm.extension.keycloak.KeycloakContextProvider; +import org.camunda.bpm.extension.keycloak.KeycloakIdentityProviderFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; + +/** + * @author Sneha Suresh + */ + +@ExtendWith(SpringExtension.class) +public class RestApiSecurityConfigTest { + + @InjectMocks + private RestApiSecurityConfig restApiSecurityConfig; + + @Mock + private RestApiSecurityConfigurationProperties configProps; + + @Mock + private IdentityService identityService; + + @Mock + private ApplicationContext applicationContext; + + @Mock + private OAuth2AuthorizedClientService clientService; + + @Mock + private Properties clientCredentialProperties; + + @Mock + private HttpSecurity http; + +// @Value("${spring.security.oauth2.client.provider.keycloak.token-uri}") +// private String accessTokenUri; +// +// @Value("${spring.security.oauth2.client.registration.keycloak.client-id}") +// private String clientId; +// +// @Value("${spring.security.oauth2.client.registration.keycloak.client-secret}") +// private String clientSecret; + +/* @Test + public void testExchange() throws Exception { + applicationContext.getEnvironment().getRequiredProperty( + "spring.security.oauth2.client.provider." + configProps.getProvider() + ".jwk-set-uri"); + restApiSecurityConfig.configure(http); + + }*/ +} \ No newline at end of file diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/task/LoggerDelegateTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/task/LoggerDelegateTest.java new file mode 100644 index 0000000000..86043ff662 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/task/LoggerDelegateTest.java @@ -0,0 +1,55 @@ +package org.camunda.bpm.extension.keycloak.task; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +import java.util.logging.Logger; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Test class for LoggerDelegate + */ +@ExtendWith(SpringExtension.class) +public class LoggerDelegateTest { + + @InjectMocks + private LoggerDelegate loggerDelegate; + + /** + * Positive test case This test case will validate if the passed data is + * printing correctly + * + * @throws Exception + */ + @Test + public void print_executionData_test() throws Exception { + DelegateExecution delegateExecution = mock(DelegateExecution.class); + when(delegateExecution.getProcessDefinitionId()).thenReturn("pro-def-1"); + when(delegateExecution.getCurrentActivityId()).thenReturn("act-3"); + when(delegateExecution.getCurrentActivityName()).thenReturn("test"); + when(delegateExecution.getProcessInstanceId()).thenReturn("proc-1"); + when(delegateExecution.getProcessBusinessKey()).thenReturn("123"); + when(delegateExecution.getId()).thenReturn("exec-1"); + loggerDelegate.execute(delegateExecution); + } + + /** + * Negative test case This test case will validate the behaviour with null input + */ + @Test + public void print_null_executionData_test() throws Exception { + DelegateExecution delegateExecution = null; + assertThrows(Exception.class, () -> { + loggerDelegate.execute(delegateExecution); + }); + } + +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/bpm/integration/ProcessIntegrationTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/bpm/integration/ProcessIntegrationTest.java similarity index 87% rename from forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/bpm/integration/ProcessIntegrationTest.java rename to forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/bpm/integration/ProcessIntegrationTest.java index 939abf8fd3..07cb827d73 100644 --- a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/bpm/integration/ProcessIntegrationTest.java +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/bpm/integration/ProcessIntegrationTest.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.test.bpm.integration; +package org.camunda.bpm.extension.keycloak.test.bpm.integration; import static org.camunda.bpm.engine.test.assertions.bpmn.AbstractAssertions.init; import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat; @@ -6,15 +6,16 @@ import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.runtimeService; import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.task; import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.withVariables; -import static org.camunda.bpm.extension.keycloak.showcase.test.util.ProcessTestAssertions.waitUntil; +import static org.camunda.bpm.extension.keycloak.test.util.ProcessTestAssertions.waitUntil; import static org.junit.Assert.assertNotNull; import org.apache.ibatis.logging.LogFactory; import org.camunda.bpm.engine.ProcessEngine; import org.camunda.bpm.engine.runtime.ProcessInstance; import org.camunda.bpm.engine.task.Task; -import org.camunda.bpm.extension.keycloak.showcase.ProcessConstants.Variable; -import org.camunda.bpm.extension.keycloak.showcase.plugin.KeycloakIdentityProvider; +import org.camunda.bpm.extension.keycloak.ProcessConstants; +import org.camunda.bpm.extension.keycloak.plugin.KeycloakIdentityProvider; +import org.camunda.bpm.extension.keycloak.test.util.ProcessTestAssertions; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -71,7 +72,7 @@ public void setup() { public void testApprovedPath() { // start process ProcessInstance pi = runtimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY, - withVariables(Variable.NAME, "Demo")); + withVariables(ProcessConstants.Variable.NAME, "Demo")); assertThat(pi).isStarted(); // check user task and approve user @@ -81,7 +82,7 @@ public void testApprovedPath() { complete(task, withVariables("approved", Boolean.TRUE)); // check service task (asynchronous continuation) - waitUntil(pi).hasPassed("ServiceTask_Logger"); + ProcessTestAssertions.waitUntil(pi).hasPassed("ServiceTask_Logger"); // check corresponding process end assertThat(pi).hasPassed("END_APPROVED"); @@ -97,7 +98,7 @@ public void testApprovedPath() { public void testNotApprovedPath() { // start process ProcessInstance pi = runtimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY, - withVariables(Variable.NAME, "Demo")); + withVariables(ProcessConstants.Variable.NAME, "Demo")); assertThat(pi).isStarted(); // check user task and do not approve user diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/bpm/local/ProcessLocalTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/bpm/local/ProcessLocalTest.java similarity index 93% rename from forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/bpm/local/ProcessLocalTest.java rename to forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/bpm/local/ProcessLocalTest.java index fac7201a7e..a84b113ed5 100644 --- a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/bpm/local/ProcessLocalTest.java +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/bpm/local/ProcessLocalTest.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.test.bpm.local; +package org.camunda.bpm.extension.keycloak.test.bpm.local; import static org.camunda.bpm.engine.test.assertions.bpmn.AbstractAssertions.init; import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat; @@ -20,8 +20,8 @@ import org.camunda.bpm.engine.test.Deployment; import org.camunda.bpm.engine.test.ProcessEngineRule; import org.camunda.bpm.engine.test.mock.Mocks; -import org.camunda.bpm.extension.keycloak.showcase.ProcessConstants.Variable; -import org.camunda.bpm.extension.keycloak.showcase.task.LoggerDelegate; +import org.camunda.bpm.extension.keycloak.ProcessConstants; +import org.camunda.bpm.extension.keycloak.task.LoggerDelegate; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -99,7 +99,7 @@ public void testParsingAndDeployment() { public void testApprovedPath() throws Exception { // start process ProcessInstance pi = runtimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY, - withVariables(Variable.NAME, "Demo")); + withVariables(ProcessConstants.Variable.NAME, "Demo")); assertThat(pi).isStarted(); // check user task and approve user @@ -128,7 +128,7 @@ public void testApprovedPath() throws Exception { public void testNotApprovedPath() throws Exception { // start process ProcessInstance pi = runtimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY, - withVariables(Variable.NAME, "Demo")); + withVariables(ProcessConstants.Variable.NAME, "Demo")); assertThat(pi).isStarted(); // check user task and do not approve user diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/util/ProcessTestAssertions.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/util/ProcessTestAssertions.java similarity index 99% rename from forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/util/ProcessTestAssertions.java rename to forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/util/ProcessTestAssertions.java index 6c5daf9730..57bc646065 100644 --- a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/showcase/test/util/ProcessTestAssertions.java +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/keycloak/test/util/ProcessTestAssertions.java @@ -1,4 +1,4 @@ -package org.camunda.bpm.extension.keycloak.showcase.test.util; +package org.camunda.bpm.extension.keycloak.test.util; import org.camunda.bpm.engine.history.HistoricProcessInstance; import org.camunda.bpm.engine.runtime.ProcessInstance; diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/OneStepApprovalTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/OneStepApprovalTest.java new file mode 100644 index 0000000000..34a3fa85c1 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/OneStepApprovalTest.java @@ -0,0 +1,57 @@ +package org.camunda.bpm.extension.process; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat; + +/** + * Created by DELL on 13-10-2021. + */ +@ExtendWith(SpringExtension.class) +public class OneStepApprovalTest /*extends ProcessEngineTestCase*/ { + + + /*private static final String PROCESS_DEFINITION_KEY = "onestepapproval"; + + @Mock + private HTTPServiceInvoker httpServiceInvoker; + + @Mock + private ApplicationAuditListener applicationAuditListener; + + @BeforeEach + public void setup() { + // set up java delegate to use the mocked tweet service + ApplicationStateListener applicationStateListener = new ApplicationStateListener(); + ReflectionTestUtils.setField(applicationStateListener, "httpServiceInvoker", this.httpServiceInvoker); + ReflectionTestUtils.setField(applicationStateListener, "applicationAuditListener", this.applicationAuditListener); + // register a bean name with mock expression manager + Mocks.register("httpServiceInvoker", this.httpServiceInvoker); + Mocks.register("applicationStateListener", applicationStateListener); + } + + @AfterAll + static void teardown() { + Mocks.reset(); + } + + @Deployment(resources = "one-step-approval.bpmn") + public void testDeployment(){ + + }*/ + +/* @Test + @Deployment(resources = "one-step-approval.bpmn") + public void testHappyPath() { + + ProcessInstance processInstance = processEngine().getRuntimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY + ,withVariables("applicationId", "id1")); + assertThat(processInstance).isStarted() + ; + *//*complete(task(), withVariables("approved", true)); + assertThat(processInstance).isWaitingAt("bookVacationUserTask"); + complete(task());*//* + assertThat(processInstance).isEnded(); + }*/ +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/SampleWorkflowTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/SampleWorkflowTest.java new file mode 100644 index 0000000000..5e1fc7bdd1 --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/SampleWorkflowTest.java @@ -0,0 +1,31 @@ +package org.camunda.bpm.extension.process; + +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.camunda.bpm.engine.test.Deployment; +import org.camunda.bpm.engine.test.ProcessEngineTestCase; +import org.junit.Test; + +import static org.camunda.bpm.engine.test.assertions.bpmn.AbstractAssertions.processEngine; +import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat; +import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.complete; +import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.task; + +public class SampleWorkflowTest extends ProcessEngineTestCase { + + private static final String PROCESS_DEFINITION_KEY = "testworkflow"; + + @Deployment(resources = "test-workflow.bpmn") + public void testDeployment(){ + + } + + @Test + @Deployment(resources = "test-workflow.bpmn") + public void testHappyPath() { + ProcessInstance processInstance = processEngine().getRuntimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY); + assertThat(processInstance).isStarted(); + assertThat(task(processInstance)).isNotNull(); + complete(task(processInstance)); + assertThat(processInstance).isEnded(); + } +} diff --git a/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/TwoStepApprovalTest.java b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/TwoStepApprovalTest.java new file mode 100644 index 0000000000..e9fe2199ab --- /dev/null +++ b/forms-flow-bpm/src/test/java/org/camunda/bpm/extension/process/TwoStepApprovalTest.java @@ -0,0 +1,11 @@ +package org.camunda.bpm.extension.process; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Created by DELL on 13-10-2021. + */ +@ExtendWith(SpringExtension.class) +public class TwoStepApprovalTest { +} diff --git a/forms-flow-bpm/src/test/resources/application.yaml b/forms-flow-bpm/src/test/resources/application.yaml index d96d83ba58..76d635cdff 100644 --- a/forms-flow-bpm/src/test/resources/application.yaml +++ b/forms-flow-bpm/src/test/resources/application.yaml @@ -1,12 +1,13 @@ # Test configuration using spring-boot +formsflow.ai: + api: + url: http://localhost:5000 + camunda.bpm: job-execution.enabled: true id-generator: simple -spring.datasource: - url: jdbc:h2:mem:camunda-spring-boot-test;DB_CLOSE_ON_EXIT=false - plugin.identity.keycloak.rest: userNameClaim: preferred_username authorityPrefix: "ROLE_" @@ -25,3 +26,26 @@ spring: spring.data.redis.repositories.enabled: false spring.autoconfigure.exclude: - org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration + +rest.security: + enabled: true + provider: keycloak + required-audience: camunda-rest-api + +plugin.identity.keycloak: + keycloakIssuerUrl: http://localhost:8080/auth/realms/forms-flow-ai + keycloakAdminUrl: http://localhost:8080/auth/admin/realms/forms-flow-ai + clientId: forms-flow-bpm + clientSecret: e3238a38-5e5a-45bb-b4e6-d7eb5855cf3a + useEmailAsCamundaUserId: false + useUsernameAsCamundaUserId: true + useGroupPathAsCamundaGroupId: true + administratorGroupName: camunda-admin + disableSSLCertificateValidation: true + +spring.datasource: + jdbc-url: jdbc:h2:./camunda-db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + username: sa + password: sa + driverClassName: org.h2.Driver + type: com.zaxxer.hikari.HikariDataSource \ No newline at end of file diff --git a/forms-flow-bpm/src/test/resources/camunda.local.cfg.xml b/forms-flow-bpm/src/test/resources/camunda.cfg.xml similarity index 66% rename from forms-flow-bpm/src/test/resources/camunda.local.cfg.xml rename to forms-flow-bpm/src/test/resources/camunda.cfg.xml index a178e46873..5d0f458d13 100644 --- a/forms-flow-bpm/src/test/resources/camunda.local.cfg.xml +++ b/forms-flow-bpm/src/test/resources/camunda.cfg.xml @@ -5,6 +5,17 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> + + + + + + + + + + + diff --git a/forms-flow-bpm/src/test/resources/one-step-approval.bpmn b/forms-flow-bpm/src/test/resources/one-step-approval.bpmn new file mode 100644 index 0000000000..9e2ce50a34 --- /dev/null +++ b/forms-flow-bpm/src/test/resources/one-step-approval.bpmn @@ -0,0 +1,117 @@ + + + + + SequenceFlow_0ociprs + + + + + + + + task.execution.setVariable('applicationStatus', task.execution.getVariable('action')); +task.execution.setVariable('deleteReason', "completed"); + + + SequenceFlow_0ociprs + SequenceFlow_0jg4sg3 + + + + + execution.setVariable('applicationStatus', 'New'); + + + + ["applicationId","applicationStatus"] + + + + + + + SequenceFlow_00bn1p7 + + + SequenceFlow_0jg4sg3 + SequenceFlow_1x38yu4 + SequenceFlow_0pc6hcp + + + + + + + + ["applicationId","applicationStatus"] + + + + + SequenceFlow_1x38yu4 + SequenceFlow_0pc6hcp + SequenceFlow_00bn1p7 + + + + ${action == 'Approved'} + + + ${action == 'Rejected'} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/forms-flow-bpm/src/test/resources/processes/two-step-approval.bpmn b/forms-flow-bpm/src/test/resources/processes/two-step-approval.bpmn new file mode 100644 index 0000000000..564e3972b4 --- /dev/null +++ b/forms-flow-bpm/src/test/resources/processes/two-step-approval.bpmn @@ -0,0 +1,309 @@ + + + + + + + + + StartEvent_1 + ExclusiveGateway_0xgo1b6 + Task_05ulff4 + + + Clerk + + + Approver + Gateway_1v4jtnt + Activity_0to53jt + Event_14ury70 + + + + + + execution.setVariable('applicationStatus', 'New'); + + + + ["applicationId", "applicationStatus"] + + + + + + + + + + + + ["applicationId", "applicationStatus"] + + + + ${action == 'Reviewed'} + + + + + execution.setVariable('applicationStatus', "Resubmitted"); + + + + + ["applicationId", "applicationStatus"] + + + + ${sendback_by == 'Clerk'} + + + + + execution.setVariable('applicationStatus', "Resubmitted"); + + + + + ["applicationId", "applicationStatus"] + + + + ${sendback_by == 'Approver'} + + + + + execution.setVariable('sendback_by', "Approver"); + + + + + + ["applicationId", "applicationStatus", "sendback_by"] + + + + ${action == 'Returned'} + + + + + execution.setVariable('sendback_by', "Clerk"); + + + + + + ["applicationId", "applicationStatus", "sendback_by"] + + + + ${action == 'Returned'} + + + + SequenceFlow_09ahed3 + SequenceFlow_009hwyx + SequenceFlow_07hh4hx + + + + + task.execution.setVariable('applicationStatus', task.execution.getVariable('action')); +task.execution.setVariable('deleteReason', "completed"); + + + SequenceFlow_0xvu6g6 + SequenceFlow_07hh4hx + Flow_0p0ggqr + + + + + task.execution.setVariable('applicationStatus', task.execution.getVariable('action')); +task.execution.setVariable('deleteReason', "completed"); + + + SequenceFlow_0byzagb + SequenceFlow_009hwyx + SequenceFlow_0xvu6g6 + SequenceFlow_0m9aeyc + + + SequenceFlow_0byzagb + + + + Flow_0p0ggqr + Flow_19h7qlh + Flow_0rjn1gz + SequenceFlow_0r45fgh + + + + + + + ["applicationId", "applicationStatus"] + + + + + Flow_19h7qlh + Flow_0rjn1gz + Flow_11o2r98 + + + ${action == 'Approved'} + + + ${action == 'Rejected'} + + + + Flow_11o2r98 + + + + + execution.setVariable('applicationStatus', "Resubmit"); + + + + + + ["applicationId", "applicationStatus"] + + + + SequenceFlow_0r45fgh + SequenceFlow_0m9aeyc + SequenceFlow_09ahed3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/forms-flow-bpm/upgrade/UPGRADE.md b/forms-flow-bpm/upgrade/UPGRADE.md new file mode 100644 index 0000000000..1003f84147 --- /dev/null +++ b/forms-flow-bpm/upgrade/UPGRADE.md @@ -0,0 +1,20 @@ +# forms-flow-bpm Upgrade + +The below given dependencies are upgraded to the latest as part of this upgrade. + + Dependency name | Old version | New version | Description | + --- | --- | --- | --- + `camunda-bpm-identity-keycloak` | `2.0.0` | `2.2.1` | Camunda keycloak identity provider upgrade + `camunda` | `7.13.0` | `7.15.0` | Camunda version upgrade + `springboot` | `2.4.2` | `2.4.8` | Springboot upgrade + `spring-security-oauth2` | `2.4.2` | `2.4.8` | Oauth2 upgrade + + + Since camunda upgrade `7.13.0` to `7.15.0` includes db changes. Please run the [upgrade file](./process-engine_7.13_to_7.15.sql) after the `forms-flow-bpm-db` service is up. + + ### Steps to run the upgrade file + +* Open a postgres client installed on your machine `eg: pgAdmin, Dbeaver etc`. +* Open the `Query Editor` to run `.sql` file. +* Copy and paste the [upgrade file](./process-engine_7.13_to_7.15.sql). +* Click on `Run` icon to execute the script. diff --git a/forms-flow-bpm/upgrade/process-engine_7.13_to_7.15.sql b/forms-flow-bpm/upgrade/process-engine_7.13_to_7.15.sql new file mode 100644 index 0000000000..bc89e17f93 --- /dev/null +++ b/forms-flow-bpm/upgrade/process-engine_7.13_to_7.15.sql @@ -0,0 +1,27 @@ +insert into ACT_GE_SCHEMA_LOG +values ('400', CURRENT_TIMESTAMP, '7.15.0'); + +ALTER TABLE ACT_RU_VARIABLE + ADD BATCH_ID_ varchar(64); +CREATE INDEX ACT_IDX_BATCH_ID ON ACT_RU_VARIABLE(BATCH_ID_); +ALTER TABLE ACT_RU_VARIABLE + ADD CONSTRAINT ACT_FK_VAR_BATCH + FOREIGN KEY (BATCH_ID_) + REFERENCES ACT_RU_BATCH (ID_); + +create index ACT_IDX_VARIABLE_TASK_NAME_TYPE on ACT_RU_VARIABLE(TASK_ID_, NAME_, TYPE_); + +create table ACT_RU_TASK_METER_LOG ( + ID_ varchar(64) not null, + ASSIGNEE_HASH_ bigint, + TIMESTAMP_ timestamp, + primary key (ID_) +); + +create index ACT_IDX_TASK_METER_LOG_TIME on ACT_RU_TASK_METER_LOG(TIMESTAMP_); + +ALTER TABLE ACT_RU_INCIDENT + ADD ANNOTATION_ varchar(4000); + +ALTER TABLE ACT_HI_INCIDENT + ADD ANNOTATION_ varchar(4000); diff --git a/forms-flow-forms/Changelog.md b/forms-flow-forms/Changelog.md index 28323ea236..19880ecb1a 100644 --- a/forms-flow-forms/Changelog.md +++ b/forms-flow-forms/Changelog.md @@ -4,6 +4,453 @@ All notable changes to this project will be documented in this file The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/) +## 2.3.0 +### Changed + - Official Release + - Updated formio-workers@1.16.0 + +## 2.3.0-rc.17 +### Changed + - Updated formiojs@4.14.0-rc.36 + +## 2.3.0-rc.16 +### Fixed + - Adding /current back to permission whitelist. + +## 2.3.0-rc.15 +### Fixed + - Issue where Reset Password was not calling next method. + +## 2.3.0-rc.14 +### Changed + - Upgrade formio-workers@1.16.0-rc.2 + +### Fixed + - FIO-805: empty stage creating issue fix + +## 2.3.0-rc.13 +### Fixed + - FIO-3783: Build fix + - FIO-3780: direct the sending of emails without user parameter to non-priority tasks queue + +### Changed + - FIO-3054: Add check of primary admin + - Upgrade formio.js@4.14.0-rc.33 + +## 2.3.0-rc.12 + - Revert "FIO-3763 Close ability to hit a form with get request as an anonymous…" + +## 2.3.0-rc.11 +### Changed + - Upgrade formio@4.14.0-rc.29 + - Upgrade mongoose@6.0.11, mocha@9.1.3 + - Revert "FIO-3783 Added renderingMethod option to Email action." + +## 2.3.0-rc.10 +### Changed + - Upgrade formio-workers@1.16.0-rc.1 + - Upgrade mongodb@4.1.3, mongoose@6.0.10, vm2@3.9.4, mocha@9.1.2, nodemon@2.0.13, @azure/ms- +rest-nodeauth@3.1.0, mailgun.js@3.6.0, nodemailer@6.7.0, adm-zip@0.5.9 + +## 2.3.0-rc.9 +### Fixed + - FIO-3436: Refactored so that any email address can be set as Reply-To + - FIO-3783: Added renderingMethod option to Email action. + - FIO-3950: Export JSON/CSV doesn't work + - FIO-3763 Close ability to hit a form with get request as an anonymous user while form access turned off + - FIO-3561: Required field is showing as invalid and form can't be submitted + +## 2.3.0-rc.8 +### Changed + - Upgrade mailgun.js@3.5.9, mongodb@4.1.2, mongoose@6.0.6, adm-zip@0.5.6 + +## 2.3.0-rc.7 +### Changed + - Upgrade formiojs@4.14.0-rc.25 + +### Fixed + - Bootup race conditions. + - FIO-3403: feat(import): search for existing roles in DB when importing an incomplete template + - FIO-1453: fixed search for missing resources + +## 2.3.0-rc.6 +### Fixed + - Problem where the MongoDB sslCA was reading it as a string and messing up the mongo driver. + +## 2.3.0-rc.5 +### Changed + - Fixed the field based access. + +## 2.3.0-rc.4 +### Changed + - Adding an index to the key of the tokens collection to resolve performance issues. + - Upgrade chance@1.1.8, csv@5.5.3, mailgun.js@3.5.8, mongoose@6.0.4, mocha@9.1.1 + +### Fixed + - Fixing issue with mailgun not working with latest version. + - Fixed an SSL Cert issue related to mongoose. + +## 2.3.0-rc.3 +### Changed + - Upgrade dependencies and fixed tests. + +## 2.3.0-rc.2 +### Fixed + - Issue with loading SSL CA file with latest mongodb driver. + +### Changed + - Upgrade mongodb@4.1.1, prompt@1.2.0, mongoose@6.0.2 + +## 2.3.0-rc.1 +### Fixed + - FIO-790: checkbox set as radio showing blank on CSV downloads issue + - FIO-1442: Adds an ability to set transformers for the specific fields in the csv exporter. + - FIO-3555, FIO-1538: Implements 2FA + - FIO-1038: limiting default email usage provider + - FIO-899: removing roles issue fix + - FIO-885: Import/Export database error handling + - FIO-2764: Fixes an issue when the signature component was set a default value with noDefaults option + - FIO-3624: fixed problem on sending get request to /token endpoint using x-token header + - FIO-3583: Fixed issue with recursion in the form load routines. + - Issues related to the MongoDB 4.1.0 upgrade. + +### Added + - FIO-3435: form definition downloading according query parameter + - FIO-3436: ability to set reply to header + +### Changed + - Upgrade formiojs@4.14.0-rc.19 + - Upgrade mongodb@4.1.0 + - Upgrade async@3.2.1, mailgun.js@3.5.7, mongoose@5.13.8, mssql@7.2.1, supertest@6.1.6, mocha@9.1.0, fast-json-patch@3.1.0 + +## 2.2.4-rc.1 +### Changed + - Upgrade formiojs@4.14.0-rc.18 + +## 2.2.3 +### Changed + - No changes. Official release. + +## 2.2.3-rc.11 +### Fixed + - Upgrade formiojs@4.14.0-rc.17 + +## 2.2.3-rc.10 +### Changed + - Upgrade formiojs@4.14.0-rc.16 + - Upgrade mongoose@5.13.5, mocha@9.0.3, supertest@6.1.4, mssql@7.2.0, eslint@7.32.0 + +## 2.2.3-rc.9 +### Fixed + - FIO-3441: resolve vulnerabilities + - FIO-898: Implements keeping POST request headers in submission.metadata.headers. + +## 2.2.3-rc.8 +### Fixed + - Fixed issues with action conditions not working when "submission" or "previous" were used in the conditional. + +### Changed + - Upgrade formiojs@4.14.0-rc.15 + +## 2.2.3-rc.7 +### Fixed + - Tests to make them more robust. + +## 2.2.3-rc.6 +### Fixed + - Resolved broken test. + +## 2.2.3-rc.5 +### Changed + - Upgrade mongoose@5.13.3, nodemailer@6.6.3, mailgun.js@3.5.2, eslint@7.31.0 + +### Fixed + - Improve validation performance by moving VM instance outside Evaluator + - FIO-1453: Add import fallbacks + - FIO-3441: resolve vulnerabilities + - Ensure we truncate the jwtIssuedAfter. + - FIO-3471: Ensure that the queries include all indexes to speed up performance. + +## 2.2.3-rc.4 +### Fixed + - FIO-2834: Fixes an issue where File's values are shown in CSV as empty + - Unhid block component label in webhook action settings form + - FIO-3099: Implements the oAuthM2M Token hook to the Login Action + - FIO-3116: Fixes an issue files inside containers and editgrids weren't attaching to an email. Added tests + - FIO-3251 fix: values which should be cleared on hide are used in calculations before it happened + +### Changed + - Upgrade formiojs@4.14.0-rc.14 + - Upgrade mongodb@3.6.10, nodemon@2.0.12 + - FIO-2764: Adds an ability to have the submission contain only data that you submitted. + - Added indexes to queries to improve performance of resource load times. + +## 2.2.3-rc.2 +### Fixed + - FIO-3369: Removed the submissionCollection hook which was messing up submission collection. + +## 2.2.3-rc.1 +### Changed + - FIO-3099: Adds a hook for the Access-Control-Expose-Headers +## 2.2.2 +### Changed + - No changes. Released 2.2.2-rc.8 as official release. + +## 2.2.2-rc.8 +### Fixed + - Issue where upgrading mailgun-transport causes server to crash. + +## 2.2.2-rc.7 +### Fixed + - Fixing tests further. + +## 2.2.2-rc.6 +### Fixed + - Custom submission collection tests. + +## 2.2.2-rc.5 +### Fixed + - Custom submission collection tests. + +## 2.2.2-rc.4 +### Fixed + - FIO-3369: Removed the submissionCollection hook which was messing up the submission collection. + +## 2.2.2-rc.3 +### Changed + - Upgrade formio-workers@1.14.16 + +## 2.2.2-rc.2 +### Fixed + - FIO-3223: Fixes an error with out of memory + - Fixing potential references to null variables. + +### Changed + - Upgrade formio-workers@1.14.15 + +## 2.2.2-rc.1 +### Fixed + - FIO-3091: added automatic useUnifiedTopology parameter setting + - FIO-3095: Allow for checking email accounts before sending emails. + - FIO-3040: Adds tests for FIO-3040 when wasn't handle the Webhook error and respond instead of spinning forever. + +## 2.2.1 +### Changed + - No changes. Released 2.2.1-rc.2 as official release. + +## 2.2.1-rc.2 +### Changed + - Upgrade formiojs@4.14.0-rc.5 + - Upgrade mongodb@3.6.7, mongoose@5.12.10 + +## 2.2.1-rc.1 +### Fixed + - FIO-2823: Fixes an issue when custom mongodb collection on a resource breaks the resource and the submission data cannot be accessed + - Changed action items "require" to "required" + - Added extra check to prevent server crashes + +### Changed + - Upgrade formiojs@4.13.2-rc.2 + - Upgrade dependencies. + +## 2.2.0 +### Changed + - Official release of 2.2.0-rc.2 + +## 2.2.0-rc.2 +### Fixed + - FIO-2766: preventing unathorized users from viewing form definition + +## 2.2.0-rc.1 +### Changed + - Upgrade formiojs@4.13.1-rc.1 + +### Fixed + - FIO-2484: Implements Split Roles PR with Group permission + +## 2.1.1 +### Changed + - No changes. Official Release. + +## 2.1.1-rc.2 +### Fixed + - Modified the expiring indexes to have try/caches around all instances. + +## 2.1.1-rc.1 +### Changed + - Adding try/catch around expiring indexes for DB's that don't support it. + +## 2.1.0 +### Changed + - Upgrade formiojs@4.13.0 + +## 2.1.0-rc.18 +### Changed + - Upgrade formiojs@4.13.0-rc.27 + +## 2.1.0-rc.17 +### Changed + - Upgrade formiojs@4.13.0-rc.26 + - Upgrade resourcejs@2.3.4 + - Upgrade other dependencies. + +## 2.1.0-rc.16 + - Upgrade formiojs@4.13.0-rc.25 + +## 2.1.0-rc.15 +### Fixed + - FIO-2634: Fixes an issue where Signatures/Files values are excluded from the response when load subForms submissions by a reference + +### Changed + - Upgrade formiojs@4.13.0-rc.23 + - Upgrade other dependencies. + +## 2.1.0-rc.14 +### Fixed + - Upgrade formiojs@4.13.0-rc.20 + +## 2.1.0-rc.13 +### Fixed + - Updated html-entities@2.1.1, mongodb@3.6.5, mocha@8.3.2, csv@5.4.0, mongoose@5.12.0, eslint@7.22.0 + +## 2.1.0-rc.12 +### Fixed + - FIO-1555: fixed an issue where server validation errors do not come from the server if component with error is not on the first wizard page + +### Changed + - Upgrade formiojs@4.13.0-rc.19 + +## 2.1.0-rc.10 +### Changed + - Using cloneDeep on vm sandboxes. + - Updated dependencies. + +## 2.1.0-rc.7 +### Changed + - Using @formio/node-fetch-http-proxy instead of local file. + - FIO-1528: FIO-1528: change default 'from' email address domain to use example in the deployment environment variable + - Ensure we cloneDeep vm context for added protection. + +## 2.1.0-rc.6 +### Fixed + - Automated tests. + +## 2.1.0-rc.5 +### Changed + - Fixed serer to work with latest formio-workers. + +## 2.1.0-rc.4 +### Changed + - Upgrade mongoose@5.11.17, eslint@7.20.0, adm-zip@0.5.3 + - Using vm2 for added security. + +### Fixed + - FIO-476: Fixes an issue when Sketch Pad didn't show data on CSV export - showed a list of empty strings. + - fix: allow Docker to load git npm paths + +## 2.1.0-rc.3 +### Added + - Added action logs to form context only. + +### Fixed + - FIO-1309: Fixed recalculation of field if calculateServer is disabled. + - FIO-888: Adds CSV Formula Injection Protection + - FIO-1140: Fixes an issue where deprecated formRevision property is added when deploying a version to a stage + +## 2.1.0-rc.2 +### Fixed + - FIO-832: fixed error code returned when trying to delete the Everyone role + +## 2.1.0-rc.1 +### Changed + - FOR-2866: Single submission bug using different collection master + - Upgrade mongoose@5.11.14, supertest@6.1.3, html-entities@2.1.0, eslint@7.19.0, adm-zip@0.5.2 + +### Fixed + - FIO-838: Fixes an issue when a "Save Submission to resource" action had an incorrect priority. + - FIO-854: Amazon DocumentDB to update default engine version to 4.0.0 + - FIO-1163: fixed an issue where submission data is deleted for components with the same key as parent layout component + - FIO-911: Entire project JSON is dumped into the server logs + - FIO-128: Added markModifiedParameters method to utils. + +## 2.0.1-rc.2 +### Fixed + - FIO-832: fixed error code returned when trying to delete the Everyone role + +### Changed + - Upgrade nodemailer@6.4.18, mocha@8.3.0 + +## 2.0.1-rc.1 +### Changed + - Upgrade formiojs@4.13.0-rc.9 + - Upgrade mongodb@3.6.4, mongoose@5.11.15, supertest@6.1.3, html-entities@2.1.0, eslint@7.19.0, adm-zip@0.5.2, moment-timezone@0.5.33 + +## 2.0.0 +### Changed + - No changes. Released 2.0.0-rc.42 as official release. + +## 2.0.0-rc.42 +### Fixed + - FIO-1175: User is being automatically logged out on remote server + - Fix: add a token for resources select components + +### Changed + - Upgrade mongoose@5.11.12, fs-extra@9.1.0, eslint@7.18.0, supertest@6.1.1 + +## 2.0.0-rc.41 +### Changed + - Temporarily reverted the expiring action logs. Will wait for 2.1.0 to release this feature. + - Changed field match access schema to have splitted permissions instead + +## 2.0.0-rc.40 +### Fixed + - FIO-1125: Unable to download a CSV report with Select component + +### Changed + - Upgrade formiojs@4.13.0-rc.6 + +## 2.0.0-rc.39 +### Changed + - FOR-2762: Changes default permissions for a new project + - Upgrade formio-workers@1.14.10, mongoose@5.11.11, resourcejs@2.3.3 + +## 2.0.0-rc.38 +### Breaking Change + - FIO-1027: Adds an ability to switch on/off permissions to access the EXISTS endpoint. Makes access with permissions by default. + +### Fixed + - FIO-847: Fixes an issue when in post submission data where any datagrid or editgrid are some not empty string, the server was crashing. + - FIO-761: Fixes an issue when the server throws 'Error: cyclic dependency detected' when calling Webhook action + +### Changed + - Upgrade formiojs@4.13.0-rc.5 + - Upgrade mongoose@5.11.10 + +## 2.0.0-rc.37 +### Changed + - Removed the LegacyValidator. + - Decreased limit for resource select to avoid error + - Fixed typo in fieldMatchAccess + - FIO-853: Added check if fieldMatchAccess object is not empty + - FIO-1035: Fixes an issue when a nested form inside the nested Form was receiving "Too many recursive requests." on submit. + +## 2.0.0-rc.36 +### Fixed + - FOR-2868: Adds an ability to pass the rejectUnauthorized flag to the fetch method. + - FIO-994: Makes onlyAvailableItems validation optional + +### Changed + - Updated formiojs@4.12.3, html-entities@1.3.3, mongoose@5.11.8, nodemailer@6.4.17, mssql@6.3.0 + +## 2.0.0-rc.35 +### Fixed + - FOR-2874: Added server side validation of recaptcha token. + - Adding expiring action items. + +### Changed + - Upgrade formiojs@4.12.2 + - Upgrade config@3.3.3, nodemailer-mailgun-transport@2.0.2, semver@7.3.4, mongoose@5.11.4, eslint@7.15.0, adm-zip@0.5.1 + ## 2.0.0-rc.34 ### Fixed - Issues with ResetPassword action not setting form object correctly within email parameters. @@ -14,7 +461,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/) ## 2.0.0-rc.32 ### Added - - FJS-1380: Adds field actions for Select and Radio which allow onlyAvailableItems validation + - FJS-1380: Adds field actions for Select and Radio which allow onlyAvailableItems validation ### Fixed - FJS-1297: fix submission of nested wizards diff --git a/forms-flow-forms/Dockerfile b/forms-flow-forms/Dockerfile index 65d7da975c..0b39584006 100644 --- a/forms-flow-forms/Dockerfile +++ b/forms-flow-forms/Dockerfile @@ -4,7 +4,7 @@ # Use Node image, maintained by Docker: # hub.docker.com/r/_/node/ -FROM docker.io/node:12.2.0-alpine +FROM node:lts-alpine3.10 # set working directory WORKDIR /forms-flow-forms/app @@ -19,6 +19,11 @@ RUN apk update && \ apk add make=4.2.1-r2 && \ apk add g++=8.3.0-r0 +# At least one buried package dependency is using a `git` path. +# Hence we need to haul in git. +RUN apk --update add git +# Use https to avoid requiring ssh keys for public repos. +RUN git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" ## Using an alternative package install location ## to allow overwriting the /app folder at runtime ## stackoverflow.com/a/13021677 diff --git a/forms-flow-forms/README.md b/forms-flow-forms/README.md index b14e3b3c83..dec123bdd8 100644 --- a/forms-flow-forms/README.md +++ b/forms-flow-forms/README.md @@ -1,10 +1,10 @@ # Form Management Platform -![Formio](https://img.shields.io/badge/formio-2.0.0--rc.34-blue) +![Formio](https://img.shields.io/badge/formio-2.3.0-blue) **formsflow.ai** leverages form.io to build "serverless" data management applications using a simple drag-and-drop form builder interface. -To know more about form.io, go to https://form.io. +To know more about form.io, go to . ## Table of Content @@ -17,6 +17,9 @@ To know more about form.io, go to https://form.io. 3. [Formsflow-forms API Requesting](#formsflow-forms-api-requesting) * [Using POSTMAN API client](#using-postman-api-client) * [Using curl command](#using-curl-command) +4. [Custom Components](#custom-components) +5. [Adding new indexes](#adding-new-indexes) +6. [LICENSE](#license) ## Prerequisites @@ -31,11 +34,11 @@ Not applicable. ### Installation - * Make sure you have a Docker machine up and running. - * Make sure your current working directory is "forms-flow-ai/forms-flow-forms". - * Rename the file [sample.env](./sample.env) to **.env**. - * Modify the environment variables in the newly created **.env** file if needed. Environment variables are given in the table below, - * **NOTE : `{your-ip-address}` given inside the .env file should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards** +* Make sure you have a Docker machine up and running. +* Make sure your current working directory is "forms-flow-ai/forms-flow-forms". +* Rename the file [sample.env](./sample.env) to **.env**. +* Modify the environment variables in the newly created **.env** file if needed. Environment variables are given in the table below, +* **NOTE : `{your-ip-address}` given inside the .env file should be changed to your host system IP address. Please take special care to identify the correct IP address if your system has multiple network cards** > :information_source: Variables with trailing :triangular_flag_on_post: in below table should be updated in the .env file @@ -47,8 +50,10 @@ Not applicable. |`FORMIO_ROOT_EMAIL`|forms-flow-forms admin login|eg. admin@example.com|`admin@example.com` |`FORMIO_ROOT_PASSWORD`|forms-flow-forms admin password|eg.changeme|`changeme` |`FORMIO_DEFAULT_PROJECT_URL`:triangular_flag_on_post:|forms-flow-forms default url||`http://{your-ip-address}:3001` +|`FORMIO_JWT_SECRET`|forms-flow-forms jwt secret| |`--- change me now ---` **Additionally, you may want to change these** + * The value of Mongo database details (especially if this instance is not just for testing purposes) * The value of ROOT user account details (especially if this instance is not just for testing purposes) @@ -58,13 +63,14 @@ Not applicable. * `cd {Your Directory}/forms-flow-ai/forms-flow-forms` * For Linux, - * Run `docker-compose -f docker-compose-linux.yml up -d` to start. + * Run `docker-compose -f docker-compose-linux.yml up -d` to start. * For Windows, - * Run `docker-compose -f docker-compose-windows.yml up -d` to start. - + * Run `docker-compose -f docker-compose-windows.yml up -d` to start. + *NOTE: Use --build command with the start command to reflect any future **.env** changes eg : `docker-compose -f docker-compose-windows.yml up --build -d`* - + #### To stop the application + * For Linux, * Run `docker-compose -f docker-compose-linux.yml stop` to stop. * For Windows, @@ -72,14 +78,13 @@ Not applicable. ### Health Check - The application should be up and available for use at port defaulted to 3001 in (i.e. http://localhost:3001/) - + The application should be up and available for use at port defaulted to 3001 in (i.e. ) + Default Login Credentials ----------------- User Name / Email : admin@example.com Password : changeme - - + ## Formsflow-forms user/role API There are two ways in which you can access data from the formsflow-forms end points. @@ -94,40 +99,40 @@ There are two ways in which you can access data from the formsflow-forms end poi * [Step 1](#step-1) Go to `forms-flow-forms/script` directory. * [Step 2](#step-2) * **For windows** - * Open command prompt and run `resourceId_windows.bat {user email} {password}` eg: `resourceId_windows.bat admin@example.com changeme` + * Open command prompt and run `resourceId_windows.bat {user email} {password}` eg: `resourceId_windows.bat admin@example.com changeme` * **For Linux and Mac** - * Open command prompt and run `./resourceId_linux.sh {user email} {password}` eg: `./resourceId_linux.sh admin@example.com changeme` + * Open command prompt and run `./resourceId_linux.sh {user email} {password}` eg: `./resourceId_linux.sh admin@example.com changeme` * [Step 3](#step-3) Copy the ID corresponding to Role Name from [Step 2](./README.md#step-2) and paste it against the Environment Variable name from the below table. |Role Name | Environment Variable Name | |--- |--- -|Administrator | DESIGNER_ROLE_ID -|Anonymous | ANONYMOUS_ID -|formsflow Client | CLIENT_ROLE_ID -|formsflow Reviewer | REVIEWER_ROLE_ID -|User | USER_RESOURCE_ID - +|Administrator | DESIGNER_ROLE_ID +|Anonymous | ANONYMOUS_ID +|formsflow Client | CLIENT_ROLE_ID +|formsflow Reviewer | REVIEWER_ROLE_ID +|User | USER_RESOURCE_ID + > **curl requests are successfully completed. You can skip the remaining sections in this page and continue with other installation steps.** ### Using POSTMAN API client * Download and install [Postman API client](https://www.postman.com/) * Import [formsflow-forms-postman-collection.json](./config/formsflow-forms-postman-collection.json) to your postman client. - - Open Postman -> Go to File - - Import -> Upload [formsflow-forms-postman-collection.json](./config/formsflow-forms-postman-collection.json) file - - Import successful. -* Follow the instructions given below to fetch the role id's from [forms-flow-forms](http://localhost:3001) - - Open Postman -> Go to Workspaces -> My Workspaces - - Collections -> Open form.io collection and send the API request in the following order. - - Get the jwt token using resource **http://localhost:3001/user/login**. (*Click on Send to make a server request*) - - Get the user resource id using resource **http://localhost:3001/user**. (*Click on Send to make a server request*) - - Copy the **_id** from Response body and replace value for **USER_RESOURCE_ID** in the **.env** file. - - Get the user role id's using resource **http://localhost:3001/role**. (*Click on Send to make a server request*) - - Copy the **_id** with title *Administrator* from Response body and replace value for **DESIGNER_ROLE_ID** in the **.env** file. - - Copy the **_id** with title *Anonymous* from Response body and replace value for **ANONYMOUS_ID** in the **.env** file. - - Copy the **_id** with title *formsflow Client* from Response body and replace value for **CLIENT_ROLE_ID** in the **.env** file. - - Copy the **_id** with title *formsflow Reviewer* from Response body and replace value for **REVIEWER_ROLE_ID** in the **.env** file. - + * Open Postman -> Go to File + * Import -> Upload [formsflow-forms-postman-collection.json](./config/formsflow-forms-postman-collection.json) file + * Import successful. +* Follow the instructions given below to fetch the role id's from [forms-flow-forms](http://localhost:3001) + * Open Postman -> Go to Workspaces -> My Workspaces + * Collections -> Open form.io collection and send the API request in the following order. + * Get the jwt token using resource ****. (*Click on Send to make a server request*) + * Get the user resource id using resource ****. (*Click on Send to make a server request*) + * Copy the **_id** from Response body and replace value for **USER_RESOURCE_ID** in the **.env** file. + * Get the user role id's using resource ****. (*Click on Send to make a server request*) + * Copy the **_id** with title *Administrator* from Response body and replace value for **DESIGNER_ROLE_ID** in the **.env** file. + * Copy the **_id** with title *Anonymous* from Response body and replace value for **ANONYMOUS_ID** in the **.env** file. + * Copy the **_id** with title *formsflow Client* from Response body and replace value for **CLIENT_ROLE_ID** in the **.env** file. + * Copy the **_id** with title *formsflow Reviewer* from Response body and replace value for **REVIEWER_ROLE_ID** in the **.env** file. + > **Postman API calls are successfully completed. You can skip the remaining sections in this page and continue with other installation steps.** ## Custom Components @@ -141,15 +146,30 @@ Custom componets available in **formsflow.ai** are: |--- | --- | --- | |**Text Area with Analytics** | To enable Text fields for sentiment analysis processing | [link](./custom-components/text-area-with-analytics/README.md)| - If you are interested in adding custom components for your use case in **formsflow.ai** we highly recommend you to take a look at [Custom Component Docs](https://formio.github.io/formio.js/app/examples/customcomponent.html) to understand how Form.io renderer allows for the creation of Custom components. You can also take a look at [formio.contrib](https://github.com/formio/contrib) to look for examples and even contribute the custom components you create. +## Adding new indexes + +You can add new indexes in Mongodb shell, according to your requirement. You can create indexes like below example: + +``` +db.submissions.createIndex({ + "data.applicationStatus ": 1, + "modified": 1, +}) +``` + +In this example: +* `submissions` is the collection name. +* `modified` and `data.applicationStatus` is the fields which are to be added in index. + ## LICENSE We have build formsflow.ai form management platform leveraging [formio](https://github.com/formio/formio). We use the OSL-v3 license similar to formio to ensure appropriate attribution is provided to form.io. Please read the [license](./LICENSE.txt) for more information. + diff --git a/forms-flow-forms/docker-compose-linux.yml b/forms-flow-forms/docker-compose-linux.yml index 38d65fa4f6..a1f9b8fd3b 100644 --- a/forms-flow-forms/docker-compose-linux.yml +++ b/forms-flow-forms/docker-compose-linux.yml @@ -16,7 +16,7 @@ version: '3.7' services: forms-flow-forms-db: - image: mongo + image: mongo:5.0 restart: unless-stopped hostname: forms-flow-forms-db ports: @@ -52,6 +52,8 @@ services: ROOT_EMAIL: ${FORMIO_ROOT_EMAIL:-admin@example.com} ROOT_PASSWORD: ${FORMIO_ROOT_PASSWORD:-changeme} FORMIO_DOMAIN: ${FORMIO_DEFAULT_PROJECT_URL} + FORMIO_JWT_SECRET: ${FORMIO_JWT_SECRET:---- change me now ---} + FORMIO_JWT_EXPIRE: ${FORMIO_JWT_EXPIRE:-240} stdin_open: true # -i tty: true # -t networks: diff --git a/forms-flow-forms/docker-compose-windows.yml b/forms-flow-forms/docker-compose-windows.yml index 3dd95f2560..34a87e88f9 100644 --- a/forms-flow-forms/docker-compose-windows.yml +++ b/forms-flow-forms/docker-compose-windows.yml @@ -18,7 +18,7 @@ services: forms-flow-forms-db: container_name: forms-flow-forms-db hostname: forms-flow-forms-db - image: mongo + image: mongo:5.0 restart: always ports: - '27018:27017' @@ -54,6 +54,8 @@ services: ROOT_EMAIL: ${FORMIO_ROOT_EMAIL:-admin@example.com} ROOT_PASSWORD: ${FORMIO_ROOT_PASSWORD:-changeme} FORMIO_DOMAIN: ${FORMIO_DEFAULT_PROJECT_URL} + FORMIO_JWT_SECRET: ${FORMIO_JWT_SECRET:---- change me now ---} + stdin_open: true # -i tty: true # -t networks: diff --git a/forms-flow-forms/index.js b/forms-flow-forms/index.js index 31f098db4d..7c74650f89 100644 --- a/forms-flow-forms/index.js +++ b/forms-flow-forms/index.js @@ -13,6 +13,7 @@ const Q = require('q'); const nunjucks = require('nunjucks'); const util = require('./src/util/util'); const log = require('debug')('formio:log'); +const gc = require('expose-gc/function'); const originalGetToken = util.Formio.getToken; const originalEvalContext = util.Formio.Components.components.component.prototype.evalContext; @@ -110,6 +111,19 @@ module.exports = function(config) { util.Formio.getToken = originalGetToken; util.Formio.Components.components.component.prototype.evalContext = originalEvalContext; + try { + if (config.maxOldSpace) { + const heap = process.memoryUsage().heapTotal / 1024 / 1024; + + if ((config.maxOldSpace * 0.8) < heap) { + gc(); + } + } + } + catch (error) { + console.log(error); + } + next(); }); @@ -180,7 +194,7 @@ module.exports = function(config) { // The access handler. if (!router.formio.hook.invoke('init', 'access', router.formio)) { - router.get('/access', router.formio.middleware.accessHandler); + router.get('/access', router.formio.middleware.tokenVerify,router.formio.middleware.accessHandler); } // Authorize all urls based on roles and permissions. @@ -200,7 +214,7 @@ module.exports = function(config) { mongoConfig.useNewUrlParser = true; } if (!mongoConfig.hasOwnProperty('keepAlive')) { - mongoConfig.keepAlive = 120; + mongoConfig.keepAlive = true; } if (process.env.MONGO_HIGH_AVAILABILITY) { mongoConfig.mongos = true; @@ -215,7 +229,6 @@ module.exports = function(config) { } mongoConfig.useUnifiedTopology = true; - mongoConfig.useCreateIndex = true; if (config.mongoSSL) { mongoConfig = { @@ -225,9 +238,7 @@ module.exports = function(config) { } // Connect to MongoDB. - mongoose.connect(mongoUrl, mongoConfig); - mongoose.set('useFindAndModify', false); - mongoose.set('useCreateIndex', true); + mongoose.connect(mongoUrl, mongoConfig ); // Trigger when the connection is made. mongoose.connection.on('error', function(err) { diff --git a/forms-flow-forms/package-lock.json b/forms-flow-forms/package-lock.json index 23691c4e4e..ecd209f700 100644 --- a/forms-flow-forms/package-lock.json +++ b/forms-flow-forms/package-lock.json @@ -1,112 +1,409 @@ { "name": "formio", - "version": "2.0.0-rc.34", + "version": "2.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@azure/abort-controller": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.3.tgz", - "integrity": "sha512-kCibMwqffnwlw3c+e879rCE1Am1I2BfhjOeO54XNA8i/cEuzktnBQbTrzh67XwibHO05YuNgZzSWy9ocVfFAGw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.4.tgz", + "integrity": "sha512-lNUmDRVGpanCsiUN3NWxFTdwmdFI53xwhkTFfHDGTYk46ca7Ind3nanJc+U6Zj9Tv+9nTCWRBscWEW1DyKOpTw==", "requires": { "tslib": "^2.0.0" }, "dependencies": { "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, + "@azure/core-asynciterator-polyfill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.0.tgz", + "integrity": "sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg==" + }, "@azure/core-auth": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.3.2.tgz", + "integrity": "sha512-7CU6DmCHIZp5ZPiZ9r3J17lTKMmYsm/zGvNkjArQwPkrLlZ1TZ+EUYfGgh2X31OLMVAQCTJZW4cXHJi02EbJnA==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.2.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/core-client": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.3.2.tgz", + "integrity": "sha512-qfkRYKmeEmisluMdGTbBtXeyBLaImjFeVW0gcT5yRAwxJmlnTvSyD+a3PjukAtjIrl/tnb4WSJOBpONSJ91+5Q==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-asynciterator-polyfill": "^1.0.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-rest-pipeline": "^1.1.0", + "@azure/core-tracing": "1.0.0-preview.13", + "tslib": "^2.2.0" + }, + "dependencies": { + "@azure/core-tracing": { + "version": "1.0.0-preview.13", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz", + "integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==", + "requires": { + "@opentelemetry/api": "^1.0.1", + "tslib": "^2.2.0" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/core-http": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-2.2.2.tgz", + "integrity": "sha512-V1DdoO9V/sFimKpdWoNBgsE+QUjQgpXYnxrTdUp5RyhsTJjvEVn/HKmTQXIHuLUUo6IyIWj+B+Dg4VaXse9dIA==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-asynciterator-polyfill": "^1.0.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-tracing": "1.0.0-preview.13", + "@azure/logger": "^1.0.0", + "@types/node-fetch": "^2.5.0", + "@types/tunnel": "^0.0.3", + "form-data": "^4.0.0", + "node-fetch": "^2.6.0", + "process": "^0.11.10", + "tough-cookie": "^4.0.0", + "tslib": "^2.2.0", + "tunnel": "^0.0.6", + "uuid": "^8.3.0", + "xml2js": "^0.4.19" + }, + "dependencies": { + "@azure/core-tracing": { + "version": "1.0.0-preview.13", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz", + "integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==", + "requires": { + "@opentelemetry/api": "^1.0.1", + "tslib": "^2.2.0" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } + } + }, + "@azure/core-lro": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.2.1.tgz", + "integrity": "sha512-HE6PBl+mlKa0eBsLwusHqAqjLc5n9ByxeDo3Hz4kF3B1hqHvRkBr4oMgoT6tX7Hc3q97KfDctDUon7EhvoeHPA==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-tracing": "1.0.0-preview.13", + "@azure/logger": "^1.0.0", + "tslib": "^2.2.0" + }, + "dependencies": { + "@azure/core-tracing": { + "version": "1.0.0-preview.13", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz", + "integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==", + "requires": { + "@opentelemetry/api": "^1.0.1", + "tslib": "^2.2.0" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/core-paging": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.2.0.tgz", - "integrity": "sha512-KUl+Nwn/Sm6Lw5d3U90m1jZfNSL087SPcqHLxwn2T6PupNKmcgsEbDjHB25gDvHO4h7pBsTlrdJAY7dz+Qk8GA==", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.0.tgz", + "integrity": "sha512-ZX1bCjm/MjKPCN6kQD/9GJErYSoKA8YWp6YWoo5EIzcTWlSBLXu3gNaBTUl8usGl+UShiKo7b4Gdy1NSTIlpZg==", + "requires": { + "@azure/core-asynciterator-polyfill": "^1.0.0", + "tslib": "^2.2.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/core-rest-pipeline": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.3.2.tgz", + "integrity": "sha512-kymICKESeHBpVLgQiAxllgWdSTopkqtmfPac8ITwMCxNEC6hzbSpqApYbjzxbBNkBMgoD4GESo6LLhR/sPh6kA==", "requires": { "@azure/abort-controller": "^1.0.0", - "tslib": "^2.0.0" + "@azure/core-auth": "^1.3.0", + "@azure/core-tracing": "1.0.0-preview.13", + "@azure/logger": "^1.0.0", + "form-data": "^4.0.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "tslib": "^2.2.0", + "uuid": "^8.3.0" + }, + "dependencies": { + "@azure/core-tracing": { + "version": "1.0.0-preview.13", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz", + "integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==", + "requires": { + "@opentelemetry/api": "^1.0.1", + "tslib": "^2.2.0" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/core-tracing": { + "version": "1.0.0-preview.12", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.12.tgz", + "integrity": "sha512-nvo2Wc4EKZGN6eFu9n3U7OXmASmL8VxoPIH7xaD6OlQqi44bouF0YIi9ID5rEsKLiAU59IYx6M297nqWVMWPDg==", + "requires": { + "@opentelemetry/api": "^1.0.0", + "tslib": "^2.2.0" }, "dependencies": { "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/identity": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-1.5.2.tgz", + "integrity": "sha512-vqyeRbd2i0h9F4mqW5JbkP1xfabqKQ21l/81osKhpOQ2LtwaJW6nw4+0PsVYnxcbPHFCIZt6EWAk74a3OGYZJA==", + "requires": { + "@azure/core-auth": "^1.3.0", + "@azure/core-client": "^1.0.0", + "@azure/core-rest-pipeline": "^1.1.0", + "@azure/core-tracing": "1.0.0-preview.12", + "@azure/logger": "^1.0.0", + "@azure/msal-node": "1.0.0-beta.6", + "@types/stoppable": "^1.1.0", + "axios": "^0.21.1", + "events": "^3.0.0", + "jws": "^4.0.0", + "keytar": "^7.3.0", + "msal": "^1.0.2", + "open": "^7.0.0", + "qs": "^6.7.0", + "stoppable": "^1.1.0", + "tslib": "^2.0.0", + "uuid": "^8.3.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/keyvault-keys": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@azure/keyvault-keys/-/keyvault-keys-4.3.0.tgz", + "integrity": "sha512-OEosl0/rE/mKD5Ji9KaQN7UH+yQnV5MS0MRhGqQIiJrG+qAvAla0MYudJzv3XvBlplpGk0+MVgyL9H3KX/UAwQ==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-http": "^2.0.0", + "@azure/core-lro": "^2.0.0", + "@azure/core-paging": "^1.1.1", + "@azure/core-tracing": "1.0.0-preview.13", + "@azure/logger": "^1.0.0", + "tslib": "^2.2.0" + }, + "dependencies": { + "@azure/core-tracing": { + "version": "1.0.0-preview.13", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz", + "integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==", + "requires": { + "@opentelemetry/api": "^1.0.1", + "tslib": "^2.2.0" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@azure/logger": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz", + "integrity": "sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g==", + "requires": { + "tslib": "^2.2.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, "@azure/ms-rest-azure-env": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-1.1.2.tgz", - "integrity": "sha512-l7z0DPCi2Hp88w12JhDTtx5d0Y3+vhfE7JKJb9O7sEz71Cwp053N8piTtTnnk/tUor9oZHgEKi/p3tQQmLPjvA==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz", + "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==" }, "@azure/ms-rest-js": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-1.11.2.tgz", - "integrity": "sha512-2AyQ1IKmLGKW7DU3/x3TsTBzZLcbC9YRI+yuDPuXAQrv3zar340K9wsxU413kHFIDjkWNCo9T0w5VtwcyWxhbQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.6.0.tgz", + "integrity": "sha512-4C5FCtvEzWudblB+h92/TYYPiq7tuElX8icVYToxOdggnYqeec4Se14mjse5miInKtZahiFHdl8lZA/jziEc5g==", "requires": { "@azure/core-auth": "^1.1.4", - "axios": "^0.21.1", - "form-data": "^2.3.2", - "tough-cookie": "^2.4.3", - "tslib": "^1.9.2", + "abort-controller": "^3.0.0", + "form-data": "^2.5.0", + "node-fetch": "^2.6.0", + "tough-cookie": "^3.0.1", + "tslib": "^1.10.0", "tunnel": "0.0.6", - "uuid": "^3.2.1", + "uuid": "^8.3.2", "xml2js": "^0.4.19" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } } }, "@azure/ms-rest-nodeauth": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-2.0.2.tgz", - "integrity": "sha512-KmNNICOxt3EwViAJI3iu2VH8t8BQg5J2rSAyO4IUYLF9ZwlyYsP419pdvl4NBUhluAP2cgN7dfD2V6E6NOMZlQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-3.1.0.tgz", + "integrity": "sha512-F4NKrbkZg0qD3+rUM8fvJHOFRkXFoEiptYTZtLBruN3VwBFIqbTFW0fmgRyBW9seZl+mX2OexQA5GzWenSA3Kw==", + "requires": { + "@azure/ms-rest-azure-env": "^2.0.0", + "@azure/ms-rest-js": "^2.0.4", + "adal-node": "^0.2.2" + } + }, + "@azure/msal-common": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-4.5.1.tgz", + "integrity": "sha512-/i5dXM+QAtO+6atYd5oHGBAx48EGSISkXNXViheliOQe+SIFMDo3gSq3lL54W0suOSAsVPws3XnTaIHlla0PIQ==", + "requires": { + "debug": "^4.1.1" + } + }, + "@azure/msal-node": { + "version": "1.0.0-beta.6", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.0.0-beta.6.tgz", + "integrity": "sha512-ZQI11Uz1j0HJohb9JZLRD8z0moVcPks1AFW4Q/Gcl67+QvH4aKEJti7fjCcipEEZYb/qzLSO8U6IZgPYytsiJQ==", "requires": { - "@azure/ms-rest-azure-env": "^1.1.2", - "@azure/ms-rest-js": "^1.8.7", - "adal-node": "^0.1.28" + "@azure/msal-common": "^4.0.0", + "axios": "^0.21.1", + "jsonwebtoken": "^8.5.1", + "uuid": "^8.3.0" } }, "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, "requires": { "@babel/highlight": "^7.10.4" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", "dev": true }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.15.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -118,60 +415,55 @@ "supports-color": "^5.3.0" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true } } }, "@babel/runtime": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", - "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", + "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@eslint/eslintrc": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz", - "integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", "espree": "^7.3.0", - "globals": "^12.1.0", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.19", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true } } }, + "@formio/bootstrap3": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@formio/bootstrap3/-/bootstrap3-2.12.0.tgz", + "integrity": "sha512-l1KRCmQFw68c9LtNzysVQ7XXeUgfg1G3roQgY4tn1hFbKXcm3yMhOSrY6xcBDJHW/PN4n5ENwbBCfRjrJVkl0Q==", + "requires": { + "resize-observer-polyfill": "^1.5.1" + } + }, "@formio/choices.js": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@formio/choices.js/-/choices.js-9.0.1.tgz", @@ -182,11 +474,80 @@ "redux": "^4.0.4" } }, + "@formio/node-fetch-http-proxy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@formio/node-fetch-http-proxy/-/node-fetch-http-proxy-1.1.0.tgz", + "integrity": "sha512-kZuv6NYf+9S98EN50WaISBoLUa2FxmvXju/fEol/J+LtkfZcw92OrekSoGKfCpaSxTMtsRsbgmmkvTAXiBL1Wg==", + "requires": { + "abort-controller": "^3.0.0", + "https-proxy-agent": "^5.0.0", + "lodash": "^4.17.21", + "node-fetch": "^2.6.1" + } + }, + "@formio/semantic": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@formio/semantic/-/semantic-2.6.0.tgz", + "integrity": "sha512-RwMEVXkyz+B6RivflrrKIqvvnGR/eZDLQs74u67StcrzO6n3/5D2J8XqTQRSUzQzr5QV6Wq0eZ51z/+mGm6THw==" + }, "@formio/vanilla-text-mask": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@formio/vanilla-text-mask/-/vanilla-text-mask-5.1.1.tgz", "integrity": "sha512-7MhrbMypySPi7RLchg0ys7HnS3Wqddbq/btAijKB1nA94TE7AOOLhpZJWcNm3kOlX0Y3nHfoavj/HP7vsvF34Q==" }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@js-joda/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-3.2.0.tgz", + "integrity": "sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==" + }, + "@opentelemetry/api": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.3.tgz", + "integrity": "sha512-puWxACExDe9nxbBB3lOymQFrLYml2dVOrd7USiVRnSbgXE+KwBu+HxFvxrzfqsiSda9IWsXJG1ef7C1O2/GmKQ==" + }, + "@sendgrid/client": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.6.0.tgz", + "integrity": "sha512-cpBVZKLlMTO+vpE18krTixubYmZa98oTbLkqBDuTiA3zRkW+urrxg7pDR24TkI35Mid0Zru8jDHwnOiqrXu0TA==", + "requires": { + "@sendgrid/helpers": "^7.6.0", + "axios": "^0.21.4" + } + }, + "@sendgrid/helpers": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-7.6.0.tgz", + "integrity": "sha512-0uWD+HSXLl4Z/X3cN+UMQC20RE7xwAACgppnfjDyvKG0KvJcUgDGz7HDdQkiMUdcVWfmyk6zKSg7XKfKzBjTwA==", + "requires": { + "deepmerge": "^4.2.2" + } + }, + "@sendgrid/mail": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-7.6.0.tgz", + "integrity": "sha512-0KdaSZzflJD/vUAZjB3ALBIuaVGoLq22hrb2fvQXZHRepU/yhRNlEOqrr05MfKBnKskzq1blnD1J0fHxiwaolw==", + "requires": { + "@sendgrid/client": "^7.6.0", + "@sendgrid/helpers": "^7.6.0" + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -207,35 +568,70 @@ "defer-to-connect": "^1.0.1" } }, - "@types/bson": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz", - "integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==", + "@tediousjs/connection-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tediousjs/connection-string/-/connection-string-0.3.0.tgz", + "integrity": "sha512-d/keJiNKfpHo+GmSB8QcsAwBx8h+V1UbdozA5TD+eSLXprNY53JAYub47J9evsSKWDdNG5uVj0FiMozLKuzowQ==" + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@types/node": { + "version": "16.11.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", + "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" + }, + "@types/node-fetch": { + "version": "2.5.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", + "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/stoppable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/stoppable/-/stoppable-1.1.1.tgz", + "integrity": "sha512-b8N+fCADRIYYrGZOcmOR8ZNBOqhktWTB/bMUl5LvGtT201QKJZOOH5UsFyI3qtteM6ZAJbJqZoBcLqqxKIwjhw==", "requires": { "@types/node": "*" } }, - "@types/mongodb": { - "version": "3.6.16", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.16.tgz", - "integrity": "sha512-D3tM0iRUet3TiIMAdvovxAIRG9gYqFd4j7visGwmPNdQj8Fq/uFFfRxyGCgEwVXAs0NnJPMI/QGVTADxDwhmSQ==", + "@types/tunnel": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz", + "integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==", "requires": { - "@types/bson": "*", "@types/node": "*" } }, - "@types/node": { - "version": "12.19.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.7.tgz", - "integrity": "sha512-zvjOU1g4CpPilbTDUATnZCUb/6lARMRAqzT7ILwl1P3YvU2leEcZ2+fw9+Jrw/paXB1CgQyXTrN4hWDtqT9O2A==" + "@types/webidl-conversions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", + "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==" }, - "@types/readable-stream": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.9.tgz", - "integrity": "sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw==", + "@types/whatwg-url": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz", + "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==", "requires": { "@types/node": "*", - "safe-buffer": "*" + "@types/webidl-conversions": "*" } }, "@ungap/promise-all-settled": { @@ -244,6 +640,20 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "@vendia/serverless-express": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@vendia/serverless-express/-/serverless-express-3.4.0.tgz", + "integrity": "sha512-/UAAbi9qRjUtjRISt5MJ1sfhtrHb26hqQ0nvE5qhMLsAdR5H7ErBwPD8Q/v2OENKm0iWsGwErIZEg7ebUeFDjQ==", + "requires": { + "binary-case": "^1.0.0", + "type-is": "^1.6.16" + } + }, + "@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==" + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -258,12 +668,6 @@ "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" }, - "abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", - "optional": true - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -288,46 +692,39 @@ } }, "acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", - "optional": true - }, - "acorn-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", - "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", - "optional": true, - "requires": { - "acorn": "^2.1.0" - } + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true }, "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true }, "adal-node": { - "version": "0.1.28", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.1.28.tgz", - "integrity": "sha1-RoxLs+u9lrEnBmn0ucuk4AZepIU=", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", + "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", "requires": { - "@types/node": "^8.0.47", - "async": ">=0.6.0", + "@xmldom/xmldom": "^0.7.0", + "async": "^2.6.3", + "axios": "^0.21.1", "date-utils": "*", "jws": "3.x.x", - "request": ">= 2.52.0", "underscore": ">= 1.3.1", "uuid": "^3.1.0", - "xmldom": ">= 0.1.x", "xpath.js": "~1.1.0" }, "dependencies": { - "@types/node": { - "version": "8.10.66", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", - "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } }, "uuid": { "version": "3.4.0", @@ -342,9 +739,9 @@ "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=" }, "adm-zip": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.0.tgz", - "integrity": "sha512-X6W8Pb1LFdDOQGMsO6OLGmRmyTzIxg5zjXitKjf2fQbqva4iAjcxWS4c01DH+HJ19n3qoQ9TstIRCxJmPOtDow==" + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz", + "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==" }, "agent-base": { "version": "6.0.2", @@ -358,27 +755,55 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" - }, - "dependencies": { - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - } } }, "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, "requires": { - "string-width": "^3.0.0" + "string-width": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, "ansi-colors": { @@ -390,22 +815,44 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -423,11 +870,6 @@ } } }, - "array-filter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", - "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -438,239 +880,70 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assertion-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=" - }, - "ast-types": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", - "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", - "requires": { - "tslib": "^2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" - } - } - }, "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, "atoa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atoa/-/atoa-1.0.0.tgz", "integrity": "sha1-DMDpGkgOc4+SPrwQNnZHF3mzSkk=" }, + "autocompleter": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/autocompleter/-/autocompleter-6.1.2.tgz", + "integrity": "sha512-DfEcgxBJOTJJwxkIRZLv/ggD3g5w/fqzZkdJsOcgk7hjxw36lH/nAfIEXzV7qDE55swnYEe43E/WhZPXmSFfsA==" + }, "available-typed-arrays": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", - "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", - "requires": { - "array-filter": "^1.0.0" - } + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "aws-serverless-express": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/aws-serverless-express/-/aws-serverless-express-3.3.8.tgz", - "integrity": "sha512-2TQdF5EhxnAtGeEi+wSi2M3xCfpiemuImnpU7HKih3onH0izJ/G2tkM+gwcGHZEsW/gLWFl/JjQAYGa3fILfvw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/aws-serverless-express/-/aws-serverless-express-3.4.0.tgz", + "integrity": "sha512-YG9ZjAOI9OpwqDDWzkRc3kKJYJuR7gTMjLa3kAWopO17myoprxskCUyCEee+RKe34tcR4UNrVtgAwW5yDe74bw==", "requires": { + "@vendia/serverless-express": "^3.4.0", "binary-case": "^1.0.0", "type-is": "^1.6.16" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "requires": { - "follow-redirects": "^1.10.0" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, - "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - } + "follow-redirects": "^1.14.0" } }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - } - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" - }, "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base-64": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcryptjs": { "version": "2.4.3", @@ -688,23 +961,51 @@ "integrity": "sha512-9Kq8m6NZTAgy05Ryuh7U3Qc4/ujLQU1AZ5vMw4cr3igTdi5itZC6kCNrRr2X8NzPiDn2oUIFTfa71DKMnue/Zg==" }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true }, "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz", + "integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==", "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "body-parser": { "version": "1.19.0", @@ -716,127 +1017,48 @@ "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - } - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" - }, - "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "color-name": "~1.1.4" + "ms": "2.0.0" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "is-fullwidth-code-point": { @@ -846,32 +1068,23 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "ansi-regex": "^5.0.1" } } } @@ -880,6 +1093,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -889,6 +1103,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -905,9 +1120,21 @@ "dev": true }, "bson": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", - "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.0.tgz", + "integrity": "sha512-8jw1NU1hglS+Da1jDOUYuNcBJ4cNHCFIqzlwoFNnsTOg2R/ox0aTYcTiBN4dzRa9q7Cvy6XErh3L8ReTEb9AQQ==", + "requires": { + "buffer": "^5.6.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, "buffer-equal-constant-time": { "version": "1.0.1", @@ -915,9 +1142,9 @@ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "bytes": { @@ -958,12 +1185,12 @@ } }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, "callsites": { @@ -973,87 +1200,89 @@ "dev": true }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", + "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==", "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chai": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-2.3.0.tgz", - "integrity": "sha1-ii9qNHSNqAEJD9cyh7Kqc5pOkJo=", - "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" - } - }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "chance": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.7.tgz", - "integrity": "sha512-bua/2cZEfzS6qPm0vi3JEvGNbriDLcMj9lKxCQOjUcCJRcyjA7umP0zZm6bKWWlBN04vA0L99QGH/CZQawr0eg==" - }, - "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, + "chance": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.8.tgz", + "integrity": "sha512-v7fi5Hj2VbR6dJEGRWLmJBA83LJMS47pkAbmROFxHWd9qmE1esHRZW8Clf1Fhzr3rjxnNZVCjOEv/ivFxeIMtg==" + }, "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - } + "readdirp": "~3.6.0" } }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "optional": true + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -1067,29 +1296,46 @@ "dev": true }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" } } } @@ -1099,6 +1345,16 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -1106,12 +1362,21 @@ "dev": true, "requires": { "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true }, "color-convert": { "version": "1.9.3", @@ -1122,11 +1387,6 @@ "color-name": "1.1.3" } }, - "color-logger": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.6.tgz", - "integrity": "sha1-5WJF7ymCJlcRDHy3WpzXhstp7Rs=" - }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", @@ -1165,7 +1425,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -1180,9 +1441,9 @@ } }, "config": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/config/-/config-3.3.3.tgz", - "integrity": "sha512-T3RmZQEAji5KYqUQpziWtyGJFli6Khz7h0rpxDwYNjSkr5ynyTWwO7WpfjHzTXclNCDfSWQRcwMb+NwxJesCKw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.6.tgz", + "integrity": "sha512-Hj5916C5HFawjYJat1epbyY2PlAgLpBtDUlr0MxGLgo3p5+7kylyvnRY18PqJHgnNWXcdd0eWDemT7eYWuFgwg==", "requires": { "json5": "^2.1.1" } @@ -1201,6 +1462,12 @@ "xdg-basedir": "^4.0.0" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true + }, "consolidate": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", @@ -1215,6 +1482,13 @@ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", "requires": { "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "content-type": { @@ -1242,20 +1516,20 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", "dev": true }, "core-js": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.0.tgz", - "integrity": "sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA==" + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.19.2.tgz", + "integrity": "sha512-ciYCResnLIATSsXuXnIOH4CbdfgV+H1Ltg16hJFN7/v6OxqnFr/IFGeLacaZ+fHLAm0TBbXwNK9/DNBzBUrO/g==" }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cors": { "version": "2.8.5", @@ -1291,64 +1565,31 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - }, - "dependencies": { - "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==" - } - } - }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "optional": true - }, - "cssstyle": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", - "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", - "optional": true, - "requires": { - "cssom": "0.3.x" - } - }, "csv": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/csv/-/csv-5.3.2.tgz", - "integrity": "sha512-odDyucr9OgJTdGM2wrMbJXbOkJx3nnUX3Pt8SFOwlAMOpsUQlz1dywvLMXJWX/4Ib0rjfOsaawuuwfI5ucqBGQ==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/csv/-/csv-5.5.3.tgz", + "integrity": "sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==", "requires": { - "csv-generate": "^3.2.4", - "csv-parse": "^4.8.8", - "csv-stringify": "^5.3.6", - "stream-transform": "^2.0.1" + "csv-generate": "^3.4.3", + "csv-parse": "^4.16.3", + "csv-stringify": "^5.6.5", + "stream-transform": "^2.1.3" } }, "csv-generate": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-3.3.0.tgz", - "integrity": "sha512-EXSru4QwEWKwM7wwsJbhrZC+mHEJrhQFoXlohHs80CAU8Qhlv9gaw1sjzNiC3Hr3oUx5skDmEiAlz+tnKWV0RA==" + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-3.4.3.tgz", + "integrity": "sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==" }, "csv-parse": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.14.1.tgz", - "integrity": "sha512-4wmcO7QbWtDAncGFaBwlWFPhEN4Akr64IbM4zvDwEOFekI8blLc04Nw7XjQjtSNy+3AUAgBgtUa9nWo5Cq89Xg==" + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", + "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==" }, "csv-stringify": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.5.3.tgz", - "integrity": "sha512-JKG8vIHpWPzdilp2SAmvjmAiIhD+XGKGdhZBGi8QIECgJAsFr7k5CmJIW2QkSxBBsctvmojM25s+UINzQ5NLTg==" + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.5.tgz", + "integrity": "sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==" }, "custom-event": { "version": "1.0.1", @@ -1365,18 +1606,10 @@ "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==" }, "date-utils": { "version": "1.2.21", @@ -1384,57 +1617,43 @@ "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=" }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "optional": true, "requires": { - "type-detect": "0.1.1" + "mimic-response": "^2.0.0" } }, "deep-equal": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.4.tgz", - "integrity": "sha512-BUfaXrVoCfgkOQY/b09QdO9L3XNoF2XH0A3aY9IQwQL/ZjLOe8FQgCNVl1wiolhsFo8kFdO9zdPViCPbmaJA5w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.5.tgz", + "integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==", "requires": { - "es-abstract": "^1.18.0-next.1", - "es-get-iterator": "^1.1.0", + "call-bind": "^1.0.0", + "es-get-iterator": "^1.1.1", + "get-intrinsic": "^1.0.1", "is-arguments": "^1.0.4", "is-date-object": "^1.0.2", "is-regex": "^1.1.1", "isarray": "^2.0.5", - "object-is": "^1.1.3", + "object-is": "^1.1.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", + "object.assign": "^4.1.2", "regexp.prototype.flags": "^1.3.0", "side-channel": "^1.0.3", "which-boxed-primitive": "^1.0.1", @@ -1445,13 +1664,13 @@ "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, "deepmerge": { "version": "4.2.2", @@ -1472,21 +1691,17 @@ "object-keys": "^1.0.12" } }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, "delete-property": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/delete-property/-/delete-property-0.0.4.tgz", @@ -1496,9 +1711,9 @@ } }, "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", + "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==" }, "depd": { "version": "1.1.2", @@ -1510,18 +1725,21 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "requires": { - "repeating": "^2.0.0" - } + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "optional": true + }, + "dialog-polyfill": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz", + "integrity": "sha512-ZbVDJI9uvxPAKze6z146rmfUZjBqNEwcnFTVamQzXH+svluiV7swmVIGr7miwADgfgt1G2JQIytypM9fbyhX4w==" }, "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "doctrine": { @@ -1533,36 +1751,10 @@ "esutils": "^2.0.2" } }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } + "dompurify": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.3.tgz", + "integrity": "sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==" }, "dot-prop": { "version": "5.3.0", @@ -1574,9 +1766,9 @@ } }, "dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" }, "downloadjs": { "version": "1.4.7", @@ -1598,15 +1790,6 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -1621,9 +1804,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "encodeurl": { @@ -1635,7 +1818,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -1649,41 +1831,44 @@ "ansi-colors": "^4.1.1" } }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, "es-get-iterator": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.1.tgz", - "integrity": "sha512-qorBw8Y7B15DVLaJWy6WdEV/ZkieBcu6QCq/xzWzGOKJqgG1j754vXRfZ3NY7HSShneqU43mPB4OkQBTkvHhFw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.1", + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", "has-symbols": "^1.0.1", - "is-arguments": "^1.0.4", - "is-map": "^2.0.1", - "is-set": "^2.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", "is-string": "^1.0.5", "isarray": "^2.0.5" } @@ -1698,18 +1883,11 @@ "is-symbol": "^1.0.2" } }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, "escape-goat": { "version": "2.1.1", @@ -1723,116 +1901,38 @@ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - } - } - }, - "esdoc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esdoc/-/esdoc-1.1.0.tgz", - "integrity": "sha512-vsUcp52XJkOWg9m1vDYplGZN2iDzvmjDL5M/Mp8qkoDG3p2s0yIQCIjKR5wfPBaM3eV14a6zhQNYiNTCVzPnxA==", - "requires": { - "babel-generator": "6.26.1", - "babel-traverse": "6.26.0", - "babylon": "6.18.0", - "cheerio": "1.0.0-rc.2", - "color-logger": "0.0.6", - "escape-html": "1.0.3", - "fs-extra": "5.0.0", - "ice-cap": "0.0.4", - "marked": "0.3.19", - "minimist": "1.2.0", - "taffydb": "2.7.3" - }, - "dependencies": { - "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "marked": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.7.tgz", - "integrity": "sha512-BJXxkuIfJchcXOJWTT2DOL+yFWifFv2yGYOUzvXg8Qz610QKw+sHCvTMYwA+qWGhlA2uivBezChZ/pBy1tWdkQ==" - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - } - } - }, - "esdoc-coverage-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esdoc-coverage-plugin/-/esdoc-coverage-plugin-1.1.0.tgz", - "integrity": "sha1-OGmGnNf4eJH5cmJXh2laKZrs5Fw=" - }, - "esdoc-type-inference-plugin": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/esdoc-type-inference-plugin/-/esdoc-type-inference-plugin-1.0.2.tgz", - "integrity": "sha512-tMIcEHNe1uhUGA7lT1UTWc9hs2dzthnTgmqXpmeUhurk7fL2tinvoH+IVvG/sLROzwOGZQS9zW/F9KWnpMzLIQ==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "eslint": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.14.0.tgz", - "integrity": "sha512-5YubdnPXrlrYAFCKybPuHIAH++PINe1pmKNc5wQRB9HSbqIK1ywAnntE3Wwua4giKu0bjligf1gLF6qxMGOYRA==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.1", + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.0", - "esquery": "^1.2.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -1840,7 +1940,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -1849,137 +1949,31 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^5.2.3", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "ansi-regex": "^5.0.1" } }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true } } }, @@ -2016,28 +2010,22 @@ } }, "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true }, "espree": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", - "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "dev": true, "requires": { "acorn": "^7.4.0", - "acorn-jsx": "^5.2.0", + "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^1.3.0" }, "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", @@ -2047,23 +2035,24 @@ } }, "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -2078,9 +2067,9 @@ }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -2088,12 +2077,14 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, "etag": { "version": "1.8.1", @@ -2116,6 +2107,11 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -2129,6 +2125,22 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "optional": true + }, + "expose-gc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/expose-gc/-/expose-gc-1.0.0.tgz", + "integrity": "sha512-ecOHrdm+zyOCGIwX18/1RHkUWgxDqGGRiGhaNC+42jReTtudbm2ID/DMa/wpaHwqy5YQHPZvsDqRM2F2iZ0uVA==" + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -2174,38 +2186,15 @@ "ms": "2.0.0" } }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "requires": { - "side-channel": "^1.0.4" - } + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -2214,20 +2203,15 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, "eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-diff": { "version": "1.2.0", @@ -2235,47 +2219,55 @@ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" }, "fast-json-patch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", - "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", - "requires": { - "fast-deep-equal": "^2.0.1" - } + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.0.tgz", + "integrity": "sha512-IhpytlsVTRndz0hU5t0/MGzS/etxLlfrpG5V5M9mVbuj9TrJLWaMfsox9REM5rkuGX0T+5qjpe8XA1o0gZ42nA==" }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, + "fetch-blob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz", + "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==" + }, + "fetch-ponyfill": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-7.1.0.tgz", + "integrity": "sha512-FhbbL55dj/qdVO3YNK7ZEkshvj3eQ7EuIGV2I6ic/2YiocvyWv+7jg2s4AyS0wdRU75s3tA8ZxI/xPigb0v5Aw==", + "requires": { + "node-fetch": "~2.6.1" + } + }, "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { - "flat-cache": "^2.0.1" + "flat-cache": "^3.0.4" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -2301,6 +2293,11 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -2321,48 +2318,31 @@ "dev": true }, "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", "dev": true }, "follow-redirects": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", - "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" + "version": "1.14.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", + "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" }, "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, "form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", @@ -2374,58 +2354,59 @@ } }, "formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", "dev": true }, "formio-workers": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/formio-workers/-/formio-workers-1.14.8.tgz", - "integrity": "sha512-qbyaW5rG4UnL1SlGhPScF/PT5c5R5aYG+mJaeZh7vf1D0WY15jWE/7Fn22ey0xCTPAgAlfNDqCSVm6cEcTDjcg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/formio-workers/-/formio-workers-1.16.0.tgz", + "integrity": "sha512-bj8rfqqlI3uh9uw+qpizHhQdgHYhD88PGiSM+ASd3HJ517HD51L4HH2zYQ/zdSlSA7Yh2SkWA3O76WB+xCDsHg==", "requires": { - "aws-serverless-express": "^3.3.8", + "aws-serverless-express": "^3.4.0", "body-parser": "^1.19.0", - "core-js": "^3.6.5", - "dotenv": "^8.2.0", + "core-js": "^3.18.3", + "dotenv": "^10.0.0", "express": "^4.17.1", - "formiojs": "^4.9.26", + "formiojs": "^4.13.7", + "lodash": "^4.17.21", "method-override": "^3.0.0", - "moment": "^2.26.0", - "nunjucks": "^3.2.1", + "moment": "^2.29.1", + "nunjucks": "^3.2.3", "nunjucks-date-filter": "^0.1.1", - "threads": "^0.12.1" + "vm2": "^3.9.5" }, "dependencies": { - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" }, "formiojs": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/formiojs/-/formiojs-4.13.1.tgz", - "integrity": "sha512-bd6QnFdYw8ctR4D/TvsdmKxDeYWydzv5P+zORd2t42+N4RLkud8HiqeKyOK/BIC0OZywAh6oFomSEQH4UNt/Sg==", + "version": "4.13.10", + "resolved": "https://registry.npmjs.org/formiojs/-/formiojs-4.13.10.tgz", + "integrity": "sha512-RIZudgKCjAaasHLeNtsQ2QE8Z62MqHfHQk1Hpr0GJa9+7tZBjxZ8BUkrHdxfhn6vdlY39ZHwcq0I3gL9qnRJQw==", "requires": { - "@formio/bootstrap3": "^2.11.0", + "@formio/bootstrap3": "^2.12.0", "@formio/choices.js": "^9.0.1", - "@formio/semantic": "^2.5.1", + "@formio/semantic": "^2.6.0", "@formio/vanilla-text-mask": "^5.1.1", - "autocompleter": "^6.1.0", + "autocompleter": "^6.1.2", "browser-cookies": "^1.2.0", "compare-versions": "^3.6.0", - "core-js": "^3.11.1", + "core-js": "^3.18.1", "custom-event-polyfill": "^1.0.7", "dialog-polyfill": "^0.5.6", - "dompurify": "^2.2.8", + "dompurify": "^2.3.3", "downloadjs": "^1.4.7", "dragula": "^3.7.3", "eventemitter3": "^4.0.7", "fast-deep-equal": "^3.1.3", - "fast-json-patch": "^2.2.1", + "fast-json-patch": "^3.1.0", "fetch-ponyfill": "^7.1.0", - "i18next": "^20.2.2", - "idb": "^6.0.0", + "i18next": "~20.4.0", + "idb": "^6.1.4", "ismobilejs": "^1.1.1", "json-logic-js": "^2.0.0", "jstimezonedetect": "^1.0.7", @@ -2442,116 +2423,34 @@ "tooltip.js": "^1.3.3", "uuid": "^8.3.2", "vanilla-picker": "^2.11.2" - }, - "dependencies": { - "@formio/bootstrap3": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@formio/bootstrap3/-/bootstrap3-2.11.0.tgz", - "integrity": "sha512-3R0X1FWYslRplvCQYkP23V66OWFmo7rjhTbhVVzIFXYlvVIWY/A019HSMVyfET7QWMQnGz42vzxmE/yVuBMI1A==", - "requires": { - "resize-observer-polyfill": "^1.5.1" - } - }, - "@formio/semantic": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@formio/semantic/-/semantic-2.5.1.tgz", - "integrity": "sha512-WEATjjCm8zNneFattKhQd4viXNW8by4PYU7j/KkesO5jiYiWFV75U7Ewc/3bCHFFXyj7NkmI49cbVH17tXnKxw==" - }, - "autocompleter": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/autocompleter/-/autocompleter-6.1.0.tgz", - "integrity": "sha512-w+gPtAuwL+0BY33rwtFaliZ2TW/iJlbQ0AaFFi7sy7kh1MdOM5VpAMJ2s/6yygIkWkLQP8WF+ajlG39Ft8459Q==" - }, - "core-js": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.12.1.tgz", - "integrity": "sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==" - }, - "dialog-polyfill": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz", - "integrity": "sha512-ZbVDJI9uvxPAKze6z146rmfUZjBqNEwcnFTVamQzXH+svluiV7swmVIGr7miwADgfgt1G2JQIytypM9fbyhX4w==" - }, - "dompurify": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.8.tgz", - "integrity": "sha512-9H0UL59EkDLgY3dUFjLV6IEUaHm5qp3mxSqWw7Yyx4Zhk2Jn2cmLe+CNPP3xy13zl8Bqg+0NehQzkdMoVhGRww==" - }, - "fetch-ponyfill": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-7.1.0.tgz", - "integrity": "sha512-FhbbL55dj/qdVO3YNK7ZEkshvj3eQ7EuIGV2I6ic/2YiocvyWv+7jg2s4AyS0wdRU75s3tA8ZxI/xPigb0v5Aw==", - "requires": { - "node-fetch": "~2.6.1" - } - }, - "i18next": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.3.0.tgz", - "integrity": "sha512-eFv4aQvaGykp48mI4JEaCcoD/j4zoYjFnDYhChe3ukwvbHx3q4mKZlB8YnmhYrHQR5FopLlCrzcSuY0ZWfiakA==", - "requires": { - "@babel/runtime": "^7.12.0" - } - }, - "idb": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.1.tgz", - "integrity": "sha512-5AnQiuTwELdLlriQ+UTVEzT3J7cC/4NSF0S0H5WC35FcOME4dbPHnfsbzkdfJWaFadiXvATHIV06bK/yilmjqQ==" - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "moment-timezone": { - "version": "0.5.33", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", - "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "vanilla-picker": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.11.2.tgz", - "integrity": "sha512-2cP7LlUnxHxwOf06ReUVtd2RFJMnJGaxN2s0p8wzBH3In5b00Le7fFZ9VrIoBE0svZkSq/BC/Pwq/k/9n+AA2g==", - "requires": { - "@sphinxxxx/color-conversion": "^2.2.2" - } - } } } } }, "formiojs": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/formiojs/-/formiojs-4.13.1.tgz", - "integrity": "sha512-bd6QnFdYw8ctR4D/TvsdmKxDeYWydzv5P+zORd2t42+N4RLkud8HiqeKyOK/BIC0OZywAh6oFomSEQH4UNt/Sg==", + "version": "4.14.0-rc.38", + "resolved": "https://registry.npmjs.org/formiojs/-/formiojs-4.14.0-rc.38.tgz", + "integrity": "sha512-HLSMB7Pe5KbucXaWS3JHmpFPez/4KVVClzfD4h1aHKakxpx/kQK3lVRS2pjmANHFWZpYi/6L7GCHkEEBjTb6eQ==", "requires": { - "@formio/bootstrap3": "^2.11.0", + "@formio/bootstrap3": "^2.12.0", "@formio/choices.js": "^9.0.1", - "@formio/semantic": "^2.5.1", + "@formio/semantic": "^2.6.0", "@formio/vanilla-text-mask": "^5.1.1", - "autocompleter": "^6.1.0", + "autocompleter": "^6.1.2", "browser-cookies": "^1.2.0", "compare-versions": "^3.6.0", - "core-js": "^3.11.1", + "core-js": "^3.18.3", "custom-event-polyfill": "^1.0.7", "dialog-polyfill": "^0.5.6", - "dompurify": "^2.2.8", + "dompurify": "^2.3.3", "downloadjs": "^1.4.7", "dragula": "^3.7.3", "eventemitter3": "^4.0.7", "fast-deep-equal": "^3.1.3", - "fast-json-patch": "^2.2.1", + "fast-json-patch": "^3.1.0", "fetch-ponyfill": "^7.1.0", - "i18next": "^20.2.2", - "idb": "^6.0.0", + "i18next": "^21.3.3", + "idb": "^6.1.5", "ismobilejs": "^1.1.1", "json-logic-js": "^2.0.0", "jstimezonedetect": "^1.0.7", @@ -2570,157 +2469,55 @@ "vanilla-picker": "^2.11.2" }, "dependencies": { - "@formio/bootstrap3": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@formio/bootstrap3/-/bootstrap3-2.11.0.tgz", - "integrity": "sha512-3R0X1FWYslRplvCQYkP23V66OWFmo7rjhTbhVVzIFXYlvVIWY/A019HSMVyfET7QWMQnGz42vzxmE/yVuBMI1A==", - "requires": { - "resize-observer-polyfill": "^1.5.1" - } - }, - "@formio/semantic": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@formio/semantic/-/semantic-2.5.1.tgz", - "integrity": "sha512-WEATjjCm8zNneFattKhQd4viXNW8by4PYU7j/KkesO5jiYiWFV75U7Ewc/3bCHFFXyj7NkmI49cbVH17tXnKxw==" - }, - "autocompleter": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/autocompleter/-/autocompleter-6.1.0.tgz", - "integrity": "sha512-w+gPtAuwL+0BY33rwtFaliZ2TW/iJlbQ0AaFFi7sy7kh1MdOM5VpAMJ2s/6yygIkWkLQP8WF+ajlG39Ft8459Q==" - }, - "core-js": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.12.1.tgz", - "integrity": "sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==" - }, - "dialog-polyfill": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz", - "integrity": "sha512-ZbVDJI9uvxPAKze6z146rmfUZjBqNEwcnFTVamQzXH+svluiV7swmVIGr7miwADgfgt1G2JQIytypM9fbyhX4w==" - }, - "dompurify": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.8.tgz", - "integrity": "sha512-9H0UL59EkDLgY3dUFjLV6IEUaHm5qp3mxSqWw7Yyx4Zhk2Jn2cmLe+CNPP3xy13zl8Bqg+0NehQzkdMoVhGRww==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fetch-ponyfill": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-7.1.0.tgz", - "integrity": "sha512-FhbbL55dj/qdVO3YNK7ZEkshvj3eQ7EuIGV2I6ic/2YiocvyWv+7jg2s4AyS0wdRU75s3tA8ZxI/xPigb0v5Aw==", - "requires": { - "node-fetch": "~2.6.1" - } - }, "i18next": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.3.0.tgz", - "integrity": "sha512-eFv4aQvaGykp48mI4JEaCcoD/j4zoYjFnDYhChe3ukwvbHx3q4mKZlB8YnmhYrHQR5FopLlCrzcSuY0ZWfiakA==", + "version": "21.5.4", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.5.4.tgz", + "integrity": "sha512-ukwRJpLhYg4EUfCOtbaKjlwF71qyel1XMXQN78OkQMcaQG68UzlYgLC6g2fhoTNBvoH2tJkaaqzDumhC9skAhA==", "requires": { "@babel/runtime": "^7.12.0" } - }, - "idb": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.1.tgz", - "integrity": "sha512-5AnQiuTwELdLlriQ+UTVEzT3J7cC/4NSF0S0H5WC35FcOME4dbPHnfsbzkdfJWaFadiXvATHIV06bK/yilmjqQ==" - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "moment-timezone": { - "version": "0.5.33", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", - "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "vanilla-picker": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.11.2.tgz", - "integrity": "sha512-2cP7LlUnxHxwOf06ReUVtd2RFJMnJGaxN2s0p8wzBH3In5b00Le7fFZ9VrIoBE0svZkSq/BC/Pwq/k/9n+AA2g==", - "requires": { - "@sphinxxxx/color-conversion": "^2.2.2" - } } } }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "optional": true + }, "fs-extra": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", - "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", - "universalify": "^1.0.0" + "universalify": "^2.0.0" } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "optional": true }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2737,6 +2534,22 @@ "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.6.1.tgz", "integrity": "sha512-hT9yh/tiinkmirKrlv4KWOjztdoZo1mx9Qh4KvWqC7isoXwdUY3PNWUxceF4/qO9R6riA2C29jdTOeQOIROjgw==" }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2744,9 +2557,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", - "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -2762,41 +2575,26 @@ "pump": "^3.0.0" } }, - "get-uri": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", - "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "~3.0.2", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "requires": { - "assert-plus": "^1.0.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" } }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "optional": true + }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2806,19 +2604,40 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "global-dirs": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", - "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", "dev": true, "requires": { - "ini": "^1.3.5" + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + } } }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } }, "got": { "version": "9.6.0", @@ -2837,12 +2656,29 @@ "p-cancelable": "^1.0.0", "to-readable-stream": "^1.0.0", "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "growl": { "version": "1.10.5", @@ -2850,20 +2686,6 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2872,13 +2694,10 @@ "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" }, "has-flag": { "version": "3.0.0", @@ -2887,9 +2706,23 @@ "dev": true }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "optional": true }, "has-yarn": { "version": "2.1.0", @@ -2903,40 +2736,10 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "hoek": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", - "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==" - }, "html-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", - "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==" - }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==" }, "http-cache-semantics": { "version": "4.1.0", @@ -2957,40 +2760,13 @@ } }, "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" } }, "https-proxy-agent": { @@ -3002,93 +2778,12 @@ "debug": "4" } }, - "i": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", - "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=" - }, - "ice-cap": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/ice-cap/-/ice-cap-0.0.4.tgz", - "integrity": "sha1-im0xq0ysjUtW3k+pRt8zUlYbbhg=", + "i18next": { + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.4.0.tgz", + "integrity": "sha512-89iWWJudmaHJwzIdJ/1eu98GtsJnwBhOUWwlAre70itPMuTE/NTPtgVeaS1CGaB8Q3XrYBGpEqlq4jsScDx9kg==", "requires": { - "cheerio": "0.20.0", - "color-logger": "0.0.3" - }, - "dependencies": { - "cheerio": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", - "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "~3.8.1", - "jsdom": "^7.0.2", - "lodash": "^4.1.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - } - } - }, - "color-logger": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.3.tgz", - "integrity": "sha1-2bIt0dlz4Waxi/MT+fSBu6TfIBg=" - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "requires": { - "domelementtype": "1" - } - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - }, - "dependencies": { - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" - } - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } + "@babel/runtime": "^7.12.0" } }, "iconv-lite": { @@ -3099,6 +2794,16 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "idb": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", + "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -3112,21 +2817,13 @@ "dev": true }, "import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } } }, "import-lazy": { @@ -3141,15 +2838,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3163,21 +2856,22 @@ "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "requires": { - "loose-envify": "^1.0.0" + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" } }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" }, "ipaddr.js": { "version": "1.9.1", @@ -3185,32 +2879,44 @@ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } }, "is-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", - "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "requires": { "binary-extensions": "^2.0.0" } }, "is-boolean-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", - "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" }, "is-ci": { "version": "2.0.0", @@ -3222,69 +2928,81 @@ } }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "requires": { "is-extglob": "^2.1.1" } }, "is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, "requires": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" } }, "is-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", - "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==" }, "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" }, "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", "dev": true }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-obj": { "version": "2.0.0", @@ -3293,9 +3011,9 @@ "dev": true }, "is-path-inside": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", - "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, "is-plain-obj": { @@ -3304,83 +3022,99 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { - "has-symbols": "^1.0.1" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-set": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", - "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==" }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==" }, "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-typed-array": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", - "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", "requires": { - "available-typed-arrays": "^1.0.0", - "es-abstract": "^1.17.4", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", "foreach": "^2.0.5", - "has-symbols": "^1.0.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "has-tostringtag": "^1.0.0" } }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true }, "is-weakmap": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==" }, + "is-weakref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", + "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "requires": { + "call-bind": "^1.0.0" + } + }, "is-weakset": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==" }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, "is-yarn-global": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", @@ -3392,14 +3126,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, - "isemail": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", - "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", - "requires": { - "punycode": "2.x.x" - } - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3411,89 +3137,36 @@ "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==" }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, - "joi": { - "version": "14.3.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz", - "integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==", - "requires": { - "hoek": "6.x.x", - "isemail": "3.x.x", - "topo": "3.x.x" - } - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } - } - }, - "jsbi": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.1.4.tgz", - "integrity": "sha512-52QRRFSsi9impURE8ZUbzAMCLjPm4THO7H2fcuIvaaeFTbSysvkodbQQXIVsNgq/ypDbq6dJiuGKL0vZ/i9hUg==" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsdom": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", - "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", - "optional": true, - "requires": { - "abab": "^1.0.0", - "acorn": "^2.4.0", - "acorn-globals": "^1.0.4", - "cssom": ">= 0.3.0 < 0.4.0", - "cssstyle": ">= 0.2.29 < 0.3.0", - "escodegen": "^1.6.1", - "nwmatcher": ">= 1.3.7 < 2.0.0", - "parse5": "^1.5.1", - "request": "^2.55.0", - "sax": "^1.1.4", - "symbol-tree": ">= 3.1.0 < 4.0.0", - "tough-cookie": "^2.2.0", - "webidl-conversions": "^2.0.0", - "whatwg-url-compat": "~0.6.5", - "xml-name-validator": ">= 2.0.1 < 3.0.0" - }, - "dependencies": { - "parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", - "optional": true - } + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + "jsbi": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", + "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" }, "json-buffer": { "version": "3.0.0", @@ -3502,19 +3175,15 @@ "dev": true }, "json-logic-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/json-logic-js/-/json-logic-js-2.0.0.tgz", - "integrity": "sha512-cQBDOXgFtFladCg99wnQ7YfN+nv1+Sznj4K6bp3CTgDJNJKgEXJE2VCXzVBjEU2e1UagDHSek52IQk5Ha38n7Q==" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/json-logic-js/-/json-logic-js-2.0.1.tgz", + "integrity": "sha512-J3hhqM4IY66sL8qyzU7cwLmTAt3kA6ZsYxyuZBEwhcc+OYPTmAHc64fBTXHT6K5RwFeUqJUX1tfO7wpKsUx+9A==" }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -3522,24 +3191,12 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "requires": { "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } } }, "jsonfile": { @@ -3549,13 +3206,6 @@ "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } } }, "jsonparse": { @@ -3580,11 +3230,6 @@ "semver": "^5.6.0" }, "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -3592,17 +3237,6 @@ } } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "jstimezonedetect": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/jstimezonedetect/-/jstimezonedetect-1.0.7.tgz", @@ -3637,6 +3271,16 @@ "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" }, + "keytar": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", + "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", + "optional": true, + "requires": { + "node-addon-api": "^3.0.0", + "prebuild-install": "^6.0.0" + } + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -3646,6 +3290,36 @@ "json-buffer": "3.0.0" } }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "ky": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.25.1.tgz", + "integrity": "sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA==" + }, + "ky-universal": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.8.2.tgz", + "integrity": "sha512-xe0JaOH9QeYxdyGLnzUOVGK4Z6FGvDVzcXFTdrYA1f33MZdEa45sUDaMBy98xQMcsd2XIBrTXRrRYnegcSdgVQ==", + "requires": { + "abort-controller": "^3.0.0", + "node-fetch": "3.0.0-beta.9" + }, + "dependencies": { + "node-fetch": { + "version": "3.0.0-beta.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.0.0-beta.9.tgz", + "integrity": "sha512-RdbZCEynH2tH46+tj0ua9caUHVWrd/RHnRfvly2EVdqGmI3ndS1Vn/xjm5KuGejDt2RNDQsVRLPNd2QPwcewVg==", + "requires": { + "data-uri-to-buffer": "^3.0.1", + "fetch-blob": "^2.1.1" + } + } + } + }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -3656,12 +3330,13 @@ } }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "locate-path": { @@ -3797,6 +3472,12 @@ "lodash.isarray": "^3.0.0" } }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -3815,6 +3496,12 @@ "resolved": "https://registry.npmjs.org/lodash.property/-/lodash.property-4.4.2.tgz", "integrity": "sha1-2gcSSCHGQJ0CXzDbjfhRMUUVv/4=" }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, "lodash.uniq": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-3.2.2.tgz", @@ -3828,71 +3515,13 @@ } }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "lowercase-keys": { @@ -3902,44 +3531,26 @@ "dev": true }, "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "mailgun-js": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.22.0.tgz", - "integrity": "sha512-a2alg5nuTZA9Psa1pSEIEsbxr1Zrmqx4VkgGCQ30xVh0kIH7Bu57AYILo+0v8QLSdXtCyLaS+KVmdCrQo0uWFA==", - "requires": { - "async": "^2.6.1", - "debug": "^4.1.0", - "form-data": "^2.3.3", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "^3.0.3", - "tsscmp": "^1.0.6" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - }, - "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - } - } - } + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mailgun.js": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-3.7.3.tgz", + "integrity": "sha512-DHP9v6dNPRM2puOx4HVJVjQKWzgzpQ5Fh1ICW632qaDVgd/QqGRhOjCoHe12JJqrFkhgDvXBhENYeZDHYdkJHQ==", + "requires": { + "base-64": "^1.0.0", + "bluebird": "^3.7.2", + "ky": "^0.25.1", + "ky-universal": "^0.8.2", + "url": "^0.11.0", + "url-join": "0.0.1", + "web-streams-polyfill": "^3.0.1", + "webpack-merge": "^5.4.0" } }, "make-dir": { @@ -4003,6 +3614,11 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -4017,99 +3633,117 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "requires": { - "mime-db": "1.44.0" + "mime-db": "1.51.0" } }, "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "optional": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, "mixme": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mixme/-/mixme-0.5.1.tgz", - "integrity": "sha512-NaeZIckeBFT7i0XBEpGyFcAE0/bLcQ9MHErTpnU3bLWVE5WZbxG5Y3fDsMxYGifTo5khDA42OquXCC2ngKJB+g==" + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mixme/-/mixme-0.5.4.tgz", + "integrity": "sha512-3KYa4m4Vlqx98GPdOHghxSdNtTvcP8E0kkaJ5Dlh+h2DRzF7zpuVVcA8B0QpKd11YJeP9QQ7ASkKzOeu195Wzw==" }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } - } + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "optional": true }, "mocha": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", - "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", + "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.4.3", - "debug": "4.2.0", - "diff": "4.0.2", + "chokidar": "3.5.2", + "debug": "4.3.2", + "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.14.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", - "ms": "2.1.2", - "nanoid": "3.1.12", - "serialize-javascript": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.1.25", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", - "supports-color": "7.2.0", + "supports-color": "8.1.1", "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.2", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", + "workerpool": "6.1.5", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-flag": { "version": "4.0.0", @@ -4117,16 +3751,31 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -4140,115 +3789,124 @@ "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, "moment-timezone": { - "version": "0.5.32", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.32.tgz", - "integrity": "sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA==", + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", "requires": { "moment": ">= 2.9.0" } }, "mongodb": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz", - "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.2.0.tgz", + "integrity": "sha512-lg3MJ9dAKxhogRnIB6/j63gfD7JryZwRC0nNzZ82RhENw4nCmscZVqRfOmNzTvSNndJx9ZhxZpm9JvnKuH/GTA==", + "requires": { + "bson": "^4.5.4", + "denque": "^2.0.1", + "mongodb-connection-string-url": "^2.2.0", + "saslprep": "^1.0.3" + } + }, + "mongodb-connection-string-url": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.2.0.tgz", + "integrity": "sha512-U0cDxLUrQrl7DZA828CA+o69EuWPWEJTwdMPozyd7cy/dbtncUZczMw7wRHcwMD7oKOn0NM2tF9jdf5FFVW9CA==", "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + }, + "dependencies": { + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } } }, "mongoose": { - "version": "5.12.11", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.12.11.tgz", - "integrity": "sha512-16TVqYhHQdZNR8RTis/8iiTPy+nJPq0UhKyBFTucLLU3PWcDLY2gAGv6aOk0LygTNhEfgNnENgUUHhjVqTuh8w==", + "version": "6.0.14", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.0.14.tgz", + "integrity": "sha512-SZ0kBlHrz/G70yWdVXLfM/gH4NsY85+as4MZRdtWxBTDEcmoE3rCFAz1/Ho2ycg5mJAeOBwdGZw4a5sn/WrwUA==", "requires": { - "@types/mongodb": "^3.5.27", - "bson": "^1.1.4", + "bson": "^4.2.2", "kareem": "2.3.2", - "mongodb": "3.6.8", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.8.3", - "mquery": "3.2.5", + "mongodb": "4.1.4", + "mpath": "0.8.4", + "mquery": "4.0.0", "ms": "2.1.2", "regexp-clone": "1.0.0", - "safe-buffer": "5.2.1", "sift": "13.5.2", "sliced": "1.0.1" }, "dependencies": { "mongodb": { - "version": "3.6.8", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.8.tgz", - "integrity": "sha512-sDjJvI73WjON1vapcbyBD3Ao9/VN3TKYY8/QX9EPbs22KaCSrQ5rXo5ZZd44tWJ3wl3FlnrFZ+KyUtNH6+1ZPQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.1.4.tgz", + "integrity": "sha512-Cv/sk8on/tpvvqbEvR1h03mdyNdyvvO+WhtFlL4jrZ+DSsN/oSQHVqmJQI/sBCqqbOArFcYCAYDfyzqFwV4GSQ==", "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" + "bson": "^4.5.4", + "denque": "^2.0.1", + "mongodb-connection-string-url": "^2.1.0", + "saslprep": "^1.0.3" } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, - "mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" - }, "mpath": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz", - "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==" + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", + "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==" }, "mquery": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", - "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.0.tgz", + "integrity": "sha512-nGjm89lHja+T/b8cybAby6H0YgA4qYC/lx6UlwvHGqvTq8bDaNeCwl1sY8uRELrNbVWJzIihxVd+vphGGn1vBw==", "requires": { - "bluebird": "3.5.1", - "debug": "3.1.0", + "debug": "4.x", "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", "sliced": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "msal": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/msal/-/msal-1.4.15.tgz", + "integrity": "sha512-H/CxkeZJ4laEK6GZ/cDKQoYjBTvDNFK3hDC8mfU8IkuZvKFfFdo9KM89r8spXY7xnBK9SQBAjIuQgwUogeUw7g==", + "requires": { + "tslib": "^1.9.3" + } }, "mssql": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mssql/-/mssql-6.2.3.tgz", - "integrity": "sha512-4TW/fA9UgzmVTNgjl65r6ISr6aL5QHnlptEt1A3jIpdzkNbFPIkRbUNz90324HIdE+5pKc3VqikOImcTrhd4og==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/mssql/-/mssql-7.3.0.tgz", + "integrity": "sha512-3NGxDomH5Lci2g0EUrsejHIsvtFwlIE6A9SNFWQ2/JD4Dh0+5XVFHeyB4RXKb+nRMDosSUBAQDIVSuLXo5XFZA==", "requires": { - "debug": "^4", - "tarn": "^1.1.5", - "tedious": "^6.6.2" + "@tediousjs/connection-string": "^0.3.0", + "debug": "^4.3.2", + "rfdc": "^1.3.0", + "tarn": "^3.0.1", + "tedious": "^11.4.0" } }, "mute-stream": { @@ -4265,14 +3923,27 @@ "readable-stream": "2.3.7", "safe-buffer": "5.1.2", "sqlstring": "2.3.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "nanoid": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "optional": true + }, "native-duplexpair": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", @@ -4289,25 +3960,46 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "ncp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", - "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=" - }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, - "netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "optional": true, + "requires": { + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "optional": true + } + } + }, + "node-abort-controller": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-2.0.0.tgz", + "integrity": "sha512-L8RfEgjBTHAISTuagw51PprVAqNZoG6KSB6LQ6H1bskMVkFs5E71IyjauLBv3XbuomJlguWF/VnRHdJ1gqiAqA==" + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "optional": true }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "requires": { + "whatwg-url": "^5.0.0" + } }, "node-paginate-anything": { "version": "1.0.0", @@ -4315,17 +4007,30 @@ "integrity": "sha1-WR/jCw1r8J/7yrl9ETt2z6mdHZs=" }, "nodemailer": { - "version": "6.4.16", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.16.tgz", - "integrity": "sha512-68K0LgZ6hmZ7PVmwL78gzNdjpj5viqBdFqKrTtr9bZbJYj6BRj5W6WGkxXrEnUl3Co3CBXi3CZBUlpV/foGnOQ==" + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.2.tgz", + "integrity": "sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q==" }, "nodemailer-mailgun-transport": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/nodemailer-mailgun-transport/-/nodemailer-mailgun-transport-2.0.2.tgz", - "integrity": "sha512-4j0G4yUrYrJ2o/1Ow3d5HeW/ed9anWQ1+He7HuL2+0XcSyLLjNkft30zodFTyTWlFaiLiaIJ9Ssnjmz+qrtIZg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/nodemailer-mailgun-transport/-/nodemailer-mailgun-transport-2.1.3.tgz", + "integrity": "sha512-mh/oWKUX0E6tBPcvELLIkxjNZXyqoa9J9SwgtG0Q5I7jct17aHQLk4okm48FMNtBAvpwC8fSzIxXRFVEgV2xXw==", "requires": { "consolidate": "^0.15.1", - "mailgun-js": "^0.22.0" + "form-data": "^4.0.0", + "mailgun.js": "^3.3.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } } }, "nodemailer-mandrill-transport": { @@ -4339,29 +4044,28 @@ } }, "nodemailer-sendgrid-transport": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nodemailer-sendgrid-transport/-/nodemailer-sendgrid-transport-0.2.0.tgz", - "integrity": "sha1-pRZZO/49HyeM/hcGDh2yNlio9Pw=", + "version": "git+https://github.com/formio/nodemailer-sendgrid-transport.git#ff72e254c4d5c90123e49900842097e5e6efe7d4", + "from": "git+https://github.com/formio/nodemailer-sendgrid-transport.git", "requires": { - "sendgrid": "^1.8.0" + "@sendgrid/mail": "^7.4.5" } }, "nodemon": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz", - "integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", + "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", "dev": true, "requires": { - "chokidar": "^3.2.2", - "debug": "^3.2.6", + "chokidar": "^3.5.2", + "debug": "^3.2.7", "ignore-by-default": "^1.0.1", "minimatch": "^3.0.4", - "pstree.remy": "^1.1.7", + "pstree.remy": "^1.1.8", "semver": "^5.7.1", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.3", - "update-notifier": "^4.1.0" + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" }, "dependencies": { "debug": { @@ -4373,26 +4077,11 @@ "ms": "^2.1.1" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, @@ -4408,30 +4097,40 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "optional": true, "requires": { - "boolbase": "~1.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true + }, "nunjucks": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.2.tgz", - "integrity": "sha512-KUi85OoF2NMygwODAy28Lh9qHmq5hO3rBlbkYoC8v377h4l8Pt5qFjILl0LWpMbOrZ18CzfVVUvIHUIrtED3sA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz", + "integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==", "requires": { "a-sync-waterfall": "^1.0.0", "asap": "^2.0.3", - "chokidar": "^3.3.0", "commander": "^5.1.0" } }, @@ -4443,34 +4142,23 @@ "moment": "^2.9.0" } }, - "nwmatcher": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", - "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", - "optional": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==" }, "object-is": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", - "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "object-keys": { @@ -4505,22 +4193,27 @@ "wrappy": "1" } }, - "optional-require": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", - "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==" + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, "os-shim": { @@ -4553,80 +4246,6 @@ "p-limit": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pac-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", - "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", - "requires": { - "agent-base": "^4.2.0", - "debug": "^4.1.1", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - }, - "dependencies": { - "netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" - } - } - }, "package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -4661,14 +4280,6 @@ "callsites": "^3.0.0" } }, - "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", - "requires": { - "@types/node": "*" - } - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -4683,7 +4294,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "3.1.1", @@ -4691,40 +4303,16 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "requires": { - "inflection": "~1.3.0" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=" - } - } - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" - }, - "pkginfo": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", - "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true }, "popper.js": { "version": "1.16.1", @@ -4795,10 +4383,32 @@ } } }, + "prebuild-install": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "optional": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.21.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, "prepend-http": { "version": "2.0.0", @@ -4806,6 +4416,11 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4816,90 +4431,34 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, - "promisify-call": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", - "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", - "requires": { - "with-callback": "^1.0.2" - } - }, "prompt": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz", - "integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.2.0.tgz", + "integrity": "sha512-iGerYRpRUg5ZyC+FJ/25G5PUKuWAGRjW1uOlhX7Pi3O5YygdK6R+KEaBjRbHSkU5vfS5PZCltSPZdDtUYwRCZA==", "requires": { + "async": "~0.9.0", "colors": "^1.1.2", - "pkginfo": "0.x.x", "read": "1.0.x", "revalidator": "0.1.x", - "utile": "0.3.x", - "winston": "2.1.x" + "winston": "2.x" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + } } }, "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, - "proxy-agent": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", - "integrity": "sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==", - "requires": { - "agent-base": "^4.2.0", - "debug": "4", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^3.0.1", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -4921,7 +4480,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -4946,6 +4504,16 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, "quill": { "version": "2.0.0-dev.4", "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.0-dev.4.tgz", @@ -5013,26 +4581,11 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - } } }, "read": { @@ -5061,30 +4614,35 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "requires": { "picomatch": "^2.2.1" } }, "redux": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", - "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", "requires": { - "loose-envify": "^1.4.0", - "symbol-observable": "^1.2.0" + "@babel/runtime": "^7.9.2" } }, "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "regexp-clone": { "version": "1.0.0", @@ -5092,38 +4650,18 @@ "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" }, "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, "registry-auth-token": { @@ -5144,221 +4682,49 @@ "rc": "^1.2.8" } }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" }, "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true }, "resourcejs": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/resourcejs/-/resourcejs-2.3.2.tgz", - "integrity": "sha512-H7XNH8lydXDpevXMdzm/YnBRsEKNrdm/oDENI0ca4H6F37lk1APRyjfVaFq1CcGxS7Xdv6+i68TvK1xpDaybAg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/resourcejs/-/resourcejs-2.4.0.tgz", + "integrity": "sha512-UKu4l5D5GAjfDwspi5fYZoktblob7GKoU7HlteA//DCvfwWR5Vkw9NPtDRDM1GcvgjHAx7k+tQVBQcL50bODGA==", "requires": { - "debug": "^4.1.1", - "fast-json-patch": "^3.0.0-1", - "moment": "^2.28.0", - "mongodb": "^3.6.2", + "debug": "^4.3.2", + "fast-json-patch": "^3.1.0", + "moment": "^2.29.1", + "mongodb": "^4.1.1", "node-paginate-anything": "^1.0.0", - "range-parser": "^1.2.1" - }, - "dependencies": { - "fast-json-patch": { - "version": "3.0.0-1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.0.0-1.tgz", - "integrity": "sha512-6pdFb07cknxvPzCeLsFHStEy+MysPJPgZQ9LbQ/2O67unQF93SNqfdSqnPPl71YMHX+AD8gbl7iuoGFzHEdDuw==" - } - } - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "restler": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/restler/-/restler-3.4.0.tgz", - "integrity": "sha1-dB7As9FrlJ/uooE9DDxoUp6IjZs=", - "requires": { - "iconv-lite": "0.2.11", - "qs": "1.2.0", - "xml2js": "0.4.0", - "yaml": "0.2.3" - }, - "dependencies": { - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "iconv-lite": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", - "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=" - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "sax": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", - "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "xml2js": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.0.tgz", - "integrity": "sha1-Ek/EEUtBKcgQgA7LKshs8lRiy5o=", - "requires": { - "sax": "0.5.x", - "xmlbuilder": ">=0.4.2" - } - } + "range-parser": "^1.2.1" + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" } }, "revalidator": { @@ -5366,18 +4732,24 @@ "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=" }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "requires": { "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -5399,9 +4771,12 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } }, "semver-diff": { "version": "3.1.1", @@ -5462,28 +4837,10 @@ } } }, - "sendgrid": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/sendgrid/-/sendgrid-1.9.2.tgz", - "integrity": "sha1-1AfmogawoqaWQkbdnAZBwQvwLxk=", - "requires": { - "lodash": "^3.0.1 || ^2.0.0", - "mime": "^1.2.9", - "request": "^2.60.0", - "smtpapi": "^1.2.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - } - } - }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -5504,13 +4861,21 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "optional": true }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "requires": { + "kind-of": "^6.0.2" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5527,12 +4892,13 @@ "dev": true }, "side-channel": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", - "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "requires": { - "es-abstract": "^1.18.0-next.0", - "object-inspect": "^1.8.0" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" } }, "sift": { @@ -5541,35 +4907,72 @@ "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, "signature_pad": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/signature_pad/-/signature_pad-2.3.2.tgz", "integrity": "sha512-peYXLxOsIY6MES2TrRLDiNg2T++8gGbpP2yaC+6Ohtxr+a2dzoaqWosWDY9sWqTAAk6E/TyQO+LJw9zQwyu5kA==" }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "optional": true + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "optional": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-name": "~1.1.4" } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true } } }, @@ -5578,56 +4981,6 @@ "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" }, - "smart-buffer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", - "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" - }, - "smtpapi": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/smtpapi/-/smtpapi-1.4.4.tgz", - "integrity": "sha512-sVixyAfytmpSFonYGN7cggpLaYvtsBEkPN/ilWb/WFcL/hu93P7OaWthPabsEpMZsq3UK4w93V3ywz2gHS2ksw==", - "requires": { - "chai": "^2.3.0", - "esdoc": "^1.0.3", - "esdoc-coverage-plugin": "^1.1.0", - "esdoc-type-inference-plugin": "^1.0.1" - } - }, - "socks": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true - }, "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -5657,22 +5010,6 @@ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -5683,12 +5020,17 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==" + }, "stream-transform": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.0.tgz", - "integrity": "sha512-bwQO+75rzQbug7e5OOHnOR3FgbJ0fCjHmDIdynkwUaFzleBXugGmv2dx3sX3aIHUQRLjrcisRPgN9BWl63uGgw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.3.tgz", + "integrity": "sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==", "requires": { - "mixme": "^0.5.0" + "mixme": "^0.5.1" } }, "string-hash": { @@ -5697,48 +5039,31 @@ "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=" }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, @@ -5748,21 +5073,28 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "superagent": { "version": "6.1.0", @@ -5784,9 +5116,9 @@ }, "dependencies": { "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -5794,27 +5126,10 @@ "mime-types": "^2.1.12" } }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "dev": true - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true }, "qs": { @@ -5836,17 +5151,6 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } } } }, @@ -5866,13 +5170,13 @@ } }, "supertest": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-5.0.0.tgz", - "integrity": "sha512-2JAWpPrUOZF4hHH5ZTCN2xjKXvJS3AEwPNXl0HUseHsfcXFvMy9kcsufIHCNAmQ5hlGCvgeAqaR5PBEouN3hlQ==", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.1.6.tgz", + "integrity": "sha512-0hACYGNJ8OHRg8CRITeZOdbjur7NLuNs0mBjVhdpxi7hP6t3QIbOzLON5RTUmZcy2I9riuII3+Pr2C7yztrIIg==", "dev": true, "requires": { - "methods": "1.1.2", - "superagent": "6.1.0" + "methods": "^1.1.2", + "superagent": "^6.1.0" } }, "supertest-capture-error": { @@ -5882,94 +5186,128 @@ "dev": true }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "optional": true + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", + "integrity": "sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==", "dev": true, "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "ajv": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", + "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } } } }, - "taffydb": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz", - "integrity": "sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ=" - }, - "tarn": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.5.tgz", - "integrity": "sha512-PMtJ3HCLAZeedWjJPgGnCvcphbCOMbtZpjKgLq3qM5Qq9aQud+XHrL0WlrlgnTyS8U+jrjGbEXprFcQrxPy52g==" + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "optional": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } }, - "tedious": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/tedious/-/tedious-6.7.0.tgz", - "integrity": "sha512-8qr7+sB0h4SZVQBRWUgHmYuOEflAOl2eihvxk0fVNvpvGJV4V5UC/YmSvebyfgyfwWcPO22/AnSbYVZZqf9wuQ==", + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "optional": true, "requires": { - "@azure/ms-rest-nodeauth": "2.0.2", - "@types/node": "^12.12.17", - "@types/readable-stream": "^2.3.5", - "bl": "^3.0.0", - "depd": "^2.0.0", - "iconv-lite": "^0.5.0", - "jsbi": "^3.1.1", - "native-duplexpair": "^1.0.0", - "punycode": "^2.1.0", - "readable-stream": "^3.4.0", - "sprintf-js": "^1.1.2" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "dependencies": { "bl": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz", - "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==", - "requires": { - "readable-stream": "^3.0.1" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "iconv-lite": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "optional": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + } } }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -5978,11 +5316,45 @@ } } }, - "term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true + "tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==" + }, + "tedious": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/tedious/-/tedious-11.8.0.tgz", + "integrity": "sha512-GtFrO694x/7CRiUBt0AI4jrMtrkXV+ywifiOrDy4K0ufJLeKB4rgmPjy5Ws366fCaBaKlqQ9RnJ+sCJ1Jbd1lw==", + "requires": { + "@azure/identity": "^1.3.0", + "@azure/keyvault-keys": "^4.1.0", + "@azure/ms-rest-nodeauth": "^3.0.6", + "@js-joda/core": "^3.2.0", + "adal-node": "^0.2.1", + "bl": "^5.0.0", + "depd": "^2.0.0", + "iconv-lite": "^0.6.3", + "jsbi": "^3.1.5", + "native-duplexpair": "^1.0.0", + "node-abort-controller": "^2.0.0", + "punycode": "^2.1.0", + "sprintf-js": "^1.1.2" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } }, "text-mask-addons": { "version": "3.8.0", @@ -5995,42 +5367,16 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "threads": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/threads/-/threads-0.12.1.tgz", - "integrity": "sha512-2USeV2FDNZtVP1xt3TW86solU7W6WYjaTMd+gvAHJat+dEMFh7of2DR9MEFLkhMerxc1t5b1DMJiVx1meRzk0w==", - "requires": { - "eventemitter3": "^2.0.2", - "native-promise-only": "^0.8.1" - }, - "dependencies": { - "eventemitter3": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=" - } - } - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" - }, "ticky": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ticky/-/ticky-1.0.1.tgz", "integrity": "sha1-t8+nHnaPHJAAxJe5FRswlHxQ5G0=" }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" - }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -6041,6 +5387,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -6058,14 +5405,6 @@ "popper.js": "^1.0.2" } }, - "topo": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", - "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", - "requires": { - "hoek": "6.x.x" - } - }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -6076,10 +5415,11 @@ } }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", "requires": { + "ip-regex": "^2.1.0", "psl": "^1.1.28", "punycode": "^2.1.1" } @@ -6087,24 +5427,13 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "optional": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" - }, "tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -6114,32 +5443,24 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "optional": true, "requires": { "safe-buffer": "^5.0.1" } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=" - }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, "type-is": { @@ -6166,26 +5487,23 @@ "is-typedarray": "^1.0.0" } }, - "undefsafe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", - "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", - "dev": true, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", "requires": { - "debug": "^2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" } }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "underscore": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", @@ -6201,9 +5519,9 @@ } }, "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "unpipe": { "version": "1.0.0", @@ -6211,85 +5529,57 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", "dev": true, "requires": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", + "boxen": "^5.0.0", + "chalk": "^4.1.0", "configstore": "^5.0.1", "has-yarn": "^2.1.0", "import-lazy": "^2.1.0", "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", "semver-diff": "^3.1.1", "xdg-basedir": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-join": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", + "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=" + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -6304,42 +5594,30 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "utile": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", - "integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=", - "requires": { - "async": "~0.9.0", - "deep-equal": "~0.2.1", - "i": "0.3.x", - "mkdirp": "0.x.x", - "ncp": "1.0.x", - "rimraf": "2.x.x" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" - }, - "deep-equal": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", - "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=" - } - } - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "vanilla-picker": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.1.tgz", + "integrity": "sha512-2qrEP9VYylKXbyzXKsbu2dferBTvqnlsr29XjHwFE+/MEp0VNj6oEUESLDtKZ7DWzGdSv1x/+ujqFZF+KsO3cg==", + "requires": { + "@sphinxxxx/color-conversion": "^2.2.2" + } + }, "vanilla-text-mask": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/vanilla-text-mask/-/vanilla-text-mask-5.1.1.tgz", @@ -6350,29 +5628,37 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } + "vm2": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.5.tgz", + "integrity": "sha512-LuCAHZN75H9tdrAiLFf030oW7nJV5xwNMuk1ymOZwopmuK3d2H4L1Kv4+GFHgarKiLfXXLFU+7LDABHnwOkWng==" + }, + "web-streams-polyfill": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", + "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==" }, "webidl-conversions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", - "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", - "optional": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" }, - "whatwg-url-compat": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", - "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", - "optional": true, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", "requires": { - "tr46": "~0.0.1" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "which": { @@ -6385,15 +5671,15 @@ } }, "which-boxed-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", - "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "requires": { - "is-bigint": "^1.0.0", - "is-boolean-object": "^1.0.0", - "is-number-object": "^1.0.3", - "is-string": "^1.0.4", - "is-symbol": "^1.0.2" + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" } }, "which-collection": { @@ -6407,79 +5693,26 @@ "is-weakset": "^2.0.1" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "which-typed-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", - "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", + "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", "requires": { - "available-typed-arrays": "^1.0.2", - "es-abstract": "^1.17.5", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", "foreach": "^2.0.5", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.1", - "is-typed-array": "^1.1.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.7" } }, "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "widest-line": { @@ -6492,15 +5725,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "is-fullwidth-code-point": { @@ -6510,38 +5737,42 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } } } }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + }, "winston": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz", - "integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz", + "integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==", "requires": { "async": "~1.0.0", "colors": "1.0.x", "cycle": "1.0.x", "eyes": "0.1.x", "isstream": "0.1.x", - "pkginfo": "0.3.x", "stack-trace": "0.0.x" }, "dependencies": { @@ -6554,63 +5785,86 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - }, - "pkginfo": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", - "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" } } }, - "with-callback": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", - "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=" - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true }, "workerpool": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", - "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" } } } @@ -6620,15 +5874,6 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, "write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", @@ -6647,12 +5892,6 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, - "xml-name-validator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", - "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", - "optional": true - }, "xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", @@ -6667,109 +5906,76 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, - "xmldom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", - "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==" - }, "xpath.js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==" }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" - }, "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yaml": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-0.2.3.tgz", - "integrity": "sha1-tUUOkudu82td0k42YAkeuu7z5cc=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, - "locate-path": { + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "p-try": "^2.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "ansi-regex": "^5.0.1" } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true } } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true }, "yargs-unparser": { "version": "2.0.0", @@ -6781,20 +5987,6 @@ "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } } }, "yocto-queue": { diff --git a/forms-flow-forms/package.json b/forms-flow-forms/package.json index c0ef07bbda..9b2db60fe4 100644 --- a/forms-flow-forms/package.json +++ b/forms-flow-forms/package.json @@ -1,6 +1,6 @@ { "name": "formio", - "version": "2.0.0-rc.34", + "version": "2.3.0", "description": "The formio server application.", "license": "OSL-3.0", "main": "index.js", @@ -8,7 +8,6 @@ "test": "env TEST_SUITE=1 mocha test/test.js -b -t 60000 --exit", "start": "node main.js", "start:dev": "nodemon main.js", - "preinstall": "npx npm-force-resolutions", "lint": "eslint ." }, "author": "support@form.io", @@ -18,63 +17,63 @@ "schema": "3.1.4", "templateVersion": "2.0.0", "dependencies": { + "@azure/ms-rest-nodeauth": "^3.1.0", + "@formio/node-fetch-http-proxy": "^1.1.0", + "@sendgrid/mail": "^7.5.0", "JSONStream": "^1.3.5", - "abort-controller": "^3.0.0", - "adm-zip": "^0.5.0", - "async": "^3.2.0", + "adm-zip": "^0.5.9", + "async": "^3.2.1", "bcryptjs": "^2.4.3", "body-parser": "^1.19.0", - "chance": "^1.1.7", + "chance": "^1.1.8", "clone": "^2.1.2", "colors": "^1.4.0", - "config": "^3.3.2", + "config": "^3.3.6", "cors": "^2.8.5", - "csv": "^5.3.2", - "debug": "^4.3.1", + "csv": "^5.5.3", + "debug": "^4.3.2", "delete-property": "0.0.4", "dotenv": "^8.2.0", "eslint-config-formio": "^1.1.2", "event-chain": "^0.0.1", + "expose-gc": "^1.0.0", "express": "^4.17.1", - "fast-json-patch": "^2.2.1", - "formio-workers": "^1.14.8", - "formiojs": "^4.13.1", - "fs-extra": "^9.0.1", - "html-entities": "^1.3.1", - "https-proxy-agent": "^5.0.0", - "joi": "^14.3.1", + "fast-json-patch": "^3.1.0", + "formio-workers": "^1.16.0", + "formiojs": "^4.14.0-rc.38", + "fs-extra": "^10.0.0", + "html-entities": "^2.3.2", "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", + "mailgun.js": "^3.7.0", "memory-cache": "^0.2.0", "moment": "^2.29.1", - "moment-timezone": "^0.5.32", - "mongodb": "^3.6.3", - "mongoose": "^5.12.11", - "mssql": "^6.2.3", + "moment-timezone": "^0.5.33", + "mongodb": "^4.1.3", + "mongoose": "^6.0.11", + "mssql": "^7.2.1", "mysql": "^2.18.1", - "netmask": "^2.0.2", - "node-fetch": "^2.6.1", - "nodemailer": "^6.4.16", - "nodemailer-mailgun-transport": "2.0.2", + "nodemailer": "^6.7.0", + "nodemailer-mailgun-transport": "^2.1.3", "nodemailer-mandrill-transport": "^1.2.0", - "nodemailer-sendgrid-transport": "^0.2.0", + "nodemailer-sendgrid-transport": "https://github.com/formio/nodemailer-sendgrid-transport.git", "progress": "^2.0.3", - "prompt": "^1.0.0", + "prompt": "^1.2.0", "q": "^1.5.0", - "resourcejs": "^2.3.2", - "restler": "^3.4.0", - "semver": "^7.3.2", + "resourcejs": "^2.4.0", + "semver": "^7.3.5", "superagent-retry": "^0.6.0", "through": "^2.3.8", - "vanilla-text-mask": "^5.1.1" + "vanilla-text-mask": "^5.1.1", + "vm2": "^3.9.5" }, "devDependencies": { - "eslint": "^7.13.0", - "mocha": "^8.2.1", - "nodemon": "^2.0.6", + "eslint": "^7.32.0", + "mocha": "^9.1.3", + "nodemon": "^2.0.14", "pre-commit": "^1.2.2", "superagent-use": "^0.1.0", - "supertest": "^5.0.0", + "supertest": "^6.1.6", "supertest-capture-error": "^1.0.0" }, "directories": { @@ -91,15 +90,6 @@ "bugs": { "url": "https://github.com/formio/formio/issues" }, - "resolutions": { - "lodash": "^4.17.21", - "marked": "^2.0.5", - "minimist": "^1.2.5", - "qs": "^6.10.1", - "netmask": "^2.0.2", - "css-what": "^5.0.1", - "glob-parent": "^5.1.2" - }, "homepage": "https://github.com/formio/formio#readme", "pre-commit": [ "lint" diff --git a/forms-flow-forms/sample.env b/forms-flow-forms/sample.env index aabb4e7719..1039e08c5d 100644 --- a/forms-flow-forms/sample.env +++ b/forms-flow-forms/sample.env @@ -16,4 +16,7 @@ #FORMIO_ROOT_PASSWORD=changeme #URL of forms-flow-forms -FORMIO_DEFAULT_PROJECT_URL=http://{your-ip-address}:3001 \ No newline at end of file +FORMIO_DEFAULT_PROJECT_URL=http://{your-ip-address}:3001 + +#FORMIO_JWT_SECRET=--- change me now --- + diff --git a/forms-flow-forms/src/actions/EmailAction.js b/forms-flow-forms/src/actions/EmailAction.js index f0d91ca104..cc0e7dced9 100644 --- a/forms-flow-forms/src/actions/EmailAction.js +++ b/forms-flow-forms/src/actions/EmailAction.js @@ -1,5 +1,5 @@ 'use strict'; -const fetch = require('../util/fetch'); +const fetch = require('@formio/node-fetch-http-proxy'); const LOG_EVENT = 'Email Action'; @@ -18,6 +18,9 @@ module.exports = (router) => { */ class EmailAction extends Action { static info(req, res, next) { + if (!hook.alter('hasEmailAccess', req)) { + return next(null); + } next(null, { name: 'email', title: 'Email', @@ -53,7 +56,8 @@ module.exports = (router) => { key: 'transport', placeholder: 'Select the email transport.', template: '{{ item.title }}', - defaultValue: 'default', + defaultValue: availableTransports.find(provider=>provider.transport==='default')? + 'default':availableTransports[0].transport, dataSrc: 'json', data: { json: JSON.stringify(availableTransports), @@ -68,12 +72,21 @@ module.exports = (router) => { label: 'From:', key: 'from', inputType: 'text', - defaultValue: 'no-reply@form.io', + defaultValue: router.formio.config.defaultEmailSource, input: true, placeholder: 'Send the email from the following address', type: 'textfield', multiple: false, }, + { + label: 'Reply-To: Email Address', + key: 'replyTo', + inputType: 'text', + input: true, + placeholder: 'Reply to an alternative email address', + type: 'textfield', + multiple: false + }, { label: 'To: Email Address', key: 'emails', @@ -142,6 +155,27 @@ module.exports = (router) => { placeholder: 'Enter the message you would like to send.', input: true, }, + { + label: 'Rendering Method', + key: 'renderingMethod', + type: 'radio', + defaultValue: 'dynamic', + values: [ + { + label: 'Dynamic', + value: 'dynamic', + }, + { + label: 'Static', + value: 'static', + } + ], + inline: true, + optionsLabelPosition: 'right', + // eslint-disable-next-line max-len + tooltip: 'Dynamic rendering uses formio.js to render email. While static relies on outdated set of mappers.\r\n\r\nStatic rendering considered deprecated and should not be used for most cases.', + input: true, + }, ]; next(null, settingsForm); diff --git a/forms-flow-forms/src/actions/LoginAction.js b/forms-flow-forms/src/actions/LoginAction.js index b050ca1db1..91536ae865 100644 --- a/forms-flow-forms/src/actions/LoginAction.js +++ b/forms-flow-forms/src/actions/LoginAction.js @@ -55,9 +55,10 @@ module.exports = (router) => { placeholder: 'Select the resources we should login against.', dataSrc: 'url', data: {url: `${basePath}?type=resource&limit={{ limit }}`}, + authenticate: true, valueProperty: '_id', template: '{{ item.title }}', - limit: 4294967295, + limit: 10000, multiple: true, validate: { required: true, @@ -292,13 +293,23 @@ module.exports = (router) => { req.token = response.token.decoded; res.token = response.token.token; req['x-jwt-token'] = response.token.token; - router.formio.auth.currentUser(req, res, (err) => { - if (err) { - log(req, ecode.auth.EAUTH, err); - return res.status(401).send(err.message); + + hook.alter('getPrimaryProjectAdminRole', req, res, (err, role) => { + if (req.user.roles.includes(role)) { + req.isAdmin = true; } - next(); + hook.alter('oAuthResponse', req, res, () => { + router.formio.auth.currentUser(req, res, (err) => { + if (err) { + log(req, ecode.auth.EAUTH, err); + return res.status(401).send(err.message); + } + hook.alter('currentUserLoginAction', req, res); + + next(); + }); + }); }); }); }, diff --git a/forms-flow-forms/src/actions/ResetPassword.js b/forms-flow-forms/src/actions/ResetPassword.js index 14755ab37f..60b0e72675 100644 --- a/forms-flow-forms/src/actions/ResetPassword.js +++ b/forms-flow-forms/src/actions/ResetPassword.js @@ -57,6 +57,7 @@ module.exports = (router) => { placeholder: 'Select the resources we should reset password against.', dataSrc: 'url', data: {url: `${basePath}?type=resource`}, + authenticate: true, valueProperty: '_id', template: '{{ item.title }}', multiple: true, @@ -139,7 +140,7 @@ module.exports = (router) => { label: 'From:', key: 'from', inputType: 'email', - defaultValue: 'no-reply@form.io', + defaultValue: router.formio.config.defaultEmailSource, input: true, placeholder: 'Send the email from the following address', type: 'textfield', @@ -298,11 +299,11 @@ module.exports = (router) => { this.getSubmission(req, token, (err, submission) => { if (err || !submission) { log(req, ecode.user.ENOUSER, err); - return res.status(400).send(ecode.user.ENOUSER); + return next(ecode.user.ENOUSER); } // Generate a temporary token for resetting their password. - const resetToken = jwt.sign(token, router.formio.config.jwt.secret, { + const resetToken = jwt.sign(token, process.env.FORMIO_JWT_SECRET||router.formio.config.jwt.secret , { expiresIn: 5 * 60, }); diff --git a/forms-flow-forms/src/actions/SaveSubmission.js b/forms-flow-forms/src/actions/SaveSubmission.js index 7221e0b161..47f4c38d63 100644 --- a/forms-flow-forms/src/actions/SaveSubmission.js +++ b/forms-flow-forms/src/actions/SaveSubmission.js @@ -2,7 +2,7 @@ const _ = require('lodash'); const async = require('async'); -const vm = require('vm'); +const {VM} = require('vm2'); const util = require('../util/util'); const LOG_EVENT = 'Save Submission Action'; @@ -15,16 +15,6 @@ module.exports = function(router) { const logOutput = router.formio.log || debug; const log = (...args) => logOutput(LOG_EVENT, ...args); - // Execute a pre-save method for the SaveSubmission action. - Action.schema.pre('save', function(next) { - if (this.name === 'save') { - // Ensure that save actions with resource associations are always executed - // before the ones without resource association. - this.priority = (this.settings && this.settings.resource) ? 11 : 10; - } - next(); - }); - class SaveSubmission extends Action { static info(req, res, next) { next(null, { @@ -213,15 +203,24 @@ module.exports = function(router) { }); if (this.settings.transform) { - const script = new vm.Script(this.settings.transform); - const sandbox = { - submission: (res.resource && res.resource.item) ? res.resource.item : req.body, - data: submission.data, - }; - script.runInContext(vm.createContext(sandbox), { - timeout: 500 - }); - submission.data = sandbox.data; + try { + let vm = new VM({ + timeout: 500, + sandbox: { + submission: (res.resource && res.resource.item) ? res.resource.item : req.body, + data: submission.data, + }, + eval: false, + fixAsync: true + }); + + const newData = vm.run(this.settings.transform); + submission.data = newData; + vm = null; + } + catch (err) { + debug(`Error in submission transform: ${err.message}`); + } } return submission; diff --git a/forms-flow-forms/src/actions/WebhookAction.js b/forms-flow-forms/src/actions/WebhookAction.js index 106f97eb98..54fef34fae 100644 --- a/forms-flow-forms/src/actions/WebhookAction.js +++ b/forms-flow-forms/src/actions/WebhookAction.js @@ -1,6 +1,6 @@ 'use strict'; -const rest = require('restler'); +const fetch = require('@formio/node-fetch-http-proxy'); const _ = require('lodash'); const util = require('../util/util'); @@ -62,7 +62,7 @@ module.exports = function(router) { defaultValue: false, key: 'block', label: 'Block request for Webhook feedback', - hideLabel: true, + hideLabel: false, tableView: true, inputType: 'checkbox', input: true @@ -137,13 +137,14 @@ module.exports = function(router) { */ const handleError = (data, response) => { setActionItemMessage('Webhook failed', response); - logerr(data.message || data || response.statusMessage); + const message = data ? (data.message || data) : response.statusMessage; + logerr(message); if (!_.get(settings, 'block') || _.get(settings, 'block') === false) { return; } - return next(data.message || data || response.statusMessage); + return next(message); }; try { @@ -191,30 +192,63 @@ module.exports = function(router) { url = this.settings.url; } + // eslint-disable-next-line + const onParseError = (err, response) => { + if (response.status === 404) { + return handleError(null, response); + } + throw err; + }; + + const makeRequest = (url, method, credentials, payload)=> { + const options = { + method, + headers: { + 'content-type': 'application/json', + 'accept': 'application/json', + }, + }; + if (credentials.username) { + // eslint-disable-next-line max-len + options.headers.Authorization = `Basic ${Buffer.from(`${credentials.username}:${credentials.password}`).toString('base64')}`; + } + + if (payload) { + options.body = JSON.stringify(payload); + } + + fetch(url, options) + .then((response) => { + if (!response.bodyUsed && method === 'DELETE') { + if (response.ok) { + return handleSuccess({}, response); + } + else { + return handleError({}, response); + } + } + else { + if (response.ok) { + return response.json().then((body) => handleSuccess(body, response)); + } + else { + return response.json().then((body) => handleError(body, response)); + } + } + }) + .catch((err) => { + handleError(err); + }); + }; + // Make the request. setActionItemMessage('Making request', { method: req.method, url, options }); - switch (req.method.toLowerCase()) { - case 'get': - rest.get(url, options).on('success', handleSuccess).on('fail', handleError); - break; - case 'post': - rest.postJson(url, payload, options).on('success', handleSuccess).on('fail', handleError); - break; - case 'patch': - case 'put': - rest.putJson(url, payload, options).on('success', handleSuccess).on('fail', handleError); - break; - case 'delete': - options.query = req.params; - rest.del(url, options).on('success', handleSuccess).on('fail', handleError); - break; - default: - return handleError(`Could not match request method: ${req.method.toLowerCase()}`); - } + url = req.method!=='DELETE' ? url: `${url}?${new URLSearchParams(req.params).toString()}`; + makeRequest(url, req.method, options, payload); } catch (e) { setActionItemMessage('Error occurred', e, 'error'); diff --git a/forms-flow-forms/src/actions/actions.js b/forms-flow-forms/src/actions/actions.js index 6511fdef0f..e0badbe097 100644 --- a/forms-flow-forms/src/actions/actions.js +++ b/forms-flow-forms/src/actions/actions.js @@ -2,7 +2,7 @@ const Resource = require('resourcejs'); const async = require('async'); -const vm = require('vm'); +const {VM} = require('vm2'); const _ = require('lodash'); const debug = { error: require('debug')('formio:error'), @@ -20,6 +20,7 @@ const moment = require('moment'); */ module.exports = (router) => { const hook = require('../util/hook')(router.formio); + const middlewares = require('../middleware/middleware')(router); /** * Create the ActionIndex object. @@ -154,6 +155,67 @@ module.exports = (router) => { }); }, + /** + * Create an action item if the form is enabled with action logs. + * @param req + * @param res + * @param action + * @param handler + * @param method + * @param done + */ + createActionItem(req, res, action, handler, method, done) { + // Only trigger if they have logs enabled for this form. + if (!_.get(req.currentForm, 'settings.logs', false)) { + return done(null, {}); + } + // Instantiate ActionItem here. + router.formio.mongoose.models.actionItem.create(hook.alter('actionItem', { + title: action.title, + form: req.formId, + submission: res.resource ? res.resource.item._id : req.body._id, + action: action.name, + handler, + method, + state: 'inprogress', + messages: [ + { + datetime: new Date(), + info: 'Starting Action', + data: {} + } + ] + }, req), (err, actionItem) => { + if (err) { + return done(err); + } + return done(null, actionItem); + }); + }, + + updateActionItem(req, actionItem, message, data = {}, state = null) { + // Only trigger if they have logs enabled for this form. + if (!_.get(req.currentForm, 'settings.logs', false)) { + return; + } + if (!req.actionItemPromise) { + req.actionItemPromise = Promise.resolve(); + } + req.actionItemPromise = req.actionItemPromise.then(() => { + actionItem.messages.push({ + datetime: new Date(), + info: message, + data + }); + + if (state) { + actionItem.state = state; + } + + return actionItem.save(); + }); + }, + /** * Execute an action provided a handler, form, and request params. * @@ -186,59 +248,23 @@ module.exports = (router) => { // Resolve the action. router.formio.log('Action', req, handler, method, action.name, action.title); - // Instantiate ActionItem here. - router.formio.mongoose.models.actionItem.create(hook.alter('actionItem', { - title: action.title, - form: req.formId, - submission: res.resource ? res.resource.item._id : req.body._id, - action: action.name, - handler, - method, - state: 'inprogress', - messages: [ - { - datetime: new Date(), - info: 'Starting Action', - data: {} - } - ] - }, req), (err, actionItem) => { - // Mongoose has issues if you call "save" too frequently on the same item. We need to wait till the previous - // save is complete before calling again. - if (!req.actionItemPromise) { - req.actionItemPromise = Promise.resolve(); - } - const setActionItemMessage = (message, data = {}, state = null) => { - req.actionItemPromise = req.actionItemPromise.then(() => { - actionItem.messages.push({ - datetime: new Date(), - info: message, - data - }); - - if (state) { - actionItem.state = state; - } - - return actionItem.save(); - }); - }; - + // Create a new action item. + this.createActionItem(req, res, action, handler, method, (err, actionItem) => { action.resolve(handler, method, req, res, (err) => { if (err) { // Error has occurred. - setActionItemMessage('Error Occurred', err, 'error'); + this.updateActionItem(req, actionItem,'Error Occurred', err, 'error'); return cb(err); } // Action has completed successfully - setActionItemMessage( + this.updateActionItem(req, actionItem, 'Action Resolved (no longer blocking)', {}, actionItem.state === 'inprogress' ? 'complete' : actionItem.state, ); return cb(); - }, setActionItemMessage); + }, (...args) => this.updateActionItem(req, actionItem, ...args)); }); }); }, (err) => { @@ -268,11 +294,7 @@ module.exports = (router) => { } try { - const script = new vm.Script(json - ? `execute = jsonLogic.apply(${condition.custom}, { data, form, _, util })` - : condition.custom); - - const sandbox = await hook.alter('actionContext', { + const params = await hook.alter('actionContext', { jsonLogic: util.FormioUtils.jsonLogic, data: req.body.data, form: req.form, @@ -285,11 +307,33 @@ module.exports = (router) => { _ }, req); - script.runInContext(vm.createContext(sandbox), { - timeout: 500 + let vm = new VM({ + timeout: 500, + sandbox: { + execute: params.execute, + query: params.query, + data: params.data, + form: params.form, + submission: params.submission, + previous: params.previous, + }, + eval: false, + fixAsync: true }); - return sandbox.execute; + vm.freeze(params.jsonLogic, 'jsonLogic'); + vm.freeze(params.FormioUtils, 'util'); + vm.freeze(params.moment, 'moment'); + vm.freeze(params._, '_'); + + const result = vm.run(json ? + `execute = jsonLogic.apply(${condition.custom}, { data, form, _, util })` : + condition.custom + ); + + vm = null; + + return result; } catch (err) { router.formio.log( @@ -594,7 +638,7 @@ JSON: { "in": [ "authenticated", { "var": "data.roles" } ] }`; } // Return a list of available actions. - router.get('/form/:formId/actions', (req, res, next) => { + router.get('/form/:formId/actions', middlewares.tokenVerify,(req, res, next) => { const result = []; // Add an action to the results array. diff --git a/forms-flow-forms/src/actions/fields/index.js b/forms-flow-forms/src/actions/fields/index.js index 4e062c0c80..a232879bda 100644 --- a/forms-flow-forms/src/actions/fields/index.js +++ b/forms-flow-forms/src/actions/fields/index.js @@ -6,6 +6,4 @@ module.exports = (router) => ({ form: require('./form')(router), email: require('./email')(router.formio), datetime: require('./datetime')(router.formio), - select: require('./select')(router.formio), - radio: require('./radio')(router.formio), }); diff --git a/forms-flow-forms/src/actions/fields/password.js b/forms-flow-forms/src/actions/fields/password.js index 89470654de..f66a8ff899 100644 --- a/forms-flow-forms/src/actions/fields/password.js +++ b/forms-flow-forms/src/actions/fields/password.js @@ -37,7 +37,7 @@ module.exports = (formio) => { } if (!req.skipTokensInvalidation) { - _.set(req.body, 'metadata.jwtIssuedAfter', req.tokenIssued || (Date.now() / 1000)); + _.set(req.body, 'metadata.jwtIssuedAfter', req.tokenIssued || Math.trunc(Date.now() / 1000)); } resolve(); }); diff --git a/forms-flow-forms/src/actions/fields/radio.js b/forms-flow-forms/src/actions/fields/radio.js deleted file mode 100644 index f5ef499cb0..0000000000 --- a/forms-flow-forms/src/actions/fields/radio.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; -const _ = require('lodash'); - -module.exports = (formio) => async (component, data, handler, action, {validation}) => { - // Only perform before validation has occurred. - if (!validation && ['put', 'post', 'patch'].includes(action)) { - const value = _.get(data, component.key); - - if (value) { - if (component.validate) { - component.validate.onlyAvailableItems = true; - } - else { - component.validate = {onlyAvailableItems: true}; - } - } - } -}; diff --git a/forms-flow-forms/src/actions/fields/select.js b/forms-flow-forms/src/actions/fields/select.js deleted file mode 100644 index 6495583f44..0000000000 --- a/forms-flow-forms/src/actions/fields/select.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; -const _ = require('lodash'); - -module.exports = (formio) => async (component, data, handler, action, {validation}) => { - // Only perform before validation has occurred. - if (!validation && ['put', 'post', 'patch'].includes(action)) { - const value = _.get(data, component.key); - const {dataSrc} = component; - - if (value && (dataSrc === 'json' || dataSrc === 'values' || dataSrc === 'custom' || !dataSrc)) { - if (component.validate) { - component.validate.onlyAvailableItems = true; - } - else { - component.validate = {onlyAvailableItems: true}; - } - } - } -}; diff --git a/forms-flow-forms/src/actions/fields/signature.js b/forms-flow-forms/src/actions/fields/signature.js index 5201bcab31..198734b595 100644 --- a/forms-flow-forms/src/actions/fields/signature.js +++ b/forms-flow-forms/src/actions/fields/signature.js @@ -11,7 +11,7 @@ module.exports = (formio) => async (component, data, handler, action, {validatio } // Coerse the value into an empty string. - if (!value && value !== '') { + if (!value && value !== '' && value !== undefined) { _.set(data, component.key, ''); } break; @@ -24,7 +24,7 @@ module.exports = (formio) => async (component, data, handler, action, {validatio // of data that came from the index request (where the signature is not populated). // Coerse the value into an empty string. - if (!value && (value !== '')) { + if (!value && (value !== '') && value !== undefined) { value = ''; _.set(data, component.key, ''); } diff --git a/forms-flow-forms/src/actions/properties/reference.js b/forms-flow-forms/src/actions/properties/reference.js index 5158f4cd33..35df5cfe3d 100644 --- a/forms-flow-forms/src/actions/properties/reference.js +++ b/forms-flow-forms/src/actions/properties/reference.js @@ -24,6 +24,7 @@ module.exports = (router) => { sub.req.noResponse = true; sub.req.skipOwnerFilter = false; sub.req.formId = sub.req.params.formId = formId; + sub.req.doNotMinify = true; // Make sure to change the submission id. if (subQuery && subQuery._id) { diff --git a/forms-flow-forms/src/authentication/index.js b/forms-flow-forms/src/authentication/index.js index 43b101d843..57f312db44 100644 --- a/forms-flow-forms/src/authentication/index.js +++ b/forms-flow-forms/src/authentication/index.js @@ -28,11 +28,13 @@ module.exports = (router) => { * * @param payload {Object} * The decoded JWT. + * @param customSecret {String} + * Optional secret. * * @return {String|Boolean} * The JWT from the given payload, or false if the jwt payload is still valid. */ - const getToken = (tokenInfo) => { + const getToken = (tokenInfo, customSecret) => { // Clone to make sure we don't change original. const payload = Object.assign({}, tokenInfo); delete payload.iat; @@ -43,17 +45,21 @@ module.exports = (router) => { secret, } = jwtConfig; - return jwt.sign(payload, secret, { - expiresIn: expireTime * 60, + // changed the secret and expire to the env + + + return jwt.sign(payload, customSecret ||process.env.FORMIO_JWT_SECRET||secret , { + expiresIn: (expireTime ||240) * 60, }); }; - + // Number(process.env.FORMIO_JWT_EXPIRE)|| todo /** * Checks to see if a decoded token is allowed to access this path. * @param req * @param decoded * @return {boolean} */ + const isTokenAllowed = (req, decoded) => { if (!decoded.allow) { return true; @@ -145,9 +151,9 @@ module.exports = (router) => { // Delete the previous expiration so we can generate a new one. delete tempToken.exp; - + // Sign the token. - jwt.sign(tempToken, jwtConfig.secret, { + jwt.sign(tempToken,process.env.FORMIO_JWT_SECRET||jwtConfig.secret, { expiresIn: expire, }, (err, token) => { if (err) { @@ -174,7 +180,7 @@ module.exports = (router) => { } let adminKey = false; - if (process.env.ADMIN_KEY && process.env.ADMIN_KEY === req.headers['x-admin-key']) { + if (process.env.ADMIN_KEY && process.env.ADMIN_KEY === req.headers['x-admin-key'] || req.isAdmin) { adminKey = true; } else if (!req.token) { @@ -348,7 +354,8 @@ module.exports = (router) => { // Set the headers if they haven't been sent yet. if (!res.headersSent) { - res.setHeader('Access-Control-Expose-Headers', 'x-jwt-token'); + const headers = router.formio.hook.alter('accessControlExposeHeaders', 'x-jwt-token'); + res.setHeader('Access-Control-Expose-Headers', headers); res.setHeader('x-jwt-token', res.token); } diff --git a/forms-flow-forms/src/cache/cache.js b/forms-flow-forms/src/cache/cache.js index 78b389d834..93289710af 100644 --- a/forms-flow-forms/src/cache/cache.js +++ b/forms-flow-forms/src/cache/cache.js @@ -424,7 +424,7 @@ module.exports = function(router) { const formId = component.form.toString(); formIds.push(formId); debug.loadSubForms(`Found subform ${formId}`); - // TO-DO: Figure out why there are two revisions here?... + // 'formRevision' was used in the older builder versions if (component.revision || component.formRevision) { formRevs.push(component); } @@ -465,6 +465,10 @@ module.exports = function(router) { }, setFormComponents(components, forms) { + if (components.noRecurse) { + return; + } + components.noRecurse = true; util.eachComponent(components, (component) => { if ((component.type === 'form') && component.form) { const formId = component.form.toString(); diff --git a/forms-flow-forms/src/db/index.js b/forms-flow-forms/src/db/index.js index 9c1ebcd2fe..a5bcd1fe50 100644 --- a/forms-flow-forms/src/db/index.js +++ b/forms-flow-forms/src/db/index.js @@ -3,7 +3,7 @@ const async = require('async'); const MongoClient = require('mongodb').MongoClient; const semver = require('semver'); -const fetch = require('../util/fetch'); +const fetch = require('@formio/node-fetch-http-proxy'); const _ = require('lodash'); const fs = require('fs'); const debug = { @@ -78,18 +78,21 @@ module.exports = function(formio) { } currentLock.isLocked = false; - schema.findOneAndUpdate( + schema.updateOne( {key: 'formio'}, {$set: {isLocked: currentLock.isLocked}}, - {returnOriginal: false}, - (err, result) => { + (err) => { if (err) { return next(err); } - - currentLock = result.value; - debug.db('Lock unlocked'); - next(); + schema.findOne({key: 'formio'}, (err, result) => { + if (err) { + return next(err); + } + currentLock = result; + debug.db('Lock unlocked'); + next(); + }); } ); }; @@ -106,50 +109,8 @@ module.exports = function(formio) { return next(); } - // If they provide the SA url, then fetch it from there. - if (CA.indexOf('http') === 0) { - debug.db(`Fetching MongoDB Public Key ${CA}`); - fetch(CA) - .then((response) => { - if (response.ok) { - return response.text(); - } - throw new Error(response.statusText); - }) - .then((body) => { - if (body) { - debug.db('Fetched MongoDB Public Key'); - config.mongoSA = config.mongoCA = body; - return next(); - } - throw new Error('Empty Body'); - }) - .catch((error) => { - debug.db(`Unable to fetch MongoDB Public Key: ${error}`); - unlock(() => { - throw new Error(`Unable to fetch the SA Certificate: ${CA}.`); - }); - config.mongoSA = config.mongoCA = ''; - return next(); - }); - } - else if (CA.indexOf('/') === 0) { - // This is a file path, load it directly. - try { - config.mongoSA = config.mongoCA = fs.readFileSync(CA); - } - catch (err) { - debug.db(`Unable to read MongoDB Public Key: ${err}`); - unlock(() => { - throw new Error(`Unable to read the MongoDB Public Key: ${CA}. ${err}`); - }); - config.mongoSA = config.mongoCA = ''; - } - return next(); - } - else { - return next(); - } + config.mongoSA = config.mongoCA = CA; + return next(); }; /** @@ -248,7 +209,7 @@ module.exports = function(formio) { mongoConfig.useUnifiedTopology = true; // Establish a connection and continue with execution. - MongoClient.connect(dbUrl, mongoConfig, function(err, client) { + MongoClient.connect(dbUrl, mongoConfig, async function(err, client) { if (err) { debug.db(`Connection Error: ${err}`); unlock(function() { @@ -256,22 +217,18 @@ module.exports = function(formio) { }); } db = client.db(client.s.options.dbName); - debug.db('Connection successful'); - - db.collection('schema', function(err, collection) { + try { + const collection = await db.collection('schema'); debug.db('Schema collection opened'); - if (err) { - return next(err); - } - - // Store our reference to the Schema Collection. schema = collection; - - // Load the tools available to help manage updates. - tools = require('./tools')(db, schema); - next(); - }); + } + catch (err) { + return next(err); + } + // Load the tools available to help manage updates. + tools = require('./tools')(db, schema); + next(); }); }; @@ -279,22 +236,24 @@ module.exports = function(formio) { * Test to see if the application has been installed. Install if not. */ const checkSetup = function(next) { + setTimeout(() => { formio.util.log('Checking for db setup.'); - db.listCollections().toArray().then(function(collections) { - debug.db(`Collections found: ${collections.length}`); - // 3 is an arbitrary length. We just want a general idea that things have been installed. - if (collections.length < 3) { - formio.util.log(' > No collections found. Starting new setup.'); - require(path.join(__dirname, '/install'))(db, config, function() { + db.listCollections().toArray().then(function(collections) { + debug.db(`Collections found: ${collections.length}`); + // 3 is an arbitrary length. We just want a general idea that things have been installed. + if (collections.length < 3) { + formio.util.log(' > No collections found. Starting new setup.'); + require(path.join(__dirname, '/install'))(db, config, function() { + formio.util.log(' > Setup complete.\n'); + next(); + }); + } + else { formio.util.log(' > Setup complete.\n'); - next(); - }); - } - else { - formio.util.log(' > Setup complete.\n'); - return next(); - } - }); + return next(); + } + }); + },Math.random() * 1000); }; const checkEncryption = function(next) { @@ -540,18 +499,22 @@ module.exports = function(formio) { } else { // Lock - schema.findOneAndUpdate( + schema.updateOne( {key: 'formio'}, {$set: {isLocked: (new Date()).getTime()}}, - {returnOriginal: false}, - (err, result) => { + (err) => { if (err) { throw err; } - currentLock = result.value; - debug.db('Lock engaged'); - next(); + schema.findOne({key: 'formio'}, (err, result) => { + if (err) { + return next(err); + } + currentLock = result; + debug.db('Lock engaged'); + next(); + }); } ); } diff --git a/forms-flow-forms/src/db/tools.js b/forms-flow-forms/src/db/tools.js index e21f0123f9..79207288eb 100644 --- a/forms-flow-forms/src/db/tools.js +++ b/forms-flow-forms/src/db/tools.js @@ -17,10 +17,10 @@ module.exports = function(db, schema) { * @returns {Function} */ updateLockVersion(version, callback) { - schema.findOneAndUpdate( + schema.updateOne( {key: 'formio'}, {$set: {version: version}}, - (err, document) => { + (err) => { if (err) { throw err; } diff --git a/forms-flow-forms/src/db/updates/2.3.0.js b/forms-flow-forms/src/db/updates/2.3.0.js index 64923a01b8..5b14c7a77c 100644 --- a/forms-flow-forms/src/db/updates/2.3.0.js +++ b/forms-flow-forms/src/db/updates/2.3.0.js @@ -2,7 +2,7 @@ let _ = require('lodash'); let async = require('async'); -let ObjectId = require('mongodb').ObjectID; +let ObjectId = require('mongodb').ObjectId; /** * Update 2.3.0 @@ -78,7 +78,7 @@ module.exports = function(db, config, tools, done) { let updateAuthenticationAction = function(actionId, roleId, cb) { let query = {_id: ObjectId(actionId)}; let update = {$set: {'settings.role': ObjectId(roleId)}}; - actions.findOneAndUpdate(query, update, cb); + actions.updateOne(query, update, cb); }; // Delete the roleAction with the given actionId; @@ -208,7 +208,7 @@ module.exports = function(db, config, tools, done) { let addRoleToAuthAction = function(actionId, roleId, cb) { let query = {_id: ObjectId(actionId)}; let update = {$set: {'settings.role': ObjectId(roleId.toString())}}; - actions.findOneAndUpdate(query, update, function(err, result) { + actions.updateOne(query, update, function(err, result) { if (err) { return cb(err); } diff --git a/forms-flow-forms/src/db/updates/2.3.2.js b/forms-flow-forms/src/db/updates/2.3.2.js index aaff8800d5..ae59661c60 100644 --- a/forms-flow-forms/src/db/updates/2.3.2.js +++ b/forms-flow-forms/src/db/updates/2.3.2.js @@ -24,7 +24,7 @@ module.exports = function(db, config, tools, done) { comparison = form.path.toString() + (++iter).toString(); } - forms.findOneAndUpdate({_id: form._id}, {$set: {path: comparison.toLowerCase()}}, function(err) { + forms.updateOne({_id: form._id}, {$set: {path: comparison.toLowerCase()}}, function(err) { if (err) { return cb(err); } @@ -61,7 +61,7 @@ module.exports = function(db, config, tools, done) { .snapshot({$snapshot: true}) .toArray(function(err, docs) { async.eachSeries(docs, function(form, cb) { - forms.findOneAndUpdate({_id: form._id}, {$set: {path: form.name.toLowerCase()}}, function(err) { + forms.updateOne({_id: form._id}, {$set: {path: form.name.toLowerCase()}}, function(err) { if (err) { return cb(err); } diff --git a/forms-flow-forms/src/db/updates/2.4.1.js b/forms-flow-forms/src/db/updates/2.4.1.js index aba88a108a..41981f6a35 100644 --- a/forms-flow-forms/src/db/updates/2.4.1.js +++ b/forms-flow-forms/src/db/updates/2.4.1.js @@ -2,7 +2,7 @@ let Q = require('q'); let util = require('../../util/util'); let deleteProp = require('delete-property').default; -let ObjectID = require('mongodb').ObjectID; +let ObjectID = require('mongodb').ObjectId; let _ = require('lodash'); /** * Update 2.4.1 diff --git a/forms-flow-forms/src/db/updates/2.4.2.js b/forms-flow-forms/src/db/updates/2.4.2.js index 1c616ecbe1..027229c320 100644 --- a/forms-flow-forms/src/db/updates/2.4.2.js +++ b/forms-flow-forms/src/db/updates/2.4.2.js @@ -97,10 +97,9 @@ module.exports = function(db, config, tools, done) { {type: 'delete_all', roles: [role._id]} ]; - projects.findOneAndUpdate( + projects.updateOne( {_id: project._id, deleted: {$eq: null}}, {$set: {access: access}}, - {returnOriginal: false}, function(err) { if (err) { return cb(err); @@ -138,10 +137,9 @@ module.exports = function(db, config, tools, done) { } async.forEachOf(docs, function(project, key, next) { - projects.findOneAndUpdate( + projects.updateOne( {_id: project._id}, {$set: {settings: null}}, - {returnOriginal: false}, function(err) { if (err) { return next(err); @@ -226,7 +224,7 @@ module.exports = function(db, config, tools, done) { }); // Finalize the updates to each forms component list (including forms that had layout component key changes). - forms.findOneAndUpdate({_id: form._id}, {$set: {components: form.components}}, function(err) { + forms.updateOne({_id: form._id}, {$set: {components: form.components}}, function(err) { if (err) { return then(err); } diff --git a/forms-flow-forms/src/db/updates/2.4.3.js b/forms-flow-forms/src/db/updates/2.4.3.js index 931ceb6e40..3bccffcdd5 100644 --- a/forms-flow-forms/src/db/updates/2.4.3.js +++ b/forms-flow-forms/src/db/updates/2.4.3.js @@ -24,10 +24,9 @@ module.exports = function(db, config, tools, done) { // Update each submission to be the owner of itself. async.forEachOf(docs, function(submission, key, next) { - submissions.findOneAndUpdate( + submissions.updateOne( {_id: submission._id}, {$set: {owner: submission._id}}, - {returnOriginal: false}, function(err) { if (err) { return next(err); diff --git a/forms-flow-forms/src/db/updates/3.0.0.js b/forms-flow-forms/src/db/updates/3.0.0.js index e81ad03b70..1a609c8422 100644 --- a/forms-flow-forms/src/db/updates/3.0.0.js +++ b/forms-flow-forms/src/db/updates/3.0.0.js @@ -25,10 +25,9 @@ module.exports = function(db, config, tools, done) { } async.forEachOf(docs, function(project, key, next) { let machineName = project.name.toLowerCase().replace(/\W/g, ''); - projects.findOneAndUpdate( + projects.updateOne( {_id: project._id}, {$set: {machineName: machineName}}, - {returnOriginal: false}, function (err) { if (err) { return next(err); @@ -63,10 +62,9 @@ module.exports = function(db, config, tools, done) { machineName = project.machineName + ':'; } machineName = machineName + form.name; - forms.findOneAndUpdate( + forms.updateOne( {_id: form._id}, {$set: {machineName: machineName}}, - {returnOriginal: false}, function (err) { if (err) { return next(err); } next(); @@ -100,10 +98,9 @@ module.exports = function(db, config, tools, done) { machineName = form.machineName + ':'; } machineName = machineName + action.name; - actions.findOneAndUpdate( + actions.updateOne( {_id: action._id}, {$set: {machineName: machineName}}, - {returnOriginal: false}, function (err) { if (err) { return next(err); } next(); @@ -137,10 +134,9 @@ module.exports = function(db, config, tools, done) { machineName = project.machineName + ':'; } machineName = machineName + _.camelCase(role.title); - roles.findOneAndUpdate( + roles.updateOne( {_id: role._id}, {$set: {machineName: machineName}}, - {returnOriginal: false}, function (err) { if (err) { return next(err); } next(); diff --git a/forms-flow-forms/src/db/updates/3.0.2.js b/forms-flow-forms/src/db/updates/3.0.2.js index 16d6199cfa..c883b7f193 100644 --- a/forms-flow-forms/src/db/updates/3.0.2.js +++ b/forms-flow-forms/src/db/updates/3.0.2.js @@ -3,7 +3,7 @@ let async = require('async'); let util = require('../../util/util'); let _ = require('lodash'); -let ObjectId = require('mongodb').ObjectID; +let ObjectId = require('mongodb').ObjectId; /** * Update 3.0.2 diff --git a/forms-flow-forms/src/db/updates/3.1.2.js b/forms-flow-forms/src/db/updates/3.1.2.js index 915d5e6e2e..6196ee32fb 100644 --- a/forms-flow-forms/src/db/updates/3.1.2.js +++ b/forms-flow-forms/src/db/updates/3.1.2.js @@ -1,6 +1,6 @@ 'use strict'; const _ = require('lodash'); -const ObjectID = require('mongodb').ObjectID; +const ObjectID = require('mongodb').ObjectId; const util = require('../../util/util'); /** diff --git a/forms-flow-forms/src/db/updates/3.1.3.js b/forms-flow-forms/src/db/updates/3.1.3.js index ecb7b63ec6..10ef765810 100644 --- a/forms-flow-forms/src/db/updates/3.1.3.js +++ b/forms-flow-forms/src/db/updates/3.1.3.js @@ -1,7 +1,7 @@ 'use strict'; const utils = require('../../util/util'); const _ = require('lodash'); -const ObjectID = require('mongodb').ObjectID; +const ObjectID = require('mongodb').ObjectId; const ProgressBar = require('progress'); /** diff --git a/forms-flow-forms/src/export/export.js b/forms-flow-forms/src/export/export.js index c428d5e284..c7a793b814 100644 --- a/forms-flow-forms/src/export/export.js +++ b/forms-flow-forms/src/export/export.js @@ -87,6 +87,10 @@ module.exports = (router) => { if (!components) { return Promise.resolve(components); } + if (components.noRecurse) { + return Promise.resolve(components); + } + components.noRecurse = true; const newComponents = components.map(component => { if (component.type === 'form' && component.form) { const subForm = router.formio.mongoose.models.form.findById(component.form) @@ -203,7 +207,7 @@ module.exports = (router) => { cursor.on('error', (error) => { debug(error); router.formio.util.log(error); - res.status(400).send(error); + next(error); }); // When the DB cursor ends, allow the output stream a tick to perform the last write, // then manually end it by pushing a null item to the output stream's queue @@ -213,7 +217,7 @@ module.exports = (router) => { }) .catch((error) => { // Send the error. - res.status(400).send(error); + next(error); }); }); }); diff --git a/forms-flow-forms/src/export/exporters/CSVExporter.js b/forms-flow-forms/src/export/exporters/CSVExporter.js index 4a088496cf..adb2d11780 100644 --- a/forms-flow-forms/src/export/exporters/CSVExporter.js +++ b/forms-flow-forms/src/export/exporters/CSVExporter.js @@ -5,7 +5,7 @@ const util = require('../../util/util'); const through = require('through'); const csv = require('csv'); const _ = require('lodash'); -const Entities = require('html-entities').AllHtmlEntities; +const Entities = require('html-entities'); const moment = require('moment-timezone'); const {conformToMask} = require('vanilla-text-mask'); const Formio = require('formiojs/formio.form'); @@ -42,6 +42,8 @@ class CSVExporter extends Exporter { }); this.fields = []; + this.customTransformers = {}; + const formattedView = req.query.view === 'formatted'; this.formattedView = formattedView; @@ -145,7 +147,12 @@ class CSVExporter extends Exporter { }); } else if (component.type === 'checkbox') { - items.push({type: 'boolean'}); + if (component.name && component.inputType === 'radio') { + items.push({name: component.name, rename: component.name}); + } + else { + items.push({type: 'boolean'}); + } } else if (component.type === 'survey') { _.each(component.questions, (question) => { @@ -207,7 +214,8 @@ class CSVExporter extends Exporter { return tempVal; } else if (component.type === 'select') { - return value; + // eslint-disable-next-line max-depth + return this.customTransform(path, value); } } else { @@ -241,7 +249,7 @@ class CSVExporter extends Exporter { } return _.isObject(value) ? valuesExtractor(value) - : primitiveValueHandler(value); + : primitiveValueHandler(value.toString()); } }); } @@ -316,6 +324,39 @@ class CSVExporter extends Exporter { } }); } + else if (component.type === 'sketchpad') { + items.push({ + preprocessor: (value) => { + if (_.isObject(value)) { + return _.isEmpty(value) ? '' : '[Visual Data]'; + } + + return value; + } + }); + } + else if (component.type === 'file') { + items.push({ + preprocessor: (value) => { + if (!value || !value.length) { + return ''; + } + const formatted = value + .map((file) => { + const fileName = file && (file.name || file.originalName); + + if (req.googleSheetAction && typeof req.googleSheetAction === 'function') { + return req.googleSheetAction(file, fileName); + } + + return fileName; + }) + .filter((val) => !!val) + .join(', '); + return formatted; + } + }); + } else { // Default to the current component item. items.push({}); @@ -345,6 +386,13 @@ class CSVExporter extends Exporter { finalItem.preprocessor = item.preprocessor; } + if (item.hasOwnProperty('name')) { + if (_.find(this.fields, {path: item.name})) { + return; + } + finalItem.path = item.name; + } + this.fields.push(finalItem); }); @@ -473,7 +521,7 @@ class CSVExporter extends Exporter { */ coerceToString(data, column, submission) { data = (column.preprocessor || _.identity)(data, submission); - + let result = ''; if (Array.isArray(data) && data.length > 0) { const fullPath = column.subpath ? `${column.key}.${column.subpath}` @@ -481,21 +529,56 @@ class CSVExporter extends Exporter { return data.map((item) => `"${this.coerceToString(_.get(item, fullPath, item), column)}"`).join(','); } - if (_.isString(data)) { + else if (_.isString(data)) { if (column.type === 'boolean') { - return Boolean(data).toString(); + result = Boolean(data).toString(); + } + else { + result = data.toString(); } - - return data.toString(); } - if (_.isNumber(data)) { - return data.toString(); + else if (_.isNumber(data)) { + result = data.toString(); } - if (_.isObject(data)) { + else if (_.isObject(data)) { return this.coerceToString(_.get(data, column.subpath, ''), column); } + else { + result = JSON.stringify(data); + } + + return this.injectionProtector(result); + } + + injectionProtector(data) { + if (!data) { + return data; + } + + if (!_.isString(data)) { + data = data.toString(); + } + + const riskyChars = ['=', '+', '-', '@']; + const regexStr = `(?<=(?:^|"|“)\\s*)([${riskyChars.join('\\')}])`; + const regExp = new RegExp(regexStr, 'gm'); + + return _.replace(data, regExp, (char) => { + return `\`${char}`; + }); + } + + addCustomTransformer(path, fn) { + this.customTransformers[path] = fn; + } + + customTransform(path, value, ...rest) { + const transformer = this.customTransformers[path]; + if (transformer && typeof transformer === 'function') { + return transformer(value, ...rest); + } - return JSON.stringify(data); + return value; } } diff --git a/forms-flow-forms/src/middleware/bootstrapFormAccess.js b/forms-flow-forms/src/middleware/bootstrapFormAccess.js index 85b817b1b9..2e12f308f8 100644 --- a/forms-flow-forms/src/middleware/bootstrapFormAccess.js +++ b/forms-flow-forms/src/middleware/bootstrapFormAccess.js @@ -46,22 +46,29 @@ module.exports = function(router) { }); // Update the form. - router.formio.resources.form.model.findOneAndUpdate( + router.formio.resources.form.model.updateOne( {_id: res.resource.item._id, deleted: {$eq: null}}, - {$set: {access: [{type: 'read_all', roles: roles}]}}, - {new: true} - ).lean().exec((err, form) => { + {$set: {access: [{type: 'read_all', roles: roles}]}} + ).exec((err) => { if (err) { debug(err); return next(err); } - if (!form) { - return next(); - } - // Update the response to reflect the access changes. - // Filter the response to have no __v and deleted key. - res.resource.item = _.omit(_.omit(form, 'deleted'), '__v'); - next(); + router.formio.resources.form.model.findOne( + {_id: res.resource.item._id, deleted: {$eq: null}} + ).lean().exec((err, form) => { + if (err) { + debug(err); + return next(err); + } + if (!form) { + return next(); + } + // Update the response to reflect the access changes. + // Filter the response to have no __v and deleted key. + res.resource.item = _.omit(_.omit(form, 'deleted'), '__v'); + next(); + }); }); }); }; diff --git a/forms-flow-forms/src/middleware/deleteRoleHandler.js b/forms-flow-forms/src/middleware/deleteRoleHandler.js index 49716c1b7e..0b600f927b 100644 --- a/forms-flow-forms/src/middleware/deleteRoleHandler.js +++ b/forms-flow-forms/src/middleware/deleteRoleHandler.js @@ -33,6 +33,10 @@ module.exports = (router) => { return next(); } + if (roleId === '000000000000000000000000') { + return res.sendStatus(405); + } + // Load the role in question. router.formio.resources.role.model.findById(roleId).lean().exec(function(err, role) { if (err || !role) { diff --git a/forms-flow-forms/src/middleware/filterProtectedFields.js b/forms-flow-forms/src/middleware/filterProtectedFields.js index 3522fdf840..4e8da9c3dd 100644 --- a/forms-flow-forms/src/middleware/filterProtectedFields.js +++ b/forms-flow-forms/src/middleware/filterProtectedFields.js @@ -21,7 +21,7 @@ module.exports = function(router) { return next(err); } - util.removeProtectedFields(form, action, res.resource.item); + util.removeProtectedFields(form, action, res.resource.item, req.doNotMinify); next(); }); }; diff --git a/forms-flow-forms/src/middleware/formHandler.js b/forms-flow-forms/src/middleware/formHandler.js index 97bfda8502..fe6e98edaa 100644 --- a/forms-flow-forms/src/middleware/formHandler.js +++ b/forms-flow-forms/src/middleware/formHandler.js @@ -47,10 +47,8 @@ module.exports = function(router) { const formQuery = hook.alter('formQuery', {}, req); req.countQuery = req.countQuery || req.model || this.model; req.modelQuery = req.modelQuery || req.model || this.model; - if (!req.params.formId) { - req.countQuery = req.countQuery.find(formQuery); - req.modelQuery = req.modelQuery.find(formQuery); - } + req.countQuery = req.countQuery.find(formQuery); + req.modelQuery = req.modelQuery.find(formQuery); } next(); }; diff --git a/forms-flow-forms/src/middleware/middleware.js b/forms-flow-forms/src/middleware/middleware.js index d6563ed881..55a4cb206f 100644 --- a/forms-flow-forms/src/middleware/middleware.js +++ b/forms-flow-forms/src/middleware/middleware.js @@ -38,5 +38,7 @@ module.exports = function(router) { restrictRequestTypes: require('./restrictRequestTypes')(router), filterIndex: require('./filterIndex')(router), mongodbConnectionState: require('./mongodbConnectionState')(router), + revisionLoader: require('./revisionLoader')(router), + tokenVerify:require("./tokenVerify")(router) }; }; diff --git a/forms-flow-forms/src/middleware/permissionHandler.js b/forms-flow-forms/src/middleware/permissionHandler.js index a94f78084d..8a61182d8e 100644 --- a/forms-flow-forms/src/middleware/permissionHandler.js +++ b/forms-flow-forms/src/middleware/permissionHandler.js @@ -182,6 +182,9 @@ module.exports = function(router) { // Iterate through each permission level Object.entries(req.submissionFieldMatchAccess).forEach(([permissionLevel, conditions]) => { + if (!Array.isArray(conditions)) { + return; + } // Iterate through each condition within a permission level conditions.forEach((condition) => { // Get intersection of roles within condition and the user's roles @@ -280,7 +283,6 @@ module.exports = function(router) { // Add this access handlers for all to use. router.formio.access = { - /** * Get the access for all defined entities. * @@ -403,12 +405,17 @@ module.exports = function(router) { return roleId; }) : []; + if (access.primaryAdminRole) { + validRoles.push(access.primaryAdminRole); + } + // Default the access roles. access.roles = [access.defaultRole]; // Ensure the user only has valid roles. if (req.user) { - access.roles = _(req.user.roles || []) + let userRoles = _.clone(access.roles); + userRoles = _(req.user.roles || []) .filter() .map(util.idToString) .intersection(validRoles) @@ -416,8 +423,11 @@ module.exports = function(router) { .value(); if (req.user._id && (req.user._id !== 'external')) { - access.roles.push(req.user._id.toString()); + userRoles.push(req.user._id.toString()); } + + userRoles = hook.alter('userRoles', userRoles, access.defaultRole, req); + access.roles =_.clone( userRoles); } // Add the EVERYONE role. @@ -440,7 +450,7 @@ module.exports = function(router) { return callback(`No Form found with formId: ${req.formId}`); } - if (item.fieldMatchAccess) { + if (item.fieldMatchAccess && !_.isEmpty(item.fieldMatchAccess)) { req.submissionFieldMatchAccess = item.fieldMatchAccess; } return callback(null); @@ -454,8 +464,16 @@ module.exports = function(router) { return callback(null); } - if (req.submissionFieldMatchAccess) { - req.submissionFieldMatchAccessFilter = true; + if (req.submissionFieldMatchAccess && _.isObject(req.submissionFieldMatchAccess)) { + const hasRoles = Object.keys(req.submissionFieldMatchAccess).some(accessKey => { + if (!Array.isArray(req.submissionFieldMatchAccess[accessKey])) { + return false; + } + return req.submissionFieldMatchAccess[accessKey].some(item=>{ + return item.roles.some(role => req.accessRoles.includes(role.toString())); + }); + }); + req.submissionFieldMatchAccessFilter = hasRoles; } return callback(null); }, @@ -569,6 +587,9 @@ module.exports = function(router) { } userRoles.forEach(function(roleEntity) { + if ( typeof roleEntity !== 'string') { + return; + } const role = roleEntity.split(':')[1]; if (role && readBlockingRoles.includes(role)) { @@ -614,8 +635,9 @@ module.exports = function(router) { /* eslint-disable max-statements */ hasAccess(req, access, entity, res) { const method = req.method.toUpperCase(); - const user = req.user ? util.idToString(req.user._id) : null; + let user = req.user ? util.idToString(req.user._id) : null; + user = hook.alter('twoFAuthenticatedUser', user, req); // Setup some flags for other handlers. req.isAdmin = false; @@ -653,6 +675,14 @@ module.exports = function(router) { return true; } + // Check to see if this user has an admin role of the primary project. + const hasPrimaryAdminRole = access.primaryAdminRole ? (_.indexOf(access.roles, access.primaryAdminRole) !== -1) : false; + + if (hasPrimaryAdminRole) { + req.isAdmin = true; + return true; + } + // There should be an entity at this point. if (!entity || !access.hasOwnProperty(entity.type)) { return false; diff --git a/forms-flow-forms/src/middleware/recaptcha.js b/forms-flow-forms/src/middleware/recaptcha.js index cb5c49be28..e00ae5eef8 100644 --- a/forms-flow-forms/src/middleware/recaptcha.js +++ b/forms-flow-forms/src/middleware/recaptcha.js @@ -1,7 +1,7 @@ 'use strict'; const querystring = require('querystring'); -const fetch = require('../util/fetch'); +const fetch = require('@formio/node-fetch-http-proxy'); module.exports = function(router) { const hook = require('../util/hook')(router.formio); @@ -27,7 +27,21 @@ module.exports = function(router) { if (!body) { throw new Error('No response from Google'); } - res.send(body); + + const expirationTime = 600000; // 10 minutes + + // Create temp token with recaptcha response token as value + // to verify it on validation step + router.formio.mongoose.models.token.create({ + value: req.query.recaptchaToken, + expireAt: Date.now() + expirationTime, + }, (err) => { + if (err) { + return res.status(400).send(err.message); + } + + res.send(body); + }); }); }); }); diff --git a/forms-flow-forms/src/middleware/revisionLoader.js b/forms-flow-forms/src/middleware/revisionLoader.js new file mode 100644 index 0000000000..886ccd31d8 --- /dev/null +++ b/forms-flow-forms/src/middleware/revisionLoader.js @@ -0,0 +1,32 @@ +'use strict'; + +/** + * Middleware to load a form revision if needed. + * + * @param req + * @param res + * @param next + * @returns {*} + */ + + module.exports = function(router) { + const hook = require('../util/hook')(router.formio); + + return (req, res, next) => { + if ( req.query.formRevision && res.resource.item.revisions === 'original') { + hook.alter('loadRevision', res.resource.item, req.query.formRevision, (revision, err)=>{ + if ( err ) { + return next(err); + } + res.resource.item = revision; + if ( revision===null ) { + res.resource.status = 404; + } + return next(); + }); + } + else { + return next(); + } + }; + }; diff --git a/forms-flow-forms/src/middleware/submissionFieldMatchAccessFilter.js b/forms-flow-forms/src/middleware/submissionFieldMatchAccessFilter.js index 5b88945a7d..b5ea2b01d4 100644 --- a/forms-flow-forms/src/middleware/submissionFieldMatchAccessFilter.js +++ b/forms-flow-forms/src/middleware/submissionFieldMatchAccessFilter.js @@ -35,7 +35,7 @@ module.exports = function(router) { // Map permissions to array of Mongo conditions const fieldsToCheck = Object.entries(req.submissionFieldMatchAccess).flatMap(([, conditions]) => { - return conditions.map((condition) => { + return Array.isArray(conditions) ? conditions.map((condition) => { if (hasRolesIntersection(condition)) { const {formFieldPath, operator, value, valueType} = condition; @@ -43,7 +43,7 @@ module.exports = function(router) { return {[formFieldPath]: {[operator]: util.castValue(valueType, value)}}; } } - }); + }) : []; }).filter((condition) => !!condition); if (userId) { @@ -61,6 +61,11 @@ module.exports = function(router) { return res.sendStatus(401); } + if (req.modelQuery) { + const orCondition = _.get(req.modelQuery, '_conditions["$or"]', []); + query['$or'].push(...orCondition); + } + req.modelQuery = req.modelQuery || req.model || this.model; req.modelQuery = req.modelQuery.find(query); diff --git a/forms-flow-forms/src/middleware/submissionHandler.js b/forms-flow-forms/src/middleware/submissionHandler.js index dd1776f36b..233aea7987 100644 --- a/forms-flow-forms/src/middleware/submissionHandler.js +++ b/forms-flow-forms/src/middleware/submissionHandler.js @@ -3,7 +3,6 @@ const _ = require('lodash'); const async = require('async'); const util = require('../util/util'); -const LegacyValidator = require('../resources/LegacyValidator'); const Validator = require('../resources/Validator'); const setDefaultProperties = require('../actions/properties/setDefaultProperties'); @@ -76,13 +75,11 @@ module.exports = (router, resourceName, resourceId) => { // If this is a get method, then filter the model query. if (isGet) { + const submissionQuery = hook.alter('submissionQuery', {form: req.currentForm._id}, req); req.countQuery = req.countQuery || req.model || this.model; req.modelQuery = req.modelQuery || req.model || this.model; - if (req.handlerName !== 'beforeGet') { - // Set the model query to filter based on the ID. - req.countQuery = req.countQuery.find({form: req.currentForm._id}); - req.modelQuery = req.modelQuery.find({form: req.currentForm._id}); - } + req.countQuery = req.countQuery.find(submissionQuery); + req.modelQuery = req.modelQuery.find(submissionQuery); } // If the request has a body. @@ -100,6 +97,21 @@ module.exports = (router, resourceName, resourceId) => { req.body.data = {}; } + if (req.method === 'POST') { + const blackList = [ + 'x-admin', + 'x-jwt-token', + 'x-token', + 'x-remote-token' + ]; + + const reqHeaders = _.omitBy(req.headers, (value, key) => { + return blackList.includes(key) || key.match(/auth/gi); + }); + + _.set(req.body, 'metadata.headers', reqHeaders); + } + // Ensure that the _fvid is a number. if (req.body.hasOwnProperty('_fvid') && !_.isNaN(parseInt(req.body._fvid))) { req.body._fvid = parseInt(req.body._fvid); @@ -116,18 +128,17 @@ module.exports = (router, resourceName, resourceId) => { // Allow them to alter the body. req.body = hook.alter('submissionRequest', req.body); - // See if they provided an update to the roles. - if (req.method === 'PUT' && req.params.submissionId && req.rolesUpdate && req.rolesUpdate.length) { + if (req.method === 'PUT' && req.params.submissionId) { router.formio.cache.loadCurrentSubmission(req, (err, current) => { - if (current.roles && current.roles.length) { + if ( req.rolesUpdate && req.rolesUpdate.length && current.roles && current.roles.length) { const newRoles = _.intersection( current.roles.map((role) => role.toString()), req.rolesUpdate ); - if (newRoles.length !== req.rolesUpdate.length) { req.body.roles = newRoles.map((roleId) => util.idToBson(roleId)); - } } + + req.currentSubmissionData = current && current.data; done(); }); } @@ -187,25 +198,28 @@ module.exports = (router, resourceName, resourceId) => { // Next we need to validate the input. hook.alter('validateSubmissionForm', req.currentForm, req.body, async form => { // eslint-disable-line max-statements - // Allow use of the legacy validator - const useLegacyValidator = ( - process.env.LEGACY_VALIDATOR || - req.headers['legacy-validator'] || - req.query.legacy_validator - ); - // Get the submission model. const submissionModel = req.submissionModel || router.formio.resources.submission.model; // Next we need to validate the input. const token = util.getRequestValue(req, 'x-jwt-token'); - const _Validator = useLegacyValidator ? LegacyValidator : Validator; + const validator = new Validator(req.currentForm, submissionModel, token, req.token, hook); + validator.validateReCaptcha = (responseToken) => { + return new Promise((resolve, reject) => { + router.formio.mongoose.models.token.findOne({value: responseToken}, (err, token) => { + if (err) { + return reject(err); + } - if (useLegacyValidator) { - _Validator.setHook(hook); - } + if (!token) { + return reject(new Error('ReCaptcha: Response token not found')); + } - const validator = new _Validator(req.currentForm, submissionModel, token, req.token, hook); + // Remove temp token after submission with reCaptcha + return token.remove(() => resolve(true)); + }); + }); + }; // Validate the request. validator.validate(req.body, (err, data, visibleComponents) => { @@ -218,6 +232,9 @@ module.exports = (router, resourceName, resourceId) => { if (!_.isEqual(visibleComponents, req.currentForm.components)) { req.currentFormComponents = visibleComponents; } + else if (req.hasOwnProperty('currentFormComponents') && req.currentFormComponents) { + delete req.currentFormComponents; + } done(); }); }); @@ -270,18 +287,30 @@ module.exports = (router, resourceName, resourceId) => { action, path, }) => { + const componentPath = util.valuePath(path, component.key); + // Remove not persistent data if ( data && component.hasOwnProperty('persistent') && - !component.persistent + !component.persistent && + !['columns', 'fieldset', 'panel', 'table', 'tabs'].includes(component.type) ) { util.deleteProp(component.key)(data); } + else if (req.method === 'PUT') { + // Restore value of components with calculated value and disabled server calculation + // if they don't present in submission data + const newCompData = _.get(submissionData, componentPath, undefined); + const currentCompData = _.get(req.currentSubmissionData, componentPath); + + if (component.calculateValue && !component.calculateServer && currentCompData && newCompData === undefined) { + _.set(submissionData, componentPath, _.get(req.currentSubmissionData, componentPath)); + } + } const fieldActions = hook.alter('fieldActions', fActions); const propertyActions = hook.alter('propertyActions', pActions); - const componentPath = util.valuePath(path, component.key); // Execute the property handlers after validation has occurred. const handlerArgs = [ diff --git a/forms-flow-forms/src/middleware/tokenHandler.js b/forms-flow-forms/src/middleware/tokenHandler.js index 89a1d88dfe..17eae92cfe 100644 --- a/forms-flow-forms/src/middleware/tokenHandler.js +++ b/forms-flow-forms/src/middleware/tokenHandler.js @@ -43,7 +43,8 @@ module.exports = (router) => { // Set the headers if they haven't been sent yet. if (!res.headersSent) { - res.setHeader('Access-Control-Expose-Headers', 'x-jwt-token'); + const headers = router.formio.hook.alter('accessControlExposeHeaders', 'x-jwt-token'); + res.setHeader('Access-Control-Expose-Headers', headers); res.setHeader('x-jwt-token', res.token); } }; @@ -121,7 +122,8 @@ module.exports = (router) => { } // Decode/refresh the token and store for later middleware. - jwt.verify(token, jwtConfig.secret, (err, decoded) => { + + jwt.verify(token, process.env.FORMIO_JWT_SECRET||jwtConfig.secret, (err, decoded) => { if (err || !decoded) { debug.handler(err || `Token could not decoded: ${token}`); router.formio.audit('EAUTH_TOKENBAD', req, err); diff --git a/forms-flow-forms/src/middleware/tokenVerify.js b/forms-flow-forms/src/middleware/tokenVerify.js new file mode 100644 index 0000000000..1cd3c1e99b --- /dev/null +++ b/forms-flow-forms/src/middleware/tokenVerify.js @@ -0,0 +1,72 @@ +'use strict'; + +const jwt = require("jsonwebtoken"); +const util = require('../util/util'); +const debug = { + error: require('debug')('formio:error'), + handler: require('debug')('formio:middleware:tokenHandler'), + }; + +module.exports=(router)=>{ + const hook = require('../util/hook')(router.formio); + const { + jwt: jwtConfig, + } = router.formio.config; + return (req, res, next) => { + if (req.user && req.token && res.token) { + return next(); + } + const token = util.getRequestValue(req, 'x-jwt-token'); + if (!token) { + return res.status(401).send("unauthorized"); + } + jwt.verify(token,process.env.FORMIO_JWT_SECRET||jwtConfig.secret, (err, decoded)=>{ + if (err || !decoded) { + debug.handler(err || `Token could not decoded: ${token}`); + router.formio.audit('EAUTH_TOKENBAD', req, err); + router.formio.log('Token', req, 'Token could not be decoded'); + // If the token has expired, send a 440 error (Login Timeout) + if (err && (err.name === 'JsonWebTokenError')) { + router.formio.log('Token', req, 'Bad Token'); + return res.status(400).send('Bad Token'); + } + else if (err && (err.name === 'TokenExpiredError')) { + router.formio.audit('EAUTH_TOKENEXPIRED', req, err); + router.formio.log('Token', req, 'Token Expired'); + return res.status(440).send('Token Expired'); + } + else { + res.status(401).send("unauthorized"); + } + } + hook.alter('tokenDecode', decoded, req, (err, decoded) => { + // Check to see if this token is allowed to access this path. + if (!router.formio.auth.isTokenAllowed(req, decoded)) { + res.status(401).send("unauthorized"); + } + + // If this is a temporary token, then decode it and set it in the request. + if (decoded.temp) { + router.formio.log('Token', req, 'Using temp token'); + debug.handler('Temp token'); + req.tempToken = decoded; + req.user = null; + req.token = null; + res.token = null; + return next(); + } + if (decoded.isAdmin) { + router.formio.log('Token', req, 'User is admin'); + if (req.user) { + router.formio.log('User', req, req.user._id); + } + req.permissionsChecked = true; + req.isAdmin = true; + req.token = decoded; + return next(); + } + }); + return next(); + }); +}; +}; diff --git a/forms-flow-forms/src/models/Action.js b/forms-flow-forms/src/models/Action.js index 7b9e47741b..aa3c031d72 100644 --- a/forms-flow-forms/src/models/Action.js +++ b/forms-flow-forms/src/models/Action.js @@ -117,5 +117,15 @@ module.exports = function(formio) { }); }; + // Execute a pre-save method for the SaveSubmission action. + Action.schema.pre('save', function(next) { + if (this.name === 'save') { + // Ensure that save actions with resource associations are always executed + // before the ones without resource association. + this.priority = (this.settings && this.settings.resource) ? 11 : 10; + } + next(); + }); + return Action; }; diff --git a/forms-flow-forms/src/models/ActionItem.js b/forms-flow-forms/src/models/ActionItem.js index 92c2b5eaad..34287e0847 100644 --- a/forms-flow-forms/src/models/ActionItem.js +++ b/forms-flow-forms/src/models/ActionItem.js @@ -28,15 +28,15 @@ module.exports = function(formio) { }, action: { type: String, - require: true + required: true }, handler: { type: String, - require: true + required: true }, method: { type: String, - require: true + required: true }, state: { type: String, @@ -57,5 +57,17 @@ module.exports = function(formio) { schema: ActionItemSchema }); + try { + model.schema.index({created: 1}, {expireAfterSeconds: 2592000}); + } + catch (err) { + console.log(err.message); + } + + // Add indexes to speed up the action items pages. + model.schema.index(hook.alter('schemaIndex', {state: 1, deleted: 1, modified: -1})); + model.schema.index(hook.alter('schemaIndex', {handler: 1, deleted: 1, modified: -1})); + model.schema.index(hook.alter('schemaIndex', {handler: 1, method: 1, deleted: 1, modified: -1})); + return model; }; diff --git a/forms-flow-forms/src/models/BaseModel.js b/forms-flow-forms/src/models/BaseModel.js index b55368d5b1..733aac5e4b 100644 --- a/forms-flow-forms/src/models/BaseModel.js +++ b/forms-flow-forms/src/models/BaseModel.js @@ -4,7 +4,7 @@ module.exports = (model) => { const timestamps = require('../plugins/timestamps'); // Add timestamps to the schema. - model.schema.plugin(timestamps, {index: true}); + model.schema.plugin(timestamps); // Disable removal of empty objects model.schema.set('minimize', false); diff --git a/forms-flow-forms/src/models/FieldMatchAccessPermissionSchema.js b/forms-flow-forms/src/models/FieldMatchAccessPermissionSchema.js index 44f34f5409..79de9b1ac6 100644 --- a/forms-flow-forms/src/models/FieldMatchAccessPermissionSchema.js +++ b/forms-flow-forms/src/models/FieldMatchAccessPermissionSchema.js @@ -8,11 +8,15 @@ module.exports = function(formio) { return new formio.mongoose.Schema(hook.alter('fieldMatchAccessPermissionSchema', { formFieldPath: { type: String, - required: true + required: function() { + return (typeof this.formFieldPath === 'string') ? false : true; + } }, value: { type: String, - required: true + required: function() { + return (typeof this.value === 'string') ? false : true; + } }, operator: { type: String, @@ -22,7 +26,9 @@ module.exports = function(formio) { valueType: { type: String, enum: ['string', 'number', 'boolean', '[string]', '[number]'], - required: true, + required: function() { + return (typeof this.valueType === 'string') ? false : true; + }, default: 'string', validate: [ { diff --git a/forms-flow-forms/src/models/Form.js b/forms-flow-forms/src/models/Form.js index 2cc6abfdc1..02c73d9be3 100644 --- a/forms-flow-forms/src/models/Form.js +++ b/forms-flow-forms/src/models/Form.js @@ -151,37 +151,11 @@ module.exports = (formio) => { type: { read: [formio.schemas.FieldMatchAccessPermissionSchema], write: [formio.schemas.FieldMatchAccessPermissionSchema], - ceate: [formio.schemas.FieldMatchAccessPermissionSchema], - admin: [formio.schemas.FieldMatchAccessPermissionSchema] + create: [formio.schemas.FieldMatchAccessPermissionSchema], + admin: [formio.schemas.FieldMatchAccessPermissionSchema], + delete: [formio.schemas.FieldMatchAccessPermissionSchema], + update: [formio.schemas.FieldMatchAccessPermissionSchema], }, - validate: [ - { - validator: function(accessLevels) { - const roles = {}; - Object.entries(accessLevels).forEach(([accessLevel, permissions]) => { - permissions.forEach((permission) => { - permission.roles.forEach((role) => { - if (!roles[role]) { - roles[role] = {}; - } - roles[role][accessLevel] = true; - }); - }); - }); - let errMsg = ''; - Object.entries(roles).forEach(([role, accessLevels]) => { - if (Object.keys(accessLevels).length > 1) { - const levelsWithTheSameRole = Object.keys(accessLevels).join(', '); - errMsg += `The ${role} role has an access on multiple levels: ${levelsWithTheSameRole} /n`; - } - }); - if (errMsg) { - throw new Error(errMsg); - } - return true; - } - } - ] }, owner: { type: formio.mongoose.Schema.Types.Mixed, @@ -250,6 +224,9 @@ module.exports = (formio) => { }) }); + model.schema.index(hook.alter('schemaIndex', {type: 1, deleted: 1, modified: -1})); + model.schema.index(hook.alter('schemaIndex', {name: 1, deleted: 1})); + // Add a partial index for deleted forms. model.schema.index({ deleted: 1 diff --git a/forms-flow-forms/src/models/Submission.js b/forms-flow-forms/src/models/Submission.js index 6db992a659..181f73ad51 100644 --- a/forms-flow-forms/src/models/Submission.js +++ b/forms-flow-forms/src/models/Submission.js @@ -83,6 +83,10 @@ module.exports = function(formio) { })) }); + model.schema.index(hook.alter('schemaIndex', {deleted: 1})); + model.schema.index(hook.alter('schemaIndex', {form: 1, deleted: 1})); + model.schema.index(hook.alter('schemaIndex', {form: 1, deleted: 1, created: -1})); + // Ensure that all _id's within the data are ObjectId's model.schema.pre('save', function(next) { utils.ensureIds(this.data); @@ -98,6 +102,8 @@ module.exports = function(formio) { // Add a "recommmended" combined index. model.schema.index({ + "data.process_pid ": 1, + "data.applicationId": 1, form: 1, deleted: 1, created: -1 diff --git a/forms-flow-forms/src/models/Token.js b/forms-flow-forms/src/models/Token.js index f3c4511b97..89becfe2cd 100644 --- a/forms-flow-forms/src/models/Token.js +++ b/forms-flow-forms/src/models/Token.js @@ -14,6 +14,7 @@ module.exports = (formio) => { const TokenSchema = hook.alter('tokenSchema', new formio.mongoose.Schema({ key: { type: String, + index: true, required: true, default: () => chance.string({ pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', @@ -51,7 +52,12 @@ module.exports = (formio) => { }, })); - TokenSchema.index({expireAt: 1}, {expireAfterSeconds: 0}); + try { + TokenSchema.index({expireAt: 1}, {expireAfterSeconds: 0}); + } + catch (err) { + console.log(err.message); + } const model = require('./BaseModel')({ schema: TokenSchema, diff --git a/forms-flow-forms/src/plugins/timestamps.js b/forms-flow-forms/src/plugins/timestamps.js index 83b3ebae39..2d6d9dd576 100644 --- a/forms-flow-forms/src/plugins/timestamps.js +++ b/forms-flow-forms/src/plugins/timestamps.js @@ -1,15 +1,17 @@ 'use strict'; -module.exports = (schema, options = {}) => { +module.exports = (schema) => { + const created = { + type: Date, + index: true, + description: 'The date this resource was created.', + default: Date.now, + __readonly: true, + }; + // Add the created and modified params. schema.add({ - created: { - type: Date, - index: true, - description: 'The date this resource was created.', - default: Date.now, - __readonly: true, - }, + created, modified: { type: Date, index: true, @@ -18,12 +20,6 @@ module.exports = (schema, options = {}) => { }, }); - // If we wish to make these an index. - if (options.index) { - schema.path('created').index(options.index); - schema.path('modified').index(options.index); - } - // On pre-save, we will update the modified date. schema.pre('save', function(next) { this.modified = new Date(); diff --git a/forms-flow-forms/src/resources/FormResource.js b/forms-flow-forms/src/resources/FormResource.js index 39d7c3e861..89755cad0e 100644 --- a/forms-flow-forms/src/resources/FormResource.js +++ b/forms-flow-forms/src/resources/FormResource.js @@ -76,18 +76,16 @@ module.exports = function(router) { after: [ sanitizeValidations, router.formio.middleware.bootstrapFormAccess, + router.formio.middleware.revisionLoader, router.formio.middleware.formLoader, router.formio.middleware.formActionHandler('after'), router.formio.middleware.filterResourcejsResponse(['deleted', '__v']), - router.formio.middleware.filterIndex(['components']) + router.formio.middleware.filterIndex(['components', 'properties']) ], hooks: { put: { before(req, res, item, next) { - if (item.components) { - item.markModified('components'); - } - + util.markModifiedParameters(item, ['components', 'properties']); return next(); } } diff --git a/forms-flow-forms/src/resources/LegacyValidator.js b/forms-flow-forms/src/resources/LegacyValidator.js deleted file mode 100644 index 4bde77a0e5..0000000000 --- a/forms-flow-forms/src/resources/LegacyValidator.js +++ /dev/null @@ -1,1111 +0,0 @@ -'use strict'; - -const vm = require('vm'); -const Joi = require('joi'); -const _ = require('lodash'); -const moment = require('moment'); -const cache = require('memory-cache'); -const querystring = require('querystring'); -const util = require('../util/util'); - -const debug = { - validator: require('debug')('formio:validator'), - error: require('debug')('formio:error') -}; - -let hook = null; - -const getErrorMessage = (component, message) => { - return _.get(component, 'validate.customMessage', message); -}; - -/* - * Returns true or false based on visibility. - * - * @param {Object} component - * The form component to check. - * @param {Object} row - * The local data to check. - * @param {Object} data - * The full submission data. - */ -const checkConditional = (form, component, row, data, recurse = false) => { - let isVisible = true; - - if (!component || !component.hasOwnProperty('key')) { - return isVisible; - } - - // Custom conditional logic. Need special case so the eval is isolated in a sandbox - if (component.customConditional) { - try { - // Create the sandbox. - const sandbox = vm.createContext(hook.alter('evalContext', { - data, - row, - component, - moment, - _, - form - }, form)); - - // Execute the script. - const script = new vm.Script(component.customConditional); - script.runInContext(sandbox, { - timeout: 250 - }); - - if (util.isBoolean(sandbox.show)) { - isVisible = util.boolean(sandbox.show); - } - } - catch (e) { - debug.validator('Custom Conditional Error: '); - debug.validator(e); - debug.error(e); - } - } - else { - try { - isVisible = util.checkCondition(component, row, data); - } - catch (err) { - debug.error(err); - } - } - - // If visible and recurse, continue down tree to check parents. - if (isVisible && recurse && component.parent.type !== 'form') { - return !component.parent || checkConditional(form, component.parent, row, data, true); - } - else { - return isVisible; - } -}; - -const getRules = (type) => [ - { - name: 'custom', - params: { - component: Joi.any(), - data: Joi.any(), - form: Joi.any(), - }, - validate(params, value, state, options) { - const {component, data, form} = params; - - let row = state.parent; - let valid = true; - - if (!_.isArray(row)) { - row = [row]; - } - - // If a component has multiple rows of data, e.g. Datagrids, validate each row of data on the backend. - for (let b = 0; b < row.length; b++) { - const _row = row[b]; - - // Try a new sandboxed validation. - try { - // Replace with variable substitutions. - const replace = /({{\s{0,}(.*[^\s]){1}\s{0,}}})/g; - component.validate.custom = component.validate.custom.replace(replace, (match, $1, $2) => _.get(data, $2)); - - // Create the sandbox. - const sandbox = vm.createContext(hook.alter('evalContext', { - input: _.isObject(_row) ? util.getValue({data: _row}, component.key) : _row, - data, - row: _row, - scope: {data}, - component: component, - valid, - form, - _, - moment, - }, form)); - - // Execute the script. - const script = new vm.Script(component.validate.custom); - script.runInContext(sandbox, { - timeout: 100 - }); - valid = sandbox.valid; - } - catch (err) { - // Say this isn't valid based on bad code executed... - valid = err.toString(); - } - - // If there is an error, then set the error object and break from iterations. - if (valid !== true) { - return this.createError(`${type}.custom`, {message: valid}, state, options); - } - } - - return value; // Everything is OK - } - }, - { - name: 'json', - params: { - component: Joi.any(), - data: Joi.any() - }, - validate(params, value, state, options) { - const component = params.component; - const data = params.data; - let row = state.parent; - let valid = true; - - if (!_.isArray(row)) { - row = [row]; - } - - // If a component has multiple rows of data, e.g. Datagrids, validate each row of data on the backend. - for (let b = 0; b < row.length; b++) { - const _row = row[b]; - - try { - valid = util.jsonLogic.apply(component.validate.json, { - data, - row: _row - }); - } - catch (err) { - valid = err.message; - } - - // If there is an error, then set the error object and break from iterations. - if (valid !== true) { - return this.createError(`${type}.json`, {message: valid}, state, options); - } - } - - return value; // Everything is OK - } - }, - { - name: 'hidden', - params: { - component: Joi.any(), - data: Joi.any(), - form: Joi.any(), - }, - validate(params, value, state, options) { - // If we get here than the field has thrown an error. - // If we are hidden, sanitize the data and return true to override the error. - // If not hidden, return an error so the original error remains on the field. - - const {component, data, form} = params; - const row = state.parent; - const isVisible = checkConditional(form, component, row, data, true); - - if (isVisible) { - return value; - } - - return this.createError(`${type}.hidden`, {message: 'hidden with value'}, state, options); - } - }, - { - name: 'maxWords', - params: { - maxWords: Joi.any() - }, - validate(params, value, state, options) { - if (value.trim().split(/\s+/).length <= parseInt(params.maxWords, 10)) { - return value; - } - - return this.createError(`${type}.maxWords`, {message: 'exceeded maximum words.'}, state, options); - } - }, - { - name: 'minWords', - params: { - minWords: Joi.any() - }, - validate(params, value, state, options) { - if (value.trim().split(/\s+/).length >= parseInt(params.minWords, 10)) { - return value; - } - - return this.createError(`${type}.minWords`, {message: 'does not have enough words.'}, state, options); - } - }, - { - name: 'select', - params: { - component: Joi.any(), - submission: Joi.any(), - token: Joi.any(), - async: Joi.any(), - requests: Joi.any() - }, - validate(params, value, state, options) { - // Empty values are fine. - if (!value) { - return value; - } - - const component = params.component; - const submission = params.submission; - const token = params.token; - const async = params.async; - const requests = params.requests; - - // Initialize the request options. - let url = _.get(component, 'validate.select'); - const method = 'GET'; - const query = {}; - const headers = {}; - - // If the url is a boolean value. - if (util.isBoolean(url)) { - url = util.boolean(url); - if (!url) { - return value; - } - - if (component.dataSrc !== 'url') { - return value; - } - - if (!component.data.url || !component.searchField) { - return value; - } - - // Get the validation url. - url = component.data.url; - - // Add the search field. - query[component.searchField] = value; - - // Add the filters. - if (component.filter) { - url += (!url.includes('?') ? '?' : '&') + component.filter; - } - - // If they only wish to return certain fields. - if (component.selectFields) { - query.select = component.selectFields; - } - } - - if (!url) { - return value; - } - - url += (!url.includes('?') ? '?' : '&') + querystring.stringify(query); - - // Make sure to interpolate. - url = util.FormioUtils.interpolate(url, { - data: submission.data - }); - - // Set custom headers. - if (component.data && component.data.headers) { - _.each(component.data.headers, (header) => { - if (header.key) { - headers[header.key] = header.value; - } - }); - } - - // Set form.io authentication. - if (component.authenticate && token) { - headers['x-jwt-token'] = token; - } - - async.push(new Promise((resolve, reject) => { - const cacheKey = `${method}:${url}`; - const cacheTime = (process.env.VALIDATOR_CACHE_TIME || (3 * 60)) * 60 * 1000; - - // Check if this request was cached - const result = cache.get(cacheKey); - if (result !== null) { - debug.validator(cacheKey, 'hit!'); - // Null means no cache hit but is also used as a success callback which we are faking with true here. - if (result === true) { - return resolve(null); - } - else { - return resolve(result); - } - } - debug.validator(cacheKey, 'miss'); - - // Us an existing promise or create a new one. - requests[cacheKey] = requests[cacheKey] || util.fetch(url, {method, headers}) - .then((res) => (res.ok ? res.json() : null)); - - requests[cacheKey] - .then(body => { - if (!body || !body.length) { - const error = { - message: `"${value}" for "${component.label || component.key}" is not a valid selection.`, - path: state.path, - type: 'any.select' - }; - cache.put(cacheKey, error, cacheTime); - return resolve(error); - } - - cache.put(cacheKey, true, cacheTime); - return resolve(null); - }) - .catch(result => { - const error = { - message: `Select validation error: ${result.error}`, - path: state.path, - type: 'any.select' - }; - cache.put(cacheKey, error, cacheTime); - return resolve(error); - }); - })); - - return value; - } - }, - { - name: 'distinct', - params: { - component: Joi.any(), - submission: Joi.any(), - model: Joi.any(), - async: Joi.any() - }, - validate(params, value, state, options) { - const component = params.component; - const submission = params.submission; - const model = params.model; - const async = params.async; - - const path = `data.${state.path.join('.')}`; - - // Allow empty. - if (!value) { - return value; - } - if (_.isEmpty(value)) { - return value; - } - - // Get the query. - const query = {form: util.idToBson(submission.form)}; - if (_.isString(value)) { - query[path] = {$regex: new RegExp(`^${util.escapeRegExp(value)}$`), $options: 'i'}; - } - // FOR-213 - Pluck the unique location id - else if ( - !_.isString(value) && - value.hasOwnProperty('address_components') && - value.hasOwnProperty('place_id') - ) { - query[`${path}.place_id`] = {$regex: new RegExp(`^${util.escapeRegExp(value.place_id)}$`), $options: 'i'}; - } - // Compare the contents of arrays vs the order. - else if (_.isArray(value)) { - query[path] = {$all: value}; - } - else if (_.isObject(value)) { - query[path] = {$eq: value}; - } - - // Only search for non-deleted items. - if (!query.hasOwnProperty('deleted')) { - query['deleted'] = {$eq: null}; - } - - async.push(new Promise((resolve, reject) => { - // Try to find an existing value within the form. - model.findOne(query, (err, result) => { - if (err) { - return resolve({ - message: getErrorMessage(component, err), - path: state.path, - type: 'any.unique' - }); - } - else if (result && submission._id && (result._id.toString() === submission._id)) { - // This matches the current submission which is allowed. - return resolve(null); - } - else if (result) { - return resolve({ - message: getErrorMessage(component, `"${component.label}" must be unique.`), - path: state.path, - type: 'any.unique' - }); - } - return resolve(null); - }); - })); - - return value; // Everything is OK - } - } -]; - -const JoiX = Joi.extend([ - { - name: 'any', - language: { - custom: '{{message}}', - json: '{{message}}', - hidden: '{{message}}', - select: '{{message}}', - distinct: '{{message}}' - }, - rules: getRules('any') - }, - { - name: 'string', - base: Joi.string(), - language: { - custom: '{{message}}', - maxWords: '{{message}}', - minWords: '{{message}}', - json: '{{message}}', - hidden: '{{message}}', - select: '{{message}}', - distinct: '{{message}}' - }, - rules: getRules('string') - }, - { - name: 'array', - base: Joi.array(), - language: { - custom: '{{message}}', - json: '{{message}}', - hidden: '{{message}}', - select: '{{message}}', - distinct: '{{message}}' - }, - rules: getRules('array') - }, - { - name: 'object', - base: Joi.object(), - language: { - custom: '{{message}}', - json: '{{message}}', - hidden: '{{message}}', - select: '{{message}}', - distinct: '{{message}}' - }, - rules: getRules('object') - }, - { - name: 'number', - base: Joi.number(), - language: { - custom: '{{message}}', - json: '{{message}}', - hidden: '{{message}}', - select: '{{message}}', - distinct: '{{message}}' - }, - rules: getRules('number') - }, - { - name: 'boolean', - base: Joi.boolean(), - language: { - custom: '{{message}}', - json: '{{message}}', - hidden: '{{message}}', - select: '{{message}}', - distinct: '{{message}}' - }, - rules: getRules('boolean') - }, - { - name: 'date', - base: Joi.date(), - language: { - custom: '{{message}}', - json: '{{message}}', - hidden: '{{message}}', - select: '{{message}}', - distinct: '{{message}}' - }, - rules: getRules('date') - } -]); - -/** - * @TODO: Add description. - * - * @param form - * @param model - * @constructor - */ -class Validator { - constructor(form, model, token, decodedToken) { - this.model = model; - this.async = []; - this.requests = {}; - this.form = form; - this.token = token; - this.decodedToken = decodedToken; - } - - /** - * Returns a validator per component. - * - * @param {Object} schema - * The validation schema to modify. - * @param {Object} component - * The form component. - * @param {Object} componentData - * The submission data corresponding to this component. - */ - buildSchema(schema, components, componentData, submission) { - if (!Array.isArray(components)) { - return schema; - } - // Add a validator for each component in the form, with its componentData. - /* eslint-disable max-statements */ - components.forEach((component) => { - let fieldValidator = null; - let componentKey = component.key; - - this.applyLogic(component, componentData, submission.data); - this.calculateValue(component, componentData, submission.data, submission); - - // The value is persistent if it doesn't say otherwise or explicitly says so. - const isPersistent = !component.hasOwnProperty('persistent') || component.persistent; - - let objectSchema; - const stringValidators = { - minLength: 'min', - maxLength: 'max', - minWords: 'minWords', - maxWords: 'maxWords' - }; - /* eslint-disable max-depth, valid-typeof */ - switch (component.type) { - case 'form': { - // Ensure each sub submission at least has an empty object or it won't validate. - _.update(componentData, `${component.key}.data`, value => value ? value : {}); - - const subSubmission = _.get(componentData, component.key, {}); - - // If this has already been submitted, then it has been validated. - if (!subSubmission._id && component.components) { - const formSchema = this.buildSchema( - {}, - component.components, - subSubmission, - subSubmission - ); - fieldValidator = JoiX.object().unknown(true).keys({ - data: JoiX.object().keys(formSchema) - }); - } - else { - fieldValidator = JoiX.object(); - } - break; - } - case 'dynamicWizard': - case 'editgrid': - case 'datagrid': - component.multiple = false; - objectSchema = this.buildSchema( - {}, - component.components, - _.get(componentData, component.key, componentData), - submission - ); - - fieldValidator = JoiX.array().items(JoiX.object().keys(objectSchema)).options({stripUnknown: false}); - break; - case 'tagpad': - objectSchema = this.buildSchema( - {}, - component.components, - _.get(componentData, component.key, componentData).map(dot => dot.data), - submission - ); - fieldValidator = JoiX.array().items(JoiX.object({ - coordinate: JoiX.object({ - x: JoiX.number(), - y: JoiX.number(), - width: JoiX.number(), - height: JoiX.number() - }), - data: JoiX.object().keys(objectSchema) - })).options({stripUnknown: false}); - break; - case 'tree': - objectSchema = this.buildSchema( - {}, - component.components, - _.get(componentData, component.key, componentData).data, - submission - ); - fieldValidator = JoiX.object({ - data: JoiX.object().keys(objectSchema), - children: JoiX.array().items(JoiX.lazy(() => fieldValidator)) - }).options({stripUnknown: false}); - break; - case 'container': - objectSchema = this.buildSchema( - {}, - component.components, - _.get(componentData, component.key, componentData), - submission - ); - - fieldValidator = JoiX.object().keys(objectSchema); - break; - case 'address': - objectSchema = this.buildSchema( - {}, - component.components, - componentData, - submission - ); - - fieldValidator = fieldValidator || JoiX.any(); - break; - case 'fieldset': - case 'panel': - case 'well': - this.buildSchema(schema, component.components, componentData, submission); - break; - case 'table': - if (!Array.isArray(component.rows)) { - break; - } - component.rows.forEach((row) => { - if (!Array.isArray(row)) { - return; - } - row.forEach((column) => { - this.buildSchema(schema, column.components, componentData, submission); - }); - }); - break; - case 'columns': - if (!Array.isArray(component.columns)) { - break; - } - component.columns.forEach((column) => { - this.buildSchema(schema, column.components, componentData, submission); - }); - break; - case 'textfield': - case 'textarea': - case 'phonenumber': - if (component.as === 'json') { - fieldValidator = JoiX.object(); - } - else { - fieldValidator = JoiX.string().allow(''); - for (const name in stringValidators) { - const funcName = stringValidators[name]; - if ( - component.validate && - component.validate.hasOwnProperty(name) && - _.isNumber(component.validate[name]) && - component.validate[name] >= 0 - ) { - fieldValidator = fieldValidator[funcName](component.validate[name]); - } - } - } - break; - case 'select': - if (component.validate && component.validate.select) { - fieldValidator = JoiX.any().select(component, submission, this.token, this.async, this.requests); - } - fieldValidator = fieldValidator || JoiX.any(); - break; - case 'email': - fieldValidator = JoiX.string().email().allow(''); - break; - case 'number': - fieldValidator = JoiX.number().empty(null); - if (component.validate) { - // If the step is provided... we can infer float vs. integer. - if (component.validate.step && (component.validate.step !== 'any')) { - const parts = component.validate.step.split('.'); - if (parts.length === 1) { - fieldValidator = fieldValidator.integer(); - } - else { - fieldValidator = fieldValidator.precision(parts[1].length); - } - } - - _.each(['min', 'max', 'greater', 'less'], (check) => { - if (component.validate.hasOwnProperty(check) && _.isNumber(component.validate[check])) { - fieldValidator = fieldValidator[check](component.validate[check]); - } - }); - } - break; - case 'signature': - fieldValidator = JoiX.string().allow(''); - break; - case 'checkbox': - if (component.name && !_.find(components, ['key', component.name])) { - componentKey = component.name; - } - fieldValidator = fieldValidator || JoiX.any(); - break; - default: - // Allow custom components to have subcomponents as well (like layout components). - if (component.components && Array.isArray(component.components)) { - if (component.tree) { - objectSchema = this.buildSchema( - {}, - component.components, - _.get(componentData, component.key, componentData), - submission - ); - fieldValidator = JoiX.object().keys(objectSchema); - } - else { - this.buildSchema( - schema, - component.components, - componentData, - submission - ); - } - } - fieldValidator = fieldValidator || JoiX.any(); - break; - } - /* eslint-enable max-depth, valid-typeof */ - - if (componentKey && (componentKey.indexOf('.') === -1) && component.validate) { - // Add required validator. - if (component.validate.required) { - fieldValidator = fieldValidator.required().empty().disallow('', null); - } - - // Add regex validator - if (component.validate.pattern) { - try { - const regex = new RegExp(component.validate.pattern); - fieldValidator = fieldValidator.regex(regex); - } - catch (err) { - debug.error(err); - } - } - - // Add the custom validations. - if (component.validate && component.validate.custom) { - fieldValidator = fieldValidator.custom(component, submission.data, this.form); - } - - // Add the json logic validations. - if (component.validate && component.validate.json) { - fieldValidator = fieldValidator.json(component, submission.data); - } - } - - // If the value must be unique. - if (component.unique) { - fieldValidator = fieldValidator.distinct(component, submission, this.model, this.async); - } - - //if multiple masks input, then data is object with 'value' field, and validation should be applied to that field - if (component.allowMultipleMasks) { - fieldValidator = JoiX.object().keys({ - value: fieldValidator, - maskName: JoiX.string() - }); - //additionally apply required rule to the field itself - if (component.validate && component.validate.required) { - fieldValidator = fieldValidator.required(); - } - } - - // Make sure to change this to an array if multiple is checked or component type is file. - if (component.multiple || component.type === 'file') { - // Allow(null) was added since some text fields have empty strings converted to null when multiple which then - // throws an error on re-validation. Allowing null fixes the issue. - fieldValidator = JoiX.array().sparse().items(fieldValidator.allow(null)).options({stripUnknown: false}); - if (component.validate) { - // If a multi-value is required, make sure there is at least one. - if (component.validate.required && !component.validate.minItems) { - fieldValidator = fieldValidator.min(1).required(); - } - else if (component.validate.minItems) { - fieldValidator = fieldValidator.min(component.validate.minItems).required(); - } - if (component.validate.maxItems) { - fieldValidator = fieldValidator.max(component.validate.maxItems); - } - } - } - - // Only run validations for persistent fields. - if (componentKey && fieldValidator && isPersistent) { - schema[componentKey] = fieldValidator.hidden(component, submission.data, this.form); - } - }); - /* eslint-enable max-statements */ - - return schema; - } - - static setHook(_hook) { - hook = _hook; - } - - evalContext(context) { - context.form = this.form; - return hook.alter('evalContext', context, this.form); - } - - applyLogic(component, row, data) { - if (!Array.isArray(component.logic)) { - return; - } - - component.logic.forEach((logic) => { - if (!Array.isArray(logic.actions)) { - return; - } - - const result = util.FormioUtils.checkTrigger(component, logic.trigger, row, data); - if (result) { - logic.actions.forEach((action) => { - switch (action.type) { - case 'property': - util.FormioUtils.setActionProperty(component, action, result, row, data); - break; - case 'value': - try { - // Create the sandbox. - const sandbox = vm.createContext(this.evalContext({ - value: _.get(row, component.key), - data, - row, - component, - token: this.decodedToken, - result, - })); - - // Execute the script. - const script = new vm.Script(action.value); - script.runInContext(sandbox, { - timeout: 250, - }); - - _.set(row, component.key, sandbox.value); - } - catch (e) { - debug.validator('Custom Logic Error: '); - debug.validator(e); - debug.error(e); - } - break; - case 'mergeComponentSchema': { - const sandbox = vm.createContext(this.evalContext({ - value: _.get(row, component.key), - data, - row, - component, - result, - })); - - const script = new vm.Script(action.schemaDefinition); - script.runInContext(sandbox, { - timeout: 250, - }); - - _.assign(component, sandbox.schema); - - break; - } - } - }); - } - }); - } - - calculateValue(component, row, data, submission) { - if (component.calculateServer && component.calculateValue) { - if (_.isString(component.calculateValue)) { - try { - const sandbox = vm.createContext(this.evalContext({ - value: _.get(row, component.key), - form: this.form, - submission, - data, - row, - component, - util, - utils: util, - moment, - _, - token: this.decodedToken, - })); - - // Execute the script. - const script = new vm.Script(component.calculateValue); - script.runInContext(sandbox, { - timeout: 250 - }); - - _.set(row, component.key, sandbox.value); - } - catch (e) { - debug.error(e); - } - } - else { - try { - _.set(row, component.key, util.jsonLogic(component.calculateValue, { - form: this.form, - submission, - data, - row, - component, - util, - utils: util, - moment, - _, - token: this.decodedToken, - })); - } - catch (e) { - debug.error(e); - } - } - } - } - - /** - * Validate a submission for a form. - * - * @param {Object} submission - * The data submission object. - * @param next - * The callback function to pass the results. - */ - /* eslint-disable max-statements */ - validate(submission, next) { - debug.validator('Starting validation'); - - // Skip validation if no data is provided. - if (!submission.data) { - debug.validator('No data skipping validation'); - debug.validator(submission); - return next(); - } - - // Build the JoiX validation schema. - let schema = { - // Start off with the _id key. - _id: JoiX.string().meta({primaryKey: true}) - }; - - // Create the validator schema. - schema = JoiX.object().keys(this.buildSchema(schema, this.form.components, submission.data, submission)); - - // Iterate the list of components one time to build the path map. - const components = {}; - util.eachComponent(this.form.components, (component, path) => { - if (component.hasOwnProperty('key')) { - components[path] = component; - } - }, true, '', true); - - JoiX.validate(submission.data, schema, {stripUnknown: true, abortEarly: false}, (validateErr, value) => { - // Wait for all async validators to complete and add any errors. - Promise.all(this.async).then(errors => { - errors = errors.filter(item => item); - // Add in any asyncronous errors. - if (errors.length) { - if (!validateErr) { - validateErr = new Error('Validation failed'); - validateErr.name = 'ValidationError'; - validateErr.details = errors; - } - else { - validateErr.details = validateErr.details.concat(errors); - } - } - if (validateErr) { - // Remove any conditionally hidden validations. Joi will still throw the errors but we don't want them since the - // fields are hidden. - validateErr.details = validateErr.details.filter((detail) => { - let result = { - hidden: false - }; - if (detail.type.includes('.hidden')) { - const component = components[detail.path.filter(isNaN).join('.')]; - - const clearOnHide = util.isBoolean(_.get(component, 'clearOnHide')) ? - util.boolean(_.get(component, 'clearOnHide')) : true; - - if (clearOnHide) { - _.unset(value, detail.path); - } - - result.hidden = true; - } - else { - // Walk up the path tree to determine if the component is hidden. - result = detail.path.reduce((result, key) => { - result.path.push(key); - - const component = components[result.path.filter(isNaN).join('.')]; - - // Form "data" keys don't have components. - if (component) { - result.hidden = result.hidden || - !checkConditional(this.form, component, - _.get(value, result.path.slice(0, result.path.length - 1), value), result.submission, true); - - const clearOnHide = util.isBoolean(_.get(component, 'clearOnHide')) ? - util.boolean(_.get(component, 'clearOnHide')) : true; - - if (clearOnHide && result.hidden) { - _.unset(value, result.path); - } - } - else { - // Since this is a subform, change the submission object going to the conditionals. - result.submission = _.get(value, result.path); - } - - return result; - }, {path: [], hidden: false, submission: value}); - } - - return !result.hidden; - }); - - // Only throw error if there are still errors. - if (validateErr.details.length) { - validateErr._validated = value; - - return next(validateErr); - } - else { - validateErr._object = value; - } - } - - submission.data = value; - next(null, value); - }); - }); - } - /* eslint-enable max-statements */ -} - -module.exports = Validator; diff --git a/forms-flow-forms/src/resources/SubmissionResource.js b/forms-flow-forms/src/resources/SubmissionResource.js index d99394f9e9..bcd53a6f6c 100644 --- a/forms-flow-forms/src/resources/SubmissionResource.js +++ b/forms-flow-forms/src/resources/SubmissionResource.js @@ -120,13 +120,26 @@ module.exports = (router) => { if (!submission || !submission._id) { return res.status(404).send('Not found'); } - - // Send only the id as a response if the submission exists. - return res.status(200).json({ - _id: submission._id.toString(), - }); + // By default check permissions to access the endpoint. + const withoutPermissions = _.get(form, 'settings.allowExistsEndpoint', false); + + if (withoutPermissions) { + // Send only the id as a response if the submission exists. + return res.status(200).json({ + _id: submission._id.toString(), + }); + } + else { + req.subId = submission._id.toString(); + req.permissionsChecked = false; + return next(); + } }); }); + }, router.formio.middleware.permissionHandler, (req, res, next) => { + return res.status(200).json({ + _id: req.subId, + }); }); class SubmissionResource extends Resource { diff --git a/forms-flow-forms/src/resources/Validator.js b/forms-flow-forms/src/resources/Validator.js index 6646771134..d8a72cd0b7 100644 --- a/forms-flow-forms/src/resources/Validator.js +++ b/forms-flow-forms/src/resources/Validator.js @@ -63,14 +63,18 @@ class Validator { const emptyData = _.isEmpty(submission.data); let unsetsEnabled = false; + const {validateReCaptcha} = this; + // Create the form, then check validity. Formio.createForm(this.form, { server: true, + noDefaults: true, hooks: { setDataValue: function(value, key, data) { if (!unsetsEnabled) { return value; } + // Check if this component is not persistent. if (this.component.hasOwnProperty('persistent') && (!this.component.persistent || this.component.persistent === 'client-only') @@ -90,7 +94,14 @@ class Validator { unsets.push({key, data}); } return value; - } + }, + validateReCaptcha(responseToken) { + if (validateReCaptcha) { + return validateReCaptcha(responseToken); + } + + return true; + }, } }).then((form) => { // Set the validation config. @@ -105,8 +116,8 @@ class Validator { form.data = submission.data; // Perform calculations and conditions. - form.calculateValue(); form.checkConditions(); + form.calculateValue(); // Reset the data form.data = {}; @@ -134,6 +145,11 @@ class Validator { return next(null, submission.data, visibleComponents); } + if (form.form.display === 'wizard') { + // Wizard errors object contains all wizard errors only on last page + form.page = form.pages.length - 1; + } + const details = []; form.errors.forEach((error) => error.messages.forEach((message) => details.push(message))); diff --git a/forms-flow-forms/src/templates/default.json b/forms-flow-forms/src/templates/default.json index 6fd80fbf8a..02fe53e083 100644 --- a/forms-flow-forms/src/templates/default.json +++ b/forms-flow-forms/src/templates/default.json @@ -516,5 +516,31 @@ "lockWait": 1800 } } - } + }, + "access": [ + { + "type": "create_all", + "roles": [ + "administrator" + ] + }, + { + "type": "read_all", + "roles": [ + "administrator" + ] + }, + { + "type": "update_all", + "roles": [ + "administrator" + ] + }, + { + "type": "delete_all", + "roles": [ + "administrator" + ] + } + ] } diff --git a/forms-flow-forms/src/templates/empty.json b/forms-flow-forms/src/templates/empty.json index 6fe2129eab..4c5df4d0ad 100644 --- a/forms-flow-forms/src/templates/empty.json +++ b/forms-flow-forms/src/templates/empty.json @@ -25,5 +25,31 @@ }, "forms": {}, "actions": {}, - "resources": {} + "resources": {}, + "access": [ + { + "type": "create_all", + "roles": [ + "administrator" + ] + }, + { + "type": "read_all", + "roles": [ + "administrator" + ] + }, + { + "type": "update_all", + "roles": [ + "administrator" + ] + }, + { + "type": "delete_all", + "roles": [ + "administrator" + ] + } + ] } diff --git a/forms-flow-forms/src/templates/import.js b/forms-flow-forms/src/templates/import.js index 40f9892170..06852232aa 100644 --- a/forms-flow-forms/src/templates/import.js +++ b/forms-flow-forms/src/templates/import.js @@ -35,6 +35,13 @@ module.exports = (router) => { */ const baseAlter = (item, template, done) => done(null, item); + const updateRevisionProperty = (item, newValue) => { + if (item.hasOwnProperty('formRevision')) { + item.formRevision = newValue; + } + item.revision = newValue; + }; + /** * Converts an entities role id (machineName) to bson id. * @@ -46,8 +53,8 @@ module.exports = (router) => { * @returns {boolean} * Whether or not the conversion was successful. */ - const roleMachineNameToId = (template, entity) => { - if (!entity || !template.hasOwnProperty(`roles`)) { + const roleMachineNameToId = (template, entity, fallbacks = []) => { + if (!entity) { return false; } @@ -57,10 +64,13 @@ module.exports = (router) => { entity.role = EVERYONE; return true; } - else if (template.roles.hasOwnProperty(entity.role)) { + else if (template.roles && template.roles.hasOwnProperty(entity.role)) { entity.role = template.roles[entity.role]._id.toString(); return true; } + else { + fallbacks.push(entity); + } } return false; @@ -70,23 +80,23 @@ module.exports = (router) => { // Used for permissions arrays. _.each(entity, (access) => { + let accessPushedToFallback = false; _.each(access.roles, (role, i) => { if (role === 'everyone') { access.roles[i] = EVERYONE; changes = true; } - else if (template.roles.hasOwnProperty(role) && template.roles[role]._id) { + else if (template.roles && template.roles.hasOwnProperty(role) && template.roles[role]._id) { access.roles[i] = template.roles[role]._id.toString(); changes = true; } else { - // Remove any unknown roles, they should always be known at this point of the import. - delete access.roles[i]; + if (!accessPushedToFallback) { + fallbacks.push(access); + } + accessPushedToFallback = true; } }); - - // Filter any unknown roles from the pruning process. - access.roles = _.filter(access.roles); }); return changes; @@ -111,14 +121,14 @@ module.exports = (router) => { if (template.hasOwnProperty(`forms`) && template.forms.hasOwnProperty(entity.form)) { entity.form = template.forms[formName]._id.toString(); if (template.forms[formName].hasOwnProperty('_vid') && template.forms[formName]._vid) { - entity.formRevision = template.forms[formName]._vid.toString(); + updateRevisionProperty(entity, template.forms[formName]._vid.toString()); } return true; } if (template.hasOwnProperty(`resources`) && template.resources.hasOwnProperty(entity.form)) { entity.form = template.resources[formName]._id.toString(); if (template.resources[formName].hasOwnProperty('_vid') && template.resources[formName]._vid) { - entity.formRevision = template.resources[formName]._vid.toString(); + updateRevisionProperty(entity, template.resources[formName]._vid.toString()); } return true; } @@ -126,7 +136,7 @@ module.exports = (router) => { return false; }; - const setFormProperty = (template, entity) => { + const setFormProperty = (template, entity, fallbacks) => { if ( !entity || !entity.form || @@ -144,26 +154,32 @@ module.exports = (router) => { const formName = entity.form; // Attempt to add a form. - if (template.forms && template.forms[entity.form] && template.forms[entity.form]._id) { - entity.form = template.forms[formName]._id.toString(); - if (template.forms[formName].hasOwnProperty('_vid') && template.forms[formName]._vid) { - entity.formRevision = template.forms[formName]._vid.toString(); + if (template.forms && template.forms[entity.form]) { + // Form has been already imported + if (template.forms[entity.form]._id) { + entity.form = template.forms[formName]._id.toString(); + if (template.forms[formName].hasOwnProperty('_vid') && template.forms[formName]._vid) { + updateRevisionProperty(entity, template.forms[formName]._vid.toString()); + } + else if (template.forms[formName].revisions) { + // Make sure revision is set if revisions are enabled on the form + updateRevisionProperty(entity, getFormRevision(template.forms[formName]._vid)); + } + changes = true; } - else if (template.forms[formName].revisions) { - // Make sure revision is set if revisions are enabled on the form - entity.formRevision = getFormRevision(template.forms[formName]._vid); + else { + fallbacks.push(entity); } - changes = true; } // Attempt to add a resource if (!changes && template.resources && template.resources[entity.form] && template.resources[entity.form]._id) { entity.form = template.resources[entity.form]._id.toString(); if (template.resources[formName].hasOwnProperty('_vid') && template.resources[formName]._vid) { - entity.formRevision = template.resources[formName]._vid.toString(); + updateRevisionProperty(entity, template.resources[formName]._vid.toString()); } else if (template.resources[formName].revisions) { - entity.formRevision = getFormRevision(template.resources[formName]._vid); + updateRevisionProperty(entity, getFormRevision(template.resources[formName]._vid)); } changes = true; } @@ -224,7 +240,7 @@ module.exports = (router) => { * @returns {boolean} * Whether or not the any changes were made. */ - const componentMachineNameToId = (template, components) => { + const componentMachineNameToId = (template, components, fallbacks = []) => { let changed = false; util.eachComponent(components, (component) => { // Update resource machineNames for resource components. @@ -233,7 +249,7 @@ module.exports = (router) => { } // Update the form property on the form component. - if ((component.type === 'form') && setFormProperty(template, component)) { + if ((component.type === 'form') && setFormProperty(template, component, fallbacks)) { changed = true; } @@ -256,6 +272,91 @@ module.exports = (router) => { return changed; }; + const fallbackNestedForms = (nestedForms, template, cb) => { + return async.forEach(nestedForms, (nestedForm, next) => { + const query = { + $or: [ + { + name: nestedForm.form, + deleted: {$eq: null}, + project: formio.util.idToBson(template._id), + }, + { + path: nestedForm.form, + deleted: {$eq: null}, + project: formio.util.idToBson(template._id), + }, + { + machineName: nestedForm.form, + deleted: {$eq: null}, + project: formio.util.idToBson(template._id), + }, + ] + }; + formio.resources.form.model.findOne(query).exec((err, doc) => { + if (err) { + debug.install(err); + return next(err); + } + if (doc) { + nestedForm.form = formio.util.idToString(doc._id); + } + next(); + }); + }, (err) => { + if (err) { + return cb(err); + } + else { + return cb(); + } + }); + }; + + const fallbackRoles = (entities, template, cb) => { + const query = { + $or: [ + { + deleted: {$eq: null}, + project: formio.util.idToBson(template._id), + }, + ] + }; + return formio.resources.role.model.find(query).exec((err, docs = []) => { + if (err) { + debug.install(err); + return cb(err); + } + try { + const rolesMap = {}; + docs.forEach((doc) => { + rolesMap[_.camelCase(doc.title)] = doc; + }); + entities.forEach((entity) => { + if (entity && entity.role && rolesMap.hasOwnProperty(entity.role)) { + entity.role = rolesMap[entity.role]._id.toString(); + } + else if (entity && entity.roles && entity.roles.length) { + entity.roles.forEach((role, i) => { + if (rolesMap.hasOwnProperty(role)) { + entity.roles[i] = rolesMap[role]._id.toString(); + } + else { + entity.roles[i] = undefined; + } + }); + // Filter any unknown roles from the pruning process. + entity.roles = _.filter(entity.roles); + } + }); + return cb(); + } + catch (err) { + return cb(err); + } + }); + }; + /** * The list of installable entities. Each entity must have a model and a transform. * @@ -288,7 +389,7 @@ module.exports = (router) => { ] }; return hook.alter(`importRoleQuery`, query, document, template); - } + }, }, resource: { model: formio.resources.form.model, @@ -299,9 +400,9 @@ module.exports = (router) => { return false; }, - transform: (template, resource) => { - roleMachineNameToId(template, resource.submissionAccess); - roleMachineNameToId(template, resource.access); + transform: (template, resource, fallbacks) => { + roleMachineNameToId(template, resource.submissionAccess, fallbacks.roles); + roleMachineNameToId(template, resource.access, fallbacks.roles); componentMachineNameToId(template, resource.components); return resource; }, @@ -314,21 +415,27 @@ module.exports = (router) => { } debug.cleanUp(`Need to update resource component _ids for`, machineName); - model.findOneAndUpdate( + model.updateOne( {_id: resource._id, deleted: {$eq: null}}, - {components: resource.components}, - {new: true} - ).lean().exec((err, doc) => { + {$set: {components: resource.components}} + ).exec((err) => { if (err) { return next(err); } - if (!doc) { - return next(); - } + model.findOne( + {_id: resource._id, deleted: {$eq: null}} + ).lean().exec((err, doc) => { + if (err) { + return next(err); + } + if (!doc) { + return next(); + } - resources[machineName] = doc; - debug.cleanUp(`Updated resource component _ids for`, machineName); - next(); + resources[machineName] = doc; + debug.cleanUp(`Updated resource component _ids for`, machineName); + next(); + }); }); }, done); }, @@ -350,7 +457,17 @@ module.exports = (router) => { ] }; return hook.alter(`importFormQuery`, query, document, template); - } + }, + fallBack: ({roles}, form, template, done) => { + return async.series([ + (cb) => fallbackRoles(roles, template, cb), + ], (err) => { + if (err) { + return done(err); + } + return done(); + }); + }, }, form: { model: formio.resources.form.model, @@ -361,10 +478,10 @@ module.exports = (router) => { return false; }, - transform: (template, form) => { - roleMachineNameToId(template, form.submissionAccess); - roleMachineNameToId(template, form.access); - componentMachineNameToId(template, form.components); + transform: (template, form, fallbacks) => { + roleMachineNameToId(template, form.submissionAccess, fallbacks.roles); + roleMachineNameToId(template, form.access, fallbacks.roles); + componentMachineNameToId(template, form.components, fallbacks.nestedForms); return form; }, cleanUp: (template, forms, done) => { @@ -376,21 +493,27 @@ module.exports = (router) => { } debug.cleanUp(`Need to update form component _ids for`, machineName); - model.findOneAndUpdate( + model.updateOne( {_id: form._id, deleted: {$eq: null}}, - {components: form.components}, - {new: true} - ).lean().exec((err, doc) => { + {$set: {components: form.components}}, + ).exec((err) => { if (err) { return next(err); } - if (!doc) { - return next(); - } + model.findOne( + {_id: form._id, deleted: {$eq: null}} + ).lean().exec((err, doc) => { + if (err) { + return next(err); + } + if (!doc) { + return next(); + } - forms[machineName] = doc; - debug.cleanUp(`Updated form component _ids for`, machineName); - next(); + forms[machineName] = doc; + debug.cleanUp(`Updated form component _ids for`, machineName); + next(); + }); }); }, done); }, @@ -417,8 +540,22 @@ module.exports = (router) => { const prun = require('../util/delete')(router); prun.action(null, form).then(() => { done(); + }) + .catch(error=>{ + done(error); }); - } + }, + fallBack: ({nestedForms, roles}, form, template, done) => { + return async.series([ + (cb) => fallbackNestedForms(nestedForms, template, cb), + (cb) => fallbackRoles(roles, template, cb), + ], (err) => { + if (err) { + return done(err); + } + return done(); + }); + }, }, action: { model: formio.actions.model, @@ -429,13 +566,13 @@ module.exports = (router) => { return false; }, - transform: (template, action) => { + transform: (template, action, fallbacks) => { const isResourceChanged = resourceMachineNameToId(template, action.settings); if (!isResourceChanged && action.settings && action.settings.resource) { action.settings.resource = ''; } - roleMachineNameToId(template, action.settings); + roleMachineNameToId(template, action.settings, fallbacks.roles); // If no changes were made, the form was invalid and we can't insert the action. if (formMachineNameToId(template, action) === false) { @@ -454,7 +591,17 @@ module.exports = (router) => { ] }; return hook.alter(`importActionQuery`, query, document, template); - } + }, + fallBack: ({roles}, form, template, done) => { + return async.series([ + (cb) => fallbackRoles(roles, template, cb), + ], (err) => { + if (err) { + return done(err); + } + return done(); + }); + }, } }; @@ -488,25 +635,15 @@ module.exports = (router) => { } alter = alter || baseAlter; - debug.items(items); + debug.items(Object.keys(items)); // If the given items don't have a valid structure for this entity, skip the import. if (valid && !valid(items)) { - debug.install(`The given items were not valid: ${JSON.stringify(items)}`); + debug.install(`The given items were not valid: ${JSON.stringify(Object.keys(items))}`); return done(); } - async.forEachOfSeries(items, (item, machineName, next) => { - const document = transform - ? transform(template, item) - : item; - - // If no document was provided before the alter, skip the insertion. - if (!document) { - debug.items(`Skipping item ${item}`); - return next(); - } - + const performInstall = (document, machineName, item, next) => { // Set the document machineName using the import value. document.machineName = machineName; alter(document, template, (err, document) => { @@ -515,11 +652,11 @@ module.exports = (router) => { } // If no document was provided after the alter, skip the insertion. if (!document) { - debug.install(`No document was given to install after the alter ${item} (${machineName})`); + debug.install(`No document was given to install after the alter ${item.name} (${machineName})`); return next(); } - debug.install(document); + debug.install(document.name); const query = entity.query ? entity.query(document, template) : { machineName: document.machineName, deleted: {$eq: null} @@ -539,8 +676,7 @@ module.exports = (router) => { } items[machineName] = result.toObject(); - debug.save(machineName); - debug.save(items[machineName]); + debug.save(items[machineName].machineName); if (entity.hasOwnProperty('deleteAllActions')) { return entity.deleteAllActions(updatedDoc._id, next); } @@ -565,7 +701,7 @@ module.exports = (router) => { debug.install(`Existing found`); doc = _.assign(doc, document); setVid(doc, 0); - debug.install(doc); + debug.install(doc.machineName); return saveDoc(doc); } else { @@ -575,6 +711,32 @@ module.exports = (router) => { } }); }); + }; + + async.forEachOfSeries(items, (item, machineName, next) => { + const fallbacks = { + roles: [], + nestedForms: [], + nestedResources: [], + }; + const document = transform + ? transform(template, item, fallbacks) + : item; + + // If no document was provided before the alter, skip the insertion. + if (!document) { + debug.items(`Skipping item ${item}`); + return next(); + } + + if (typeof entity.fallBack === 'function' && Object.values(fallbacks).some((items) => !!items.length)) { + entity.fallBack(fallbacks, document, template, () => { + performInstall(document, machineName, item, next); + }); + } + else { + performInstall(document, machineName, item, next); + } }, (err) => { if (err) { debug.install(err); @@ -678,6 +840,85 @@ module.exports = (router) => { }); }; + function tryToLoadComponents(components, template, projectId, isFormId) { + async.each(components, (component) => { + const query = { + deleted: {$eq: null} + }; + + if ( projectId ) { + query.project = projectId; + } + + if (!isFormId) { + query.path = component.form; + } + else { + query._id = component.form; + } + + return formio.resources.form.model.find(query).exec().then((results) => { + if (results.length) { + const result = results[0]; + const newItem = { + "title": result.title , + "type": result.type, + "name": result.name, + "path": result.path, + "tags": result.tags, + "components": result.components + }; + + if (isFormId) { + component.form = result.path; + } + + if (result.type==='form') { + template.forms[newItem.name]=newItem; + } + else { + template.resources[newItem.name]=newItem; + } + const formComponents = checkTemplate(newItem.components, template); + if (formComponents.length !== 0) { + tryToLoadComponents(formComponents, template, projectId, true); + } + else { + return; + } + } + }) + .catch(err => { + debug.template(err); + }); + }); + } + + function findProjectId(template) { + const query = { + deleted: {$eq: null}, + name: template.name + }; + return formio.resources.project.model.findOne(query).exec().then( project => { + return project._id; + }) + .catch(err => { + debug.template(err); + }); + } + + function checkTemplate(components, template) { + const resultArr = []; + util.eachComponent(components, (component)=>{ + if (component.hasOwnProperty('form') && + !(template.forms.hasOwnProperty(component.form) || + template.resources.hasOwnProperty(component.form))) { + resultArr.push(component); + } + }); + return resultArr; +} + // Implement an import endpoint. if (router.post) { router.post('/import', (req, res, next) => { @@ -688,14 +929,31 @@ module.exports = (router) => { template = JSON.parse(template); } - template = hook.alter('importOptions', template, req, res); - importTemplate(template, alters, (err, data) => { - if (err) { - return next(err.message || err); - } - - return res.status(200).send('Ok'); - }); + const components = Object.values(template.forms).concat(Object.values(template.resources)); + + const missingComponents = checkTemplate(components, template); + if (missingComponents.length !== 0 ) { + findProjectId(template) + .then((projectId) => { + tryToLoadComponents(missingComponents, template, projectId); + template = hook.alter('importOptions', template, req, res); + importTemplate(template, alters, (err, data) => { + if (err) { + return next(err.message || err); + } + return res.status(200).send('Ok'); + }); + }); + } + else { + template = hook.alter('importOptions', template, req, res); + importTemplate(template, alters, (err, data) => { + if (err) { + return next(err.message || err); + } + return res.status(200).send('Ok'); + }); + } }); } diff --git a/forms-flow-forms/src/util/email.js b/forms-flow-forms/src/util/email.js index 1f1b2dd3ea..b2b06fd2dd 100644 --- a/forms-flow-forms/src/util/email.js +++ b/forms-flow-forms/src/util/email.js @@ -10,11 +10,13 @@ const debug = { error: require('debug')('formio:error'), nunjucksInjector: require('debug')('formio:email:nunjucksInjector') }; -const rest = require('restler'); +const fetch = require('@formio/node-fetch-http-proxy'); const util = require('./util'); const _ = require('lodash'); + const EMAIL_OVERRIDE = process.env.EMAIL_OVERRIDE; const EMAIL_CHUNK_SIZE = process.env.EMAIL_CHUNK_SIZE || 100; +const NON_PRIORITY_QUEUE_TIMEOUT = process.env.NON_PRIORITY_QUEUE_TIMEOUT || 1000; /** * The email sender for emails. @@ -39,12 +41,7 @@ module.exports = (formio) => { } // Build the list of available transports, based on the present project settings. - let availableTransports = [ - { - transport: 'default', - title: 'Default (charges may apply)', - }, - ]; + let availableTransports = []; if (_.get(settings, 'email.custom.url')) { availableTransports.push({ transport: 'custom', @@ -140,12 +137,15 @@ module.exports = (formio) => { // The form components. params.components = {}; + params.componentsWithPath = {}; const replacements = []; // Flatten the resource data. - util.eachComponent(form.components, (component) => { + util.eachComponent(form.components, (component, path) => { params.components[component.key] = component; + params.componentsWithPath[path] = component; + params.componentsWithPath[path].compPath = path; if (component.type === 'resource' && params.data[component.key]) { params.data[`${component.key}Obj`] = params.data[component.key]; replacements.push( @@ -385,21 +385,30 @@ module.exports = (formio) => { break; case 'custom': if (_.has(settings, 'email.custom')) { - transporter.sendMail = (mail, cb) => { - const options = {}; + transporter.sendMail = async (mail, cb) => { + const authHeader = {}; if (settings.email.custom.username) { - options.username = settings.email.custom.username; - options.password = settings.email.custom.password; + const payload = `${settings.email.custom.username}:${settings.email.custom.password}`; + authHeader.Authorization = `Basic ${Buffer.from(payload).toString('base64')}`; } - rest.postJson(settings.email.custom.url, mail, options) - .on('complete', (result, response) => { - if (result instanceof Error) { - return cb(result); - } - - return cb(null, result); - }); + const response = await fetch(settings.email.custom.url, { + method: 'POST', + headers: { + 'content-type': 'application/json', + 'accept': 'application/json', + ...authHeader + }, + body: JSON.stringify(mail), + }); + + if (response.ok) { + const result = await response.json(); + return cb(null, result); + } + else { + return cb(new Error(`${response.status }: ${ response.statusText}`)); + } }; } break; @@ -434,16 +443,22 @@ module.exports = (formio) => { subject, message: html, transport, + replyTo, + renderingMethod, } = message; const mail = { - from: from || 'no-reply@form.io', + from: from || formio.config.defaultEmailSource, to: formatNodemailerEmailAddress(emails), subject, html, msgTransport: transport, transport: emailType, + renderingMethod, }; + if (replyTo) { + mail.replyTo = replyTo || from; + } const cc = (rawCc || []).map(_.trim).filter(Boolean); const bcc = (rawBcc || []).map(_.trim).filter(Boolean); @@ -460,7 +475,8 @@ module.exports = (formio) => { params, }; - nunjucksInjector(mail, options) + const sendEmails = () => nunjucksInjector(mail, options) + .then((email) => hook.alter('checkEmailPermission', email, params.form)) .then((email) => { let emails = []; @@ -520,12 +536,26 @@ module.exports = (formio) => { ); })); }, Promise.resolve()); - }) - .then((response) => next(null, response)) + }); + + const throttledSendEmails = _.throttle(sendEmails , NON_PRIORITY_QUEUE_TIMEOUT); + + if (req.user) { + return sendEmails() + .then((response) => next(null, response)) + .catch((err) => { + debug.error(err); + return next(err); + }); + } + else { + throttledSendEmails() .catch((err) => { debug.error(err); return next(err); }); + return next(); + } }); }; diff --git a/forms-flow-forms/src/util/fetch.js b/forms-flow-forms/src/util/fetch.js index 40171efc9d..948d0533e4 100644 --- a/forms-flow-forms/src/util/fetch.js +++ b/forms-flow-forms/src/util/fetch.js @@ -76,6 +76,8 @@ module.exports = (url, options = {}) => { // Parse the request input information const input = parseUrl(url); + let {rejectUnauthorized} = options; + // Check that the target url is a valid URL if (!input.host) { return Promise.reject(new TypeError('Only absolute URLs are supported')); @@ -105,8 +107,10 @@ module.exports = (url, options = {}) => { // Check if using HTTPS const isHTTPS = input.protocol === 'https:'; - // Check if system is forcing invalid tls rejection (should be rejected by default) - const rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0'; + if (typeof rejectUnauthorized === 'undefined') { + // Check if system is forcing invalid tls rejection (should be rejected by default) + rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0'; + } // Check if we need to use http(s) proxy or not if (!noProxy(input)) { diff --git a/forms-flow-forms/src/util/util.js b/forms-flow-forms/src/util/util.js index 986a9c5b76..edc3253027 100644 --- a/forms-flow-forms/src/util/util.js +++ b/forms-flow-forms/src/util/util.js @@ -1,14 +1,15 @@ 'use strict'; +require('@azure/ms-rest-nodeauth'); const mongoose = require('mongoose'); -const ObjectID = require('mongodb').ObjectID; +const ObjectID = require('mongodb').ObjectId; const _ = require('lodash'); const nodeUrl = require('url'); const deleteProp = require('delete-property').default; -const workerUtils = require('formio-workers/util'); +const workerUtils = require('formio-workers/workers/util'); const errorCodes = require('./error-codes.js'); -const fetch = require('./fetch'); -const vm = require('vm'); +const fetch = require('@formio/node-fetch-http-proxy'); +const {VM} = require('vm2'); const debug = { idToBson: require('debug')('formio:util:idToBson'), getUrlParams: require('debug')('formio:util:getUrlParams'), @@ -29,7 +30,7 @@ global.document = { firstElementChild: {appendChild: () => {}} } }; -global.window = {addEventListener: () => {}, Event: {}, navigator: global.navigator}; +global.window = {addEventListener: () => {}, Event: function() {}, navigator: global.navigator}; global.btoa = (str) => { return (str instanceof Buffer) ? str.toString('base64') : @@ -44,24 +45,27 @@ _.each(Formio.Displays.displays, (display) => { display.prototype.onChange = _.noop; }); +const vm = new VM({ + timeout: 250, + sandbox: { + result: null, + }, + fixAsync: true +}); + Formio.Utils.Evaluator.noeval = true; Formio.Utils.Evaluator.evaluator = function(func, args) { return function() { - const params = _.keys(args); - const sandbox = vm.createContext({ - result: null, - args - }); + let result = null; /* eslint-disable no-empty */ try { - const script = new vm.Script(`result = (function({${params.join(',')}}) {${func}})(args);`); - script.runInContext(sandbox, { - timeout: 250 - }); + vm.freeze(args, 'args'); + + result = vm.run(`result = (function({${_.keys(args).join(',')}}) {${func}})(args);`); } catch (err) {} /* eslint-enable no-empty */ - return sandbox.result; + return result; }; }; @@ -584,7 +588,7 @@ const Utils = { return changed; }, - removeProtectedFields(form, action, submissions) { + removeProtectedFields(form, action, submissions, doNotMinify) { if (!Array.isArray(submissions)) { submissions = [submissions]; } @@ -599,17 +603,22 @@ const Utils = { debug.removeProtectedFields('Removing protected field:', component.key); modifyFields.push(deleteProp(path)); } - else if ((component.type === 'signature') && (action === 'index')) { + else if ((component.type === 'signature') && (action === 'index') && !doNotMinify) { modifyFields.push(((submission) => { const data = _.get(submission, path); _.set(submission, path, (!data || (data.length < 25)) ? '' : 'YES'); })); } - else if (component.type === 'file' && action === 'index') { + else if (component.type === 'file' && action === 'index' && !doNotMinify) { modifyFields.push(((submission) => { const data = _.map( _.get(submission, path), - file => (file.url || '').startsWith('data:') ? _.omit(file, 'url') : file + (file) => { + if (file && file.url && file.url.startsWith('data:')) { + return _.omit(file, 'url'); + } + return file; + } ); _.set(submission, path, data); })); @@ -739,15 +748,18 @@ const Utils = { if (Array.isArray(component.components)) { // If tree type is an array of objects like datagrid and editgrid. if (['datagrid', 'editgrid', 'dynamicWizard'].includes(component.type) || component.arrayTree) { - (_.get(data, component.key) || []).forEach((row, index) => { - this.eachValue( - component.components, - row, - fn, - context, - this.valuePath(path, `${component.key}[${index}]`), - ); - }); + const value = _.get(data, component.key) || []; + if (Array.isArray(value)) { + value.forEach((row, index) => { + this.eachValue( + component.components, + row, + fn, + context, + this.valuePath(path, `${component.key}[${index}]`), + ); + }); + } } else if (['form'].includes(component.type)) { this.eachValue( @@ -821,6 +833,13 @@ const Utils = { }); }); }, + markModifiedParameters: (item, modifiedParameters)=>{ + modifiedParameters.map((parameter)=>{ + if (item[parameter]) { + item.markModified(parameter); + } + }); + }, }; module.exports = Utils; diff --git a/forms-flow-forms/src/worker/Worker.js b/forms-flow-forms/src/worker/Worker.js index 1f7d4ccf22..f2d96438d9 100644 --- a/forms-flow-forms/src/worker/Worker.js +++ b/forms-flow-forms/src/worker/Worker.js @@ -9,7 +9,7 @@ module.exports = (formio) => { constructor(type) { this.worker = hook.alter('worker', type); if (!this.worker || (this.worker === type)) { - this.worker = new Thread(Thread.Tasks[type]); + this.worker = new Thread(type); } } diff --git a/forms-flow-forms/test/actions.js b/forms-flow-forms/test/actions.js index d15edff13a..3e84ad543e 100644 --- a/forms-flow-forms/test/actions.js +++ b/forms-flow-forms/test/actions.js @@ -7,6 +7,7 @@ const _ = require('lodash'); const chance = new (require('chance'))(); const http = require('http'); const url = require('url'); +const { UV_FS_O_FILEMAP } = require('constants'); const docker = process.env.DOCKER; module.exports = (app, template, hook) => { @@ -478,17 +479,27 @@ module.exports = (app, template, hook) => { let port = 4002; let webhookSubmission = null; let webhookHandler = () => {}; + let webhookServer = null; // Create a new server. const newServer = (ready) => { - const server = http.createServer((request) => { + const server = http.createServer((request, response) => { let body = []; - request.on('data', (chunk) => { - body.push(chunk); - }).on('end', () => { - body = Buffer.concat(body).toString(); - webhookHandler(body ? JSON.parse(body) : body, url.parse(request.url, true)); - }); + + if (request.url === '/plain-text') { + response.setHeader('Content-Type', 'text/plain; charset=utf-8;'); + response.write('200 OK'); + response.statusCode = 200; + response.end(); + } + else { + request.on('data', (chunk) => { + body.push(chunk); + }).on('end', () => { + body = Buffer.concat(body).toString(); + webhookHandler(body ? JSON.parse(body) : body, url.parse(request.url, true)); + }); + } }); server.port = port++; server.url = `http://localhost:${server.port}`; @@ -505,6 +516,8 @@ module.exports = (app, template, hook) => { return done(err); } + webhookServer = server; + request(app) .post(hook.alter('url', '/form', template)) .set('x-jwt-token', template.users.admin.token) @@ -660,6 +673,163 @@ module.exports = (app, template, hook) => { } }); }); + + if (app.hasProject) { + describe('Webhook with non JSON response', () => { + if (docker) { + return; + } + + // The temp form with the add RoleAction for existing submissions. + let webhookForm2 = { + title: 'Webhook Form 2', + name: 'webhookform2', + path: 'webhookform2', + type: 'form', + access: [], + submissionAccess: [], + components: [ + { + type: 'textfield', + validate: { + custom: '', + pattern: '', + maxLength: '', + minLength: '', + required: false, + }, + defaultValue: '', + multiple: false, + suffix: '', + prefix: '', + placeholder: 'foo', + key: 'firstName', + label: 'First Name', + inputMask: '', + inputType: 'text', + input: true, + }, + { + type: 'textfield', + validate: { + custom: '', + pattern: '', + maxLength: '', + minLength: '', + required: false, + }, + defaultValue: '', + multiple: false, + suffix: '', + prefix: '', + placeholder: 'foo', + key: 'lastName', + label: 'Last Name', + inputMask: '', + inputType: 'text', + input: true, + }, + { + type: 'email', + persistent: true, + unique: false, + protected: false, + defaultValue: '', + suffix: '', + prefix: '', + placeholder: 'Enter your email address', + key: 'email', + label: 'Email', + inputType: 'email', + tableView: true, + input: true, + }, + { + type: 'password', + persistent: true, + unique: false, + protected: false, + defaultValue: '', + suffix: '', + prefix: '', + placeholder: 'Enter your password', + key: 'password', + label: 'Password', + inputType: 'password', + tableView: true, + input: true, + }, + ], + }; + + it('Should create the form and action for the webhook tests 2', (done) => { + request(app) + .post(hook.alter('url', '/form', template)) + .set('x-jwt-token', template.users.admin.token) + .send(webhookForm2) + .expect('Content-Type', /json/) + .expect(201) + .end((err, res) => { + if (err) { + return done(err); + } + + webhookForm2 = res.body; + template.users.admin.token = res.headers['x-jwt-token']; + request(app) + .post(hook.alter('url', `/form/${webhookForm2._id}/action`, template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + title: 'Webhook', + name: 'webhook', + form: webhookForm2._id.toString(), + handler: ['after'], + method: ['create', 'update', 'delete'], + priority: 1, + settings: { + url: `${webhookServer.url}/plain-text`, + username: '', + password: '', + block: true + }, + }) + .expect('Content-Type', /json/) + .expect(201) + .end((err, res) => { + if (err) { + return done(err); + } + + template.users.admin.token = res.headers['x-jwt-token']; + + done(); + }); + }); + }); + + it('Should send a webhook with create data and receive a 400 error.', (done) => { + request(app) + .post(hook.alter('url', `/form/${webhookForm2._id}/submission`, template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + data: { + firstName: 'Test', + lastName: 'Person', + email: 'test@example.com', + password: '123testing', + }, + }) + .expect(400) + .end((err, res) => { + if (err) { + return done(err); + } + assert.equal(res.text.indexOf('invalid json response body'), 0); + done(); + }); + }); + }); + } }); describe('EmailAction Functionality tests', () => { @@ -667,6 +837,17 @@ module.exports = (app, template, hook) => { return; } + const adminUser = (token) => { + const user = template.users.formioAdmin ? 'formioAdmin' : 'admin'; + + if (token) { + template.users[user].token = token; + } + else { + return template.users[user]; + } + }; + // The temp form with the add RoleAction for existing submissions. const emailForm = { title: 'Email Form', @@ -723,7 +904,7 @@ module.exports = (app, template, hook) => { // Create the form. request(app) .post(hook.alter('url', '/form', template)) - .set('x-jwt-token', template.users.admin.token) + .set('x-jwt-token', adminUser().token) .send(testForm) .expect('Content-Type', /json/) .expect(201) @@ -734,12 +915,12 @@ module.exports = (app, template, hook) => { testForm = res.body; testAction.form = testForm._id; - template.users.admin.token = res.headers['x-jwt-token']; + adminUser(res.headers['x-jwt-token']); // Add the action to the form. request(app) .post(hook.alter('url', `/form/${testForm._id}/action`, template)) - .set('x-jwt-token', template.users.admin.token) + .set('x-jwt-token', adminUser().token) .send(testAction) .expect('Content-Type', /json/) .expect(201) @@ -749,16 +930,17 @@ module.exports = (app, template, hook) => { } testAction = res.body; - template.users.admin.token = res.headers['x-jwt-token']; + adminUser(res.headers['x-jwt-token']); done(null, testForm, testAction); }); }); }; - it('Should send an email with messages.', (done) => { + it('Should send an email with messages (without Reply-To header).', (done) => { newEmailTest({ from: 'travis@form.io', + replyTo: '', emails: '{{ data.email }}', sendEach: false, subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', @@ -781,7 +963,7 @@ module.exports = (app, template, hook) => { request(app) .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) - .set('x-jwt-token', template.users.admin.token) + .set('x-jwt-token', adminUser().token) .send({ data: { firstName: 'Test', @@ -799,9 +981,55 @@ module.exports = (app, template, hook) => { }); }); - it('Should send an email with multiple recipients.', (done) => { + it('Should send an email with messages (with Reply-To header).', (done) => { + newEmailTest({ + from: 'travis@form.io', + replyTo: 'reply@example.com', + emails: '{{ data.email }}', + sendEach: false, + subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', + message: 'Howdy, {{ id }}', + }, (err, testForm) => { + if (err) { + return done(err); + } + + // Check for an email. + const event = template.hooks.getEmitter(); + event.once('newMail', (email) => { + assert.equal(email.from, 'travis@form.io'); + assert.equal(email.to, 'test@example.com'); + assert(email.html.startsWith('Howdy, ')); + assert.equal(email.subject, 'Hello there Test Person'); + assert.equal(email.replyTo, 'reply@example.com'); + + done(); + }); + + request(app) + .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) + .set('x-jwt-token', adminUser().token) + .send({ + data: { + firstName: 'Test', + lastName: 'Person', + email: 'test@example.com', + }, + }) + .expect(201) + .expect('Content-Type', /json/) + .end((err) => { + if (err) { + return done(err); + } + }); + }); + }); + + it('Should send an email with multiple recipients (without Reply-To header).', (done) => { newEmailTest({ from: '{{ data.email }}', + replyTo: '', emails: '{{ data.email }}, gary@form.io', subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', message: 'Howdy, {{ id }}', @@ -823,7 +1051,7 @@ module.exports = (app, template, hook) => { request(app) .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) - .set('x-jwt-token', template.users.admin.token) + .set('x-jwt-token', adminUser().token) .send({ data: { firstName: 'Joe', @@ -841,9 +1069,54 @@ module.exports = (app, template, hook) => { }); }); - it('Should send an email with multiple separate messages.', (done) => { + it('Should send an email with multiple recipients (with Reply-To header).', (done) => { + newEmailTest({ + from: '{{ data.email }}', + replyTo: 'reply@example.com', + emails: '{{ data.email }}, gary@form.io', + subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', + message: 'Howdy, {{ id }}', + }, (err, testForm) => { + if (err) { + return done(err); + } + + // Check for an email. + const event = template.hooks.getEmitter(); + event.once('newMail', (email) => { + assert.equal(email.from, 'joe@example.com'); + assert.equal(email.to, 'joe@example.com, gary@form.io'); + assert(email.html.startsWith('Howdy, ')); + assert.equal(email.subject, 'Hello there Joe Smith'); + assert.equal(email.replyTo, 'reply@example.com'); + + done(); + }); + + request(app) + .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) + .set('x-jwt-token', adminUser().token) + .send({ + data: { + firstName: 'Joe', + lastName: 'Smith', + email: 'joe@example.com', + }, + }) + .expect(201) + .expect('Content-Type', /json/) + .end((err) => { + if (err) { + return done(err); + } + }); + }); + }); + + it('Should send an email with multiple separate messages (without Reply-To header).', (done) => { newEmailTest({ from: 'travis@form.io', + replyTo: '', emails: '{{ data.email }}, gary@form.io', sendEach: true, subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', @@ -870,7 +1143,7 @@ module.exports = (app, template, hook) => { request(app) .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) - .set('x-jwt-token', template.users.admin.token) + .set('x-jwt-token', adminUser().token) .send({ data: { firstName: 'Test', @@ -888,14 +1161,64 @@ module.exports = (app, template, hook) => { }); }); - it('Should send a giant email to large amount of people.', (done) => { + it('Should send an email with multiple separate messages (with Reply-To header).', (done) => { + newEmailTest({ + from: 'travis@form.io', + replyTo: 'reply@example.com', + emails: '{{ data.email }}, gary@form.io', + sendEach: true, + subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', + message: 'Howdy, {{ id }}', + }, (err, testForm) => { + if (err) { + return done(err); + } + + // Check for an email. + const event = template.hooks.getEmitter(); + const emailTos = {'gary@form.io': true, 'test@example.com': true}; + event.on('newMail', (email) => { + assert.equal(email.from, 'travis@form.io'); + assert(emailTos[email.to]); + delete emailTos[email.to]; + assert.equal(email.html.indexOf('Howdy, '), 0); + assert.equal(email.subject, 'Hello there Test Person'); + assert.equal(email.replyTo, 'reply@example.com'); + if (Object.keys(emailTos).length === 0) { + event.removeAllListeners('newMail'); + done(); + } + }); + + request(app) + .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) + .set('x-jwt-token', adminUser().token) + .send({ + data: { + firstName: 'Test', + lastName: 'Person', + email: 'test@example.com', + }, + }) + .expect(201) + .expect('Content-Type', /json/) + .end((err) => { + if (err) { + done(err); + } + }); + }); + }); + + it('Should send a giant email to large amount of people (without Reply-To header).', (done) => { const amountOfEmails = 10000; const addresses = _.range(amountOfEmails).map((index) => `test${index}@example.com`).join(','); - const message = chance.paragraph({ sentences: 1000 }); + const message = chance.paragraph({sentences: 1000}); let receivedEmails = 0; newEmailTest({ from: 'travis@form.io', + replyTo: false, emails: addresses, sendEach: true, subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', @@ -908,11 +1231,64 @@ module.exports = (app, template, hook) => { // Check for an email. const event = template.hooks.getEmitter(); event.on('newMail', (email) => { + assert.equal(email.from, 'travis@form.io'); + // assert.equal(email.to, `test${receivedEmails}@example.com`); + assert.equal(email.html, message); + assert.equal(email.subject, 'Hello there Test Person'); + + receivedEmails += 1; + + if (receivedEmails === amountOfEmails) { + event.removeAllListeners('newMail'); + done(); + } + }); + + request(app) + .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) + .set('x-jwt-token', adminUser().token) + .send({ + data: { + firstName: 'Test', + lastName: 'Person', + }, + }) + .expect(201) + .expect('Content-Type', /json/) + .end((err) => { + if (err) { + done(err); + } + }); + }); + }); + + it('Should send a giant email to large amount of people (with Reply-To header).', (done) => { + const amountOfEmails = 10000; + const addresses = _.range(amountOfEmails).map((index) => `test${index}@example.com`).join(','); + const message = chance.paragraph({sentences: 1000}); + let receivedEmails = 0; + + newEmailTest({ + from: 'travis@form.io', + replyTo: 'reply@example.com', + emails: addresses, + sendEach: true, + subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', + message, + }, (err, testForm) => { + if (err) { + return done(err); + } + // Check for an email. + const event = template.hooks.getEmitter(); + event.on('newMail', (email) => { assert.equal(email.from, 'travis@form.io'); // assert.equal(email.to, `test${receivedEmails}@example.com`); assert.equal(email.html, message); assert.equal(email.subject, 'Hello there Test Person'); + assert.equal(email.replyTo, 'reply@example.com'); receivedEmails += 1; @@ -924,7 +1300,7 @@ module.exports = (app, template, hook) => { request(app) .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) - .set('x-jwt-token', template.users.admin.token) + .set('x-jwt-token', adminUser().token) .send({ data: { firstName: 'Test', @@ -940,6 +1316,147 @@ module.exports = (app, template, hook) => { }); }); }); + + if (template.users.formioAdmin) { + describe('EmailAction form.io domain permissions', () => { + if (docker) { + return; + } + + // The temp form with the add RoleAction for existing submissions. + const emailForm = { + title: 'Email Form', + name: 'emailform2', + path: 'emailform2', + type: 'form', + access: [], + submissionAccess: [], + components: [ + { + type: 'textfield', + key: 'firstName', + label: 'First Name', + input: true, + }, + { + type: 'textfield', + key: 'lastName', + label: 'Last Name', + input: true, + }, + { + type: 'email', + key: 'email', + label: 'Email', + input: true, + }, + ], + }; + + // The temp role add action for existing submissions. + const emailAction = { + title: 'Email', + name: 'email', + handler: ['after'], + method: ['create'], + priority: 1, + settings: {}, + }; + + let numTests = 0; + const newEmailTest = (settings, done) => { + numTests++; + settings.transport = 'test'; + let testForm = _.assign(_.cloneDeep(emailForm), { + title: (emailForm.title + numTests), + name: (emailForm.name + numTests), + path: (emailForm.path + numTests), + }); + let testAction = _.assign(_.cloneDeep(emailAction), { + settings, + }); + + // Create the form. + request(app) + .post(hook.alter('url', '/form', template)) + .set('x-jwt-token', template.users.admin.token) + .send(testForm) + .expect('Content-Type', /json/) + .expect(201) + .end((err, res) => { + if (err) { + return done(err); + } + + testForm = res.body; + testAction.form = testForm._id; + template.users.admin.token = res.headers['x-jwt-token']; + + // Add the action to the form. + request(app) + .post(hook.alter('url', `/form/${testForm._id}/action`, template)) + .set('x-jwt-token', template.users.admin.token) + .send(testAction) + .expect('Content-Type', /json/) + .expect(201) + .end((err, res) => { + if (err) { + return done(err); + } + + testAction = res.body; + template.users.admin.token = res.headers['x-jwt-token']; + + done(null, testForm, testAction); + }); + }); + }; + + it('Shouldn\'t send an email from form.io domain if owner is not related to form.io domain.', (done) => { + newEmailTest({ + from: 'travis@form.io', + emails: '{{ data.email }}', + sendEach: false, + subject: 'Hello there {{ data.firstName }} {{ data.lastName }}', + message: 'Howdy, {{ id }}', + }, (err, testForm) => { + if (err) { + return done(err); + } + + // Check for an email. + const event = template.hooks.getEmitter(); + event.once('newMail', (email) => { + done('Shouldn\'t send an email from form.io domain if owner is not related to form.io domain.'); + }); + + request(app) + .post(hook.alter('url', `/form/${testForm._id}/submission`, template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + data: { + firstName: 'Test', + lastName: 'Person', + email: 'test@example.com', + }, + }) + .expect(201) + .expect('Content-Type', /json/) + .end((err) => { + if (err) { + event.removeAllListeners('newMail'); + return done(err); + } + console.log('Script execution timed out after 15000ms'); + setTimeout(() => { + event.removeAllListeners('newMail'); + done(); + }, 15000); + }); + }); + }); + }); + } }); describe('RoleAction Functionality tests', () => { @@ -2093,7 +2610,7 @@ module.exports = (app, template, hook) => { }); }); - if (!docker) + if (!docker) it('A deleted Action should remain in the database', (done) => { const formio = hook.alter('formio', app.formio); formio.actions.model.findOne({_id: tempAction._id}) @@ -2171,7 +2688,7 @@ module.exports = (app, template, hook) => { request(app) .post(hook.alter('url', `/form/${template.forms.userLogin._id}/action`, template)) .set('x-jwt-token', template.users.admin.token) - .send({ data: actionLogin }) + .send({data: actionLogin}) .expect('Content-Type', /json/) .expect(201) .end((err, res) => { @@ -2226,7 +2743,7 @@ module.exports = (app, template, hook) => { request(app) .post(hook.alter('url', `/form/${template.forms.userRegister._id}/action`, template)) .set('x-jwt-token', template.users.admin.token) - .send({ data: actionRegister }) + .send({data: actionRegister}) .expect('Content-Type', /json/) .expect(201) .end((err, res) => { @@ -2278,7 +2795,7 @@ module.exports = (app, template, hook) => { request(app) .post(hook.alter('url', `/form/${template.forms.userRegister._id}/action`, template)) .set('x-jwt-token', template.users.admin.token) - .send({ data: actionRole }) + .send({data: actionRole}) .expect('Content-Type', /json/) .expect(201) .end((err, res) => { @@ -2519,34 +3036,18 @@ module.exports = (app, template, hook) => { it('Should NOT execute any role actions.', (done) => { helper - .submission(helper.contextName, { + .submission({ email: 'test@example.com', roles: ['test'], - }, helper.owner, [ - /json/, - 400 - ]) + }) .execute((err) => { if (err) { return done(err); } - const invalidRolesValueError = { - message: 'Roles is an invalid value.', - level: 'error', - path: ['roles'], - context: { - validator: 'onlyAvailableItems', - setting: true, - key: 'roles', - label: 'Roles', - value: 'test' - } - }; - - const responseBody = helper.lastResponse.body; - assert.strictEqual(responseBody.name, 'ValidationError', 'Should return validation error'); - assert.deepStrictEqual(responseBody.details[0], invalidRolesValueError); + const submission = helper.getLastSubmission(); + assert(!submission.roles.includes(helper.template.roles.administrator._id)); + assert(!submission.roles.includes(helper.template.roles.authenticated._id)); done(); }); diff --git a/forms-flow-forms/test/auth.js b/forms-flow-forms/test/auth.js index cd8711e010..6d65031943 100644 --- a/forms-flow-forms/test/auth.js +++ b/forms-flow-forms/test/auth.js @@ -8,6 +8,7 @@ var async = require('async'); var chance = new (require('chance'))(); var docker = process.env.DOCKER; var customer = process.env.CUSTOMER; +const defaultEmail = process.env.DEFAULT_EMAIL_SOURCE || 'no-reply@example.com'; let EventEmitter = require('events'); module.exports = function(app, template, hook) { @@ -104,6 +105,53 @@ module.exports = function(app, template, hook) { }); }); + if (template.users.formioAdmin) { + it('Register a form.io administrator', function(done) { + request(app) + .post(hook.alter('url', '/form/' + template.forms.adminRegister._id + '/submission', template)) + .send({ + data: { + 'email': template.users.formioAdmin.data.email, + 'password': template.users.formioAdmin.data.password + } + }) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) { + return done(err); + } + + var response = res.body; + assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.'); + assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.'); + assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.'); + assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.'); + assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.'); + assert.equal(response.data.email, template.users.formioAdmin.data.email); + assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.'); + assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.'); + assert.equal(response.form, template.resources.admin._id); + assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.'); + assert(response.hasOwnProperty('owner'), 'The response should contain the resource `owner`.'); + assert.notEqual(response.owner, null); + assert.equal(response.owner, response._id); + assert.equal(response.roles.length, 1); + assert.equal(response.roles[0].toString(), template.roles.administrator._id.toString()); + + // Update our testProject.owners data. + var tempPassword = template.users.formioAdmin.data.password; + template.users.formioAdmin = response; + template.users.formioAdmin.data.password = tempPassword; + + // Store the JWT for future API calls. + template.users.formioAdmin.token = res.headers['x-jwt-token']; + + done(); + }); + }); + } + it('A Form.io User should be able to login as administrator', function(done) { request(app) .post(hook.alter('url', '/form/' + template.forms.adminLogin._id + '/submission', template)) @@ -296,7 +344,7 @@ module.exports = function(app, template, hook) { } }) .then(email => { - assert.equal(email.from, 'no-reply@form.io'); + assert.equal(email.from, defaultEmail); assert.equal(email.to, template.users.user1.data.email); assert.equal(email.subject, 'New user ' + template.users.user1._id.toString() + ' created'); assert.equal(email.html, 'Email: ' + template.users.user1.data.email); diff --git a/forms-flow-forms/test/export/CSVExporter/CSVExporter.js b/forms-flow-forms/test/export/CSVExporter/CSVExporter.js index 10218ef8ee..76303cd135 100644 --- a/forms-flow-forms/test/export/CSVExporter/CSVExporter.js +++ b/forms-flow-forms/test/export/CSVExporter/CSVExporter.js @@ -4,26 +4,47 @@ module.exports = function(app, template, hook) { const Helper = require('../../helper')(app); let helper = null; const test = require('../../fixtures/forms/datetime-format.js'); + const testFile = require('../../fixtures/forms/fileComponent.js'); + + function getComponentValue(exportedText, compKey, submissionIndex) { + const rows = exportedText.split('\n'); + const headerRow = rows[0]; + const headings = headerRow.split(/,(?=")/); + const compColIndex = headings.indexOf(`"${compKey}"`); + const submissionRow = rows[submissionIndex + 1]; + const submissionRowValues = submissionRow.split(/,(?=")/);; + const compValue = submissionRowValues[compColIndex]; + console.log({ + rows, + headerRow, + headings, + compColIndex, + submissionRow, + submissionRowValues, + compValue + }); + return compValue; + } describe('CSVExporter', () => { it('Sets up a default project', (done) => { let owner = (app.hasProjects || docker) ? template.formio.owner : template.users.admin; helper = new Helper(owner); - helper.project().user('user', 'user1').execute(done); + helper.project().user('user', 'user1').execute(done); }); - it (`Export works in case when format is not set`, (done) => { + it(`Export works in case when format is not set`, (done) => { let owner = (app.hasProjects || docker) ? template.formio.owner : template.users.admin; helper = new Helper(owner); helper .project() .form('test', test.components) - .submission({data: {dateTime: '2020-03-10T09:00:00.000Z'}}) + .submission({ data: { dateTime: '2020-03-10T09:00:00.000Z' } }) .execute((err) => { if (err) { return done(err); } - helper.getExport(helper.template.forms.test,'csv', (error, result) => { + helper.getExport(helper.template.forms.test, 'csv', (error, result) => { if (error) { done(error); } @@ -31,6 +52,53 @@ module.exports = function(app, template, hook) { done(); }); }); - }) - }) -}; \ No newline at end of file + }); + + it(`Test displaying File values`, (done) => { + let owner = (app.hasProjects || docker) ? template.formio.owner : template.users.admin; + helper = new Helper(owner); + helper + .project() + .form('testFile', testFile.components) + .submission({ + data: { + file: [ + { + name: 'myFilePrefix-sunil-naik-0eNs9-dO9jM-unsplash-91e11557-3e57-465f-acf7-2e6ae867f45b.jpg', + originalName: 'sunil-naik-0eNs9-dO9jM-unsplash.jpg', + size: 2752197, + storage: 'base64', + type: 'image/jpeg', + url: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD', + }, + { + name: 'myFilePrefix-szabolcs-toth-t6A2qw9gjAo-unsplash-e88df4aa-0de1-4f40-982c-12cf88974c51.jpg', + originalName: 'szabolcs-toth-t6A2qw9gjAo-unsplash.jpg', + size: 1296003, + storage: 'base64', + type: 'image/jpeg', + url: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAA', + } + ] + } + }) + .execute((err) => { + if (err) { + return done(err); + } + helper.getExport(helper.template.forms.testFile, 'csv', (error, result) => { + if (error) { + done(error); + } + + const fileValue = getComponentValue(result.text, 'file', 0); + const expectedValue = + '"myFilePrefix-sunil-naik-0eNs9-dO9jM-unsplash-91e11557-3e57-465f-acf7-2e6ae867f45b.jpg, ' + + 'myFilePrefix-szabolcs-toth-t6A2qw9gjAo-unsplash-e88df4aa-0de1-4f40-982c-12cf88974c51.jpg"'; + assert.strictEqual(fileValue, expectedValue); + done(); + }); + }); + }); + }); +}; diff --git a/forms-flow-forms/test/fixtures/email/test3/form.json b/forms-flow-forms/test/fixtures/email/test3/form.json new file mode 100644 index 0000000000..bf4228a9c1 --- /dev/null +++ b/forms-flow-forms/test/fixtures/email/test3/form.json @@ -0,0 +1,99 @@ +{ + "_id": "5762cbed65901601001cc5c8", + "modified": "2016-06-16T18:49:57.831Z", + "title": "Test Form", + "display": "form", + "type": "form", + "name": "testForm", + "path": "test", + "project": "5762cb1365901601001cc5b5", + "created": "2016-06-16T15:55:25.495Z", + "components": [ + { + "label": "Upload", + "tableView": false, + "storage": "s3", + "webcam": false, + "fileTypes": [ + { + "label": "", + "value": "" + } + ], + "key": "file", + "type": "file", + "input": true + }, + { + "label": "Container", + "tableView": false, + "key": "container", + "type": "container", + "input": true, + "components": [ + { + "label": "Upload in container", + "tableView": false, + "storage": "s3", + "webcam": false, + "fileTypes": [ + { + "label": "", + "value": "" + } + ], + "key": "file", + "type": "file", + "input": true + } + ] + }, + { + "label": "Edit Grid", + "tableView": false, + "rowDrafts": false, + "key": "editGrid", + "type": "editgrid", + "displayAsTable": false, + "input": true, + "components": [ + { + "label": "Upload", + "tableView": false, + "storage": "s3", + "webcam": false, + "fileTypes": [ + { + "label": "", + "value": "" + } + ], + "key": "file", + "type": "file", + "input": true + } + ] + }, + { + "type": "button", + "label": "Submit", + "key": "submit", + "disableOnInvalid": true, + "input": true, + "tableView": false + } + ], + "owner": "57605b5965901601001cbbd2", + "submissionAccess": [], + "access": [ + { + "type": "read_all", + "roles": [ + "5762cb1365901601001cc5b6", + "5762cb1365901601001cc5b7", + "5762cb1365901601001cc5b8" + ] + } + ], + "tags": [] +} diff --git a/forms-flow-forms/test/fixtures/email/test3/message.html b/forms-flow-forms/test/fixtures/email/test3/message.html new file mode 100644 index 0000000000..c9bcd4c6b2 --- /dev/null +++ b/forms-flow-forms/test/fixtures/email/test3/message.html @@ -0,0 +1 @@ +
{{ content }}
diff --git a/forms-flow-forms/test/fixtures/email/test3/submission.json b/forms-flow-forms/test/fixtures/email/test3/submission.json new file mode 100644 index 0000000000..5c28b054c3 --- /dev/null +++ b/forms-flow-forms/test/fixtures/email/test3/submission.json @@ -0,0 +1,72 @@ +{ + "_id": "5762f53b65901601001cc657", + "modified": "2016-06-16T18:51:39.375Z", + "data": { + "file": [ + { + "storage": "s3", + "name": "BMW_logo_-gray-.svg-fca9e4cf-f105-4a33-9bfa-8faa0e211c90.png", + "bucket": "formio", + "key": "BMW_logo_-gray-.svg-fca9e4cf-f105-4a33-9bfa-8faa0e211c90.png", + "url": "http://localhost:9000/BMW_logo_-gray-.svg-fca9e4cf-f105-4a33-9bfa-8faa0e211c90.png", + "acl": "private", + "size": 180493, + "type": "image/png", + "originalName": "BMW_logo_(gray).svg.png" + } + ], + "container": { + "file": [ + { + "storage": "s3", + "name": "BMW_logo_-gray-.svg-db4c6d8a-b87a-4153-9152-85a51e3cc448.png", + "bucket": "formio", + "key": "BMW_logo_-gray-.svg-db4c6d8a-b87a-4153-9152-85a51e3cc448.png", + "url": "http://localhost:9000/BMW_logo_-gray-.svg-db4c6d8a-b87a-4153-9152-85a51e3cc448.png", + "acl": "private", + "size": 180493, + "type": "image/png", + "originalName": "BMW_logo_(gray).svg.png" + } + ] + }, + "editGrid": [ + { + "file": [ + { + "storage": "s3", + "name": "dirrected by-5dc0e228-bda3-483e-83fe-314edec1cea6.jpg", + "bucket": "formio", + "key": "dirrected by-5dc0e228-bda3-483e-83fe-314edec1cea6.jpg", + "url": "http://localhost:9000/dirrected by-5dc0e228-bda3-483e-83fe-314edec1cea6.jpg", + "acl": "private", + "size": 11360, + "type": "image/jpeg", + "originalName": "dirrected by.jpg" + } + ] + }, + { + "file": [ + { + "storage": "s3", + "name": "dirrected by-ab9d0f62-d7b4-4858-9be6-a50217eca094.png", + "bucket": "formio", + "key": "dirrected by-ab9d0f62-d7b4-4858-9be6-a50217eca094.png", + "url": "http://localhost:9000/dirrected by-ab9d0f62-d7b4-4858-9be6-a50217eca094.png", + "acl": "private", + "size": 24794, + "type": "image/png", + "originalName": "dirrected by.png" + } + ] + } + ] + }, + "form": "5762cbed65901601001cc5c8", + "created": "2016-06-16T18:51:39.374Z", + "externalIds": [], + "access": [], + "roles": [], + "owner": "57605b5965901601001cbbd2" +} diff --git a/forms-flow-forms/test/fixtures/forms/complex.js b/forms-flow-forms/test/fixtures/forms/complex.js index 8103efd221..4a84231ba4 100644 --- a/forms-flow-forms/test/fixtures/forms/complex.js +++ b/forms-flow-forms/test/fixtures/forms/complex.js @@ -1,5 +1,3 @@ -'use strict'; - module.exports = { components: [ { @@ -76,6 +74,7 @@ module.exports = { "legend": "", "components": [ { + "searchField": "data.apparatusId", "conditional": { "eq": "", "when": null, @@ -94,6 +93,7 @@ module.exports = { "filter": "", "refreshOn": "", "defaultValue": "", + "valueProperty": "data.apparatusId", "dataSrc": "values", "data": { "project": "57ae043a78c4691a181d23f0", @@ -158,6 +158,7 @@ module.exports = { "project": "57ae043a78c4691a181d23f0" }, "dataSrc": "values", + "valueProperty": "data.shortName", "defaultValue": "", "refreshOn": "", "filter": "", @@ -176,6 +177,7 @@ module.exports = { "when": null, "eq": "" }, + "searchField": "data.shortName" }, { "tags": [], @@ -206,6 +208,7 @@ module.exports = { "project": "57ae043a78c4691a181d23f0" }, "dataSrc": "values", + "valueProperty": "data.fullName", "defaultValue": "", "refreshOn": "", "filter": "sort=data.fullName", @@ -224,6 +227,7 @@ module.exports = { "when": null, "eq": "" }, + "searchField": "data.fullName" }, { "tabindex": "2", @@ -326,4 +330,4 @@ module.exports = { ] }] } -}; +}; \ No newline at end of file diff --git a/forms-flow-forms/test/fixtures/forms/fileComponent.js b/forms-flow-forms/test/fixtures/forms/fileComponent.js new file mode 100644 index 0000000000..53dad1837c --- /dev/null +++ b/forms-flow-forms/test/fixtures/forms/fileComponent.js @@ -0,0 +1,33 @@ +module.exports = { + type: "form", + components: [ + { + label: "Upload", + tableView: false, + storage: "base64", + fileNameTemplate: "myFilePrefix-{{fileName}}", + webcam: false, + fileTypes: [ + { + label: "", + value: "" + } + ], + multiple: true, + key: "file", + type: "file", + input: true + }, + { + type: "button", + label: "Submit", + key: "submit", + disableOnInvalid: true, + input: true, + tableView: false + } + ], + title: "FIO-2834", + display: "form", + name: "fio2834", +}; diff --git a/forms-flow-forms/test/fixtures/forms/servercalculate.js b/forms-flow-forms/test/fixtures/forms/servercalculate.js new file mode 100644 index 0000000000..c8f76b2c61 --- /dev/null +++ b/forms-flow-forms/test/fixtures/forms/servercalculate.js @@ -0,0 +1,151 @@ +module.exports = { + components: [ + { + "label": "Columns", + "columns": [ + { + "components": [ + { + "label": "Select the Number of Widgets", + "widget": "choicesjs", + "tableView": true, + "data": { + "values": [ + { + "label": "1", + "value": "1" + }, + { + "label": "2", + "value": "2" + }, + { + "label": "3", + "value": "3" + }, + { + "label": "4", + "value": "4" + }, + { + "label": "5", + "value": "5" + } + ] + }, + "dataType": "number", + "selectThreshold": 0.3, + "validate": { + "required": true + }, + "key": "numberOfWidgets", + "type": "select", + "indexeddb": { + "filter": {} + }, + "input": true, + "hideOnChildrenHidden": false + }, + { + "label": "Price per Widget", + "mask": false, + "spellcheck": true, + "tableView": false, + "currency": "USD", + "inputFormat": "plain", + "calculateValue": "value = 29.95;", + "calculateServer": true, + "key": "pricePerWidget", + "type": "currency", + "input": true, + "delimiter": true, + "hideOnChildrenHidden": false + }, + { + "label": "Choose One", + "optionsLabelPosition": "right", + "inline": false, + "tableView": false, + "values": [ + { + "label": "Option 1", + "value": "option1", + "shortcut": "" + }, + { + "label": "Option 2", + "value": "option2", + "shortcut": "" + }, + { + "label": "Option 3", + "value": "option3", + "shortcut": "" + } + ], + "validate": { + "required": true + }, + "key": "chooseOne", + "type": "radio", + "input": true, + "hideOnChildrenHidden": false + }, + { + "label": "Total", + "mask": false, + "spellcheck": true, + "tableView": false, + "currency": "USD", + "inputFormat": "plain", + "calculateValue": "value = data.numberOfWidgets * data.pricePerWidget;", + "calculateServer": true, + "key": "total", + "type": "currency", + "input": true, + "delimiter": true, + "hideOnChildrenHidden": false + } + ], + "width": 4, + "offset": 0, + "push": 0, + "pull": 0, + "size": "md" + }, + { + "components": [], + "width": 4, + "offset": 0, + "push": 0, + "pull": 0, + "size": "md" + } + ], + "key": "columns", + "type": "columns", + "input": false, + "tableView": false + }, + { + "label": "Submit", + "showValidations": false, + "tableView": false, + "key": "submit", + "type": "button", + "input": true + } + ], + submission: { + "numberOfWidgets": 2, + "pricePerWidget": 29.95, + "chooseOne": "option1", + "total": 59.9 + }, + falseSubmission: { + "numberOfWidgets": "nothing", + "pricePerWidget": 29.95, + "chooseOne": "option1", + "total": null + } +}; diff --git a/forms-flow-forms/test/fixtures/template.js b/forms-flow-forms/test/fixtures/template.js index 5ea57b3199..c950a8b001 100644 --- a/forms-flow-forms/test/fixtures/template.js +++ b/forms-flow-forms/test/fixtures/template.js @@ -1,6 +1,7 @@ 'use strict'; let _ = require('lodash'); +const defaultEmail = process.env.DEFAULT_EMAIL_SOURCE || 'no-reply@example.com'; module.exports = () => { // The default project template. @@ -86,7 +87,7 @@ module.exports = () => { handler: ['after'], settings: { transport: 'test', - from: 'no-reply@form.io', + from: defaultEmail, emails: '{{ data.email }}', subject: 'New user {{ _id }} created', message: 'Email: {{ data.email }}' diff --git a/forms-flow-forms/test/form.js b/forms-flow-forms/test/form.js index 601b23e9a0..37d6cd8100 100644 --- a/forms-flow-forms/test/form.js +++ b/forms-flow-forms/test/form.js @@ -827,6 +827,104 @@ module.exports = function(app, template, hook) { .expect(401) .end(done); }); + + it('Delete Anonymous role from Read Form Definition', function(done) { + request(app) + .put(hook.alter('url', '/form/' + template.forms.tempForm._id, template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + ...tempForm, + access: [{type: 'read_all', roles: [template.roles.authenticated._id.toString(), template.roles.administrator._id.toString()]}] + }) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + + it('An Anonymous user should not be able to Read a Form for a User-Created Project after deleting Anonymous role from Read Form Definition', function(done) { + request(app) + .get(hook.alter('url', '/form/' + template.forms.tempForm._id, template)) + .expect(401) + .end(done); + }); + + it('Add Field Match Based Access for not Anonymous users', function(done) { + request(app) + .put(hook.alter('url', '/form/' + template.forms.tempForm._id, template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + ...tempForm, + fieldMatchAccess: { + read: [{ + formFieldPath:"data.textField", + valueType:"string", + value:"test1", + operator:"$eq", + roles: [template.roles.authenticated._id.toString()] + }] + } + }) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + + it('An Anonymous user should not be able to Read a Form for a User-Created Project after deleting Anonymous role from Read Form Definition', function(done) { + request(app) + .get(hook.alter('url', '/form/' + template.forms.tempForm._id, template)) + .expect(401) + .end(done); + }); + + it('Add Field Match Based Access for Anonymous users', function(done) { + request(app) + .put(hook.alter('url', '/form/' + template.forms.tempForm._id, template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + ...tempForm, + fieldMatchAccess: { + read: [{ + formFieldPath:"data.textField", + valueType:"string", + value:"test1", + operator:"$eq", + roles: [template.roles.anonymous._id.toString()] + }] + } + }) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + var response = res.body; + template.forms.tempForm = response; + done(); + }); + }); + + it('An Anonymous user should not be able to Read a Form with Match Based Access for Anonymous users', function(done) { + request(app) + .get(hook.alter('url', '/form/' + template.forms.tempForm._id, template)) + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + var response = res.body; + assert.deepEqual(_.omit(response, ignoreFields), _.omit(template.forms.tempForm, ignoreFields)); + done(); + }); + }); }); describe('Form Normalization', function() { @@ -4631,5 +4729,115 @@ module.exports = function(app, template, hook) { }); }); }); + + describe('Form with checkboxes grouped as radio', () => { + let formId; + it('Create form with checkboxes grouped as radio', (done) => { + request(app) + .post(hook.alter('url', '/form', template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + "title":"test1", + "display":"form", + "type":"form", + "components":[ + { + "label": "One", + "inputType": "radio", + "tableView": false, + "defaultValue": false, + "key": "checkbox", + "type": "checkbox", + "name": "check", + "value": "one", + "input": true + }, + { + "label": "Two", + "inputType": "radio", + "tableView": false, + "defaultValue": false, + "key": "checkbox1", + "type": "checkbox", + "name": "check", + "value": "two", + "input": true + }, + { + "label": "Three", + "inputType": "radio", + "tableView": false, + "defaultValue": false, + "key": "checkbox2", + "type": "checkbox", + "name": "check", + "value": "three", + "input": true + }, + { + "type":"button", + "label":"Submit", + "key":"submit", + "disableOnInvalid":true, + "input":true, + "tableView":false + } + ], + "access":[], + "submissionAccess":[], + "controller":"", + "properties":{}, + "settings":{}, + "builder":false, + "name":"test1", + "path":"test1" + }) + .expect('Content-Type', /json/) + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + formId = res.body._id; + done() + }) + }); + + it('Submit form', (done) => { + request(app) + .post(hook.alter('url', '/form/' + formId + '/submission', template)) + .set('x-jwt-token', template.users.admin.token) + .send({ + "data": { + "submit": true, + "check": "two" + }, + "state": "submitted" + }) + .expect('Content-Type', /json/) + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + done() + }) + }); + + it('Checkboxes data grouped as radio', (done) => { + request(app) + .get(hook.alter('url', '/form/' + formId + '/export', template)) + .set('x-jwt-token', template.users.admin.token) + .expect('Content-Type', /json/) + .expect(200) + .end((err, res) => { + if (err) { + return done(err); + } + assert.equal(_.isEqual(res.body[0].data, { check: 'two' }), true) + done() + }) + }); + }); }); }; diff --git a/forms-flow-forms/test/helper.js b/forms-flow-forms/test/helper.js index bbbadf2257..dd784ee364 100644 --- a/forms-flow-forms/test/helper.js +++ b/forms-flow-forms/test/helper.js @@ -34,7 +34,7 @@ module.exports = function(app) { permsConfig.push({ type: name, roles: _.map(roles, (roleName) => { - return this.template.roles[roleName]._id.toString(); + return this.template.roles[roleName]._id.toString() }) }); }); @@ -56,7 +56,7 @@ module.exports = function(app) { .end((err, res) => { this.owner.token = res.headers['x-jwt-token']; done(err, res); - }); + }) }; Helper.prototype.getTemplate = function() { @@ -71,7 +71,7 @@ module.exports = function(app) { Helper.prototype.getForms = function(done) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } url += '/form?limit=9999'; request(app) @@ -104,9 +104,9 @@ module.exports = function(app) { Helper.prototype.getActions = function(form, done) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ this.template.forms[form]._id }/action`; + url += '/form/' + this.template.forms[form]._id + '/action'; request(app) .get(url) .set('x-jwt-token', this.owner.token) @@ -117,7 +117,7 @@ module.exports = function(app) { return done(err, res); } if (!res.body) { - return done('No response', res); + return done('No response', res) } this.lastResponse = res; @@ -179,9 +179,9 @@ module.exports = function(app) { if (_action) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ this.template.forms[form]._id }/action/${ _action._id}`; + url += '/form/' + this.template.forms[form]._id + '/action/' + _action._id; request(app) .delete(url) @@ -192,7 +192,7 @@ module.exports = function(app) { return done(err, res); } if (!res.body) { - return done('No response', res); + return done('No response', res) } this.lastResponse = res; @@ -210,7 +210,7 @@ module.exports = function(app) { Helper.prototype.getRoles = function(done) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } url += '/role?limit=9999'; @@ -277,7 +277,7 @@ module.exports = function(app) { } request(app) - .get(`/project/${ this.template.project._id}`) + .get('/project/' + this.template.project._id) .set('x-jwt-token', this.owner.token) .expect('Content-Type', /json/) .expect(200) @@ -337,9 +337,9 @@ module.exports = function(app) { Helper.prototype.updateForm = function(form, done) { let url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ form._id}`; + url += '/form/' + form._id; request(app).put(url) .send(_.omit(form, 'modified')) @@ -354,7 +354,7 @@ module.exports = function(app) { this.template.forms[form.name] = res.body; done(null, res.body); }); - }; + } Helper.prototype.upsertForm = function(form, done) { this.contextName = form.name; @@ -382,7 +382,7 @@ module.exports = function(app) { var status = 201; var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } url += '/form'; var data = { @@ -397,7 +397,7 @@ module.exports = function(app) { if (this.template.forms.hasOwnProperty(form.name)) { method = 'put'; status = 200; - url += `/${ this.template.forms[form.name]._id}`; + url += '/' + this.template.forms[form.name]._id; data = { components: form.components }; @@ -473,7 +473,7 @@ module.exports = function(app) { if (this.template.forms.hasOwnProperty(_id)) { _id = this.template.forms[_id]._id.toString(); } - let url = `/form/${ _id}`; + let url = '/form/' + _id; if (this.hook) { url = this.hook.alter('url', url, this.template); } @@ -537,9 +537,9 @@ module.exports = function(app) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ this.template.forms[form]._id }/action/${ _action._id}`; + url += '/form/' + this.template.forms[form]._id + '/action/' + _action._id; request(app) .put(url) @@ -552,7 +552,7 @@ module.exports = function(app) { return done(err, res); } if (!res.body) { - return done('No response', res); + return done('No response', res) } this.lastResponse = res; @@ -610,9 +610,9 @@ module.exports = function(app) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ this.template.forms[form]._id }/action`; + url += '/form/' + this.template.forms[form]._id + '/action'; request(app) .post(url) @@ -667,9 +667,9 @@ module.exports = function(app) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ submission.form }/submission/${ submission._id}`; + url += '/form/' + submission.form + '/submission/' + submission._id; let currentRequest = request(app).put(url).send(submission); if (user) { @@ -739,9 +739,9 @@ module.exports = function(app) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ this.template.forms[form]._id }/submission`; + url += '/form/' + this.template.forms[form]._id + '/submission'; // Allow passing in the submission as well if (!data.hasOwnProperty('data')) { @@ -834,12 +834,12 @@ module.exports = function(app) { var url = ''; var subIndex = true; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ this.template.forms[form]._id }/submission`; + url += '/form/' + this.template.forms[form]._id + '/submission'; if (typeof id === 'string') { subIndex = false; - url += `/${ id}`; + url += '/' + id; } let currentRequest = request(app).get(url).send(); @@ -910,9 +910,9 @@ module.exports = function(app) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/form/${ submission.form }/submission/${ submission._id}`; + url += '/form/' + submission.form + '/submission/' + submission._id; let currentRequest = request(app).delete(url).send(submission); if (user) { @@ -956,7 +956,7 @@ module.exports = function(app) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } url += '/role'; @@ -966,7 +966,7 @@ module.exports = function(app) { _role = this.getRole(role.title || role); } - url += `/${ _role._id}`; + url += '/' + _role._id; request(app) .put(url) .send(update) @@ -1022,9 +1022,9 @@ module.exports = function(app) { var url = ''; if (this.template.project && this.template.project._id) { - url += `/project/${ this.template.project._id}`; + url += '/project/' + this.template.project._id; } - url += `/role/${ _role._id}`; + url += '/role/' + _role._id; request(app) .delete(url) @@ -1075,7 +1075,7 @@ module.exports = function(app) { this.template.users[user].data.password = data.password; // Now authenticate as this user to get JWT token. - this.createSubmission(`${form }Login`, {data: { + this.createSubmission(form + 'Login', {data: { email: this.template.users[user].data.email, password: this.template.users[user].data.password }}, null, [/application\/json/, 200], (err) => { @@ -1104,6 +1104,75 @@ module.exports = function(app) { }); }; + Helper.prototype.getSubmissions = function(form, user, expect, done) { + if (typeof form === 'object') { + form = this.contextName; + } + + if (typeof user === 'function') { + done = user; + user = this.owner; + } + + if (typeof expect === 'function') { + done = expect; + expect = []; + } + + expect = expect || []; + if (typeof user === 'string') { + user = this.template.users[user]; + } + + if (user === undefined) { + user = this.owner; + } + + if (!this.template.forms.hasOwnProperty(form)) { + return done('Form not found'); + } + + let url = ''; + if (this.template.project && this.template.project._id) { + url += `/project/${ this.template.project._id}`; + } + url += `/form/${ this.template.forms[form]._id }/submission?limit=10&skip=0`; + + let currentRequest = request(app).get(url).send(); + if (user) { + currentRequest = currentRequest.set('x-jwt-token', user.token); + } + if (expect.length) { + currentRequest = currentRequest.expect('Content-Type', expect[0]).expect(expect[1]); + } + else { + currentRequest = currentRequest.expect('Content-Type', /json/).expect(200); + } + currentRequest.end((err, res) => { + if (err) { + return done(err); + } + + this.lastResponse = res; + if (expect.length && expect[1] > 299) { + return done(); + } + + if (user && res.headers['x-jwt-token']) { + user.token = res.headers['x-jwt-token']; + } + this.template.submissions = this.template.submissions || {}; + if (this.template.submissions[form]) { + this.template.submissions[form] = res.body; + } + else { + this.template.submissions[form] = []; + } + + done(null, res.body); + }); + }; + Helper.assert = { propertiesEqual: (source, compare) => { _.each(source, (value, key) => { diff --git a/forms-flow-forms/test/roles.js b/forms-flow-forms/test/roles.js index 6c1df7fac8..a7c67fd8dc 100644 --- a/forms-flow-forms/test/roles.js +++ b/forms-flow-forms/test/roles.js @@ -293,7 +293,7 @@ module.exports = function(app, template, hook) { describe('Role Normalization', function() { it('A Form.io Project Owner should be able to Delete a Role', function(done) { - request(app) + request(app) .delete(hook.alter('url', '/role/' + template.roles.tempRole._id, template)) .set('x-jwt-token', template.users.admin.token) .expect(200) @@ -943,17 +943,37 @@ module.exports = function(app, template, hook) { }); }); - it('Should allow the manager to remove a role, but not add one.', (done) => { + it('Should not allow the manager to add role.', (done) => { manager.roles = [ + accessHelper.template.roles['access-employee']._id.toString(), accessHelper.template.roles['access-manager']._id.toString(), accessHelper.template.roles.authenticated._id.toString() ]; + accessHelper.submission('access-manager', manager, manager).execute((err) => { if (err) { return done(err); } - const updated = accessHelper.getLastSubmission(); + assert.deepEqual(updated.roles, [ + accessHelper.template.roles['access-employee']._id.toString(), + accessHelper.template.roles['access-manager']._id.toString(), + ]); + _.assign(manager, updated); + done(); + }); + }); + + it('Should allow the manager to remove a role.', (done) => { + manager.roles = [ + accessHelper.template.roles['access-manager']._id.toString(), + ]; + + accessHelper.submission('access-manager', manager, manager).execute((err) => { + if (err) { + return done(err); + } + const updated = accessHelper.getLastSubmission(); assert.deepEqual(updated.roles, [ accessHelper.template.roles['access-manager']._id.toString() ]); @@ -993,7 +1013,7 @@ module.exports = function(app, template, hook) { async.series( [ - (next) => accessHelper.deleteRole('access-manager', next), + (next) => accessHelper.deleteRole('access-manager', next), (next) => accessHelper.deleteRole('access-employee', next) ], (err) => { diff --git a/forms-flow-forms/test/submission-access.js b/forms-flow-forms/test/submission-access.js index f655a5a2b3..3aa1649c52 100644 --- a/forms-flow-forms/test/submission-access.js +++ b/forms-flow-forms/test/submission-access.js @@ -1613,6 +1613,7 @@ module.exports = function(app, template, hook) { it('Test if a submissions exists', function(done) { request(app) .get(hook.alter('url', '/form/' + tempForm._id + '/exists?data.value=foo&owner=' + template.users.user1._id.toString(), template)) + .set('x-jwt-token', template.users.admin.token) .expect(200) .end(function(err, res) { if (err) { @@ -1634,6 +1635,7 @@ module.exports = function(app, template, hook) { it('Test if a submissions exists', function(done) { request(app) .get(hook.alter('url', '/form/' + tempForm._id + '/exists?data.value=foo&owner=' + template.users.user2._id.toString(), template)) + .set('x-jwt-token', template.users.admin.token) .expect(200) .end(function(err, res) { if (err) { @@ -1645,9 +1647,17 @@ module.exports = function(app, template, hook) { }); }); + it('Should give an unuthorized error for anonymous', function(done) { + request(app) + .get(hook.alter('url', '/form/' + tempForm._id + '/exists?data.value=foo&owner=' + template.users.user2._id.toString(), template)) + .expect(401) + .end(done); + }); + it('Test if a submissions exists', function(done) { request(app) .get(hook.alter('url', '/form/' + tempForm._id + '/exists?data.value=foo', template)) + .set('x-jwt-token', template.users.admin.token) .expect(200) .end(done); }); @@ -1655,6 +1665,7 @@ module.exports = function(app, template, hook) { it('Test if a submissions exists', function(done) { request(app) .get(hook.alter('url', '/form/' + tempForm._id + '/exists?owner=' + template.users.user2._id.toString(), template)) + .set('x-jwt-token', template.users.admin.token) .expect(200) .end(function(err, res) { if (err) { @@ -1669,6 +1680,7 @@ module.exports = function(app, template, hook) { it('Should 404 if it does not exist', function(done) { request(app) .get(hook.alter('url', '/form/' + tempForm._id + '/exists?data.value=test&owner=' + template.users.user2._id.toString(), template)) + .set('x-jwt-token', template.users.admin.token) .expect(404) .end(done); }); @@ -1676,6 +1688,7 @@ module.exports = function(app, template, hook) { it('Should 404 if it does not exist', function(done) { request(app) .get(hook.alter('url', '/form/' + tempForm._id + '/exists?data.value=test', template)) + .set('x-jwt-token', template.users.admin.token) .expect(404) .end(done); }); diff --git a/forms-flow-forms/test/submission.js b/forms-flow-forms/test/submission.js index 38ef4ae5c0..d4aea15939 100644 --- a/forms-flow-forms/test/submission.js +++ b/forms-flow-forms/test/submission.js @@ -1,5 +1,5 @@ -'use strict'; - +/* eslint-disable strict */ +/* eslint-disable max-len */ /* eslint-env mocha */ const request = require('./formio-supertest'); var assert = require('assert'); @@ -12,6 +12,21 @@ module.exports = function(app, template, hook) { var Helper = require('./helper')(app); var helper = null; + function updateFormAndGetSubmissions(form, done) { + helper.updateForm(form, (err) => { + if (err) { + return done(err); + } + + helper.getSubmissions(form.name, (err, formsubs) => { + if (err) { + return done(err); + } + done(null, formsubs); + }); + }); + } + describe('Form Submissions', function() { it('Sets up a default project', function(done) { var owner = (app.hasProjects || docker) ? template.formio.owner : template.users.admin; @@ -233,6 +248,42 @@ module.exports = function(app, template, hook) { }); }); + describe('Server Calculated', function() { + it('Recalculate value on server', function(done) { + var test = require('./fixtures/forms/servercalculate.js'); + helper + .form('test', test.components) + .submission(test.submission) + .execute(function(err) { + if (err) { + return done(err); + } + + var submission = helper.getLastSubmission(); + assert.deepEqual(test.submission, submission.data); + + done(); + }); + }); + + it('Fails to recalculate value because of corrupted submission', function(done) { + var test = require('./fixtures/forms/servercalculate.js'); + helper + .form('test', test.components) + .submission(test.falseSubmission) + .execute(function(err) { + if (err) { + return done(err); + } + + var submission = helper.getLastSubmission(); + assert.deepEqual(test.falseSubmission, submission.data); + + done(); + }); + }); + }); + describe('Fieldset nesting', function() { it('Nests single value components in a fieldset', function(done) { var test = require('./fixtures/forms/singlecomponents1.js'); @@ -1560,10 +1611,11 @@ module.exports = function(app, template, hook) { assert.deepEqual(submission.details, [ { context: { + hasLabel: true, + index: 0, key: 'requiredField', setting: true, validator: 'required', - value: '', label: 'Required Field' }, message: 'Required Field is required', @@ -1573,7 +1625,6 @@ module.exports = function(app, template, hook) { ]); done(); }); - }); it('Doesn\'t require a conditionally hidden field', function(done) { @@ -1928,11 +1979,12 @@ module.exports = function(app, template, hook) { assert.deepEqual(submission.details, [ { context: { + hasLabel: true, + index: 0, key: 'requiredField', label: 'Required Field', setting: true, validator: 'required', - value: '' }, message: 'Required Field is required', level: 'error', @@ -1941,7 +1993,6 @@ module.exports = function(app, template, hook) { ]); done(); }); - }); it('Doesn\'t require a conditionally hidden field in a panel', function(done) { @@ -2636,6 +2687,8 @@ module.exports = function(app, template, hook) { assert.deepEqual(submission.details, [ { context: { + hasLabel: true, + index: 0, key: 'textField', label: 'Text Field', setting: false, @@ -2758,9 +2811,11 @@ module.exports = function(app, template, hook) { var submission = helper.getLastSubmission(); assert.equal(helper.lastResponse.statusCode, 400); assert.equal(helper.lastResponse.body.name, 'ValidationError'); - assert.equal(helper.lastResponse.body.details.length, 1); + assert.equal(helper.lastResponse.body.details.length, 2); assert.equal(helper.lastResponse.body.details[0].message, 'Text Field is required'); + assert.equal(helper.lastResponse.body.details[1].message, 'Text Field must be a non-empty array'); assert.deepEqual(helper.lastResponse.body.details[0].path, ['textField']); + assert.deepEqual(helper.lastResponse.body.details[1].path, ['textField']); done(); }); }); @@ -3147,7 +3202,8 @@ module.exports = function(app, template, hook) { var submission = helper.getLastSubmission(); assert.deepEqual(submission.data, {name: 'testing'}); - assert.deepEqual(submission.metadata, {testing: 'hello'}); + assert(submission.metadata.hasOwnProperty('headers') && !_.isEmpty(submission.metadata.headers), 'Submission metadata should include post headers'); + assert.deepEqual(_.omit(submission.metadata, ['headers']), {testing: 'hello'}); done(); }); }); @@ -3470,11 +3526,12 @@ module.exports = function(app, template, hook) { assert.deepEqual(submission.details, [ { context: { + hasLabel: true, + index: 0, key: 'changeme', label: 'Two', setting: true, validator: 'required', - value: '' }, level: 'error', message: 'Two is required', @@ -3681,11 +3738,12 @@ module.exports = function(app, template, hook) { assert.deepEqual(res.body.details, [ { context: { + hasLabel: true, + index: 0, key: 'test', label: 'Test', setting: true, validator: 'required', - value: '' }, level: 'error', message: 'Test is required', @@ -4052,6 +4110,153 @@ module.exports = function(app, template, hook) { }); }); + if (app.hasProjects && !docker) { + describe('Custom Submission collections', function() { + before((done) => { + if (helper.getForm('fruits')) { + return done(); + } + // Create a resource to keep records. + helper + .form('fruits', [ + { + "input": true, + "tableView": true, + "inputType": "text", + "inputMask": "", + "label": "Name", + "key": "name", + "placeholder": "", + "prefix": "", + "suffix": "", + "multiple": false, + "defaultValue": "", + "protected": false, + "unique": false, + "persistent": true, + "validate": { + "required": false, + "minLength": "", + "maxLength": "", + "pattern": "", + "custom": "", + "customPrivate": false + }, + "conditional": { + "show": null, + "when": null, + "eq": "" + }, + "type": "textfield" + } + ]) + .submission('fruits', {name: 'Apple'}) + .submission('fruits', {name: 'Pear'}) + .submission('fruits', {name: 'Banana'}) + .submission('fruits', {name: 'Orange'}) + .execute(function(err) { + if (err) { + return done(err); + } + + done(); + }); + }); + + it('Should allow to use a custom submission collection', done => { + const hosted = template.config.formio.hosted; + template.config.formio.hosted = false; + const isDone = function(err) { + template.config.formio.hosted = hosted; + done(err); + }; + const setProjectCollection = function(form, next) { + _.set(form, 'settings.collection', 'testCollection'); + updateFormAndGetSubmissions(form, (err, submissions) => { + if (err) { + assert(err && err.message && err.message.indexOf('Only Enterprise projects can set different form collections') !== -1); + request(app) + .post('/project/' + helper.template.project._id + '/upgrade') + .set('x-jwt-token', helper.owner.token) + .send({plan: 'commercial'}) + .expect(200) + .end(function(err) { + if (err) { + return next(err); + } + setProjectCollection(form, next); + }); + } + else { + next(null, submissions); + } + }); + }; + helper.getSubmissions('fruits', (err, formsubs) => { + if (err) { + return isDone(err); + } + + assert.equal(formsubs.length, 4); + assert.deepEqual(formsubs.map((sub) => { + return sub.data.name; + }).sort(), ['Apple', 'Banana', 'Orange', 'Pear']); + const form = helper.getForm('fruits'); + assert.equal(!!form, true); + setProjectCollection(form, (err, submissions) => { + if (err) { + return isDone(err); + } + assert.equal(submissions.length, 0); + helper + .submission('fruits', {name: 'Peach'}) + .submission('fruits', {name: 'Blueberry'}) + .submission('fruits', {name: 'Strawberry'}) + .execute(function(err) { + if (err) { + return isDone(err); + } + helper.getSubmissions('fruits', (err, formsubs) => { + if (err) { + isDone(err); + } + assert.equal(formsubs.length, 3); + assert.deepEqual(formsubs.map((sub) => { + return sub.data.name; + }).sort(), ['Blueberry', 'Peach', 'Strawberry']); + helper.deleteSubmission(formsubs.find(sub => (sub.data.name === 'Strawberry')), (err) => { + if (err) { + isDone(err); + } + helper.getSubmissions('fruits', (err, formsubs) => { + if (err) { + isDone(err); + } + assert.equal(formsubs.length, 2); + assert.deepEqual(formsubs.map((sub) => { + return sub.data.name; + }).sort(), ['Blueberry', 'Peach']); + _.unset(form, 'settings.collection'); + updateFormAndGetSubmissions(form, (err, formsubs) => { + if (err) { + return isDone(err); + } + assert.equal(formsubs.length, 4); + assert.deepEqual(formsubs.map((sub) => { + return sub.data.name; + }).sort(), ['Apple', 'Banana', 'Orange', 'Pear']); + isDone(); + }); + }); + }); + }); + }); + }); + }); + }); + }); + } + // if (app.hasProjects || docker) // it('Should allow an update to the submission where all sub-submissions are also updated.', (done) => { // const existing = _.cloneDeep(helper.lastSubmission); @@ -4088,4 +4293,55 @@ module.exports = function(app, template, hook) { // }); // }); }); + + describe('Submissions without Default Values', (done) => { + before((done) => { + // Create a resource to keep records. + helper + .form('defaultValuesForm', [ + { + "label": "Text Field", + "tableView": true, + "key": "textField", + "type": "textfield", + "input": true + }, + { + "label": "Checkbox", + "tableView": false, + "key": "checkbox", + "type": "checkbox", + "input": true + } + ]) + .execute(function(err) { + if (err) { + return done(err); + } + done(); + }); + }); + + it('Should set submission without default value', (done) => { + helper + .submission('defaultValuesForm', { + data: { + textField: '123' + } + }) + .execute((err) => { + if (err) { + return done(err); + } + + const submission = helper.lastSubmission; + const expectedData = { + textField: '123' + }; + + assert.equal(JSON.stringify(submission.data), JSON.stringify(expectedData)); + done(); + }); + }); + }); }; diff --git a/forms-flow-forms/test/unit.js b/forms-flow-forms/test/unit.js index ca85f9133f..4c4b301f9a 100644 --- a/forms-flow-forms/test/unit.js +++ b/forms-flow-forms/test/unit.js @@ -15,7 +15,7 @@ module.exports = function(app, template, hook) { */ describe('Nunjucks Rendering', function() { it('Should render a string with tokens', function(done) { - new Thread(Thread.Tasks.nunjucks).start({ + new Thread('nunjucks').start({ render: '{{ data.firstName }} {{ data.lastName }}', context: { data: { @@ -39,225 +39,6 @@ module.exports = function(app, template, hook) { }) .catch(done); }); - - it('Should timeout if someone puts bad code in the template', function(done) { - new Thread(Thread.Tasks.nunjucks).start({ - render: '{{ callme() }}', - context: { - callme: function() { - // Loop forever!!!! - while (true) {} - } - } - }) - .then(test => { - // FA-857 - No email will be sent if bad code is given. - assert.equal(test, null); - done(); - }) - .catch(done); - }); - - it('email template threads wont block eachother', function(done) { - let request1 = new Promise((resolve, reject) => { - new Thread(Thread.Tasks.nunjucks).start({ - render: '{{ callme() }}', - context: { - callme: function() { - // Loop forever!!!! - while (true) {} - } - } - }) - .then(test => { - // FA-857 - No email will be sent if bad code is given. - assert.equal(test, null); - resolve(); - }) - .catch(reject); - }); - let request2 = new Promise((resolve, reject) => { - setTimeout(() => { - new Thread(Thread.Tasks.nunjucks).start({ - render: '{{ callme2() }}', - context: { - callme2: function() { - return `hello world`; - } - } - }) - .then(test => { - // FA-857 - No email will be sent if bad code is given. - assert.equal(test, `hello world`); - resolve(); - }) - .catch(reject); - }, 5000); - }); - - Promise.all([request1, request2]) - .then(() => { - return done(); - }) - .catch(done); - }); - - it('email template threads wont block other api requests', function(done) { - let started = []; - let finished = []; - let request1 = new Promise((resolve, reject) => { - started.push('request1'); - new Thread(Thread.Tasks.nunjucks).start({ - render: '{{ callme() }}', - context: { - callme: function() { - // Loop forever!!!! - while (true) {} - } - } - }) - .then(test => { - finished.push('request1'); - // FA-857 - No email will be sent if bad code is given. - assert.equal(test, null); - resolve(); - }) - .catch(reject); - }); - let request2 = new Promise((resolve, reject) => { - setTimeout(() => { - started.push('request2'); - const email = chance.email(); - const password = chance.word({length: 10}); - request(app) - .post(hook.alter('url', '/form/' + template.forms.adminRegister._id + '/submission', template)) - .send({ - data: { - 'email': email, - 'password': password, - } - }) - .expect(200) - .expect('Content-Type', /json/) - .end(function(err, res) { - if (err) { - return reject(err); - } - finished.push('request2'); - - let response = res.body; - assert(response.hasOwnProperty('_id'), 'The response should contain an `_id`.'); - assert(response.hasOwnProperty('modified'), 'The response should contain a `modified` timestamp.'); - assert(response.hasOwnProperty('created'), 'The response should contain a `created` timestamp.'); - assert(response.hasOwnProperty('data'), 'The response should contain a submission `data` object.'); - assert(response.data.hasOwnProperty('email'), 'The submission `data` should contain the `email`.'); - assert.equal(response.data.email, email); - assert(!response.data.hasOwnProperty('password'), 'The submission `data` should not contain the `password`.'); - assert(response.hasOwnProperty('form'), 'The response should contain the resource `form`.'); - assert.equal(response.form, template.resources.admin._id); - assert(res.headers.hasOwnProperty('x-jwt-token'), 'The response should contain a `x-jwt-token` header.'); - assert(response.hasOwnProperty('owner'), 'The response should contain the resource `owner`.'); - assert.notEqual(response.owner, null); - assert.equal(response.owner, response._id); - assert.equal(response.roles.length, 1); - assert.equal(response.roles[0].toString(), template.roles.administrator._id.toString()); - - resolve(); - }); - }, 5000); - }); - - Promise.all([request1, request2]) - .then(() => { - assert.equal(started.length, 2); - assert.equal(started[0], 'request1'); - assert.equal(started[1], 'request2'); - assert.equal(finished.length, 2); - assert.equal(finished[0], 'request2'); - assert.equal(finished[1], 'request1'); - return done(); - }) - .catch(done); - }); - - it('Should not allow them to modify parameters in the template', function(done) { - new Thread(Thread.Tasks.nunjucks).start({ - render: '{% set form = "246" %}{{ form | test1 }} {{ data.firstName }} {{ data.lastName }}', - context: { - form: '123', - data: { - firstName: 'Travis', - lastName: 'Tidwell' - } - }, - filters: { - test1: function(string) { - return this.env.params.form + ' : ' + string; - }.toString() - } - }) - .then(test => { - assert.equal(test, '123 : 246 Travis Tidwell'); - done(); - }) - .catch(done); - }); - - it('Should not expose private context variables.', function(done) { - new Thread(Thread.Tasks.nunjucks).start({ - render: '{{ _private.secret }}', - context: { - _private: { - secret: '5678' - }, - form: '123', - data: { - firstName: 'Travis', - lastName: 'Tidwell' - } - }, - filters: { - test: function(string, param) { - var retVal = this.env.params.form + ' : ' + string; - if (param) { - retVal += ' : ' + param; - } - return retVal; - } - } - }) - .then(test => { - assert.equal(test, ''); - done(); - }) - .catch(done); - }); - - it('Should allow filters to have access to secret variables.', function(done) { - new Thread(Thread.Tasks.nunjucks).start({ - render: '{{ "test" | secret }}', - context: { - _private: { - secret: '5678' - }, - form: '123', - data: { - firstName: 'Travis', - lastName: 'Tidwell' - } - }, - filters: { - secret: function(string, param) { - return this.env.params._private.secret; - }.toString() - } - }) - .then(test => { - assert.equal(test, '5678'); - done(); - }) - .catch(done); - }); }); describe('Email Template Rendering', function() { @@ -267,7 +48,7 @@ module.exports = function(app, template, hook) { var formio = hook.alter('formio', app.formio); var email = require('../src/util/email')(formio); - var sendMessage = function(to, from, message, content, cb) { + var sendMessage = function(to, from, message, content, cb, attachFiles = false) { var dirName = 'fixtures/email/' + message + '/'; var submission = require('./' + dirName + 'submission.json'); var form = require('./' + dirName + 'form.json'); @@ -300,7 +81,8 @@ module.exports = function(app, template, hook) { sendEach: false, subject: 'New submission for {{ form.title }}.', template: '', - message: messageText + message: messageText, + attachFiles }; email.getParams(req, res, form, submission) @@ -349,7 +131,9 @@ module.exports = function(app, template, hook) { assert.equal(getValue('lastName', email.html), 'Smith'); assert.equal(getLabel('birthdate', email.html), 'Birth Date'); //assert.equal(getValue('birthdate', email.html), '2016-06-17'); + assert.equal(getValue('vehicles', email.html), '
MakeModelYear
ChevySuburban2014
ChevyTahoe2014
FordF1502011
'); + assert.equal(getValue('house', email.html), '
Area2500
Single Familytrue
RoomsMaster, Bedroom, Full Bath, Half Bath, Kitchen, Dining, Living, Garage
Address1234 Main, Hampton, AR 71744, USA
'); done(); }); @@ -368,5 +152,24 @@ module.exports = function(app, template, hook) { done(); }); }); + + // Disable until we can resolve test failurs. + if (false) { + it('Should render an email with attached files inside containers and editFrids.', function(done) { + template.hooks.reset(); + sendMessage(['test@example.com'], 'me@example.com', 'test3', '

Hello

', (err, emails) => { + if (err) { + return done(err); + } + + const email = emails[0]; + assert.equal(email.subject, 'New submission for Test Form.'); + + assert(email.attachments.length === 4, 'Email should have all attachments'); + + done(); + }, true); + }); + } }); }; diff --git a/forms-flow-idm/.DS_Store b/forms-flow-idm/.DS_Store deleted file mode 100644 index 6be89cf89766b45fc6a3f7661c8147db63795723..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyG{c!5S)b+K{QuV`U{Zw0~1{e3L5wU6jBDIqQ5HN#h=0KLx^xeqM<>v(t7Om zjxA4ddker;uiG170I;Mx;^4#FeBXU$XB9CbooC!*jcdGMd$*fqpAI*bAq`_;hfH z7J#^5IE?e?C5X)f#9lZhGD5SY5|e7xVp!4{Z~aIC<2E(fpwYx)oU|1n7`DIf*@l>)XHAIBA+RJC>XIIp#h{zUhjH@X|=LE#YP km>A`l3opl4k(7DO=iKjwQ)18=4?0ml1Fnlq3jDPKAI2IZumAu6 diff --git a/forms-flow-idm/LICENSE b/forms-flow-idm/LICENSE new file mode 100644 index 0000000000..cc235ca76b --- /dev/null +++ b/forms-flow-idm/LICENSE @@ -0,0 +1,203 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + Copyright 2020 AppsOnTime Technologies Ltd. + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/forms-flow-idm/keycloak/README.md b/forms-flow-idm/keycloak/README.md index d30b4a2680..63a7946045 100644 --- a/forms-flow-idm/keycloak/README.md +++ b/forms-flow-idm/keycloak/README.md @@ -27,14 +27,15 @@ ### Environment Configuration - * Make sure you have a Docker machine up and running. - * Make sure your current working directory is [forms-flow-ai/forms-flow-idm/keycloak](). - >* *Optional*: Rename the file [sample.env](./sample.env) to **.env**. Skip this step if you want to use the default values as mentioned in the table below. - >* *Optional*: Modify the environment variables in the newly created **.env** file if needed. Environment variables are given in the table below, +* Make sure you have a Docker machine up and running. +* Make sure your current working directory is [forms-flow-ai/forms-flow-idm/keycloak](). +>- *Optional*: Rename the file [sample.env](./sample.env) to **.env**. Skip this step if you want to use the default values as mentioned in the table below. +>* *Optional*: Modify the environment variables in the newly created **.env** file if needed. Environment variables are given in the table below, ### Environment Variables - + #### Keycloak Database Connection Details + ----------------------------------------- ***Skip this for default setup*** @@ -46,6 +47,7 @@ Variable name | Meaning | Possible values | Default value | `KEYCLOAK_JDBC_PASSWORD`|keycloak database postgres password|Used on installation to create the database.Choose your own|`changeit` #### Keycloak Admin Details + ----------------------------------------- ***Skip this for default setup*** @@ -61,38 +63,41 @@ Variable name | Meaning | Possible values | Default value | * `cd {Your Directory}/forms-flow-ai/forms-flow-idm/keycloak` #### To start the keycloak server - + * Run `docker-compose up -d` to start. *NOTE: Use --build command with the start command to reflect any future **.env** changes eg : `docker-compose -f docker-compose-windows.yml up --build -d`* #### To stop the keycloak server - * Run `docker-compose stop` to stop. +* Run `docker-compose stop` to stop. ### Health Check - The application should be up and available for use in http://localhost:8080 - ``` - Login Credentials - ----------------- - User Name : admin - Password : changeme - ``` - +The application should be up and available for use in http://localhost:8080 + +``` +Login Credentials +----------------- +User Name : admin +Password : changeme +``` + #### formsflow-ai user credentials + ----------------------------------- - * Default User credentials are generated when keycloak started for the first time, you can modify the values on your keycloak service. - - User Role | User Name | Password | User Group | - --- | --- | --- | --- - `Designer`|`formsflow-designer`|`changeme`|`formsflow-designer` - `Client`|`formsflow-client`|`changeme`|`formsflow-client` - `Reviewer`|`formsflow-reviewer`|`changeme`|`formsflow-reviewer` - `Clerk`|`formsflow-clerk`|`changeme`|`formsflow-reviewer` - `Approver`|`formsflow-approver`|`changeme`|`formsflow-reviewer` +* Default User credentials are generated when keycloak started for the first time, you can modify the values on your keycloak service. + +User Role | User Name | Password | User Group | +--- | --- | --- | --- +`Designer`|`formsflow-designer`|`changeme`|`formsflow-designer` +`Client`|`formsflow-client`|`changeme`|`formsflow-client` +`Reviewer`|`formsflow-reviewer`|`changeme`|`formsflow-reviewer` +`Clerk`|`formsflow-clerk`|`changeme`|`formsflow-reviewer` +`Approver`|`formsflow-approver`|`changeme`|`formsflow-reviewer` --- + **NOTE** All the default configurations are imported to keycloak during the startup, so no manual changes are required at this stage. @@ -113,7 +118,7 @@ Create a realm **forms-flow-ai** * Login to keycloak with admin privileges * Click the button "Create Realm" to add new realm **forms-flow-ai** -* Click Create +* Click Create. ### Create Keycloak setup for formsflow web @@ -155,10 +160,20 @@ Create a realm **forms-flow-ai** * Mapper Type = Audience * Included Client Audience = forms-flow-web * Click Save - + * Click Create + * Name = dashboard-mapper + * Mapper Type = User Attribute + * User Attribute = dashboards + * Token Claim Name = dashboards + * Add to ID Token = ON + * Add to access token = ON + * Add to userinfo = ON + * Multivalued = ON + * Aggregate attribute values = ON + * Click Save ### Create Keycloak setup for formsflow analytics -#### Create a forms-flow-analytics Client. +#### Create a forms-flow-analytics Client * Login to KeyCloak Realm with admin privileges * Configure > Clients > Create @@ -267,6 +282,17 @@ Create groups to support operations * Click Save * Default Groups Tab (Assign Default Group to self-registering users) * From available groups; map the group "formsflow-client" to "Default Groups". +* Create Main group by Clicking New + * Name = formsflow-analytics + * Click Save +* Create Sub group by Clicking on Main group created on step-1 i.e. formsflow-analytics, and then click New + * Name = group1 + * Click Save +* Create Sub group by Clicking on Main group created on step-1 i.e. formsflow-analytics, and then click New + * Name = group2 + * Click Save + +You can create as many sub-groups as you want for dashboard authorization feature #### Map roles to group diff --git a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json index 5cbe78e2cf..f738937120 100644 --- a/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json +++ b/forms-flow-idm/keycloak/imports/formsflow-ai-realm.json @@ -429,6 +429,31 @@ ] } ] + }, + { + "name": "formsflow-analytics", + "path": "/formsflow-analytics", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "name": "group2", + "path": "/formsflow-analytics/group2", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + }, + { + "name": "group1", + "path": "/formsflow-analytics/group1", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + } + ] } ], "defaultRoles": [ @@ -437,7 +462,8 @@ ], "defaultGroups": [ "/camunda-admin", - "/formsflow" + "/formsflow", + "/formsflow-analytics" ], "requiredCredentials": [ "password" @@ -540,7 +566,7 @@ "disableableCredentialTypes" : [ ], "requiredActions" : [ "UPDATE_PASSWORD" ], "notBefore" : 0, - "groups" : [ "/formsflow/formsflow-reviewer/approver", "/camunda-admin", "/formsflow" ] + "groups" : [ "/formsflow/formsflow-reviewer/approver", "/camunda-admin", "/formsflow" , "/formsflow-analytics/group1"] }, { "createdTimestamp" : 1625009564217, "username" : "formsflow-clerk", @@ -559,7 +585,7 @@ "disableableCredentialTypes" : [ ], "requiredActions" : [ "UPDATE_PASSWORD" ], "notBefore" : 0, - "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer/clerk", "/formsflow" ] + "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer/clerk", "/formsflow", "/formsflow-analytics/group2" ] }, { "createdTimestamp" : 1621862578318, "username" : "formsflow-reviewer", @@ -582,7 +608,7 @@ "account" : [ "view-profile", "manage-account" ] }, "notBefore" : 0, - "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer" ] + "groups" : [ "/camunda-admin", "/formsflow/formsflow-reviewer", "/formsflow-analytics/group1" ] }, { "createdTimestamp" : 1621585233480, "username" : "service-account-forms-flow-bpm", @@ -1101,6 +1127,21 @@ "claim.name": "groups", "userinfo.token.claim": "true" } + }, + { + "name": "dashboard-mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "true", + "userinfo.token.claim": "true", + "multivalued": "true", + "user.attribute": "dashboards", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "dashboards" + } } ], "defaultClientScopes": [ diff --git a/forms-flow-web/Dockerfile b/forms-flow-web/Dockerfile index f933b6492f..0490f9958b 100644 --- a/forms-flow-web/Dockerfile +++ b/forms-flow-web/Dockerfile @@ -17,8 +17,6 @@ ARG REACT_APP_API_SERVER_URL ARG REACT_APP_API_PROJECT_URL ARG REACT_APP_KEYCLOAK_CLIENT ARG REACT_APP_ANONYMOUS_ID -ARG REACT_APP_INSIGHT_API_BASE -ARG REACT_APP_INSIGHTS_API_KEY ARG REACT_APP_WEB_BASE_URL ARG REACT_APP_CAMUNDA_API_URI ARG REACT_APP_WEBSOCKET_ENCRYPT_KEY @@ -27,6 +25,7 @@ ARG REACT_APP_KEYCLOAK_URL ARG REACT_APP_APPLICATION_NAME ARG REACT_APP_USER_ACCESS_PERMISSIONS ARG REACT_APP_WEB_BASE_CUSTOM_URL +ARG REACT_APP_FORMIO_JWT_SECRET ENV NODE_ENV ${NODE_ENV} ENV GENERATE_SOURCEMAP ${GENERATE_SOURCEMAP} @@ -41,8 +40,6 @@ ENV REACT_APP_API_SERVER_URL ${REACT_APP_API_SERVER_URL} ENV REACT_APP_API_PROJECT_URL ${REACT_APP_API_PROJECT_URL} ENV REACT_APP_KEYCLOAK_CLIENT ${REACT_APP_KEYCLOAK_CLIENT} ENV REACT_APP_ANONYMOUS_ID ${REACT_APP_ANONYMOUS_ID} -ENV REACT_APP_INSIGHT_API_BASE ${REACT_APP_INSIGHT_API_BASE} -ENV REACT_APP_INSIGHTS_API_KEY ${REACT_APP_INSIGHTS_API_KEY} ENV REACT_APP_WEB_BASE_URL ${REACT_APP_WEB_BASE_URL} ENV REACT_APP_CAMUNDA_API_URI ${REACT_APP_CAMUNDA_API_URI} ENV REACT_APP_WEBSOCKET_ENCRYPT_KEY ${REACT_APP_WEBSOCKET_ENCRYPT_KEY} @@ -51,7 +48,7 @@ ENV REACT_APP_KEYCLOAK_URL ${REACT_APP_KEYCLOAK_URL} ENV REACT_APP_APPLICATION_NAME ${REACT_APP_APPLICATION_NAME} ENV REACT_APP_USER_ACCESS_PERMISSIONS ${REACT_APP_USER_ACCESS_PERMISSIONS} ENV REACT_APP_WEB_BASE_CUSTOM_URL ${REACT_APP_WEB_BASE_CUSTOM_URL} - +ENV REACT_APP_FORMIO_JWT_SECRET ${REACT_APP_FORMIO_JWT_SECRET} # add `/app/node_modules/.bin` to $PATH ENV PATH /forms-flow-web/app/node_modules/.bin:$PATH diff --git a/forms-flow-web/LICENSE b/forms-flow-web/LICENSE new file mode 100644 index 0000000000..cc235ca76b --- /dev/null +++ b/forms-flow-web/LICENSE @@ -0,0 +1,203 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + Copyright 2020 AppsOnTime Technologies Ltd. + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/forms-flow-web/README.md b/forms-flow-web/README.md index 93ca80659d..c73525a757 100644 --- a/forms-flow-web/README.md +++ b/forms-flow-web/README.md @@ -2,7 +2,7 @@ ![React](https://img.shields.io/badge/React-17.0.2-blue) -**formsflow.ai** delivers progressive web application with React version `17.0.2` and `create-react-app`. Also currently uses [form.io](https://github.com/formio/formio) version `2.0.0--rc.34`. +**formsflow.ai** delivers progressive web application with React version `17.0.2` and `create-react-app`. Also currently uses [form.io](https://github.com/formio/formio) version `2.3.0`. A React library for rendering out forms based on the form.io platform. @@ -19,6 +19,7 @@ with your project by installing our [npm package](https://www.npmjs.com/package/ - [Step 4 : Health Check](#health-check) 3. [How to Create Your First Form](#how-to-create-your-first-form) 4. [Logo change](#logo-change) +5. [Code coverage](#code-coverage) ## Prerequisites @@ -50,8 +51,6 @@ is mentioned on the [link](../forms-flow-idm/keycloak/README.md#create-forms-flo --- | --- | --- | --- `NODE_ENV`| Define project level configuration | `development, test, production` | `development` `FORMIO_DEFAULT_PROJECT_URL`:triangular_flag_on_post:|The URL of the form.io server||`http://{your-ip-address}:3001` - `INSIGHT_API_URL`:triangular_flag_on_post:|Insight Api base end-point||`http://{your-ip-address}:7000` - `INSIGHT_API_KEY`:triangular_flag_on_post:|API_KEY from REDASH|eg. G6ozrFn15l5YJkpHcMZaKOlAhYZxFPhJl5Xr7vQw|`Get the api key from forms-flow-analytics (REDASH) by following the 'Get the Redash API Key' steps from `[here](../forms-flow-analytics/README.md#get-the-redash-api-key) `FORMSFLOW_API_URL`:triangular_flag_on_post:|formsflow Rest API URL||`http://{your-ip-address}:5000/api` `CAMUNDA_API_URL`:triangular_flag_on_post:|Camunda Rest API URL||`http://{your-ip-address}:8000/camunda` `KEYCLOAK_URL`:triangular_flag_on_post:| URL to your Keycloak server || `http://{your-ip-address}:8080` @@ -61,6 +60,7 @@ is mentioned on the [link](../forms-flow-idm/keycloak/README.md#create-forms-flo `APPLICATION_NAME`|Application name is used to provide clients application name| `WEB_BASE_CUSTOM_URL`|Clients can use WEB_BASE_CUSTOM_URL env variable to provide their custom URL | `USER_ACCESS_PERMISSIONS`| JSON formatted permissions to enable / disable few access on user login.|| `{"accessAllowApplications":false,"accessAllowSubmissions":false}` + |`FORMIO_JWT_SECRET`|forms-flow-forms jwt secret| |`--- change me now ---` * NOTE - While configuring USER_ACCESS_PERMISSIONS the accessAllowApplications will hide / show application tab, the same way accessAllowSubmissions does for viewSubmission button. To enable this feature you need to add access-allow-applications, access-allow-submissions with the respective user group in keycloak. @@ -105,6 +105,14 @@ Variable name | Meaning | Possible values | Default value | * Default Logo can be changed to the users logo by replacing the logo.svg in public folder of forms-flow-web. The default width and height of the logo is 50 and 55 also the image format is svg * The icon can also be replaced to the users icon by replacing the favicon in the public folder of forms-flow-web + +### Code coverage + * Test cases for the files are provided at forms-flow-web using [testing-library/jest-dom](https://testing-library.com/docs/ecosystem-jest-dom/) , [testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) , [msw](https://mswjs.io/) and [redux-mock-store](https://www.npmjs.com/package/redux-mock-store). + * `cd {Your Directory}/forms-flow-ai/forms-flow-web`. + * Test files are available at `forms-flow-ai\forms-flow-web\src\_tests_` + * Run the command `npm run coverage` to get the total coverage and for individual files run `npm test --`. + * Total code coverage can obtain by opening `forms-flow-ai\forms-flow-web\coverage\lcov-report\index.html` with browser. + ## forms-flow-web Events > This section elaborates events used in forms-flow-web. > The Form.io renderer uses the [EventEmitter3](https://github.com/primus/eventemitter3) library to manage all of the event handling that occurs within the renderer. diff --git a/forms-flow-web/docker-compose.yml b/forms-flow-web/docker-compose.yml index 842801c5c3..841d70a43e 100644 --- a/forms-flow-web/docker-compose.yml +++ b/forms-flow-web/docker-compose.yml @@ -20,8 +20,6 @@ services: - REACT_APP_API_SERVER_URL=${FORMIO_DEFAULT_PROJECT_URL} - REACT_APP_API_PROJECT_URL=${FORMIO_DEFAULT_PROJECT_URL} - REACT_APP_KEYCLOAK_CLIENT=${KEYCLOAK_WEB_CLIENTID:-forms-flow-web} - - REACT_APP_INSIGHT_API_BASE=${INSIGHT_API_URL} - - REACT_APP_INSIGHTS_API_KEY=${INSIGHT_API_KEY} - REACT_APP_WEB_BASE_URL=${FORMSFLOW_API_URL} - REACT_APP_CAMUNDA_API_URI=${CAMUNDA_API_URL} - REACT_APP_WEBSOCKET_ENCRYPT_KEY=${WEBSOCKET_ENCRYPT_KEY} @@ -30,6 +28,7 @@ services: - REACT_APP_APPLICATION_NAME=${APPLICATION_NAME:-formsflow.ai} - REACT_APP_USER_ACCESS_PERMISSIONS=${USER_ACCESS_PERMISSIONS} - REACT_APP_WEB_BASE_CUSTOM_URL=${WEB_BASE_CUSTOM_URL} + - REACT_APP_FORMIO_JWT_SECRET=${FORMIO_JWT_SECRET:---- change me now ---} volumes: - ".:/app" - "/app/node_modules" diff --git a/forms-flow-web/jest.config.json b/forms-flow-web/jest.config.json new file mode 100644 index 0000000000..73b3cce233 --- /dev/null +++ b/forms-flow-web/jest.config.json @@ -0,0 +1,23 @@ +{ + "collectCoverage": true, + "coveragePathIgnorePatterns": [ + "node_modules", + "../forms-flow-web" + ], + "collectCoverageFrom": [ + "src/**/*.js", + "!**/node_modules/**", + "!**/forms-flow-web/**", + "!**/build/**", + "!**/dist/**" + ], + "coverageReporters": [ + "text-summary", + "lcov", + "cobertura" + ], + "testMatch": [ + "**/*.test.js", + "**/*.spec.js" + ] + } \ No newline at end of file diff --git a/forms-flow-web/package-lock.json b/forms-flow-web/package-lock.json index 6389af825b..487b8f7eb3 100644 --- a/forms-flow-web/package-lock.json +++ b/forms-flow-web/package-lock.json @@ -1,21 +1,21 @@ { "name": "formsflow-ai-react", - "version": "4.0.2", + "version": "4.0.4", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.16.0" } }, "@babel/compat-data": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.0.tgz", - "integrity": "sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q==" + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz", + "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==" }, "@babel/core": { "version": "7.12.3", @@ -38,146 +38,48 @@ "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } } }, "@babel/generator": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.2.tgz", - "integrity": "sha512-OnADYbKrffDVai5qcpkMxQ7caomHOoEwjkouqnN2QhydAjowFAZcsdecFIRUBdb+ZcruwYE4ythYmF1UBZU5xQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", + "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", "requires": { - "@babel/types": "^7.14.2", + "@babel/types": "^7.16.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } } }, "@babel/helper-annotate-as-pure": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", - "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz", + "integrity": "sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg==", "requires": { - "@babel/types": "^7.12.13" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz", - "integrity": "sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.0.tgz", + "integrity": "sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ==", "requires": { - "@babel/helper-explode-assignable-expression": "^7.12.13", - "@babel/types": "^7.12.13" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-explode-assignable-expression": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-compilation-targets": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz", - "integrity": "sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz", + "integrity": "sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==", "requires": { - "@babel/compat-data": "^7.13.15", - "@babel/helper-validator-option": "^7.12.17", - "browserslist": "^4.14.5", + "@babel/compat-data": "^7.16.0", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.17.6", "semver": "^6.3.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", - "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", - "escalade": "^3.1.1", - "node-releases": "^1.1.73" - } - }, - "caniuse-lite": { - "version": "1.0.30001251", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", - "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==" - }, - "electron-to-chromium": { - "version": "1.3.805", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.805.tgz", - "integrity": "sha512-uUJF59M6pNSRHQaXwdkaNB4BhSQ9lldRdG1qCjlrAFkynPGDc5wPoUcYEQQeQGmKyAWJPvGkYAWmtVrxWmDAkg==" - }, - "node-releases": { - "version": "1.1.74", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.74.tgz", - "integrity": "sha512-caJBVempXZPepZoZAPCWRTNxYQ+xtG/KAi4ozTA5A+nJ7IU+kLQCbqaUjb5Rwy14M9upBWiQ4NutcmW04LJSRw==" + "version": "^4.17.6" }, "semver": { "version": "6.3.0", @@ -187,31 +89,31 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.2.tgz", - "integrity": "sha512-6YctwVsmlkchxfGUogvVrrhzyD3grFJyluj5JgDlQrwfMLJSt5tdAzFZfPf4H2Xoi5YLcQ6BxfJlaOBHuctyIw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz", + "integrity": "sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13" + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz", - "integrity": "sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.0.tgz", + "integrity": "sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-annotate-as-pure": "^7.16.0", "regexpu-core": "^4.7.1" } }, "@babel/helper-define-polyfill-provider": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.0.tgz", - "integrity": "sha512-JT8tHuFjKBo8NnaUbblz7mIu1nnvUDiHVjXXkulZULyidvo/7P6TY7+YqpV37IfF+KUFxmlK04elKtGKXaiVgw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz", + "integrity": "sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==", "requires": { "@babel/helper-compilation-targets": "^7.13.0", "@babel/helper-module-imports": "^7.12.13", @@ -223,28 +125,6 @@ "semver": "^6.1.2" }, "dependencies": { - "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -253,471 +133,219 @@ } }, "@babel/helper-explode-assignable-expression": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz", - "integrity": "sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz", + "integrity": "sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ==", "requires": { - "@babel/types": "^7.13.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-function-name": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", - "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", + "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", "requires": { - "@babel/helper-get-function-arity": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/types": "^7.14.2" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-get-function-arity": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-get-function-arity": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", - "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", + "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", "requires": { - "@babel/types": "^7.12.13" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-hoist-variables": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz", - "integrity": "sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz", + "integrity": "sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==", "requires": { - "@babel/traverse": "^7.13.15", - "@babel/types": "^7.13.16" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", - "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz", + "integrity": "sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==", "requires": { - "@babel/types": "^7.13.12" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-module-transforms": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz", - "integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz", + "integrity": "sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==", "requires": { - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-simple-access": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/helper-validator-identifier": "^7.14.0", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.2" - }, - "dependencies": { - "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-simple-access": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/helper-validator-identifier": "^7.15.7", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-optimise-call-expression": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", - "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz", + "integrity": "sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==", "requires": { - "@babel/types": "^7.12.13" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==" + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==" }, "@babel/helper-remap-async-to-generator": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz", - "integrity": "sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg==", + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.4.tgz", + "integrity": "sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-wrap-function": "^7.13.0", - "@babel/types": "^7.13.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-wrap-function": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-replace-supers": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", - "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz", + "integrity": "sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.13.0", - "@babel/types": "^7.13.12" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-simple-access": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", - "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz", + "integrity": "sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==", "requires": { - "@babel/types": "^7.13.12" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", - "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", "requires": { - "@babel/types": "^7.12.1" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", - "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", + "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", "requires": { - "@babel/types": "^7.12.13" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.16.0" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==" }, "@babel/helper-validator-option": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", - "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==" + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==" }, "@babel/helper-wrap-function": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz", - "integrity": "sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz", + "integrity": "sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g==", "requires": { - "@babel/helper-function-name": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.13.0", - "@babel/types": "^7.13.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-function-name": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helpers": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz", - "integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.3.tgz", + "integrity": "sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w==", "requires": { - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.3", + "@babel/types": "^7.16.0" } }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.15.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } } }, "@babel/parser": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.2.tgz", - "integrity": "sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ==" + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.4.tgz", + "integrity": "sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz", + "integrity": "sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz", - "integrity": "sha512-d0u3zWKcoZf379fOeJdr1a5WPDny4aOFZ6hlfKivgK0LY7ZxNfoaHL2fWwdGtHyVvra38FC+HVYkO+byfSA8AQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.0.tgz", + "integrity": "sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.13.12" + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0" } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.2.tgz", - "integrity": "sha512-b1AM4F6fwck4N8ItZ/AtC4FP/cqZqmKRQ4FaTDutwSYyjuhtvsGEMLK4N/ztV/ImP40BjIDyMgBQAeAMsQYVFQ==", + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.4.tgz", + "integrity": "sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-remap-async-to-generator": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.16.4", "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz", - "integrity": "sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz", + "integrity": "sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.13.0", - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-create-class-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-proposal-class-static-block": { - "version": "7.13.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.13.11.tgz", - "integrity": "sha512-fJTdFI4bfnMjvxJyNuaf8i9mVcZ0UhetaGEUHaHV9KEnibLugJkZAtXikR8KcYj+NYmI4DZMS8yQAyg+hvfSqg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz", + "integrity": "sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-class-static-block": "^7.12.13" + "@babel/helper-create-class-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-proposal-decorators": { @@ -731,117 +359,117 @@ } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.2.tgz", - "integrity": "sha512-oxVQZIWFh91vuNEMKltqNsKLFWkOIyJc95k2Gv9lWVyDfPUQGSSlbDEgWuJUU1afGE9WwlzpucMZ3yDRHIItkA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz", + "integrity": "sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-export-namespace-from": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.2.tgz", - "integrity": "sha512-sRxW3z3Zp3pFfLAgVEvzTFutTXax837oOatUIvSG9o5gRj9mKwm3br1Se5f4QalTQs9x4AzlA/HrCWbQIHASUQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz", + "integrity": "sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.2.tgz", - "integrity": "sha512-w2DtsfXBBJddJacXMBhElGEYqCZQqN99Se1qeYn8DVLB33owlrlLftIbMzn5nz1OITfDVknXF433tBrLEAOEjA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz", + "integrity": "sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.2.tgz", - "integrity": "sha512-1JAZtUrqYyGsS7IDmFeaem+/LJqujfLZ2weLR9ugB0ufUPjzf8cguyVT1g5im7f7RXxuLq1xUxEzvm68uYRtGg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz", + "integrity": "sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.2.tgz", - "integrity": "sha512-ebR0zU9OvI2N4qiAC38KIAK75KItpIPTpAtd2r4OZmMFeKbKJpUFLYP2EuDut82+BmYi8sz42B+TfTptJ9iG5Q==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz", + "integrity": "sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.2.tgz", - "integrity": "sha512-DcTQY9syxu9BpU3Uo94fjCB3LN9/hgPS8oUL7KrSW3bA2ePrKZZPJcc5y0hoJAM9dft3pGfErtEUvxXQcfLxUg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz", + "integrity": "sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.2.tgz", - "integrity": "sha512-hBIQFxwZi8GIp934+nj5uV31mqclC1aYDhctDu5khTi9PCCUOczyy0b34W0oE9U/eJXiqQaKyVsmjeagOaSlbw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz", + "integrity": "sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg==", "requires": { - "@babel/compat-data": "^7.14.0", - "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/compat-data": "^7.16.0", + "@babel/helper-compilation-targets": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.14.2" + "@babel/plugin-transform-parameters": "^7.16.0" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.2.tgz", - "integrity": "sha512-XtkJsmJtBaUbOxZsNk0Fvrv8eiqgneug0A6aqLFZ4TSkar2L5dSXWcnUKHgmjJt49pyB/6ZHvkr3dPgl9MOWRQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz", + "integrity": "sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.2.tgz", - "integrity": "sha512-qQByMRPwMZJainfig10BoaDldx/+VDtNcrA7qdNaEOAj6VXud+gfrkA8j4CRAU5HjnWREXqIpSpH30qZX1xivA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz", + "integrity": "sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-private-methods": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.13.0.tgz", - "integrity": "sha512-MXyyKQd9inhx1kDYPkFRVOBXQ20ES8Pto3T7UZ92xj2mY0EVD8oAVzeyYuVfy/mxAdTSIayOvg+aVzcHV2bn6Q==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz", + "integrity": "sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.13.0", - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-create-class-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-proposal-private-property-in-object": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.0.tgz", - "integrity": "sha512-59ANdmEwwRUkLjB7CRtwJxxwtjESw+X2IePItA+RGQh+oy5RmpCh/EvVVvh5XQc3yxsm5gtv0+i9oBZhaDNVTg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz", + "integrity": "sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw==", "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-create-class-features-plugin": "^7.14.0", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-private-property-in-object": "^7.14.0" + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-create-class-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz", - "integrity": "sha512-XyJmZidNfofEkqFV5VC/bLabGmO5QzenPO/YOfGuEbgU+2sSwMmio3YLb4WtBgcmmdwZHyVyv8on77IUjQ5Gvg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz", + "integrity": "sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-async-generators": { @@ -869,19 +497,19 @@ } }, "@babel/plugin-syntax-class-static-block": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.12.13.tgz", - "integrity": "sha512-ZmKQ0ZXR0nYpHZIIuj9zE7oIqCx2hw9TKi+lIo73NNrMPAZGHfS92/VRV0ZmPj6H2ffBgyFHXvJ5NYsNeEaP2A==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-decorators": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.13.tgz", - "integrity": "sha512-Rw6aIXGuqDLr6/LoBBYE57nKOzQpz/aDkKlMqEwH+Vp0MXbG6H/TfRjaY343LKxzAKAMXIHsQ8JzaZKuDZ9MwA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.0.tgz", + "integrity": "sha512-nxnnngZClvlY13nHJAIDow0S7Qzhq64fQ/NlqS+VER3kjW/4F0jLhXjeL8jcwSwz6Ca3rotT5NJD2T9I7lcv7g==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-dynamic-import": { @@ -901,11 +529,11 @@ } }, "@babel/plugin-syntax-flow": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.12.13.tgz", - "integrity": "sha512-J/RYxnlSLXZLVR7wTRsozxKT8qbsx1mNKJzXEEjQ0Kjx1ZACcyHgbanNWNCFtc36IzuWhYWPpvJFFoexoOWFmA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.0.tgz", + "integrity": "sha512-dH91yCo0RyqfzWgoM5Ji9ir8fQ+uFbt9KHM3d2x4jZOuHS6wNA+CRmRUP/BWCsHG2bjc7A2Way6AvH1eQk0wig==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-import-meta": { @@ -925,11 +553,11 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz", - "integrity": "sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.0.tgz", + "integrity": "sha512-8zv2+xiPHwly31RK4RmnEYY5zziuF3O7W2kIDW+07ewWDh6Oi0dRq8kwvulRkFgt6DB97RlKs5c1y068iPlCUg==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -981,141 +609,117 @@ } }, "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.0.tgz", - "integrity": "sha512-bda3xF8wGl5/5btF794utNOL0Jw+9jE5C1sLZcoK7c4uonE/y3iQiyG+KbkF3WBV/paX58VCpjhxLPkdj5Fe4w==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-top-level-await": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz", - "integrity": "sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-typescript": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.13.tgz", - "integrity": "sha512-cHP3u1JiUiG2LFDKbXnwVad81GvfyIOmCD6HIEId6ojrY0Drfy2q1jw7BwN7dE84+kTnBjLkXoL3IEy/3JPu2w==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz", + "integrity": "sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.13.0.tgz", - "integrity": "sha512-96lgJagobeVmazXFaDrbmCLQxBysKu7U6Do3mLsx27gf5Dk85ezysrs2BZUpXD703U/Su1xTBDxxar2oa4jAGg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz", + "integrity": "sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.13.0.tgz", - "integrity": "sha512-3j6E004Dx0K3eGmhxVJxwwI89CTJrce7lg3UrtFuDAVQ/2+SJ/h/aSFOeE6/n0WB1GsOffsJp6MnPQNQ8nmwhg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz", + "integrity": "sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw==", "requires": { - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-remap-async-to-generator": "^7.13.0" - }, - "dependencies": { - "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.16.0" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.13.tgz", - "integrity": "sha512-zNyFqbc3kI/fVpqwfqkg6RvBgFpC4J18aKKMmv7KdQ/1GgREapSJAykLMVNwfRGO3BtHj3YQZl8kxCXPcVMVeg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz", + "integrity": "sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.2.tgz", - "integrity": "sha512-neZZcP19NugZZqNwMTH+KoBjx5WyvESPSIOQb4JHpfd+zPfqcH65RMu5xJju5+6q/Y2VzYrleQTr+b6METyyxg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz", + "integrity": "sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-classes": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.2.tgz", - "integrity": "sha512-7oafAVcucHquA/VZCsXv/gmuiHeYd64UJyyTYU+MPfNu0KeNlxw06IeENBO8bJjXVbolu+j1MM5aKQtH1OMCNg==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz", + "integrity": "sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.13.0.tgz", - "integrity": "sha512-RRqTYTeZkZAz8WbieLTvKUEUxZlUTdmL5KGMyZj7FnMfLNKV4+r5549aORG/mgojRmFlQMJDUupwAMiF2Q7OUg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz", + "integrity": "sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-destructuring": { - "version": "7.13.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz", - "integrity": "sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz", + "integrity": "sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.13.tgz", - "integrity": "sha512-foDrozE65ZFdUC2OfgeOCrEPTxdB3yjqxpXh8CH+ipd9CHd4s/iq81kcUpyH8ACGNEPdFqbtzfgzbT/ZGlbDeQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz", + "integrity": "sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.13.tgz", - "integrity": "sha512-NfADJiiHdhLBW3pulJlJI2NB0t4cci4WTZ8FtdIuNc2+8pslXdPtRRAEWqUY+m9kNOk2eRYbTAOipAxlrOcwwQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz", + "integrity": "sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.13.tgz", - "integrity": "sha512-fbUelkM1apvqez/yYx1/oICVnGo2KM5s63mhGylrmXUxK/IAXSIf87QIxVfZldWf4QsOafY6vV3bX8aMHSvNrA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz", + "integrity": "sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw==", "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-flow-strip-types": { @@ -1128,227 +732,196 @@ } }, "@babel/plugin-transform-for-of": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.13.0.tgz", - "integrity": "sha512-IHKT00mwUVYE0zzbkDgNRP6SRzvfGCYsOxIRz8KsiaaHCcT9BWIkO+H9QRJseHBLOGBZkHUdHiqj6r0POsdytg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz", + "integrity": "sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-function-name": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.13.tgz", - "integrity": "sha512-6K7gZycG0cmIwwF7uMK/ZqeCikCGVBdyP2J5SKNCXO5EOHcqi+z7Jwf8AmyDNcBgxET8DrEtCt/mPKPyAzXyqQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz", + "integrity": "sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg==", "requires": { - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-literals": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.13.tgz", - "integrity": "sha512-FW+WPjSR7hiUxMcKqyNjP05tQ2kmBCdpEpZHY1ARm96tGQCCBvXKnpjILtDplUnJ/eHZ0lALLM+d2lMFSpYJrQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz", + "integrity": "sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.13.tgz", - "integrity": "sha512-kxLkOsg8yir4YeEPHLuO2tXP9R/gTjpuTOjshqSpELUN3ZAg2jfDnKUvzzJxObun38sw3wm4Uu69sX/zA7iRvg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz", + "integrity": "sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.2.tgz", - "integrity": "sha512-hPC6XBswt8P3G2D1tSV2HzdKvkqOpmbyoy+g73JG0qlF/qx2y3KaMmXb1fLrpmWGLZYA0ojCvaHdzFWjlmV+Pw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz", + "integrity": "sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw==", "requires": { - "@babel/helper-module-transforms": "^7.14.2", - "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-module-transforms": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz", - "integrity": "sha512-EX4QePlsTaRZQmw9BsoPeyh5OCtRGIhwfLquhxGp5e32w+dyL8htOcDwamlitmNFK6xBZYlygjdye9dbd9rUlQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz", + "integrity": "sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ==", "requires": { - "@babel/helper-module-transforms": "^7.14.0", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-simple-access": "^7.13.12", + "@babel/helper-module-transforms": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-simple-access": "^7.16.0", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.13.8.tgz", - "integrity": "sha512-hwqctPYjhM6cWvVIlOIe27jCIBgHCsdH2xCJVAYQm7V5yTMoilbVMi9f6wKg0rpQAOn6ZG4AOyvCqFF/hUh6+A==", - "requires": { - "@babel/helper-hoist-variables": "^7.13.0", - "@babel/helper-module-transforms": "^7.13.0", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-validator-identifier": "^7.12.11", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz", + "integrity": "sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg==", + "requires": { + "@babel/helper-hoist-variables": "^7.16.0", + "@babel/helper-module-transforms": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-identifier": "^7.15.7", "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - } } }, "@babel/plugin-transform-modules-umd": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.0.tgz", - "integrity": "sha512-nPZdnWtXXeY7I87UZr9VlsWme3Y0cfFFE41Wbxz4bbaexAjNMInXPFUpRRUJ8NoMm0Cw+zxbqjdPmLhcjfazMw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz", + "integrity": "sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg==", "requires": { - "@babel/helper-module-transforms": "^7.14.0", - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-module-transforms": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.13.tgz", - "integrity": "sha512-Xsm8P2hr5hAxyYblrfACXpQKdQbx4m2df9/ZZSQ8MAhsadw06+jW7s9zsSw6he+mJZXRlVMyEnVktJo4zjk1WA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz", + "integrity": "sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.16.0" } }, "@babel/plugin-transform-new-target": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.13.tgz", - "integrity": "sha512-/KY2hbLxrG5GTQ9zzZSc3xWiOy379pIETEhbtzwZcw9rvuaVV4Fqy7BYGYOWZnaoXIQYbbJ0ziXLa/sKcGCYEQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz", + "integrity": "sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-object-super": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.13.tgz", - "integrity": "sha512-JzYIcj3XtYspZDV8j9ulnoMPZZnF/Cj0LUxPOjR89BdBVx+zYJI9MdMIlUZjbXDX+6YVeS6I3e8op+qQ3BYBoQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.0.tgz", + "integrity": "sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/helper-replace-supers": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.16.0" } }, "@babel/plugin-transform-parameters": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.2.tgz", - "integrity": "sha512-NxoVmA3APNCC1JdMXkdYXuQS+EMdqy0vIwyDHeKHiJKRxmp1qGSdb0JLEIoPRhkx6H/8Qi3RJ3uqOCYw8giy9A==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.3.tgz", + "integrity": "sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-property-literals": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.13.tgz", - "integrity": "sha512-nqVigwVan+lR+g8Fj8Exl0UQX2kymtjcWfMOYM1vTYEKujeyv2SkMgazf2qNcK7l4SDiKyTA/nHCPqL4e2zo1A==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz", + "integrity": "sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-react-constant-elements": { - "version": "7.13.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.13.13.tgz", - "integrity": "sha512-SNJU53VM/SjQL0bZhyU+f4kJQz7bQQajnrZRSaU21hruG/NWY41AEM9AWXeXX90pYr/C2yAmTgI6yW3LlLrAUQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.0.tgz", + "integrity": "sha512-OgtklS+p9t1X37eWA4XdvvbZG/3gqzX569gqmo3q4/Ui6qjfTQmOs5UTSrfdD9nVByHhX6Gbm/Pyc4KbwUXGWA==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-react-display-name": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.2.tgz", - "integrity": "sha512-zCubvP+jjahpnFJvPaHPiGVfuVUjXHhFvJKQdNnsmSsiU9kR/rCZ41jHc++tERD2zV+p7Hr6is+t5b6iWTCqSw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.0.tgz", + "integrity": "sha512-FJFdJAqaCpndL+pIf0aeD/qlQwT7QXOvR6Cc8JPvNhKJBi2zc/DPc4g05Y3fbD/0iWAMQFGij4+Xw+4L/BMpTg==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.13.12.tgz", - "integrity": "sha512-jcEI2UqIcpCqB5U5DRxIl0tQEProI2gcu+g8VTIqxLO5Iidojb4d77q+fwGseCvd8af/lJ9masp4QWzBXFE2xA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.0.tgz", + "integrity": "sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw==", "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/types": "^7.13.12" - }, - "dependencies": { - "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-jsx": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/plugin-transform-react-jsx-development": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.17.tgz", - "integrity": "sha512-BPjYV86SVuOaudFhsJR1zjgxxOhJDt6JHNoD48DxWEIxUCAMjV1ys6DYw4SDYZh0b1QsS2vfIA9t/ZsQGsDOUQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.0.tgz", + "integrity": "sha512-qq65iSqBRq0Hr3wq57YG2AmW0H6wgTnIzpffTphrUWUgLCOK+zf1f7G0vuOiXrp7dU1qq+fQBoqZ3wCDAkhFzw==", "requires": { - "@babel/plugin-transform-react-jsx": "^7.12.17" + "@babel/plugin-transform-react-jsx": "^7.16.0" } }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.12.13.tgz", - "integrity": "sha512-FXYw98TTJ125GVCCkFLZXlZ1qGcsYqNQhVBQcZjyrwf8FEUtVfKIoidnO8S0q+KBQpDYNTmiGo1gn67Vti04lQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.16.0.tgz", + "integrity": "sha512-97yCFY+2GvniqOThOSjPor8xUoDiQ0STVWAQMl3pjhJoFVe5DuXDLZCRSZxu9clx+oRCbTiXGgKEG/Yoyo6Y+w==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.14.2.tgz", - "integrity": "sha512-OMorspVyjxghAjzgeAWc6O7W7vHbJhV69NeTGdl9Mxgz6PaweAuo7ffB9T5A1OQ9dGcw0As4SYMUhyNC4u7mVg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.16.0.tgz", + "integrity": "sha512-8yvbGGrHOeb/oyPc9tzNoe9/lmIjz3HLa9Nc5dMGDyNpGjfFrk8D2KdEq9NRkftZzeoQEW6yPQ29TMZtrLiUUA==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-react-pure-annotations": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz", - "integrity": "sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.0.tgz", + "integrity": "sha512-NC/Bj2MG+t8Ef5Pdpo34Ay74X4Rt804h5y81PwOpfPtmAK3i6CizmQqwyBQzIepz1Yt8wNr2Z2L7Lu3qBMfZMA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-regenerator": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.13.15.tgz", - "integrity": "sha512-Bk9cOLSz8DiurcMETZ8E2YtIVJbFCPGW28DJWUakmyVWtQSm6Wsf0p4B4BfEr/eL2Nkhe/CICiUiMOCi1TPhuQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz", + "integrity": "sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg==", "requires": { "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.13.tgz", - "integrity": "sha512-xhUPzDXxZN1QfiOy/I5tyye+TRz6lA7z6xaT4CLOjPRMVg1ldRf0LHw0TDBpYL4vG78556WuHdyO9oi5UmzZBg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz", + "integrity": "sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-runtime": { @@ -1360,128 +933,105 @@ "@babel/helper-plugin-utils": "^7.10.4", "resolve": "^1.8.1", "semver": "^5.5.1" - }, - "dependencies": { - "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.13.tgz", - "integrity": "sha512-xpL49pqPnLtf0tVluuqvzWIgLEhuPpZzvs2yabUHSKRNlN7ScYU7aMlmavOeyXJZKgZKQRBlh8rHbKiJDraTSw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.0.tgz", + "integrity": "sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-spread": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.13.0.tgz", - "integrity": "sha512-V6vkiXijjzYeFmQTr3dBxPtZYLPcUfY34DebOU27jIl2M/Y8Egm52Hw82CSjjPqd54GTlJs5x+CR7HeNr24ckg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz", + "integrity": "sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.13.tgz", - "integrity": "sha512-Jc3JSaaWT8+fr7GRvQP02fKDsYk4K/lYwWq38r/UGfaxo89ajud321NH28KRQ7xy1Ybc0VUE5Pz8psjNNDUglg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz", + "integrity": "sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-template-literals": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.13.0.tgz", - "integrity": "sha512-d67umW6nlfmr1iehCcBv69eSUSySk1EsIS8aTDX4Xo9qajAh6mYtcl4kJrBkGXuxZPEgVr7RVfAvNW6YQkd4Mw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz", + "integrity": "sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.13.tgz", - "integrity": "sha512-eKv/LmUJpMnu4npgfvs3LiHhJua5fo/CysENxa45YCQXZwKnGCQKAg87bvoqSW1fFT+HA32l03Qxsm8ouTY3ZQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz", + "integrity": "sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-typescript": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz", - "integrity": "sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.1.tgz", + "integrity": "sha512-NO4XoryBng06jjw/qWEU2LhcLJr1tWkhpMam/H4eas/CDKMX/b2/Ylb6EI256Y7+FVPCawwSM1rrJNOpDiz+Lg==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.13.0", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-typescript": "^7.12.13" + "@babel/helper-create-class-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-typescript": "^7.16.0" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.13.tgz", - "integrity": "sha512-0bHEkdwJ/sN/ikBHfSmOXPypN/beiGqjo+o4/5K+vxEFNPRPdImhviPakMKG4x96l85emoa0Z6cDflsdBusZbw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.0.tgz", + "integrity": "sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A==", "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.13.tgz", - "integrity": "sha512-mDRzSNY7/zopwisPZ5kM9XKCfhchqIYwAKRERtEnhYscZB79VRekuRSoYbN0+KVe3y8+q1h6A4svXtP7N+UoCA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz", + "integrity": "sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-create-regexp-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/preset-env": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.2.tgz", - "integrity": "sha512-7dD7lVT8GMrE73v4lvDEb85cgcQhdES91BSD7jS/xjC6QY8PnRhux35ac+GCpbiRhp8crexBvZZqnaL6VrY8TQ==", - "requires": { - "@babel/compat-data": "^7.14.0", - "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.13.12", - "@babel/plugin-proposal-async-generator-functions": "^7.14.2", - "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-proposal-class-static-block": "^7.13.11", - "@babel/plugin-proposal-dynamic-import": "^7.14.2", - "@babel/plugin-proposal-export-namespace-from": "^7.14.2", - "@babel/plugin-proposal-json-strings": "^7.14.2", - "@babel/plugin-proposal-logical-assignment-operators": "^7.14.2", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.2", - "@babel/plugin-proposal-numeric-separator": "^7.14.2", - "@babel/plugin-proposal-object-rest-spread": "^7.14.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.14.2", - "@babel/plugin-proposal-optional-chaining": "^7.14.2", - "@babel/plugin-proposal-private-methods": "^7.13.0", - "@babel/plugin-proposal-private-property-in-object": "^7.14.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.12.13", + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.4.tgz", + "integrity": "sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==", + "requires": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.2", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-async-generator-functions": "^7.16.4", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-class-static-block": "^7.16.0", + "@babel/plugin-proposal-dynamic-import": "^7.16.0", + "@babel/plugin-proposal-export-namespace-from": "^7.16.0", + "@babel/plugin-proposal-json-strings": "^7.16.0", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-object-rest-spread": "^7.16.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-proposal-private-property-in-object": "^7.16.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.0", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", @@ -1491,63 +1041,49 @@ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.0", - "@babel/plugin-syntax-top-level-await": "^7.12.13", - "@babel/plugin-transform-arrow-functions": "^7.13.0", - "@babel/plugin-transform-async-to-generator": "^7.13.0", - "@babel/plugin-transform-block-scoped-functions": "^7.12.13", - "@babel/plugin-transform-block-scoping": "^7.14.2", - "@babel/plugin-transform-classes": "^7.14.2", - "@babel/plugin-transform-computed-properties": "^7.13.0", - "@babel/plugin-transform-destructuring": "^7.13.17", - "@babel/plugin-transform-dotall-regex": "^7.12.13", - "@babel/plugin-transform-duplicate-keys": "^7.12.13", - "@babel/plugin-transform-exponentiation-operator": "^7.12.13", - "@babel/plugin-transform-for-of": "^7.13.0", - "@babel/plugin-transform-function-name": "^7.12.13", - "@babel/plugin-transform-literals": "^7.12.13", - "@babel/plugin-transform-member-expression-literals": "^7.12.13", - "@babel/plugin-transform-modules-amd": "^7.14.2", - "@babel/plugin-transform-modules-commonjs": "^7.14.0", - "@babel/plugin-transform-modules-systemjs": "^7.13.8", - "@babel/plugin-transform-modules-umd": "^7.14.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13", - "@babel/plugin-transform-new-target": "^7.12.13", - "@babel/plugin-transform-object-super": "^7.12.13", - "@babel/plugin-transform-parameters": "^7.14.2", - "@babel/plugin-transform-property-literals": "^7.12.13", - "@babel/plugin-transform-regenerator": "^7.13.15", - "@babel/plugin-transform-reserved-words": "^7.12.13", - "@babel/plugin-transform-shorthand-properties": "^7.12.13", - "@babel/plugin-transform-spread": "^7.13.0", - "@babel/plugin-transform-sticky-regex": "^7.12.13", - "@babel/plugin-transform-template-literals": "^7.13.0", - "@babel/plugin-transform-typeof-symbol": "^7.12.13", - "@babel/plugin-transform-unicode-escapes": "^7.12.13", - "@babel/plugin-transform-unicode-regex": "^7.12.13", - "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.14.2", - "babel-plugin-polyfill-corejs2": "^0.2.0", - "babel-plugin-polyfill-corejs3": "^0.2.0", - "babel-plugin-polyfill-regenerator": "^0.2.0", - "core-js-compat": "^3.9.0", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.0", + "@babel/plugin-transform-async-to-generator": "^7.16.0", + "@babel/plugin-transform-block-scoped-functions": "^7.16.0", + "@babel/plugin-transform-block-scoping": "^7.16.0", + "@babel/plugin-transform-classes": "^7.16.0", + "@babel/plugin-transform-computed-properties": "^7.16.0", + "@babel/plugin-transform-destructuring": "^7.16.0", + "@babel/plugin-transform-dotall-regex": "^7.16.0", + "@babel/plugin-transform-duplicate-keys": "^7.16.0", + "@babel/plugin-transform-exponentiation-operator": "^7.16.0", + "@babel/plugin-transform-for-of": "^7.16.0", + "@babel/plugin-transform-function-name": "^7.16.0", + "@babel/plugin-transform-literals": "^7.16.0", + "@babel/plugin-transform-member-expression-literals": "^7.16.0", + "@babel/plugin-transform-modules-amd": "^7.16.0", + "@babel/plugin-transform-modules-commonjs": "^7.16.0", + "@babel/plugin-transform-modules-systemjs": "^7.16.0", + "@babel/plugin-transform-modules-umd": "^7.16.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.0", + "@babel/plugin-transform-new-target": "^7.16.0", + "@babel/plugin-transform-object-super": "^7.16.0", + "@babel/plugin-transform-parameters": "^7.16.3", + "@babel/plugin-transform-property-literals": "^7.16.0", + "@babel/plugin-transform-regenerator": "^7.16.0", + "@babel/plugin-transform-reserved-words": "^7.16.0", + "@babel/plugin-transform-shorthand-properties": "^7.16.0", + "@babel/plugin-transform-spread": "^7.16.0", + "@babel/plugin-transform-sticky-regex": "^7.16.0", + "@babel/plugin-transform-template-literals": "^7.16.0", + "@babel/plugin-transform-typeof-symbol": "^7.16.0", + "@babel/plugin-transform-unicode-escapes": "^7.16.0", + "@babel/plugin-transform-unicode-regex": "^7.16.0", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.16.0", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.4.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.19.1", "semver": "^6.3.0" }, "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -1556,9 +1092,9 @@ } }, "@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", @@ -1568,16 +1104,16 @@ } }, "@babel/preset-react": { - "version": "7.13.13", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.13.13.tgz", - "integrity": "sha512-gx+tDLIE06sRjKJkVtpZ/t3mzCDOnPG+ggHZG9lffUbX8+wC739x20YQc9V35Do6ZAxaUc/HhVHIiOzz5MvDmA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.0.tgz", + "integrity": "sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw==", "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-transform-react-display-name": "^7.12.13", - "@babel/plugin-transform-react-jsx": "^7.13.12", - "@babel/plugin-transform-react-jsx-development": "^7.12.17", - "@babel/plugin-transform-react-pure-annotations": "^7.12.1" + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-react-jsx": "^7.16.0", + "@babel/plugin-transform-react-jsx-development": "^7.16.0", + "@babel/plugin-transform-react-pure-annotations": "^7.16.0" } }, "@babel/preset-typescript": { @@ -1590,122 +1126,54 @@ } }, "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", + "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs3": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.0.tgz", - "integrity": "sha512-0R0HTZWHLk6G8jIk0FtoX+AatCtKnswS98VhXwGImFc759PJRp4Tru0PQYZofyijTFUr+gT8Mu7sgXVJLQ0ceg==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.16.3.tgz", + "integrity": "sha512-IAdDC7T0+wEB4y2gbIL0uOXEYpiZEeuFUTVbdGq+UwCcF35T/tS8KrmMomEwEc5wBbyfH3PJVpTSUqrhPDXFcQ==", "requires": { - "core-js-pure": "^3.0.0", + "core-js-pure": "^3.19.0", "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", + "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "requires": { - "@babel/highlight": "^7.12.13" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } + "@babel/code-frame": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", - "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.2", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.2", - "@babel/types": "^7.14.2", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.3.tgz", + "integrity": "sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==", + "requires": { + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.0", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-hoist-variables": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/parser": "^7.16.3", + "@babel/types": "^7.16.0", "debug": "^4.1.0", "globals": "^11.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "requires": { - "@babel/highlight": "^7.12.13" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", + "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", + "@babel/helper-validator-identifier": "^7.15.7", "to-fast-properties": "^2.0.0" } }, @@ -1745,9 +1213,9 @@ } }, "@emotion/core": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.1.1.tgz", - "integrity": "sha512-ZMLG6qpXR8x031NXD8HJqugy/AZSkAuMxxqB46pmAR7ze47MhNJ56cdoX243QPZdGctrdfo+s08yZTiwaUcRKA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.3.0.tgz", + "integrity": "sha512-C4+RI1gNycUbfg2Zojt3lcVQVWocMLK4jiwl5tO/Z5I3zyGmG+oKJl6+/uPtQeUDPN7WXHN8TQ7bqc+dnljZ0w==", "requires": { "@babel/runtime": "^7.5.5", "@emotion/cache": "^10.0.27", @@ -1803,18 +1271,18 @@ "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==" }, "@emotion/styled": { - "version": "10.0.27", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-10.0.27.tgz", - "integrity": "sha512-iK/8Sh7+NLJzyp9a5+vIQIXTYxfT4yB/OJbjzQanB2RZpvmzBQOHZWhpAMZWYEKRNNbsD6WfBw5sVWkb6WzS/Q==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-10.3.0.tgz", + "integrity": "sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ==", "requires": { - "@emotion/styled-base": "^10.0.27", + "@emotion/styled-base": "^10.3.0", "babel-plugin-emotion": "^10.0.27" } }, "@emotion/styled-base": { - "version": "10.0.31", - "resolved": "https://registry.npmjs.org/@emotion/styled-base/-/styled-base-10.0.31.tgz", - "integrity": "sha512-wTOE1NcXmqMWlyrtwdkqg87Mu6Rj1MaukEoEmEkHirO5IoHDJ8LgCQL4MjJODgxWxXibGR3opGp1p7YvkNEdXQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@emotion/styled-base/-/styled-base-10.3.0.tgz", + "integrity": "sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w==", "requires": { "@babel/runtime": "^7.5.5", "@emotion/is-prop-valid": "0.8.8", @@ -1843,14 +1311,14 @@ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, "@eslint/eslintrc": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", - "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", "espree": "^7.3.0", - "globals": "^12.1.0", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", @@ -1859,11 +1327,11 @@ }, "dependencies": { "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" } }, "ignore": { @@ -1874,9 +1342,9 @@ } }, "@formio/bootstrap3": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@formio/bootstrap3/-/bootstrap3-2.11.0.tgz", - "integrity": "sha512-3R0X1FWYslRplvCQYkP23V66OWFmo7rjhTbhVVzIFXYlvVIWY/A019HSMVyfET7QWMQnGz42vzxmE/yVuBMI1A==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@formio/bootstrap3/-/bootstrap3-2.12.0.tgz", + "integrity": "sha512-l1KRCmQFw68c9LtNzysVQ7XXeUgfg1G3roQgY4tn1hFbKXcm3yMhOSrY6xcBDJHW/PN4n5ENwbBCfRjrJVkl0Q==", "requires": { "resize-observer-polyfill": "^1.5.1" } @@ -1892,15 +1360,20 @@ } }, "@formio/semantic": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@formio/semantic/-/semantic-2.5.1.tgz", - "integrity": "sha512-WEATjjCm8zNneFattKhQd4viXNW8by4PYU7j/KkesO5jiYiWFV75U7Ewc/3bCHFFXyj7NkmI49cbVH17tXnKxw==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@formio/semantic/-/semantic-2.6.0.tgz", + "integrity": "sha512-RwMEVXkyz+B6RivflrrKIqvvnGR/eZDLQs74u67StcrzO6n3/5D2J8XqTQRSUzQzr5QV6Wq0eZ51z/+mGm6THw==" }, "@formio/vanilla-text-mask": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@formio/vanilla-text-mask/-/vanilla-text-mask-5.1.1.tgz", "integrity": "sha512-7MhrbMypySPi7RLchg0ys7HnS3Wqddbq/btAijKB1nA94TE7AOOLhpZJWcNm3kOlX0Y3nHfoavj/HP7vsvF34Q==" }, + "@gar/promisify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", + "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==" + }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -1935,6 +1408,21 @@ "@hapi/hoek": "^8.3.0" } }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, "@hypnosphi/create-react-context": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz", @@ -1995,9 +1483,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2075,9 +1563,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2116,43 +1604,6 @@ "slash": "^3.0.0" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2246,9 +1697,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2272,6 +1723,17 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + } + }, "jest-resolve": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", @@ -2287,42 +1749,15 @@ "slash": "^3.0.0" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "supports-color": { "version": "7.2.0", @@ -2342,6 +1777,13 @@ "callsites": "^3.0.0", "graceful-fs": "^4.2.4", "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "@jest/test-result": { @@ -2398,9 +1840,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2424,6 +1866,11 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2455,9 +1902,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2492,18 +1939,19 @@ } }, "@leichtgewicht/ip-codec": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.2.tgz", - "integrity": "sha512-PjsLKLzJ0jWM1iM4xdYkrMyonAHP4kHGiXm81FRNfcnjToQA9UOknwZE28bxq0AGmEAMVBPSuuHurzla2wyYyA==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz", + "integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==", + "dev": true }, "@material-ui/core": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.4.tgz", - "integrity": "sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", + "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==", "requires": { "@babel/runtime": "^7.4.4", "@material-ui/styles": "^4.11.4", - "@material-ui/system": "^4.11.3", + "@material-ui/system": "^4.12.1", "@material-ui/types": "5.1.0", "@material-ui/utils": "^4.11.2", "@types/react-transition-group": "^4.2.0", @@ -2539,9 +1987,9 @@ } }, "@material-ui/system": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.11.3.tgz", - "integrity": "sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz", + "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==", "requires": { "@babel/runtime": "^7.4.4", "@material-ui/utils": "^4.11.2", @@ -2564,29 +2012,72 @@ "react-is": "^16.8.0 || ^17.0.0" } }, + "@mswjs/cookies": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.1.6.tgz", + "integrity": "sha512-A53XD5TOfwhpqAmwKdPtg1dva5wrng2gH5xMvklzbd9WLTSVU953eCRa8rtrrm6G7Cy60BOGsBRN89YQK0mlKA==", + "dev": true, + "requires": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + } + }, + "@mswjs/interceptors": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.12.7.tgz", + "integrity": "sha512-eGjZ3JRAt0Fzi5FgXiV/P3bJGj0NqsN7vBS0J0FO2AQRQ0jCKQS4lEFm4wvlSgKQNfeuc/Vz6d81VtU3Gkx/zg==", + "dev": true, + "requires": { + "@open-draft/until": "^1.0.3", + "@xmldom/xmldom": "^0.7.2", + "debug": "^4.3.2", + "headers-utils": "^3.0.2", + "outvariant": "^1.2.0", + "strict-event-emitter": "^0.2.0" + } + }, "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "requires": { - "@nodelib/fs.stat": "2.0.4", + "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" }, "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "requires": { - "@nodelib/fs.scandir": "2.1.4", + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, + "@npmcli/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==", + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "@npmcli/move-file": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", @@ -2611,6 +2102,12 @@ } } }, + "@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==", + "dev": true + }, "@pmmmwh/react-refresh-webpack-plugin": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz", @@ -2632,9 +2129,9 @@ } }, "@popperjs/core": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz", - "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==" + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.0.tgz", + "integrity": "sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ==" }, "@restart/context": { "version": "2.1.4", @@ -2642,12 +2139,11 @@ "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q==" }, "@restart/hooks": { - "version": "0.3.26", - "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.26.tgz", - "integrity": "sha512-7Hwk2ZMYm+JLWcb7R9qIXk1OoUg1Z+saKWqZXlrvFwT3w6UArVNWgxYOzf+PJoK9zZejp8okPAKTctthhXLt5g==", + "version": "0.3.27", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.27.tgz", + "integrity": "sha512-s984xV/EapUIfkjlf8wz9weP2O9TNKR96C68FfMEy2bE69+H4cNv3RD4Mf97lW7Htt7PjZrYTjSC8f3SB9VCXw==", "requires": { - "lodash": "^4.17.20", - "lodash-es": "^4.17.20" + "dequal": "^2.0.2" } }, "@rollup/plugin-node-resolve": { @@ -2784,9 +2280,9 @@ }, "dependencies": { "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "requires": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -2803,22 +2299,6 @@ "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", "requires": { "@babel/types": "^7.12.6" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - } } }, "@svgr/plugin-jsx": { @@ -2843,9 +2323,9 @@ }, "dependencies": { "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "requires": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -2871,11 +2351,246 @@ "loader-utils": "^2.0.0" } }, - "@types/anymatch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", - "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==" - }, + "@testing-library/dom": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.1.tgz", + "integrity": "sha512-3KQDyx9r0RKYailW2MiYrSSKEfH0GTkI51UGEvJenvcoDoeRYs0PZpi2SXqtnMClQvCqdtTTpOfFETDTVADpAg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.4.4", + "pretty-format": "^27.0.2" + }, + "dependencies": { + "@jest/types": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz", + "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "pretty-format": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.2.tgz", + "integrity": "sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==", + "dev": true, + "requires": { + "@jest/types": "^27.4.2", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1", + "dev": true + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/jest-dom": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.1.tgz", + "integrity": "sha512-ajUJdfDIuTCadB79ukO+0l8O+QwN0LiSxDaYUTI4LndbbUsGi6rWU1SCexXzBA2NSjlVB9/vbkasQIL3tmPBjw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/react": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.2.tgz", + "integrity": "sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.0.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@types/anymatch": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", + "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==" + }, + "@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true + }, "@types/babel__core": { "version": "7.1.14", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz", @@ -2931,9 +2646,9 @@ } }, "@types/estree": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.47.tgz", - "integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==" + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==" }, "@types/glob": { "version": "7.1.3", @@ -2962,14 +2677,24 @@ } }, "@types/html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", + "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==" + }, + "@types/inquirer": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.1.3.tgz", + "integrity": "sha512-AayK4ZL5ssPzR1OtnOLGAwpT0Dda3Xi/h1G0l1oJDNrowp7T1423q4Zb8/emr7tzRlCy4ssEri0LWVexAqHyKQ==", + "dev": true, + "requires": { + "@types/through": "*", + "rxjs": "^7.2.0" + } }, "@types/invariant": { - "version": "2.2.34", - "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.34.tgz", - "integrity": "sha512-lYUtmJ9BqUN688fGY1U1HZoWT1/Jrmgigx2loq4ZcJpICECm/Om3V314BxdzypO0u5PORKGMM6x0OXaljV1YFg==" + "version": "2.2.35", + "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz", + "integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==" }, "@types/istanbul-lib-coverage": { "version": "2.0.3", @@ -2985,17 +2710,160 @@ } }, "@types/istanbul-reports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", - "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "requires": { "@types/istanbul-lib-report": "*" } }, + "@types/jest": { + "version": "27.0.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.3.tgz", + "integrity": "sha512-cmmwv9t7gBYt7hNKH5Spu7Kuu/DotGa+Ff+JGRKZ4db5eh8PnKS4LuebJ3YLUoyOyIHraTGyULn23YtEAm0VSg==", + "dev": true, + "requires": { + "jest-diff": "^27.0.0", + "pretty-format": "^27.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz", + "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff-sequences": { + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz", + "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.4.2.tgz", + "integrity": "sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.4.0", + "jest-get-type": "^27.4.0", + "pretty-format": "^27.4.2" + } + }, + "jest-get-type": { + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz", + "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==", + "dev": true + }, + "pretty-format": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.2.tgz", + "integrity": "sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==", + "dev": true, + "requires": { + "@jest/types": "^27.4.2", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1", + "dev": true + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@types/js-levenshtein": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.0.tgz", + "integrity": "sha512-14t0v1ICYRtRVcHASzes0v/O+TIeASb8aD55cWF1PidtInhFWSXcmhzhHqGjUWf9SUq1w70cvd1cWKUULubAfQ==", + "dev": true + }, "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, "@types/json5": { "version": "0.0.29", @@ -3003,19 +2871,19 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" }, "@types/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" }, "@types/node": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz", - "integrity": "sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==" + "version": "16.11.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", + "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" }, "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, "@types/parse-json": { "version": "4.0.0", @@ -3023,31 +2891,30 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "@types/prettier": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.3.tgz", - "integrity": "sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA==" + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz", + "integrity": "sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA==" }, "@types/prop-types": { - "version": "15.7.3", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", - "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" }, "@types/q": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", - "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" }, "@types/raf": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz", "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==", - "dev": true, "optional": true }, "@types/react": { - "version": "17.0.6", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.6.tgz", - "integrity": "sha512-u/TtPoF/hrvb63LdukET6ncaplYsvCvmkceasx8oG84/ZCsoLxz9Z/raPBP4lTAiWW1Jb889Y9svHmv8R26dWw==", + "version": "17.0.37", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.37.tgz", + "integrity": "sha512-2FS1oTqBGcH/s0E+CjrCCR9+JMpsu9b69RTFO+40ua43ZqP5MmQ4iUde/dMjWR909KxZwmOQIFq6AV6NjEG5xg==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -3055,21 +2922,24 @@ }, "dependencies": { "csstype": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", - "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" } } }, "@types/react-calendar": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/react-calendar/-/react-calendar-3.1.4.tgz", - "integrity": "sha512-7yDdyPnNaKqOIp97NmPhDxaXb7pBSag+pYWBtt+vBJyyqqiMMtXzv5bdEWjVN7AWmfWdmzGsP8kg+TzvGvwwQg==" + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/react-calendar/-/react-calendar-3.4.3.tgz", + "integrity": "sha512-k56OS9d62/g3OCTepULEpNoClVUKuWxHBBuKS4hX8/qNiNup+Gf1Qn0SXHakbqBGWEfdLK93RlIRy5XOA4+Iaw==", + "requires": { + "@types/react": "*" + } }, "@types/react-redux": { - "version": "7.1.16", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.16.tgz", - "integrity": "sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz", + "integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==", "requires": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -3078,9 +2948,9 @@ } }, "@types/react-transition-group": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz", - "integrity": "sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.4.tgz", + "integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==", "requires": { "@types/react": "*" } @@ -3094,9 +2964,18 @@ } }, "@types/scheduler": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", - "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "@types/set-cookie-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.1.tgz", + "integrity": "sha512-N0IWe4vT1w5IOYdN9c9PNpQniHS+qe25W4tj4vfhJDJ9OkvA/YA55YUhaC+HNmMMeLlOSnBW9UMno0qlt5xu3Q==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/source-list-map": { "version": "0.1.2", @@ -3104,21 +2983,46 @@ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" }, "@types/stack-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", - "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, "@types/tapable": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.7.tgz", - "integrity": "sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==" + }, + "@types/testing-library__jest-dom": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.2.tgz", + "integrity": "sha512-vehbtyHUShPxIa9SioxDwCvgxukDMH//icJG90sXQBUm5lJOHLT5kNeU9tnivhnA/TkOFMzGIXN2cTc4hY8/kg==", + "dev": true, + "requires": { + "@types/jest": "*" + } + }, + "@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/uglify-js": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.0.tgz", - "integrity": "sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", + "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", "requires": { "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "@types/warning": { @@ -3127,22 +3031,29 @@ "integrity": "sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=" }, "@types/webpack": { - "version": "4.41.28", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.28.tgz", - "integrity": "sha512-Nn84RAiJjKRfPFFCVR8LC4ueTtTdfWAMZ03THIzZWRJB+rX24BD3LqPSFnbMscWauEsT4segAsylPDIaZyZyLQ==", + "version": "4.41.32", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", + "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", "requires": { - "@types/anymatch": "*", "@types/node": "*", "@types/tapable": "^1", "@types/uglify-js": "*", "@types/webpack-sources": "*", + "anymatch": "^3.0.0", "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", "requires": { "@types/node": "*", "@types/source-list-map": "*", @@ -3157,31 +3068,31 @@ } }, "@types/yargs": { - "version": "15.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", - "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "20.2.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", - "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" }, "@typescript-eslint/eslint-plugin": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.23.0.tgz", - "integrity": "sha512-tGK1y3KIvdsQEEgq6xNn1DjiFJtl+wn8JJQiETtCbdQxw1vzjXyAaIkEmO2l6Nq24iy3uZBMFQjZ6ECf1QdgGw==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", "requires": { - "@typescript-eslint/experimental-utils": "4.23.0", - "@typescript-eslint/scope-manager": "4.23.0", - "debug": "^4.1.1", + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", - "lodash": "^4.17.15", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "dependencies": { "semver": { @@ -3195,55 +3106,55 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.23.0.tgz", - "integrity": "sha512-WAFNiTDnQfrF3Z2fQ05nmCgPsO5o790vOhmWKXbbYQTO9erE1/YsFot5/LnOUizLzU2eeuz6+U/81KV5/hFTGA==", - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.23.0", - "@typescript-eslint/types": "4.23.0", - "@typescript-eslint/typescript-estree": "4.23.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "requires": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" } }, "@typescript-eslint/parser": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.23.0.tgz", - "integrity": "sha512-wsvjksHBMOqySy/Pi2Q6UuIuHYbgAMwLczRl4YanEPKW5KVxI9ZzDYh3B5DtcZPQTGRWFJrfcbJ6L01Leybwug==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", "requires": { - "@typescript-eslint/scope-manager": "4.23.0", - "@typescript-eslint/types": "4.23.0", - "@typescript-eslint/typescript-estree": "4.23.0", - "debug": "^4.1.1" + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.23.0.tgz", - "integrity": "sha512-ZZ21PCFxPhI3n0wuqEJK9omkw51wi2bmeKJvlRZPH5YFkcawKOuRMQMnI8mH6Vo0/DoHSeZJnHiIx84LmVQY+w==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", "requires": { - "@typescript-eslint/types": "4.23.0", - "@typescript-eslint/visitor-keys": "4.23.0" + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" } }, "@typescript-eslint/types": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.23.0.tgz", - "integrity": "sha512-oqkNWyG2SLS7uTWLZf6Sr7Dm02gA5yxiz1RP87tvsmDsguVATdpVguHr4HoGOcFOpCvx9vtCSCyQUGfzq28YCw==" + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==" }, "@typescript-eslint/typescript-estree": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.23.0.tgz", - "integrity": "sha512-5Sty6zPEVZF5fbvrZczfmLCOcby3sfrSPu30qKoY1U3mca5/jvU5cwsPb/CO6Q3ByRjixTMIVsDkqwIxCf/dMw==", - "requires": { - "@typescript-eslint/types": "4.23.0", - "@typescript-eslint/visitor-keys": "4.23.0", - "debug": "^4.1.1", - "globby": "^11.0.1", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", + "requires": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", + "debug": "^4.3.1", + "globby": "^11.0.3", "is-glob": "^4.0.1", - "semver": "^7.3.2", - "tsutils": "^3.17.1" + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "dependencies": { "semver": { @@ -3257,11 +3168,11 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.23.0.tgz", - "integrity": "sha512-5PNe5cmX9pSifit0H+nPoQBXdbNzi5tOEec+3riK+ku4e3er37pKxMKDH5Ct5Y4fhWxcD4spnlYjxi9vXbSpwg==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", "requires": { - "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/types": "4.33.0", "eslint-visitor-keys": "^2.0.0" } }, @@ -3428,18 +3339,24 @@ "integrity": "sha512-1VPkkTBk07gMR1fjpBtse4G+oJqpmE+0gUFB0dg3VIL7qJmUVaBoD/vlzMm/jNeOPfvlmerl1lpnsZyBUFIRuw==" }, "@wojtekmaj/react-daterange-picker": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@wojtekmaj/react-daterange-picker/-/react-daterange-picker-3.1.0.tgz", - "integrity": "sha512-ea+uj3P/w8AWwT4AJrrHk5YAyPDVxFWbdaev/ktV2AKpVWqzyno3ZntQ/E0bP4KP/UQFGMYeVkrhJouWtko9oQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@wojtekmaj/react-daterange-picker/-/react-daterange-picker-3.3.2.tgz", + "integrity": "sha512-/6e9oh+5NO5Jo2eRx5ybO6WodDwSpuQNVrlsHzjCEzWgpLKUXEQR64ci73/KOVNXOy+sMyDW+0CxDTIzhWqm8g==", "requires": { "make-event-props": "^1.1.0", "merge-class-names": "^1.1.1", "prop-types": "^15.6.0", "react-calendar": "^3.3.1", - "react-date-picker": "^8.1.0", + "react-date-picker": "^8.3.3", "react-fit": "^1.0.3" } }, + "@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", + "dev": true + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -3450,6 +3367,11 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -3459,10 +3381,31 @@ "negotiator": "0.6.2" } }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + } + } + }, "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" }, "acorn-walk": { "version": "7.2.0", @@ -3483,6 +3426,14 @@ "regex-parser": "^2.2.11" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -3493,9 +3444,9 @@ } }, "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3544,9 +3495,7 @@ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "version": "^5.0.1" }, "ansi-styles": { "version": "3.2.1", @@ -3572,501 +3521,1069 @@ "moment": "^2.29.1" }, "dependencies": { - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" - } - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, - "arity-n": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", - "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=" - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-filter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", - "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" - }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } + "@babel/code-frame": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", + "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", + "requires": { + "@babel/highlight": "7.0.0-beta.44" } }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "@babel/generator": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", + "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "@babel/types": "7.0.0-beta.44", + "jsesc": "^2.5.1", + "lodash": "^4.2.0", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" } }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + "@babel/helper-function-name": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", + "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.44", + "@babel/template": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44" + } }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", + "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } + "@babel/types": "7.0.0-beta.44" } }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", + "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", + "requires": { + "@babel/types": "7.0.0-beta.44" + } }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "@babel/highlight": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", + "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^3.0.0" } }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "@babel/template": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", + "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "@babel/code-frame": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "lodash": "^4.2.0" } }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "@babel/traverse": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", + "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "@babel/code-frame": "7.0.0-beta.44", + "@babel/generator": "7.0.0-beta.44", + "@babel/helper-function-name": "7.0.0-beta.44", + "@babel/helper-split-export-declaration": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "debug": "^3.1.0", + "globals": "^11.1.0", + "invariant": "^2.2.0", + "lodash": "^4.2.0" } - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } + }, + "@babel/types": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", + "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.2.0", + "to-fast-properties": "^2.0.0" } }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" } }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" + "@xtuc/ieee754": "^1.2.0" } }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } + "@xtuc/long": "4.2.2" } }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" } - } - } - }, - "array.prototype.flatmap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", - "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "function-bind": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" } }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "acorn": "^3.0.4" }, "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" } } }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" + }, + "ansi-regex": { + "version": "^5.0.1" }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" + "color-convert": "^2.0.1" } }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "babel-eslint": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz", + "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "@babel/code-frame": "7.0.0-beta.44", + "@babel/traverse": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "^1.0.0" }, "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } } } }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "babel-loader": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", + "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==", + "requires": { + "find-cache-dir": "^1.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1" + } + }, + "babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==" + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" }, "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "ansi-regex": { + "version": "^5.0.1" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } } } } - } - } - }, - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "enhanced-resolve": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", + "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + }, + "dependencies": { + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "jest-worker": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.2.tgz", + "integrity": "sha512-0QMy/zPovLfUPyHuOuuU4E+kGACXXE84nRnq6lBVI9GJg5DCBiA97SATi+ZP8CpiJwEQy1oCPjRBf8AnLjN+Ag==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "jspdf": { + "version": "^2.3.1", + "requires": { + "@babel/runtime": "^7.14.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.2.0", + "fflate": "^0.4.8", + "html2canvas": "^1.0.0-rc.5" + } + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "^2.1.0" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "terser-webpack-plugin": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz", + "integrity": "sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g==", + "requires": { + "jest-worker": "^27.0.6", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.65.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.65.0.tgz", + "integrity": "sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw==", + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.50", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.17.6", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.2" + }, + "dependencies": { + "acorn": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", + "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==" + }, + "browserslist": { + "version": "^4.17.6", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + } + } + }, + "webpack-sources": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.2.tgz", + "integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==" + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } + } + } + } + }, + "xmldom": { + "version": "^0.6.0" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz", + "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } + } + } + } + }, + "yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==" + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "arity-n": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", + "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=" + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "array.prototype.flatmap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", + "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", "requires": { - "safer-buffer": "~2.1.0" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" } }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -4109,11 +4626,6 @@ } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -4142,6 +4654,11 @@ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -4163,34 +4680,32 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "autocompleter": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/autocompleter/-/autocompleter-6.1.0.tgz", - "integrity": "sha512-w+gPtAuwL+0BY33rwtFaliZ2TW/iJlbQ0AaFFi7sy7kh1MdOM5VpAMJ2s/6yygIkWkLQP8WF+ajlG39Ft8459Q==" + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/autocompleter/-/autocompleter-6.1.2.tgz", + "integrity": "sha512-DfEcgxBJOTJJwxkIRZLv/ggD3g5w/fqzZkdJsOcgk7hjxw36lH/nAfIEXzV7qDE55swnYEe43E/WhZPXmSFfsA==" }, "autoprefixer": { - "version": "9.8.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", - "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", "requires": { - "browserslist": "^4.12.0", + "browserslist": "^4.17.6", "caniuse-lite": "^1.0.30001109", - "colorette": "^1.2.1", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", "postcss": "^7.0.32", "postcss-value-parser": "^4.1.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" }, "dependencies": { "caniuse-lite": { @@ -4220,27 +4735,17 @@ "array-filter": "^1.0.0" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" - }, "axe-core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.2.0.tgz", - "integrity": "sha512-1uIESzroqpaTzt9uX48HO+6gfnKu3RwvWdCcWSrX4csMInJfCo1yvKPNXCwXFRpJqRW25tiASb6No0YH57PXqg==" + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz", + "integrity": "sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==" }, "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "requires": { - "follow-redirects": "^1.10.0" + "follow-redirects": "^1.14.0" } }, "axobject-query": { @@ -4300,9 +4805,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4377,9 +4882,9 @@ } }, "babel-plugin-emotion": { - "version": "10.0.33", - "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.33.tgz", - "integrity": "sha512-bxZbTTGz0AJQDHm8k6Rf3RQJ8tX2scsfsRyKVgAbiUPUNIRtlK+7JxP+TAd1kRLABFxe0CFm2VdK4ePkoA9FxQ==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz", + "integrity": "sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==", "requires": { "@babel/helper-module-imports": "^7.0.0", "@emotion/hash": "0.8.0", @@ -4391,24 +4896,17 @@ "escape-string-regexp": "^1.0.5", "find-root": "^1.1.0", "source-map": "^0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } } }, "babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" } }, @@ -4439,12 +4937,12 @@ "integrity": "sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==" }, "babel-plugin-polyfill-corejs2": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.0.tgz", - "integrity": "sha512-9bNwiR0dS881c5SHnzCmmGlMkJLl0OUZvxrxHo9w/iNoRuqaPjqlvBf4HrovXtQs/au5yKkpcdgfT1cC5PAZwg==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz", + "integrity": "sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==", "requires": { "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.0", + "@babel/helper-define-polyfill-provider": "^0.3.0", "semver": "^6.1.1" }, "dependencies": { @@ -4456,20 +4954,20 @@ } }, "babel-plugin-polyfill-corejs3": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.0.tgz", - "integrity": "sha512-zZyi7p3BCUyzNxLx8KV61zTINkkV65zVkDAFNZmrTCRVhjo1jAS+YLvDJ9Jgd/w2tsAviCwFHReYfxO3Iql8Yg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.4.0.tgz", + "integrity": "sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==", "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.0", - "core-js-compat": "^3.9.1" + "@babel/helper-define-polyfill-provider": "^0.3.0", + "core-js-compat": "^3.18.0" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.0.tgz", - "integrity": "sha512-J7vKbCuD2Xi/eEHxquHN14bXAW9CXtecwuLrOIDJtcZzTaPzV1VdEfoUf9AzcRBMolKUQKM9/GVojeh0hFiqMg==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz", + "integrity": "sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==", "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.0" + "@babel/helper-define-polyfill-provider": "^0.3.0" } }, "babel-plugin-syntax-jsx": { @@ -4507,9 +5005,9 @@ }, "dependencies": { "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "regenerator-runtime": { "version": "0.10.5", @@ -4568,19 +5066,6 @@ "babel-plugin-transform-react-remove-prop-types": "0.4.24" }, "dependencies": { - "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" - }, "@babel/plugin-proposal-class-properties": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", @@ -4720,15 +5205,6 @@ "requires": { "regenerator-runtime": "^0.13.4" } - }, - "@babel/types": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", - "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } } } }, @@ -4742,9 +5218,9 @@ }, "dependencies": { "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "regenerator-runtime": { "version": "0.11.1", @@ -4759,9 +5235,9 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base": { "version": "0.11.2", @@ -4817,7 +5293,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", - "dev": true, "optional": true }, "base64-js": { @@ -4830,14 +5305,6 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "bfj": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", @@ -4859,13 +5326,46 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "requires": { - "file-uri-to-path": "1.0.0" + "inherits": "~2.0.0" } }, "bluebird": { @@ -4908,10 +5408,10 @@ "ms": "2.0.0" } }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -4966,13 +5466,13 @@ } }, "bpmn-moddle": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/bpmn-moddle/-/bpmn-moddle-7.0.4.tgz", - "integrity": "sha512-/rqz1hAEGArOdiQ7y2HK/+5KmdthPRC8vO5i5wkLRx5SiRzFJx2WfWg9ES0XyjmAIVH7nPRGhihMaeV6zdzd1w==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/bpmn-moddle/-/bpmn-moddle-7.1.2.tgz", + "integrity": "sha512-Sax4LokRCTqlg26njjULN3ZGtCmwH5gZVUZTRF0jwJk+YpMQhSfSoUECxjNv8OROoLxu8Z+MjdOHIxgvJf7KwA==", "requires": { - "min-dash": "^3.0.0", - "moddle": "^5.0.1", - "moddle-xml": "^9.0.4" + "min-dash": "^3.5.2", + "moddle": "^5.0.2", + "moddle-xml": "^9.0.5" } }, "brace-expansion": { @@ -5064,6 +5564,18 @@ "parse-asn1": "^5.1.5", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "browserify-zlib": { @@ -5075,15 +5587,13 @@ } }, "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" }, "dependencies": { "caniuse-lite": { @@ -5139,9 +5649,9 @@ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "buffer-indexof": { "version": "1.1.1", @@ -5154,12 +5664,12 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "bufferutil": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", - "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", + "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", "optional": true, "requires": { - "node-gyp-build": "^4.2.0" + "node-gyp-build": "^4.3.0" } }, "builtin-modules": { @@ -5178,10 +5688,11 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacache": { - "version": "15.0.6", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.6.tgz", - "integrity": "sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", "requires": { + "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -5197,7 +5708,7 @@ "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^8.0.1", - "tar": "^6.0.2", + "tar": "^6.1.11", "unique-filename": "^1.1.1" }, "dependencies": { @@ -5215,9 +5726,7 @@ } }, "tar": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.8.tgz", - "integrity": "sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A==", + "version": "^6.1.11", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -5225,17 +5734,6 @@ "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" - }, - "dependencies": { - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - } } } } @@ -5250,19 +5748,33 @@ "get-value": "^2.0.6", "has-value": "^1.0.0", "isobject": "^3.0.1", - "set-value": "^2.0.0", + "set-value": "^4.1.0", "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" + }, + "dependencies": { + "is-primitive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", + "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==" + }, + "set-value": { + "version": "^4.1.0", + "requires": { + "is-plain-object": "^2.0.4", + "is-primitive": "^3.0.1" + } + } } }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, "caller-callsite": { @@ -5303,38 +5815,36 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", + "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==" }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "requires": { - "browserslist": "^4.0.0", + "browserslist": "^4.17.6", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" }, "dependencies": { "caniuse-lite": { @@ -5357,23 +5867,24 @@ } }, "caniuse-lite": { - "version": "1.0.30001235", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz", - "integrity": "sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==" + "version": "1.0.30001283", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz", + "integrity": "sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg==" }, "canvg": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.7.tgz", "integrity": "sha512-4sq6iL5Q4VOXS3PL1BapiXIZItpxYyANVzsAKpTPS5oq4u3SKbGfUcbZh2gdLCQ3jWpG/y5wRkMlBBAJhXeiZA==", - "dev": true, "optional": true, "requires": { - "@babel/runtime-corejs3": "^7.9.6", + "@babel/runtime": "^7.12.5", "@types/raf": "^3.4.0", + "core-js": "^3.8.3", "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", "rgbcolor": "^1.0.1", "stackblur-canvas": "^2.0.0", - "svg-pathdata": "^5.0.5" + "svg-pathdata": "^6.0.3" } }, "capture-exit": { @@ -5389,11 +5900,6 @@ "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz", "integrity": "sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ==" }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -5409,20 +5915,26 @@ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "check-types": { "version": "11.1.2", "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz", "integrity": "sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==" }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "^6.0.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", @@ -5430,11 +5942,9 @@ }, "dependencies": { "glob-parent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.1.tgz", - "integrity": "sha512-kEVjS71mQazDBHKcsq4E9u/vUzaLcw1A8EtUeydawvIWQCJM0qQ08G1H7/XTjFUulla6XQiDOG6MXSaG0HDKog==", + "version": "^6.0.2", "requires": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" } } } @@ -5490,16 +6000,23 @@ } }, "classnames": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" }, "clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", "requires": { "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "clean-stack": { @@ -5507,6 +6024,27 @@ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -5557,12 +6095,12 @@ } }, "color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", - "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.4" + "color-convert": "^1.9.3", + "color-string": "^1.6.0" } }, "color-convert": { @@ -5579,19 +6117,14 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", - "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.8.2.tgz", + "integrity": "sha512-w5ZkKRdLsc5NOYsmnpS2DpyRW71npwZGwbRpLrJTuqjfTs2Bhrba7UiV59IX9siBlCPl2pne5NtiwnVWUzvYFA==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5606,9 +6139,9 @@ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" }, "common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==" + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" }, "commondir": { "version": "1.0.1", @@ -5668,6 +6201,11 @@ "ms": "2.0.0" } }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -5689,40 +6227,6 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "confusing-browser-globals": { @@ -5736,11 +6240,11 @@ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" }, "connected-react-router": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/connected-react-router/-/connected-react-router-6.9.1.tgz", - "integrity": "sha512-BbtB6t0iqAwGwygDenJl9zmlk7vpKWIRSycULmkAOn2RUaF6+bqETprl0qcIqQmY5CTqSwKanaxkLXYWiffAfQ==", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/connected-react-router/-/connected-react-router-6.9.2.tgz", + "integrity": "sha512-bE8kNBiZv9Mivp7pYn9JvLH5ItTjLl45kk1/Vha0rmAK9I/ETb5JPJrAm0h2KCG9qLfv7vqU3Jo4UUDo0oJnQg==", "requires": { - "immutable": "^3.8.1 || ^4.0.0-rc.1", + "immutable": "^3.8.1 || ^4.0.0", "lodash.isequalwith": "^4.4.0", "prop-types": "^15.7.2", "seamless-immutable": "^7.1.3" @@ -5756,25 +6260,6 @@ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" }, - "contains-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-1.0.0.tgz", - "integrity": "sha1-NFizMhhWA+ju0Y9RjUoQiIo6vJE=", - "requires": { - "normalize-path": "^2.1.1", - "path-starts-with": "^1.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -5805,9 +6290,9 @@ } }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "requires": { "safe-buffer": "~5.1.1" }, @@ -5848,29 +6333,27 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.3.tgz", - "integrity": "sha512-DFEW9BllWw781Op5KdYGtXfj3s9Cmykzt16bY6elaVuqXHCUwF/5pv0H3IJ7/I3BGjK7OeU+GrjD1ChCkBJPuA==" + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.19.2.tgz", + "integrity": "sha512-ciYCResnLIATSsXuXnIOH4CbdfgV+H1Ltg16hJFN7/v6OxqnFr/IFGeLacaZ+fHLAm0TBbXwNK9/DNBzBUrO/g==" }, "core-js-compat": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz", - "integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.2.tgz", + "integrity": "sha512-ObBY1W5vx/LFFMaL1P5Udo4Npib6fu+cMokeziWkA8Tns4FcDemKF5j9JvaI5JhdkW8EQJQGJN1EcrzmEwuAqQ==", "requires": { - "browserslist": "^4.16.6", + "browserslist": "^4.17.6", "semver": "7.0.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -5896,43 +6379,25 @@ } }, "core-js-pure": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.12.1.tgz", - "integrity": "sha512-1cch+qads4JnDSWsvc7d6nzlKAippwjUlf6vykkTLW53VSV+NkE6muGBToAjEA8pG90cSfcud3JgVmW2ds5TaQ==" + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.19.2.tgz", + "integrity": "sha512-5LkcgQEy8pFeVnd/zomkUBSwnmIxuF1C8E9KrMAbOc8f34IBT9RGvTYeNDdp1PnvMJrrVhvk1hg/yVV5h/znlg==" }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "dependencies": { - "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - } + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" } }, "create-ecdh": { @@ -6035,9 +6500,9 @@ } }, "crypto-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", - "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" }, "crypto-random-string": { "version": "1.0.0", @@ -6053,6 +6518,13 @@ "source-map": "^0.6.1", "source-map-resolve": "^0.5.2", "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "css-blank-pseudo": { @@ -6107,7 +6579,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-1.1.1.tgz", "integrity": "sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==", - "dev": true, "optional": true, "requires": { "base64-arraybuffer": "^0.2.0" @@ -6156,15 +6627,19 @@ "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "requires": { "boolbase": "^1.0.0", - "css-what": "^3.2.1", + "css-what": "^5.0.1", "domutils": "^1.7.0", - "nth-check": "^1.0.2" + "nth-check": "^2.0.1" }, "dependencies": { "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==" + "version": "^5.0.1" + }, + "nth-check": { + "version": "^2.0.1", + "requires": { + "boolbase": "^1.0.0" + } } } }, @@ -6180,6 +6655,13 @@ "requires": { "mdn-data": "2.0.4", "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "css-vendor": { @@ -6191,6 +6673,9 @@ "is-in-browser": "^1.0.2" } }, + "css-what": { + "version": "^5.0.1" + }, "css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -6334,13 +6819,38 @@ "version": "2.0.14", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" } } }, "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" + "version": "2.6.19", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", + "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" }, "custom-event": { "version": "1.0.1", @@ -6438,14 +6948,6 @@ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==" }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -6456,15 +6958,10 @@ "whatwg-url": "^8.0.0" }, "dependencies": { - "abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" - }, "tr46": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", - "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", "requires": { "punycode": "^2.1.1" } @@ -6475,26 +6972,26 @@ "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" }, "whatwg-url": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz", - "integrity": "sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "requires": { "lodash": "^4.7.0", - "tr46": "^2.0.2", + "tr46": "^2.1.0", "webidl-conversions": "^6.1.0" } } } }, "date-fns": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.21.3.tgz", - "integrity": "sha512-HeYdzCaFflc1i4tGbj7JKMjM4cKGYoyxwcIIkHzNgCkX8xXDNJDZXgDDVchIWpN4eQc3lH37WarduXFZJOtxfw==" + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.27.0.tgz", + "integrity": "sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q==" }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { "ms": "2.1.2" }, @@ -6512,14 +7009,14 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decimal.js": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", - "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==" + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" }, "decimal.js-light": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.0.tgz", - "integrity": "sha512-b3VJCbd2hwUpeRGG3Toob+CRo8W22xplipNhP3tN7TSVB/cyMX71P1vM2Xjc9H74uV6dS2hDDmo/rHq8L87Upg==" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, "decode-uri-component": { "version": "0.2.0", @@ -6556,55 +7053,12 @@ "which-boxed-primitive": "^1.0.1", "which-collection": "^1.0.1", "which-typed-array": "^1.1.2" - }, - "dependencies": { - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - } - } - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } } }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "deepmerge": { "version": "4.2.2", @@ -6620,6 +7074,23 @@ "ip-regex": "^2.1.0" } }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + } + } + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -6723,6 +7194,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, + "dequal": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz", + "integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==" + }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -6768,6 +7244,11 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -6788,9 +7269,9 @@ } }, "diagram-js-direct-editing": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/diagram-js-direct-editing/-/diagram-js-direct-editing-1.6.2.tgz", - "integrity": "sha512-hAiSnt6iETMLHBRsCU+XeATiV7u/rovlAX/l4MnvzW6+VeHqQOn+xFetD6JwxfTHKvT3h9fAQpfMZPOPlRFNlw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/diagram-js-direct-editing/-/diagram-js-direct-editing-1.6.3.tgz", + "integrity": "sha512-OwDpK4cNJ4QYuV855HvtZcB9/krfZRQ80uaE6bwaKbyb4584sD7nCtR5yWOyhJx4dIh1gMoqhF7d7G57M4tQVQ==", "requires": { "min-dash": "^3.5.2", "min-dom": "^3.1.3" @@ -6842,9 +7323,7 @@ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" }, "dns-packet": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.0.tgz", - "integrity": "sha512-Nce7YLu6YCgWRvOmDBsJMo9M5/jV3lEZ5vUWnWXYmwURvPylHvq7nkDWhNmk1ZQoZZOP7oQh/S0lSxbisKOfHg==", + "version": "^5.2.4", "dev": true, "requires": { "@leichtgewicht/ip-codec": "^2.0.1" @@ -6866,6 +7345,12 @@ "esutils": "^2.0.2" } }, + "dom-accessibility-api": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz", + "integrity": "sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g==", + "dev": true + }, "dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -6875,18 +7360,18 @@ } }, "dom-helpers": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz", - "integrity": "sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", "requires": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" }, "dependencies": { "csstype": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz", - "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==" + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" } } }, @@ -6932,22 +7417,29 @@ } }, "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", "requires": { - "domelementtype": "1" + "domelementtype": "^2.2.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + } } }, "domify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/domify/-/domify-1.4.0.tgz", - "integrity": "sha1-EUg2F/dk+GlZdbS9x5sU8IA7Yps=" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/domify/-/domify-1.4.1.tgz", + "integrity": "sha512-x18nuiDHMCZGXr4KJSRMf/TWYtiaRo6RX8KN9fEbW54mvbQ6pieUuerC2ahBg+kEp1wycFj8MPUI0WkIOw5E9w==" }, "dompurify": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.8.tgz", - "integrity": "sha512-9H0UL59EkDLgY3dUFjLV6IEUaHm5qp3mxSqWw7Yyx4Zhk2Jn2cmLe+CNPP3xy13zl8Bqg+0NehQzkdMoVhGRww==" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.3.tgz", + "integrity": "sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==" }, "domutils": { "version": "1.7.0", @@ -6968,9 +7460,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -7056,15 +7548,6 @@ } } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -7084,9 +7567,9 @@ "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" }, "electron-to-chromium": { - "version": "1.3.728", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.728.tgz", - "integrity": "sha512-SHv4ziXruBpb1Nz4aTuqEHBYi/9GNCJMYIJgDEXrp/2V01nFXMNFUTli5Z85f5ivSkioLilQatqBYFB44wNJrA==" + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.9.tgz", + "integrity": "sha512-7AyB4SiLtGJbLACXezs8BDjDbZizuoiyHTQxbcvzfi5LYWRXVSFdmPvuDjtlWQmsVSONRicZfSBj3xgft0Wvrg==" }, "elliptic": { "version": "6.5.4", @@ -7156,11 +7639,6 @@ "tapable": "^1.0.0" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "memory-fs": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", @@ -7169,33 +7647,6 @@ "errno": "^0.1.3", "readable-stream": "^2.0.1" } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } } } }, @@ -7237,21 +7688,30 @@ } }, "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, "es-get-iterator": { @@ -7267,35 +7727,6 @@ "is-set": "^2.0.2", "is-string": "^1.0.5", "isarray": "^2.0.5" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", - "requires": { - "call-bind": "^1.0.0" - } - } } }, "es-to-primitive": { @@ -7352,28 +7783,91 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, "eslint": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz", - "integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.1", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", + "glob-parent": "^6.0.2", "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", @@ -7382,7 +7876,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.21", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -7391,7 +7885,7 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^6.0.4", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, @@ -7413,9 +7907,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7445,17 +7939,15 @@ } }, "glob-parent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.1.tgz", - "integrity": "sha512-kEVjS71mQazDBHKcsq4E9u/vUzaLcw1A8EtUeydawvIWQCJM0qQ08G1H7/XTjFUulla6XQiDOG6MXSaG0HDKog==", + "version": "^6.0.2", "requires": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" } }, "globals": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", - "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "requires": { "type-fest": "^0.20.2" } @@ -7470,38 +7962,11 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" - }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -7531,19 +7996,6 @@ "has-flag": "^4.0.0" } }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7563,30 +8015,31 @@ } }, "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } } } }, "eslint-module-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", - "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", + "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", "requires": { "debug": "^3.2.7", + "find-up": "^2.1.0", "pkg-dir": "^2.0.0" }, "dependencies": { @@ -7615,11 +8068,6 @@ "path-exists": "^3.0.0" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -7657,35 +8105,32 @@ } }, "eslint-plugin-flowtype": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.7.2.tgz", - "integrity": "sha512-7Oq/N0+3nijBnYWQYzz/Mp/7ZCpwxYvClRyW/PLAmimY9uLCBvoXsNsERcJdkKceyOjgRbFhhxs058KTrne9Mg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.10.0.tgz", + "integrity": "sha512-vcz32f+7TP+kvTUyMXZmCnNujBQZDNmcqPImw8b9PZ+16w1Qdm6ryRuYZYVaG9xRqqmAPr2Cs9FAX5gN+x/bjw==", "requires": { "lodash": "^4.17.15", "string-natural-compare": "^3.0.1" } }, "eslint-plugin-import": { - "version": "2.23.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.2.tgz", - "integrity": "sha512-LmNoRptHBxOP+nb0PIKz1y6OSzCJlB+0g0IGS3XV4KaKk2q4szqQ6s6F1utVf5ZRkxk/QOTjdxe7v4VjS99Bsg==", + "version": "2.25.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz", + "integrity": "sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==", "requires": { - "array-includes": "^3.1.3", - "array.prototype.flat": "^1.2.4", - "contains-path": "^1.0.0", + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", "debug": "^2.6.9", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.1", - "find-up": "^2.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.1", "has": "^1.0.3", - "is-core-module": "^2.4.0", + "is-core-module": "^2.8.0", + "is-glob": "^4.0.3", "minimatch": "^3.0.4", - "object.values": "^1.1.3", - "pkg-up": "^2.0.0", - "read-pkg-up": "^3.0.0", + "object.values": "^1.1.5", "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" + "tsconfig-paths": "^3.11.0" }, "dependencies": { "debug": { @@ -7693,95 +8138,49 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "requires": { - "esutils": "^2.0.2" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "ms": "2.0.0" } }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "requires": { - "p-try": "^1.0.0" + "esutils": "^2.0.2" } }, - "p-locate": { + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, "eslint-plugin-jest": { - "version": "24.3.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.3.6.tgz", - "integrity": "sha512-WOVH4TIaBLIeCX576rLcOgjNXqP+jNlCiEmRgFTfQtJ52DpwnIQKAVGlGPAN7CZ33bW6eNfHD6s8ZbEUTQubJg==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.7.0.tgz", + "integrity": "sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA==", "requires": { "@typescript-eslint/experimental-utils": "^4.0.1" } }, "eslint-plugin-jsx-a11y": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz", - "integrity": "sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", + "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", "requires": { - "@babel/runtime": "^7.11.2", + "@babel/runtime": "^7.16.3", "aria-query": "^4.2.2", - "array-includes": "^3.1.1", + "array-includes": "^3.1.4", "ast-types-flow": "^0.0.7", - "axe-core": "^4.0.2", + "axe-core": "^4.3.5", "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.6", - "emoji-regex": "^9.0.0", + "damerau-levenshtein": "^1.0.7", + "emoji-regex": "^9.2.2", "has": "^1.0.3", - "jsx-ast-utils": "^3.1.0", - "language-tags": "^1.0.5" + "jsx-ast-utils": "^3.2.1", + "language-tags": "^1.0.5", + "minimatch": "^3.0.4" }, "dependencies": { "emoji-regex": { @@ -7792,22 +8191,24 @@ } }, "eslint-plugin-react": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.23.2.tgz", - "integrity": "sha512-AfjgFQB+nYszudkxRkTFu0UR1zEQig0ArVMPloKhxwlwkzaw/fBiH0QWcBBhZONlXqQC51+nfqFrkn4EzHcGBw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz", + "integrity": "sha512-meyunDjMMYeWr/4EBLTV1op3iSG3mjT/pz5gti38UzfM4OPpNc2m0t2xvKCOMU5D6FSdd34BIMFOvQbW+i8GAA==", "requires": { - "array-includes": "^3.1.3", - "array.prototype.flatmap": "^1.2.4", + "array-includes": "^3.1.4", + "array.prototype.flatmap": "^1.2.5", "doctrine": "^2.1.0", - "has": "^1.0.3", + "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.0.4", - "object.entries": "^1.1.3", - "object.fromentries": "^2.0.4", - "object.values": "^1.1.3", + "object.entries": "^1.1.5", + "object.fromentries": "^2.0.5", + "object.hasown": "^1.1.0", + "object.values": "^1.1.5", "prop-types": "^15.7.2", "resolve": "^2.0.0-next.3", - "string.prototype.matchall": "^4.0.4" + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.6" }, "dependencies": { "doctrine": { @@ -7818,6 +8219,11 @@ "esutils": "^2.0.2" } }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, "resolve": { "version": "2.0.0-next.3", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", @@ -7826,13 +8232,18 @@ "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, "eslint-plugin-react-hooks": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", - "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", + "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==" }, "eslint-plugin-testing-library": { "version": "3.10.2", @@ -7882,6 +8293,14 @@ "eslint-visitor-keys": "^1.1.0" } }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", @@ -7907,18 +8326,11 @@ } }, "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" - } + "eslint-visitor-keys": "^2.0.0" } }, "eslint-visitor-keys": { @@ -7927,38 +8339,50 @@ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" }, "eslint-webpack-plugin": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.4.tgz", - "integrity": "sha512-7rYh0m76KyKSDE+B+2PUQrlNS4HJ51t3WKpkJg6vo2jFMbEPTG99cBV0Dm7LXSHucN4WGCG65wQcRiTFrj7iWw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.6.0.tgz", + "integrity": "sha512-V+LPY/T3kur5QO3u+1s34VDTcRxjXWPUGM4hlmTb5DwVD0OQz631yGTxJZf4SpAqAjdbBVe978S8BJeHpAdOhQ==", "requires": { - "@types/eslint": "^7.2.6", + "@types/eslint": "^7.28.2", "arrify": "^2.0.1", - "jest-worker": "^26.6.2", - "micromatch": "^4.0.2", + "jest-worker": "^27.3.1", + "micromatch": "^4.0.4", "normalize-path": "^3.0.0", - "schema-utils": "^3.0.0" + "schema-utils": "^3.1.1" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.2.tgz", + "integrity": "sha512-0QMy/zPovLfUPyHuOuuU4E+kGACXXE84nRnq6lBVI9GJg5DCBiA97SATi+ZP8CpiJwEQy1oCPjRBf8AnLjN+Ag==", "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" } }, "schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "requires": { - "@types/json-schema": "^7.0.6", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } } } }, @@ -7972,11 +8396,6 @@ "eslint-visitor-keys": "^1.3.0" }, "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", @@ -7998,9 +8417,9 @@ }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" } } }, @@ -8013,9 +8432,9 @@ }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" } } }, @@ -8039,6 +8458,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=" + }, "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -8127,6 +8551,11 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -8216,16 +8645,16 @@ "ms": "2.0.0" } }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -8234,17 +8663,17 @@ } }, "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", "requires": { - "type": "^2.0.0" + "type": "^2.5.0" }, "dependencies": { "type": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.3.0.tgz", - "integrity": "sha512-rgPIqOdfK/4J9FhiVrZ3cveAjRRo5rsQBAIhnylX874y1DX/kEKSVdLsnuHB6l1KTjHyU01VjiMBHgU2adejyg==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", + "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==" } } }, @@ -8272,6 +8701,17 @@ } } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -8331,11 +8771,6 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8347,42 +8782,30 @@ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" }, "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^6.0.2", "merge2": "^1.3.0", "micromatch": "^4.0.2", "picomatch": "^2.2.1" }, "dependencies": { "glob-parent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.1.tgz", - "integrity": "sha512-kEVjS71mQazDBHKcsq4E9u/vUzaLcw1A8EtUeydawvIWQCJM0qQ08G1H7/XTjFUulla6XQiDOG6MXSaG0HDKog==", + "version": "^6.0.2", "requires": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" } } } }, "fast-json-patch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", - "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", - "requires": { - "fast-deep-equal": "^2.0.1" - }, - "dependencies": { - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - } - } + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.0.tgz", + "integrity": "sha512-IhpytlsVTRndz0hU5t0/MGzS/etxLlfrpG5V5M9mVbuj9TrJLWaMfsox9REM5rkuGX0T+5qjpe8XA1o0gZ42nA==" }, "fast-json-stable-stringify": { "version": "2.1.0", @@ -8395,17 +8818,17 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "requires": { "reusify": "^1.0.4" } }, "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "requires": { "websocket-driver": ">=0.5.1" } @@ -8429,14 +8852,22 @@ "fflate": { "version": "0.4.8", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", - "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", - "dev": true + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -8454,34 +8885,22 @@ "schema-utils": "^3.0.0" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "requires": { - "@types/json-schema": "^7.0.6", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } } } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true + "file-saver": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", + "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" }, "filelist": { "version": "1.0.2", @@ -8525,6 +8944,11 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -8572,9 +8996,9 @@ } }, "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==" }, "flatten": { "version": "1.0.3", @@ -8588,46 +9012,12 @@ "requires": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" + "version": "1.14.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", + "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" }, "for-in": { "version": "1.0.2", @@ -8639,11 +9029,6 @@ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, "fork-ts-checker-webpack-plugin": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", @@ -8756,39 +9141,39 @@ } }, "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "formiojs": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/formiojs/-/formiojs-4.13.1.tgz", - "integrity": "sha512-bd6QnFdYw8ctR4D/TvsdmKxDeYWydzv5P+zORd2t42+N4RLkud8HiqeKyOK/BIC0OZywAh6oFomSEQH4UNt/Sg==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/formiojs/-/formiojs-4.14.0.tgz", + "integrity": "sha512-q20EgDLRxLYuZKyeEDaMFPtnG27h8k/8O4CzlJ1oUpYKJ8XTkiwmLl1N0yYZqd3cVxthPh5ZxhmiJxijqefFcQ==", "requires": { - "@formio/bootstrap3": "^2.11.0", + "@formio/bootstrap3": "^2.12.0", "@formio/choices.js": "^9.0.1", - "@formio/semantic": "^2.5.1", + "@formio/semantic": "^2.6.0", "@formio/vanilla-text-mask": "^5.1.1", - "autocompleter": "^6.1.0", + "autocompleter": "^6.1.2", "browser-cookies": "^1.2.0", "compare-versions": "^3.6.0", - "core-js": "^3.11.1", + "core-js": "^3.18.3", "custom-event-polyfill": "^1.0.7", "dialog-polyfill": "^0.5.6", - "dompurify": "^2.2.8", + "dompurify": "^2.3.3", "downloadjs": "^1.4.7", "dragula": "^3.7.3", "eventemitter3": "^4.0.7", "fast-deep-equal": "^3.1.3", - "fast-json-patch": "^2.2.1", + "fast-json-patch": "^3.1.0", "fetch-ponyfill": "^7.1.0", - "i18next": "^20.2.2", - "idb": "^6.0.0", + "i18next": "^21.3.3", + "idb": "^6.1.5", "ismobilejs": "^1.1.1", "json-logic-js": "^2.0.0", "jstimezonedetect": "^1.0.7", @@ -8805,79 +9190,33 @@ "tooltip.js": "^1.3.3", "uuid": "^8.3.2", "vanilla-picker": "^2.11.2" - }, - "dependencies": { - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } } }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" } }, "fs-extra": { @@ -8908,40 +9247,6 @@ "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "fs.realpath": { @@ -8992,9 +9297,9 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", - "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -9019,6 +9324,15 @@ "pump": "^3.0.0" } }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "get-user-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/get-user-locale/-/get-user-locale-1.4.0.tgz", @@ -9032,18 +9346,10 @@ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -9053,6 +9359,12 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "^6.0.2", + "requires": { + "is-glob": "^4.0.1" + } + }, "global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -9077,9 +9389,9 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -9090,9 +9402,15 @@ } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "graphql": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.7.2.tgz", + "integrity": "sha512-AnnKk7hFQFmU/2I9YSQf3xw44ctnSFCfp3zE0N6W174gqe9fWG/2rKaKxROK7CcI3XtERpjEKFqts8o319Kf7A==", + "dev": true }, "growly": { "version": "1.3.0", @@ -9124,20 +9442,6 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", @@ -9162,9 +9466,17 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } }, "has-value": { "version": "1.0.0", @@ -9221,6 +9533,18 @@ "inherits": "^2.0.4", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "hash.js": { @@ -9237,6 +9561,12 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "headers-utils": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/headers-utils/-/headers-utils-3.0.2.tgz", + "integrity": "sha512-xAxZkM1dRyGV2Ou5bzMxBPNLoRCjcX+ya7KSWybQD2KwLphxsapUVK6x/02o7f4VU6GPSXch9vNY2+gkU8tYWQ==", + "dev": true + }, "hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", @@ -9271,6 +9601,13 @@ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "hoopy": { @@ -9292,40 +9629,6 @@ "obuf": "^1.0.0", "readable-stream": "^2.0.1", "wbuf": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "hsl-regex": { @@ -9368,25 +9671,6 @@ "param-case": "^3.0.3", "relateurl": "^0.2.7", "terser": "^4.6.3" - }, - "dependencies": { - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - } - } - } } }, "html-webpack-plugin": { @@ -9438,29 +9722,47 @@ "version": "1.0.0-rc.7", "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-rc.7.tgz", "integrity": "sha512-yvPNZGejB2KOyKleZspjK/NruXVQuowu8NnV2HYG7gW7ytzl+umffbtUI62v2dCHQLDdsK6HIDtyJZ0W3neerA==", - "dev": true, "optional": true, "requires": { - "css-line-break": "1.1.1" + "css-line-break": "2.0.1", + "text-segmentation": "^1.0.2" } }, "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" }, "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } } } }, @@ -9489,9 +9791,9 @@ } }, "http-parser-js": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz", + "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==" }, "http-proxy": { "version": "1.18.1", @@ -9503,6 +9805,16 @@ "requires-port": "^1.0.0" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, "http-proxy-middleware": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", @@ -9611,21 +9923,20 @@ } } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", @@ -9637,21 +9948,11 @@ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, "i18next": { - "version": "20.2.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.2.2.tgz", - "integrity": "sha512-uWCv9LzKpe+OwvnKKrb8CbJwgAhasQofD58cB0PQ6bTPXEl5PlItl5C4esmY8HtriLu9nrjc2Hi0IfYv3Fy8BQ==", + "version": "21.5.4", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.5.4.tgz", + "integrity": "sha512-ukwRJpLhYg4EUfCOtbaKjlwF71qyel1XMXQN78OkQMcaQG68UzlYgLC6g2fhoTNBvoH2tJkaaqzDumhC9skAhA==", "requires": { "@babel/runtime": "^7.12.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", - "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } } }, "iconv-lite": { @@ -9671,9 +9972,9 @@ } }, "idb": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.0.0.tgz", - "integrity": "sha512-+M367poGtpzAylX4pwcrZIa7cFQLfNkAOlMMLN2kw/2jGfJP6h+TB/unQNSVYwNtP8XqkLYrfuiVnxLQNP1tjA==" + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", + "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" }, "identity-obj-proxy": { "version": "3.0.0", @@ -9699,20 +10000,14 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" }, "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" - }, - "immer": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", - "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==" + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", + "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==" }, "immutable": { - "version": "4.0.0-rc.12", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz", - "integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A==", - "optional": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==" }, "import-cwd": { "version": "2.1.0", @@ -9723,9 +10018,9 @@ } }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -9747,9 +10042,9 @@ } }, "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", + "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", "requires": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -9770,14 +10065,6 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, - "indefinite-observable": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-2.0.1.tgz", - "integrity": "sha512-G8vgmork+6H9S8lUAg1gtXEj2JxIQTo0g2PbFiYOdjkziSI0F7UYBiVwhZRuixhBCNGczAls34+5HJPyZysvxQ==", - "requires": { - "symbol-observable": "1.2.0" - } - }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -9817,6 +10104,79 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "internal-ip": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", @@ -9834,18 +10194,6 @@ "get-intrinsic": "^1.1.0", "has": "^1.0.3", "side-channel": "^1.0.4" - }, - "dependencies": { - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - } } }, "invariant": { @@ -9895,9 +10243,13 @@ } }, "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -9905,9 +10257,12 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } }, "is-binary-path": { "version": "2.1.0", @@ -9918,11 +10273,12 @@ } }, "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "requires": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-buffer": { @@ -9931,9 +10287,9 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", - "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" }, "is-ci": { "version": "2.0.0", @@ -9957,9 +10313,9 @@ } }, "is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", "requires": { "has": "^1.0.3" } @@ -9983,9 +10339,12 @@ } }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-descriptor": { "version": "0.1.6", @@ -10035,9 +10394,9 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { "is-extglob": "^2.1.1" } @@ -10047,6 +10406,12 @@ "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, "is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -10062,15 +10427,24 @@ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" }, + "is-node-process": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.0.1.tgz", + "integrity": "sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-obj": { "version": "2.0.0", @@ -10117,11 +10491,12 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { - "has-symbols": "^1.0.1" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-regexp": { @@ -10144,133 +10519,42 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==" }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-typed-array": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", - "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", "requires": { - "available-typed-arrays": "^1.0.2", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.0-next.2", + "es-abstract": "^1.18.5", "foreach": "^2.0.5", - "has-symbols": "^1.0.1" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - } + "has-tostringtag": "^1.0.0" } }, "is-typedarray": { @@ -10278,11 +10562,25 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "is-weakmap": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==" }, + "is-weakref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", + "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "requires": { + "call-bind": "^1.0.0" + } + }, "is-weakset": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", @@ -10321,24 +10619,20 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" }, "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", "requires": { - "@babel/core": "^7.7.5", + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" }, "dependencies": { @@ -10388,19 +10682,26 @@ } }, "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "requires": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz", + "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==", "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -10443,9 +10744,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10544,9 +10845,9 @@ } }, "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, "npm-run-path": { "version": "4.0.1", @@ -10621,9 +10922,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10691,9 +10992,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10732,43 +11033,6 @@ "slash": "^3.0.0" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -10799,9 +11063,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10864,9 +11128,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10912,159 +11176,6 @@ "jest-mock": "^26.6.2", "jest-util": "^26.6.2", "jsdom": "^16.4.0" - }, - "dependencies": { - "abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" - }, - "acorn": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", - "integrity": "sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==" - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - } - } - }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" - } - } - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" - }, - "jsdom": { - "version": "16.5.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.3.tgz", - "integrity": "sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==", - "requires": { - "abab": "^2.0.5", - "acorn": "^8.1.0", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "html-encoding-sniffer": "^2.0.1", - "is-potential-custom-element-name": "^1.0.0", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "request": "^2.88.2", - "request-promise-native": "^1.0.9", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.4", - "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - } - }, - "tr46": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", - "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", - "requires": { - "punycode": "^2.1.1" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" - }, - "whatwg-url": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz", - "integrity": "sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==", - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.0.2", - "webidl-conversions": "^6.1.0" - } - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" - } } }, "jest-environment-node": { @@ -11140,9 +11251,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11205,9 +11316,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11266,9 +11377,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11345,9 +11456,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11371,34 +11482,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -11455,9 +11538,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11483,54 +11566,17 @@ }, "jest-resolve": { "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", - "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", - "requires": { - "@jest/types": "^26.6.2", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^26.6.2", - "read-pkg-up": "^7.0.1", - "resolve": "^1.18.1", - "slash": "^3.0.0" - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", + "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.6.2", + "read-pkg-up": "^7.0.1", + "resolve": "^1.18.1", + "slash": "^3.0.0" } }, "supports-color": { @@ -11586,9 +11632,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11627,43 +11673,6 @@ "slash": "^3.0.0" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -11720,9 +11729,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11761,43 +11770,6 @@ "slash": "^3.0.0" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -11838,9 +11810,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11896,9 +11868,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11955,9 +11927,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12014,9 +11986,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12075,6 +12047,12 @@ } } }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true + }, "js-sha256": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", @@ -12094,10 +12072,49 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", + "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==" + }, + "ws": { + "version": "^7.4.6" + } + } }, "jsesc": { "version": "2.5.2", @@ -12119,11 +12136,6 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -12134,11 +12146,6 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "json3": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", @@ -12176,21 +12183,13 @@ "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^5.6.0" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "jspdf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.3.1.tgz", - "integrity": "sha512-1vp0USP1mQi1h7NKpwxjFgQkJ5ncZvtH858aLpycUc/M+r/RpWJT8PixAU7Cw/3fPd4fpC8eB/Bj42LnsR21YQ==", + "version": "^2.3.1", "dev": true, "requires": { + "@babel/runtime": "^7.14.0", "atob": "^2.1.2", "btoa": "^1.2.1", "canvg": "^3.0.6", @@ -12200,101 +12199,89 @@ "html2canvas": "^1.0.0-rc.5" } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "jss": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.6.0.tgz", - "integrity": "sha512-n7SHdCozmxnzYGXBHe0NsO0eUf9TvsHVq2MXvi4JmTn3x5raynodDVE/9VQmBdWFyyj9HpHZ2B4xNZ7MMy7lkw==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.8.2.tgz", + "integrity": "sha512-FkoUNxI329CKQ9OQC8L72MBF9KPf5q8mIupAJ5twU7G7XREW7ahb+7jFfrjZ4iy1qvhx1HwIWUIvkZBDnKkEdQ==", "requires": { "@babel/runtime": "^7.3.1", "csstype": "^3.0.2", - "indefinite-observable": "^2.0.1", "is-in-browser": "^1.1.3", "tiny-warning": "^1.0.2" }, "dependencies": { "csstype": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", - "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" } } }, "jss-plugin-camel-case": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.6.0.tgz", - "integrity": "sha512-JdLpA3aI/npwj3nDMKk308pvnhoSzkW3PXlbgHAzfx0yHWnPPVUjPhXFtLJzgKZge8lsfkUxvYSQ3X2OYIFU6A==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.8.2.tgz", + "integrity": "sha512-2INyxR+1UdNuKf4v9It3tNfPvf7IPrtkiwzofeKuMd5D58/dxDJVUQYRVg/n460rTlHUfsEQx43hDrcxi9dSPA==", "requires": { "@babel/runtime": "^7.3.1", "hyphenate-style-name": "^1.0.3", - "jss": "10.6.0" + "jss": "10.8.2" } }, "jss-plugin-default-unit": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.6.0.tgz", - "integrity": "sha512-7y4cAScMHAxvslBK2JRK37ES9UT0YfTIXWgzUWD5euvR+JR3q+o8sQKzBw7GmkQRfZijrRJKNTiSt1PBsLI9/w==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.8.2.tgz", + "integrity": "sha512-UZ7cwT9NFYSG+SEy7noRU50s4zifulFdjkUNKE+u6mW7vFP960+RglWjTgMfh79G6OENZmaYnjHV/gcKV4nSxg==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.6.0" + "jss": "10.8.2" } }, "jss-plugin-global": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.6.0.tgz", - "integrity": "sha512-I3w7ji/UXPi3VuWrTCbHG9rVCgB4yoBQLehGDTmsnDfXQb3r1l3WIdcO8JFp9m0YMmyy2CU7UOV6oPI7/Tmu+w==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.8.2.tgz", + "integrity": "sha512-UaYMSPsYZ7s/ECGoj4KoHC2jwQd5iQ7K+FFGnCAILdQrv7hPmvM2Ydg45ThT/sH46DqktCRV2SqjRuxeBH8nRA==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.6.0" + "jss": "10.8.2" } }, "jss-plugin-nested": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.6.0.tgz", - "integrity": "sha512-fOFQWgd98H89E6aJSNkEh2fAXquC9aZcAVjSw4q4RoQ9gU++emg18encR4AT4OOIFl4lQwt5nEyBBRn9V1Rk8g==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.8.2.tgz", + "integrity": "sha512-acRvuPJOb930fuYmhkJaa994EADpt8TxI63Iyg96C8FJ9T2xRyU5T6R1IYKRwUiqZo+2Sr7fdGzRTDD4uBZaMA==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.6.0", + "jss": "10.8.2", "tiny-warning": "^1.0.2" } }, "jss-plugin-props-sort": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.6.0.tgz", - "integrity": "sha512-oMCe7hgho2FllNc60d9VAfdtMrZPo9n1Iu6RNa+3p9n0Bkvnv/XX5San8fTPujrTBScPqv9mOE0nWVvIaohNuw==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.8.2.tgz", + "integrity": "sha512-wqdcjayKRWBZnNpLUrXvsWqh+5J5YToAQ+8HNBNw0kZxVvCDwzhK2Nx6AKs7p+5/MbAh2PLgNW5Ym/ysbVAuqQ==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.6.0" + "jss": "10.8.2" } }, "jss-plugin-rule-value-function": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.6.0.tgz", - "integrity": "sha512-TKFqhRTDHN1QrPTMYRlIQUOC2FFQb271+AbnetURKlGvRl/eWLswcgHQajwuxI464uZk91sPiTtdGi7r7XaWfA==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.8.2.tgz", + "integrity": "sha512-bW0EKAs+0HXpb6BKJhrn94IDdiWb0CnSluTkh0rGEgyzY/nmD1uV/Wf6KGlesGOZ9gmJzQy+9FFdxIUID1c9Ug==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.6.0", + "jss": "10.8.2", "tiny-warning": "^1.0.2" } }, "jss-plugin-vendor-prefixer": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.6.0.tgz", - "integrity": "sha512-doJ7MouBXT1lypLLctCwb4nJ6lDYqrTfVS3LtXgox42Xz0gXusXIIDboeh6UwnSmox90QpVnub7au8ybrb0krQ==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.8.2.tgz", + "integrity": "sha512-DeGv18QsSiYLSVIEB2+l0af6OToUe0JB+trpzUxyqD2QRC/5AzzDrCrYffO5AHZ81QbffYvSN/pkfZaTWpRXlg==", "requires": { "@babel/runtime": "^7.3.1", "css-vendor": "^2.0.8", - "jss": "10.6.0" + "jss": "10.8.2" } }, "jstimezonedetect": { @@ -12303,25 +12290,12 @@ "integrity": "sha512-ARADHortktl9IZ1tr4GHwGPIAzgz3mLNCbR/YjWtRtc/O0o634O3NeFlpLjv95EvuDA5dc8z6yfgbS8nUc4zcQ==" }, "jsx-ast-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", - "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", + "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", "requires": { - "array-includes": "^3.1.2", + "array-includes": "^3.1.3", "object.assign": "^4.1.2" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } } }, "jwa": { @@ -12373,9 +12347,9 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" }, "klona": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", - "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" }, "language-subtag-registry": { "version": "0.3.21", @@ -12405,45 +12379,18 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - } - } + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "loader-runner": { "version": "2.4.0", @@ -12451,9 +12398,9 @@ "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" }, "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -12473,21 +12420,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -12533,6 +12470,11 @@ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -12570,10 +12512,71 @@ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "loglevel": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", - "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==" }, "loose-envify": { "version": "1.4.0", @@ -12592,9 +12595,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -12606,6 +12609,12 @@ "yallist": "^4.0.0" } }, + "lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=", + "dev": true + }, "magic-string": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", @@ -12624,16 +12633,16 @@ } }, "make-event-props": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.2.0.tgz", - "integrity": "sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.3.0.tgz", + "integrity": "sha512-oWiDZMcVB1/A487251hEWza1xzgCzl6MXxe9aF24l5Bt9N9UEbqTqKumEfuuLhmlhRZYnc+suVvW4vUs8bwO7Q==" }, "makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "requires": { - "tmpl": "1.0.x" + "tmpl": "1.0.5" } }, "map-cache": { @@ -12655,9 +12664,9 @@ "integrity": "sha512-c4vLwYWyl+Ji+U43eU/G5FwxWd4ZH0ePUsFs5y0uwD9HUEFBXUQ1zUUan+78IpRD+y4pUfG0nAzNM292K7ItvA==" }, "math-expression-evaluator": { - "version": "1.2.22", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz", - "integrity": "sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ==" + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.3.8.tgz", + "integrity": "sha512-9FbRY3i6U+CbHgrdNbAUaisjWTozkm1ZfupYQJiZ87NtYHk2Zh9DvxMgp/fifxVhqTLpd5fCCLossUbpZxGeKw==" }, "md5.js": { "version": "1.3.5", @@ -12677,66 +12686,37 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "memoize-one": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", - "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" } }, "merge-class-names": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.4.0.tgz", - "integrity": "sha512-xNdBM7s+6uD+vNZJEymqrFbMBCDGzoA8clZTcj2F1XIy1QQKF+wjFVv7iDZFfdCBnViTdt54A4Ye2lmBsXrBjQ==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.4.2.tgz", + "integrity": "sha512-bOl98VzwCGi25Gcn3xKxnR5p/WrhWFQB59MS/aGENcmUc6iSm96yrFDF0XSNurX9qN4LbJm0R9kfvsQ17i8zCw==" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, + "merge-refs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-1.0.0.tgz", + "integrity": "sha512-WZ4S5wqD9FCR9hxkLgvcHJCBxzXzy3VVE6p8W2OzxRzB+hLRlcadGE2bW9xp2KSzk10rvp4y+pwwKO6JQVguMg==" + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -12788,16 +12768,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "requires": { - "mime-db": "1.44.0" + "mime-db": "1.51.0" } }, "mimic-fn": { @@ -12806,9 +12786,9 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, "min-dash": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/min-dash/-/min-dash-3.5.2.tgz", - "integrity": "sha512-YVbJZUtnzT5QsgJUp9H9uyJTW6NJgswFqI27RI/+MSox860uIjaGMbSQBftEzbMXiJVRG24hpoIh3SG666SHgA==" + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/min-dash/-/min-dash-3.8.0.tgz", + "integrity": "sha512-a0TLbmL6p4RlNGblZcLd2yjPORp+bCYRlNGvwK5OMwWaMROWh1DlRgN9W8jJm2x9gVuscvD38BEosV7cnikKnw==" }, "min-dom": { "version": "3.1.3", @@ -12821,12 +12801,18 @@ "matches-selector": "^1.2.0" } }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "mini-create-react-context": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz", - "integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", "requires": { - "@babel/runtime": "^7.5.5", + "@babel/runtime": "^7.12.1", "tiny-warning": "^1.0.3" } }, @@ -12895,9 +12881,9 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", + "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", "requires": { "yallist": "^4.0.0" } @@ -12980,32 +12966,32 @@ } }, "moddle": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/moddle/-/moddle-5.0.1.tgz", - "integrity": "sha512-RB9NCYxbnQLiY1ZJ8Y61+I8TBEmmyaMr8Tj0+fJHN8Fm6l5NqojDy1s4LNDxq+omvug4gnzERMgT8uwNsADDvw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/moddle/-/moddle-5.0.2.tgz", + "integrity": "sha512-nBEyKt7sDw6MlM6e85lTCEXButw+p7hubEoRo/JyX+dBzDcGjDoktPuby9QE+ylW1ABZqNvRy8pK0h+23tIW2g==", "requires": { "min-dash": "^3.0.0" } }, "moddle-xml": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/moddle-xml/-/moddle-xml-9.0.4.tgz", - "integrity": "sha512-RzF+hLiMGetWuEnJLuljORDdmFPJxgNYVEdog7ynmg0EK+MjtrsqYZjn786XluW9de6h7Y/FRQjVQZP4vJ9HyQ==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/moddle-xml/-/moddle-xml-9.0.5.tgz", + "integrity": "sha512-1t9N35ZMQZTYZmRDoh1mBVd0XwLB34BkBywNJ0+YlLLYxaDBjFR/I+fqwsY746ayYPBz6yNRg8JpLyFgNF+eHg==", "requires": { "min-dash": "^3.5.2", - "moddle": "^5.0.1", + "moddle": "^5.0.2", "saxen": "^8.1.2" } }, "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, "moment-timezone": { - "version": "0.5.33", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", - "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", "requires": { "moment": ">= 2.9.0" } @@ -13024,25 +13010,176 @@ } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "msw": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/msw/-/msw-0.36.0.tgz", + "integrity": "sha512-cDoyiyntDeOu1vlbuxh29nHf8jEyfxUh/4yBmrfcDRMurA/ts40vPtlwRYIhQU6kvJrdXERsKChsparvosxF4g==", + "dev": true, + "requires": { + "@mswjs/cookies": "^0.1.6", + "@mswjs/interceptors": "^0.12.7", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/inquirer": "^8.1.3", + "@types/js-levenshtein": "^1.1.0", + "chalk": "4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.1", + "graphql": "^15.5.1", + "headers-utils": "^3.0.2", + "inquirer": "^8.2.0", + "is-node-process": "^1.0.1", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.1", + "path-to-regexp": "^6.2.0", + "statuses": "^2.0.0", + "strict-event-emitter": "^0.2.0", + "type-fest": "^1.2.2", + "yargs": "^17.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "path-to-regexp": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", + "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz", + "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", + "dev": true + } + } }, "multicast-dns": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", "requires": { - "dns-packet": "^1.3.1", + "dns-packet": "^5.2.4", "thunky": "^1.0.2" }, "dependencies": { "dns-packet": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.0.tgz", - "integrity": "sha512-Nce7YLu6YCgWRvOmDBsJMo9M5/jV3lEZ5vUWnWXYmwURvPylHvq7nkDWhNmk1ZQoZZOP7oQh/S0lSxbisKOfHg==", + "version": "^5.2.4", "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" } } } @@ -13052,16 +13189,16 @@ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "optional": true + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true }, "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" + "version": "3.1.30", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz", + "integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==" }, "nanomatch": { "version": "1.2.13", @@ -13129,16 +13266,40 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } }, "node-forge": { "version": "0.10.0", @@ -13146,9 +13307,9 @@ "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" }, "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", "optional": true }, "node-int64": { @@ -13186,44 +13347,10 @@ "vm-browserify": "^1.0.1" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -13255,12 +13382,6 @@ "lru-cache": "^6.0.0" } }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "optional": true - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13273,9 +13394,9 @@ } }, "node-releases": { - "version": "1.1.72", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", - "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, "normalize-package-data": { "version": "2.5.0", @@ -13317,14 +13438,6 @@ "path-key": "^2.0.0" } }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -13335,11 +13448,6 @@ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -13374,17 +13482,17 @@ } }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==" }, "object-is": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", - "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "object-keys": { @@ -13402,394 +13510,57 @@ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", - "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - } + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" } }, "object.fromentries": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", - "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - } + "es-abstract": "^1.19.1" } }, "object.getownpropertydescriptors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", - "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", + "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - } + "es-abstract": "^1.19.1" + } + }, + "object.hasown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", + "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" } }, "object.pick": { @@ -13801,120 +13572,13 @@ } }, "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - } + "es-abstract": "^1.19.1" } }, "obuf": { @@ -13985,16 +13649,84 @@ } }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "original": { @@ -14010,6 +13742,18 @@ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "outvariant": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.2.1.tgz", + "integrity": "sha512-bcILvFkvpMXh66+Ubax/inxbKRyWTUiiFIW2DWkiS79wakrLGn3Ydy+GvukadiyfZjaL6C7YhIem4EZSM282wA==", + "dev": true + }, "p-each-series": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", @@ -14043,72 +13787,38 @@ "requires": { "aggregate-error": "^3.0.0" } - }, - "p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", - "requires": { - "retry": "^0.12.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "paginator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/paginator/-/paginator-1.0.0.tgz", - "integrity": "sha1-dWVwKvmrlhbcph/CLHDroqQ1cmU=" - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "paginator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/paginator/-/paginator-1.0.0.tgz", + "integrity": "sha1-dWVwKvmrlhbcph/CLHDroqQ1cmU=" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" } }, "param-case": { @@ -14121,9 +13831,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -14163,6 +13873,11 @@ "lines-and-columns": "^1.1.6" } }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -14178,9 +13893,9 @@ }, "dependencies": { "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -14194,15 +13909,20 @@ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "path-intersection": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/path-intersection/-/path-intersection-2.2.0.tgz", - "integrity": "sha512-1qchRuLKhRt3qYePf9CU/74fLrBo9OTiKYNn5fxfuHJW6kTThEk04ql7w8JwOgZjNANAGp1052tWGpwZ7ItNRA==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-intersection/-/path-intersection-2.2.1.tgz", + "integrity": "sha512-9u8xvMcSfuOiStv9bPdnRJQhGQXLKurew94n4GPQCdH1nj9QKC9ObbNoIpiRq8skiOBxKkt277PgOoFgAt3/rA==" }, "path-is-absolute": { "version": "1.0.1", @@ -14224,24 +13944,6 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "path-starts-with": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-starts-with/-/path-starts-with-1.0.0.tgz", - "integrity": "sha1-soJDAV6LE43lcmgqxS2kLmRq2E4=", - "requires": { - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, "path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", @@ -14279,10 +13981,15 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, "picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, "pify": { "version": "4.0.1", @@ -14351,51 +14058,38 @@ } }, "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", "requires": { - "find-up": "^2.1.0" + "find-up": "^3.0.0" }, "dependencies": { "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "requires": { - "locate-path": "^2.0.0" + "locate-path": "^3.0.0" } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "p-locate": "^2.0.0", + "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "requires": { - "p-try": "^1.0.0" - } - }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "requires": { - "p-limit": "^1.1.0" + "p-limit": "^2.0.0" } }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -14433,11 +14127,6 @@ "requires": { "ms": "^2.1.1" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -14447,22 +14136,23 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "7.0.36", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", - "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -14545,7 +14235,7 @@ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", "requires": { - "browserslist": "^4.0.0", + "browserslist": "^4.17.6", "color": "^3.0.0", "has": "^1.0.0", "postcss": "^7.0.0", @@ -14553,15 +14243,13 @@ }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -14913,7 +14601,7 @@ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", "requires": { - "browserslist": "^4.0.0", + "browserslist": "^4.17.6", "caniuse-api": "^3.0.0", "cssnano-util-same-parent": "^4.0.0", "postcss": "^7.0.0", @@ -14922,15 +14610,13 @@ }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -15000,7 +14686,7 @@ "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", "requires": { "alphanum-sort": "^1.0.0", - "browserslist": "^4.0.0", + "browserslist": "^4.17.6", "cssnano-util-get-arguments": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", @@ -15008,15 +14694,13 @@ }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -15115,22 +14799,20 @@ "integrity": "sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ==", "requires": { "@csstools/normalize.css": "^10.1.0", - "browserslist": "^4.6.2", + "browserslist": "^4.17.6", "postcss": "^7.0.17", "postcss-browser-comments": "^3.0.0", "sanitize.css": "^10.0.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -15250,21 +14932,19 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", "requires": { - "browserslist": "^4.0.0", + "browserslist": "^4.17.6", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -15376,7 +15056,7 @@ "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", "requires": { "autoprefixer": "^9.6.1", - "browserslist": "^4.6.4", + "browserslist": "^4.17.6", "caniuse-lite": "^1.0.30000981", "css-blank-pseudo": "^0.1.4", "css-has-pseudo": "^0.10.0", @@ -15415,15 +15095,13 @@ }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" }, "dependencies": { "caniuse-lite": { @@ -15476,22 +15154,20 @@ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", "requires": { - "browserslist": "^4.0.0", + "browserslist": "^4.17.6", "caniuse-api": "^3.0.0", "has": "^1.0.0", "postcss": "^7.0.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -15546,13 +15222,13 @@ }, "dependencies": { "postcss": { - "version": "8.2.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", - "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", + "version": "8.4.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.4.tgz", + "integrity": "sha512-joU6fBsN6EIer28Lj6GDFoC/5yOZzLCfn0zHAn/MYXI7aPt4m4hK5KC5ovEZXy+lnCjmYIbQWngvju2ddyEr8Q==", "requires": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map": "^0.6.1" + "nanoid": "^3.1.30", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.1" } } } @@ -15612,9 +15288,9 @@ } }, "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "postcss-values-parser": { "version": "2.0.1", @@ -15627,9 +15303,9 @@ } }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, "prepend-http": { "version": "1.0.4", @@ -15656,11 +15332,14 @@ "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", "requires": { "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", + "ansi-regex": "^5.0.1", "ansi-styles": "^4.0.0", "react-is": "^17.0.1" }, "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -15681,11 +15360,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" } } }, @@ -15734,6 +15408,13 @@ "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.8.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "prop-types-extra": { @@ -15743,14 +15424,21 @@ "requires": { "react-is": "^16.3.2", "warning": "^4.0.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, @@ -15825,9 +15513,9 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "query-string": { "version": "4.3.4", @@ -15945,9 +15633,7 @@ } }, "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "^17.0.2", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -15967,38 +15653,27 @@ } }, "react-bootstrap": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.0.tgz", - "integrity": "sha512-PaeOGeRC2+JH9Uf1PukJgXcIpfGlrKKHEBZIArymjenYzSJ/RhO2UdNX+e7nalsCFFZLRRgQ0/FKkscW2LmmRg==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.4.tgz", + "integrity": "sha512-z3BhBD4bEZuLP8VrYqAD7OT7axdcSkkyvWBWnS2U/4MhyabUihrUyucPWkan7aMI1XIHbmH4LCpEtzWGfx/yfA==", "requires": { - "@babel/runtime": "^7.13.8", + "@babel/runtime": "^7.14.0", "@restart/context": "^2.1.4", "@restart/hooks": "^0.3.26", - "@types/classnames": "^2.2.10", "@types/invariant": "^2.2.33", "@types/prop-types": "^15.7.3", - "@types/react": ">=16.9.35", + "@types/react": ">=16.14.8", "@types/react-transition-group": "^4.4.1", "@types/warning": "^3.0.0", - "classnames": "^2.2.6", - "dom-helpers": "^5.1.2", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", "invariant": "^2.2.4", "prop-types": "^15.7.2", "prop-types-extra": "^1.1.0", - "react-overlays": "^5.0.0", + "react-overlays": "^5.1.1", "react-transition-group": "^4.4.1", "uncontrollable": "^7.2.1", "warning": "^4.0.3" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", - "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } } }, "react-bootstrap-table-next": { @@ -16008,13 +15683,11 @@ "requires": { "classnames": "^2.2.5", "react-transition-group": "^4.2.0", - "underscore": "1.9.1" + "underscore": "^1.13.1" }, "dependencies": { "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + "version": "^1.13.1" } } }, @@ -16042,19 +15715,12 @@ "integrity": "sha512-nKBSezHTOkO9k8YMMuJfPEZtBVfIYrJbmP8n3u7+AXRcOrOGygXyauNVKWqdKLchQlG/cW5QR0sPkFknpp5rjQ==", "requires": { "file-saver": "2.0.2" - }, - "dependencies": { - "file-saver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", - "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" - } } }, "react-calendar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-3.3.1.tgz", - "integrity": "sha512-iDIrhE0ABz3mChAIvA+5d2UtQGEb5oaUpLiEbrRdWHBYb45MhsbO59pG9HIy2uTdHkBF/nvzRV2JBmMfdg/0Qg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-3.5.0.tgz", + "integrity": "sha512-WrDOON59188ciC7jw5YrlM/EgLTWM9TD9dflRWjgd9rlMxPScX8dNG4tJGE+z8d4xaEVccJmHbiYGCGsYdXdxQ==", "requires": { "@wojtekmaj/date-utils": "^1.0.2", "get-user-locale": "^1.2.0", @@ -16063,25 +15729,26 @@ } }, "react-date-picker": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/react-date-picker/-/react-date-picker-8.1.0.tgz", - "integrity": "sha512-JkFBMqtHM/Hxxw5r99sy6RKx5CcKXeqnEStbN/v35DzGR40dYLe/Z67hMiG+8K6WMiowfbNLjzDW7Ej0DM8LIg==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/react-date-picker/-/react-date-picker-8.3.6.tgz", + "integrity": "sha512-c1rThf0jSKROoSGLpUEPtcC8VE+XoVgqxh+ng9aLYQvjDMGWQBgoat6Qrj8nRVzvCPpdXV4jqiCB3z2vVVuseA==", "requires": { "@types/react-calendar": "^3.0.0", "@wojtekmaj/date-utils": "^1.0.3", "get-user-locale": "^1.2.0", "make-event-props": "^1.1.0", "merge-class-names": "^1.1.1", + "merge-refs": "^1.0.0", "prop-types": "^15.6.0", "react-calendar": "^3.3.1", "react-fit": "^1.0.3", - "update-input-width": "^1.1.1" + "update-input-width": "^1.2.2" } }, "react-date-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/react-date-range/-/react-date-range-1.1.3.tgz", - "integrity": "sha512-Q0+80JaEw3O2J50Lf1dcwWfqkzu3SaCZUTgtVEG9kIHy1h1x8XTNrumX08hKz+M//wg7NOymaTzP1RPBYoLpmw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-date-range/-/react-date-range-1.4.0.tgz", + "integrity": "sha512-+9t0HyClbCqw1IhYbpWecjsiaftCeRN5cdhsi9v06YdimwyMR2yYHWcgVn3URwtN/txhqKpEZB6UX1fHpvK76w==", "requires": { "classnames": "^2.2.6", "prop-types": "^15.7.2", @@ -16108,7 +15775,7 @@ "requires": { "@babel/code-frame": "7.10.4", "address": "1.1.2", - "browserslist": "4.14.2", + "browserslist": "^4.17.6", "chalk": "2.4.2", "cross-spawn": "7.0.3", "detect-port-alt": "1.1.6", @@ -16119,7 +15786,7 @@ "global-modules": "2.0.0", "globby": "11.0.1", "gzip-size": "5.1.1", - "immer": "8.0.1", + "immer": "^9.0.6", "is-root": "2.1.0", "loader-utils": "2.0.0", "open": "^7.0.2", @@ -16132,18 +15799,29 @@ "text-table": "0.2.0" }, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, + "caniuse-lite": { + "version": "1.0.30001285", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001285.tgz", + "integrity": "sha512-KAOkuUtcQ901MtmvxfKD+ODHH9YVDYnBt+TGYSz2KIfnq22CiArbUxXPN9067gNbgMlnNYRSwho8OPXZPALB9Q==" + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -16154,6 +15832,11 @@ "which": "^2.0.1" } }, + "electron-to-chromium": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.14.tgz", + "integrity": "sha512-RsGkAN9JEAYMObS72kzUsPPcPGMqX1rBqGuXi9aa4TBKLzICoLf+DAAtd0fVFzrniJqYzpby47gthCUoObfs0Q==" + }, "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", @@ -16172,6 +15855,9 @@ "slash": "^3.0.0" } }, + "immer": { + "version": "^9.0.6" + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -16181,42 +15867,26 @@ "path-exists": "^3.0.0" } }, + "node-releases": { + "version": "1.1.77", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", + "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "requires": { - "p-limit": "^2.0.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, - "pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - } - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -16230,6 +15900,19 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -16241,9 +15924,7 @@ } }, "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "^17.0.2", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -16251,9 +15932,9 @@ } }, "react-dropdown-select": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/react-dropdown-select/-/react-dropdown-select-4.7.4.tgz", - "integrity": "sha512-3fp/Bz+Vl6t+NulfoU4NGGXAZ7zjpwsQdrvLN/IPrVZzcXSSwGSIubIESrLi9L0cl4SD7bqqQHERrp/CoiVFCw==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/react-dropdown-select/-/react-dropdown-select-4.8.0.tgz", + "integrity": "sha512-4QwsPHfodUYkdjF81/9jEvfichbhvAtkLBF1xwucKQI62tcSJQuBAnU3LUNxYGzFGImdsj9meXPOo3hTMWnKqg==", "requires": { "@emotion/core": "^10.0.27", "@emotion/styled": "^10.0.27" @@ -16270,9 +15951,9 @@ "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, "react-fit": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/react-fit/-/react-fit-1.3.1.tgz", - "integrity": "sha512-MmVk/SXyVbxiz9peAeD7fWxFdGLoy/sCxte01M3w74regPIVkLqc2yT0wUAGRd1MNP1fQ40MqYKNBLpbK/aI1w==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/react-fit/-/react-fit-1.3.2.tgz", + "integrity": "sha512-Ih/ee8/I/N6EcGZjOqfo/yFq6Q/xuZ62uai21rMyud208ixx8V5xJxuRLIxedLcwNAEtyyEPEJ2Y47qeKljQHA==", "requires": { "detect-element-overflow": "^1.2.0", "prop-types": "^15.6.0" @@ -16289,18 +15970,6 @@ "formiojs": "^4.9.0", "lodash": "^4.17.15", "prop-types": "^15.7.2" - }, - "dependencies": { - "core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" - }, - "eventemitter2": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", - "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=" - } } }, "react-helmet": { @@ -16323,9 +15992,9 @@ } }, "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, "react-js-pagination": { "version": "3.0.3", @@ -16336,28 +16005,19 @@ "fstream": "1.0.12", "paginator": "^1.0.0", "prop-types": "15.x.x - 16.x.x", - "react": "15.x.x - 16.x.x", - "tar": "2.2.2" + "react": "^17.0.2", + "tar": "^6.1.11" }, "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "^17.0.2", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "tar": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.8.tgz", - "integrity": "sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A==", + "version": "^6.1.11", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -16414,14 +16074,14 @@ } }, "react-onclickoutside": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.10.0.tgz", - "integrity": "sha512-7i2L3ef+0ILXpL6P+Hg304eCQswh4jl3ynwR71BSlMU49PE2uk31k8B2GkP6yE9s2D4jTGKnzuSpzWxu4YxfQQ==" + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.12.1.tgz", + "integrity": "sha512-a5Q7CkWznBRUWPmocCvE8b6lEYw1s6+opp/60dCunhO+G6E4tDTO2Sd2jKE+leEnnrLAE2Wj5DlDHNqj5wPv1Q==" }, "react-overlays": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.0.1.tgz", - "integrity": "sha512-plwUJieTBbLSrgvQ4OkkbTD/deXgxiJdNuKzo6n1RWE3OVnQIU5hffCGS/nvIuu6LpXFs2majbzaXY8rcUVdWA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.1.1.tgz", + "integrity": "sha512-eCN2s2/+GVZzpnId4XVWtvDPYYBD2EtOGP74hE+8yDskPzFy9+pV1H3ZZihxuRdEbQzzacySaaDkR7xE0ydl4Q==", "requires": { "@babel/runtime": "^7.13.8", "@popperjs/core": "^2.8.6", @@ -16431,16 +16091,6 @@ "prop-types": "^15.7.2", "uncontrollable": "^7.2.1", "warning": "^4.0.3" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", - "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } } }, "react-popper": { @@ -16478,26 +16128,16 @@ } }, "react-redux": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.4.tgz", - "integrity": "sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA==", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz", + "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==", "requires": { - "@babel/runtime": "^7.12.1", - "@types/react-redux": "^7.1.16", + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", "hoist-non-react-statics": "^3.3.2", "loose-envify": "^1.4.0", "prop-types": "^15.7.2", "react-is": "^16.13.1" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", - "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } } }, "react-refresh": { @@ -16517,11 +16157,11 @@ } }, "react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", + "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", "requires": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "hoist-non-react-statics": "^3.1.0", "loose-envify": "^1.3.1", @@ -16531,18 +16171,25 @@ "react-is": "^16.6.0", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "react-router-dom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", - "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", + "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", "requires": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "loose-envify": "^1.3.1", "prop-types": "^15.6.2", - "react-router": "5.2.0", + "react-router": "5.2.1", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" } @@ -16650,9 +16297,9 @@ "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" }, "react-smooth": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-1.0.5.tgz", - "integrity": "sha512-eW057HT0lFgCKh8ilr0y2JaH2YbNcuEdFpxyg7Gf/qDKk9hqGMyXryZJ8iMGJEuKH0+wxS0ccSsBBB3W8yCn8w==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-1.0.6.tgz", + "integrity": "sha512-B2vL4trGpNSMSOzFiAul9kFAsxTukL9Wyy9EXtkQy3GJr6sZqW9e1nShdVOJ3hRYamPZ94O17r3Q0bjSw3UYtg==", "requires": { "lodash": "~4.17.4", "prop-types": "^15.6.0", @@ -16690,9 +16337,9 @@ } }, "react-transition-group": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", - "integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", + "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", "requires": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -16701,98 +16348,70 @@ } }, "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" }, "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" } } }, "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" } } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "requires": { "picomatch": "^2.2.1" } @@ -16816,16 +16435,16 @@ }, "dependencies": { "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" } } }, "recharts-scale": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.3.tgz", - "integrity": "sha512-t8p5sccG9Blm7c1JQK/ak9O8o95WGhNXD7TXg/BW5bYbVlr6eCeRBNpgyigD4p6pSSMehC5nSvBUPj6F68rbFA==", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", "requires": { "decimal.js-light": "^2.4.1" } @@ -16838,6 +16457,16 @@ "minimatch": "3.0.4" } }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, "reduce-css-calc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", @@ -16864,9 +16493,9 @@ } }, "redux": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", - "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", "requires": { "@babel/runtime": "^7.9.2" } @@ -16879,10 +16508,19 @@ "deep-diff": "^0.3.5" } }, + "redux-mock-store": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.4.tgz", + "integrity": "sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==", + "dev": true, + "requires": { + "lodash.isplainobject": "^4.0.6" + } + }, "redux-thunk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", - "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==" }, "regenerate": { "version": "1.4.2", @@ -16890,17 +16528,17 @@ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", + "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", "requires": { - "regenerate": "^1.4.0" + "regenerate": "^1.4.2" } }, "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "regenerator-transform": { "version": "0.14.5", @@ -16925,30 +16563,30 @@ "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" }, "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" }, "regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", + "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^9.0.0", + "regjsgen": "^0.5.2", + "regjsparser": "^0.7.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" } }, "regjsgen": { @@ -16957,9 +16595,9 @@ "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" }, "regjsparser": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", - "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", + "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", "requires": { "jsesc": "~0.5.0" }, @@ -16982,28 +16620,85 @@ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "renderkid": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz", - "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", "requires": { - "css-select": "^2.0.2", - "dom-converter": "^0.2", - "htmlparser2": "^3.10.1", - "lodash": "^4.17.20", - "strip-ansi": "^3.0.0" + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "^5.0.1" + }, + "css-select": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", + "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.0.1", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.1" + }, + "dependencies": { + "css-what": { + "version": "^5.0.1" + }, + "nth-check": { + "version": "^2.0.1" + } + } + }, + "css-what": { + "version": "^5.0.1" + }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "nth-check": { + "version": "^2.0.1", + "requires": { + "boolbase": "^1.0.0" + } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } } } } @@ -17018,51 +16713,6 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "requires": { - "lodash": "^4.17.19" - } - }, - "request-promise-native": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", - "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", - "requires": { - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -17089,10 +16739,11 @@ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" }, "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -17148,6 +16799,14 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -17170,9 +16829,47 @@ "emojis-list": "^2.0.0", "json5": "^1.0.1" } + }, + "postcss": { + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } } } }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -17223,7 +16920,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", "integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0=", - "dev": true, "optional": true }, "rimraf": { @@ -17251,13 +16947,6 @@ "@types/estree": "*", "@types/node": "*", "acorn": "^7.1.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - } } }, "rollup-plugin-babel": { @@ -17281,11 +16970,6 @@ "terser": "^4.6.2" }, "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "jest-worker": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", @@ -17310,16 +16994,6 @@ "requires": { "has-flag": "^3.0.0" } - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } } } }, @@ -17343,6 +17017,12 @@ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==" }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -17359,6 +17039,23 @@ "aproba": "^1.1.1" } }, + "rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "requires": { + "tslib": "~2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -17513,11 +17210,12 @@ "integrity": "sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg==" }, "sass": { - "version": "1.32.13", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.32.13.tgz", - "integrity": "sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.44.0.tgz", + "integrity": "sha512-0hLREbHFXGQqls/K8X+koeP+ogFRPF4ZqetVB19b7Cst9Er8cOR0rc6RU7MaI4W1JmUShd1BPgPoeqmmgMMYFw==", "requires": { - "chokidar": ">=3.0.0 <4.0.0" + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0" } }, "sass-loader": { @@ -17532,23 +17230,12 @@ "semver": "^7.3.2" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "requires": { - "@types/json-schema": "^7.0.6", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -17712,6 +17399,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", @@ -17735,10 +17427,14 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "set-cookie-parser": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", + "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==", + "dev": true + }, "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "version": "^4.1.0", "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -17812,29 +17508,12 @@ "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" - }, - "dependencies": { - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==" - } } }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, "signature_pad": { "version": "2.3.2", @@ -17938,10 +17617,10 @@ "is-extendable": "^0.1.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -18010,26 +17689,26 @@ } }, "sockjs": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", - "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "requires": { "faye-websocket": "^0.11.3", - "uuid": "^3.4.0", + "uuid": "^8.3.2", "websocket-driver": "^0.7.4" } }, "sockjs-client": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz", - "integrity": "sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz", + "integrity": "sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==", "requires": { "debug": "^3.2.6", "eventsource": "^1.0.7", "faye-websocket": "^0.11.3", "inherits": "^2.0.4", "json3": "^3.3.3", - "url-parse": "^1.5.1" + "url-parse": "^1.5.3" }, "dependencies": { "debug": { @@ -18039,11 +17718,6 @@ "requires": { "ms": "^2.1.1" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -18061,9 +17735,9 @@ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-explorer": { "version": "2.5.2", @@ -18093,9 +17767,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -18188,12 +17862,17 @@ } }, "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==" + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" } } }, + "source-map-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.1.tgz", + "integrity": "sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==" + }, "source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", @@ -18207,12 +17886,19 @@ } }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "source-map-url": { @@ -18249,9 +17935,9 @@ } }, "spdx-license-ids": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.8.tgz", - "integrity": "sha512-NDgA96EnaLSvtbM7trJj+t1LUR3pirkDCcz9nOUlPb5DMBGsH7oES6C3hs3j7R9oHEa1EMvReS/BUAIT5Tcr0g==" + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" }, "spdy": { "version": "4.0.2", @@ -18276,6 +17962,18 @@ "obuf": "^1.1.2", "readable-stream": "^3.0.6", "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "split-string": { @@ -18291,22 +17989,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", @@ -18321,9 +18003,9 @@ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" }, "stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "requires": { "escape-string-regexp": "^2.0.0" }, @@ -18339,7 +18021,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz", "integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==", - "dev": true, "optional": true }, "stackframe": { @@ -18371,17 +18052,37 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" - }, "stompjs": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/stompjs/-/stompjs-2.3.3.tgz", "integrity": "sha1-NBeKx7uO4pTMXVVK2LUPf1RZ/Y4=", "requires": { - "websocket": "^1.0.33" + "websocket": "^1.0.34" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "websocket": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", + "optional": true, + "requires": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + } + } } }, "stream-browserify": { @@ -18391,40 +18092,6 @@ "requires": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-each": { @@ -18446,40 +18113,6 @@ "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-shift": { @@ -18487,6 +18120,15 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" }, + "strict-event-emitter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.0.tgz", + "integrity": "sha512-zv7K2egoKwkQkZGEaH8m+i2D0XiKzx5jNsiSul6ja2IYFvil10A59Z9Y7PPAAe5OW53dQUf9CfsHKzjZzKkm1w==", + "dev": true, + "requires": { + "events": "^3.3.0" + } + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -18512,168 +18154,61 @@ "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "string.prototype.matchall": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz", - "integrity": "sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz", + "integrity": "sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has-symbols": "^1.0.1", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.2", "internal-slot": "^1.0.3", "regexp.prototype.flags": "^1.3.1", "side-channel": "^1.0.4" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - } } }, "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "stringify-object": { @@ -18694,11 +18229,16 @@ } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } } }, "strip-bom": { @@ -18725,6 +18265,15 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -18744,21 +18293,19 @@ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", "requires": { - "browserslist": "^4.0.0", + "browserslist": "^4.17.6", "postcss": "^7.0.0", "postcss-selector-parser": "^3.0.0" }, "dependencies": { "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "^4.17.6", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "caniuse-lite": { @@ -18829,7 +18376,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-5.0.5.tgz", "integrity": "sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==", - "dev": true, "optional": true }, "svgo": { @@ -18852,33 +18398,27 @@ "util.promisify": "~1.0.0" } }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" - }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "table": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", - "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", + "integrity": "sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==", "requires": { "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "dependencies": { "ajv": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.4.0.tgz", - "integrity": "sha512-7QD2l6+KBSLwf+7MuYocbWvRPdOu63/trReTLu2KFwkgctnub1auoF+Y1WYcm09CTM7quuscrzqmASaLHC/K4Q==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", + "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -18898,6 +18438,14 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, + "tar": { + "version": "^6.1.11", + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, "temp": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", @@ -18948,6 +18496,28 @@ "supports-hyperlinks": "^2.0.0" } }, + "terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } + }, "terser-webpack-plugin": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", @@ -18975,15 +18545,10 @@ "uri-js": "^4.2.2" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "requires": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -19015,11 +18580,11 @@ } }, "schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "requires": { - "@types/json-schema": "^7.0.6", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -19029,14 +18594,19 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, "terser": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz", - "integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", "requires": { "commander": "^2.20.0", "source-map": "~0.7.2", - "source-map-support": "~0.5.19" + "source-map-support": "~0.5.20" }, "dependencies": { "source-map": { @@ -19063,6 +18633,16 @@ "resolved": "https://registry.npmjs.org/text-mask-addons/-/text-mask-addons-3.8.0.tgz", "integrity": "sha1-F7Ye9mWk82gR8uofAaIjtL5hqyY=" }, + "text-segmentation": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.2.tgz", + "integrity": "sha512-uTqvLxdBrVnx/CFQOtnf8tfzSXFm+1Qxau7Xi54j4OPTZokuDOX8qncQzrg2G8ZicAMOM8TgzFAYTb+AqNO4Cw==", + "dev": true, + "optional": true, + "requires": { + "utrie": "^1.0.1" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -19073,6 +18653,12 @@ "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==" }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -19080,40 +18666,6 @@ "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "thunky": { @@ -19140,9 +18692,9 @@ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, "tiny-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", - "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" }, "tiny-svg": { "version": "2.2.2", @@ -19154,10 +18706,19 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, "to-arraybuffer": { "version": "1.0.1", @@ -19227,14 +18788,27 @@ } }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "dependencies": { + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -19246,9 +18820,9 @@ "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==" }, "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", "requires": { "@types/json5": "^0.0.29", "json5": "^1.0.1", @@ -19284,30 +18858,17 @@ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, "type-detect": { @@ -19316,9 +18877,9 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" }, "type-is": { "version": "1.6.18", @@ -19356,13 +18917,6 @@ "has-bigints": "^1.0.1", "has-symbols": "^1.0.2", "which-boxed-primitive": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } } }, "uncontrollable": { @@ -19377,34 +18931,32 @@ } }, "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", + "version": "^1.13.1", "dev": true }, "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" }, "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" } }, "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" }, "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" }, "union-value": { "version": "1.0.1", @@ -19414,7 +18966,21 @@ "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "set-value": "^4.1.0" + }, + "dependencies": { + "is-primitive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", + "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==" + }, + "set-value": { + "version": "^4.1.0", + "requires": { + "is-plain-object": "^2.0.4", + "is-primitive": "^3.0.1" + } + } } }, "uniq": { @@ -19513,14 +19079,14 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, "update-input-width": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/update-input-width/-/update-input-width-1.2.1.tgz", - "integrity": "sha512-zygDshqDb2C2/kgfoD423n5htv/3OBF7aTaz2u2zZy998EJki8njOHOeZjKEd8XSYeDziIX1JXfMsKaIRJeJ/Q==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-input-width/-/update-input-width-1.2.2.tgz", + "integrity": "sha512-6QwD9ZVSXb96PxOZ01DU0DJTPwQGY7qBYgdniZKJN02Xzom2m+9J6EPxMbefskqtj4x78qbe5psDSALq9iNEYg==" }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } @@ -19561,23 +19127,12 @@ "schema-utils": "^3.0.0" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "requires": { - "@types/json-schema": "^7.0.6", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -19599,12 +19154,12 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, "utf-8-validate": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz", - "integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", + "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", "optional": true, "requires": { - "node-gyp-build": "^4.2.0" + "node-gyp-build": "^4.3.0" } }, "util": { @@ -19648,10 +19203,29 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "utrie": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.1.tgz", + "integrity": "sha512-JPaDXF3vzgZxfeEwutdGzlrNoVFL5UvZcbO6Qo9D4GoahrieUPoMU8GCpVpR7MQqcKhmShIh8VlbEN3PLM3EBg==", + "dev": true, + "optional": true, + "requires": { + "base64-arraybuffer": "^1.0.1" + }, + "dependencies": { + "base64-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz", + "integrity": "sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==", + "dev": true, + "optional": true + } + } + }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache": { "version": "2.3.0", @@ -19690,9 +19264,9 @@ "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, "vanilla-picker": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.11.2.tgz", - "integrity": "sha512-2cP7LlUnxHxwOf06ReUVtd2RFJMnJGaxN2s0p8wzBH3In5b00Le7fFZ9VrIoBE0svZkSq/BC/Pwq/k/9n+AA2g==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.1.tgz", + "integrity": "sha512-2qrEP9VYylKXbyzXKsbu2dferBTvqnlsr29XjHwFE+/MEp0VNj6oEUESLDtKZ7DWzGdSv1x/+ujqFZF+KsO3cg==", "requires": { "@sphinxxxx/color-conversion": "^2.2.2" } @@ -19707,16 +19281,6 @@ "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -19736,21 +19300,14 @@ "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", "requires": { "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" - } } }, "walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "requires": { - "makeerror": "1.0.x" + "makeerror": "1.0.12" } }, "warning": { @@ -19847,7 +19404,7 @@ "async-each": "^1.0.1", "braces": "^2.3.2", "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", + "glob-parent": "^6.0.2", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", "is-glob": "^4.0.0", @@ -19858,21 +19415,19 @@ }, "dependencies": { "glob-parent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.1.tgz", - "integrity": "sha512-kEVjS71mQazDBHKcsq4E9u/vUzaLcw1A8EtUeydawvIWQCJM0qQ08G1H7/XTjFUulla6XQiDOG6MXSaG0HDKog==", + "version": "^6.0.2", "optional": true, "requires": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "dependencies": { "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "optional": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "^2.1.1" } } } @@ -19906,25 +19461,12 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } + "optional": true }, "glob-parent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.1.tgz", - "integrity": "sha512-kEVjS71mQazDBHKcsq4E9u/vUzaLcw1A8EtUeydawvIWQCJM0qQ08G1H7/XTjFUulla6XQiDOG6MXSaG0HDKog==", - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } + "version": "^6.0.2", + "requires": { + "is-glob": "^4.0.3" } }, "is-binary-path": { @@ -19956,12 +19498,6 @@ } } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "optional": true - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -19983,21 +19519,6 @@ "to-regex": "^3.0.2" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -20009,21 +19530,6 @@ "readable-stream": "^2.0.2" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", @@ -20044,6 +19550,11 @@ "minimalistic-assert": "^1.0.0" } }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" + }, "webpack": { "version": "4.44.2", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", @@ -20133,11 +19644,6 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -20255,6 +19761,11 @@ "randombytes": "^2.1.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, "ssri": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", @@ -20263,16 +19774,6 @@ "figgy-pudding": "^3.5.1" } }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } - }, "terser-webpack-plugin": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", @@ -20318,9 +19819,9 @@ }, "dependencies": { "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==" } } }, @@ -20360,14 +19861,12 @@ "url": "^0.11.0", "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", - "ws": "^6.2.1", + "ws": "^7.4.6", "yargs": "^13.3.2" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "^5.0.1" }, "anymatch": { "version": "2.0.0", @@ -20434,7 +19933,7 @@ "async-each": "^1.0.1", "braces": "^2.3.2", "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", + "glob-parent": "^6.0.2", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", "is-glob": "^4.0.0", @@ -20445,19 +19944,17 @@ }, "dependencies": { "glob-parent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.1.tgz", - "integrity": "sha512-kEVjS71mQazDBHKcsq4E9u/vUzaLcw1A8EtUeydawvIWQCJM0qQ08G1H7/XTjFUulla6XQiDOG6MXSaG0HDKog==", + "version": "^6.0.2", "requires": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "dependencies": { "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "^2.1.1" } } } @@ -20475,16 +19972,19 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "version": "^5.0.1" }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } } } } @@ -20527,25 +20027,12 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } + "optional": true }, "glob-parent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.1.tgz", - "integrity": "sha512-kEVjS71mQazDBHKcsq4E9u/vUzaLcw1A8EtUeydawvIWQCJM0qQ08G1H7/XTjFUulla6XQiDOG6MXSaG0HDKog==", - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } + "version": "^6.0.2", + "requires": { + "is-glob": "^4.0.3" } }, "import-local": { @@ -20593,11 +20080,6 @@ } } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -20640,20 +20122,6 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -20677,11 +20145,6 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -20708,34 +20171,34 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "version": "^5.0.1" }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } } } } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } } }, "supports-color": { @@ -20766,24 +20229,25 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "version": "^5.0.1" }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "^5.0.1" + } } } } }, "ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" + "version": "^7.4.6" }, "yargs": { "version": "13.3.2", @@ -20826,6 +20290,11 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" } } }, @@ -20872,12 +20341,19 @@ "requires": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "websocket": { - "version": "1.0.33", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.33.tgz", - "integrity": "sha512-XwNqM2rN5eh3G2CUQE3OHZj+0xfdH42+OFK6LdC2yqiC0YU8e5UK0nYre220T0IyyN031V/XOvtHvXozvJYFWA==", + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", "optional": true, "requires": { "bufferutil": "^4.0.1", @@ -20896,6 +20372,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "optional": true } } }, @@ -20932,6 +20414,16 @@ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -20969,149 +20461,16 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "which-typed-array": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", - "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", + "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", "requires": { - "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.0", - "es-abstract": "^1.18.0-next.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", "foreach": "^2.0.5", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.1", - "is-typed-array": "^1.1.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - } - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - } + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.7" } }, "word-wrap": { @@ -21382,9 +20741,12 @@ } }, "ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" + "version": "^7.4.6" + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" }, "xmlchars": { "version": "2.2.0", @@ -21392,9 +20754,7 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, "xmldom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", - "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==", + "version": "^0.6.0", "dev": true }, "xtend": { @@ -21419,9 +20779,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yaml": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", - "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" }, "yargs": { "version": "15.4.1", @@ -21463,4 +20823,4 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } -} +} \ No newline at end of file diff --git a/forms-flow-web/package.json b/forms-flow-web/package.json index f2755a0165..506283b94a 100644 --- a/forms-flow-web/package.json +++ b/forms-flow-web/package.json @@ -1,14 +1,16 @@ { "name": "formsflow-ai-react", "description": "React web app for formsflow.ai project", - "version": "4.0.3", + "version": "4.0.4", "main": "index.js", "scripts": { "analyze": "source-map-explorer 'build/static/js/*.js'", "start": "react-scripts start", "build": "react-scripts --max_old_space_size=6144 build", "eject": "react-scripts eject", - "preinstall": "npx npm-force-resolutions" + "preinstall": "npx npm-force-resolutions", + "test": "react-scripts test --detectOpenHandles", + "coverage": "react-scripts test --coverage --watchAll=false" }, "author": { "name": "Abhilash" @@ -19,8 +21,12 @@ }, "license": "MIT", "devDependencies": { + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^12.1.1", "dns-packet": "^5.2.4", "jspdf": "^2.3.1", + "msw": "^0.36.0", + "redux-mock-store": "^1.5.4", "underscore": "^1.12.1", "xmldom": "^0.6.0" }, @@ -28,7 +34,7 @@ "@material-ui/core": "^4.11.4", "@wojtekmaj/react-daterange-picker": "^3.1.0", "aot-formio-export": "file:forms-flow-util", - "axios": "^0.21.1", + "axios": "^0.21.4", "bpmn-js": "^7.5.0", "browserslist": "^4.16.6", "connected-react-router": "^6.9.1", @@ -78,9 +84,13 @@ "dns-packet": "^5.2.4", "ws": "^7.4.6", "css-what": "^5.0.1", - "browserslist": "^4.16.7", - "glob-parent": "^6.0.1", - "tar": "^6.1.2" + "browserslist": "^4.17.6", + "glob-parent": "^6.0.2", + "tar": "^6.1.11", + "immer": "^9.0.6", + "set-value": "^4.1.0", + "nth-check": "^2.0.1", + "ansi-regex": "^5.0.1" }, "browserslist": [ ">0.2%", diff --git a/forms-flow-web/public/config/config.sample.js b/forms-flow-web/public/config/config.sample.js index 9385493339..2e81ba370d 100644 --- a/forms-flow-web/public/config/config.sample.js +++ b/forms-flow-web/public/config/config.sample.js @@ -34,8 +34,8 @@ window["_env_"] = { ////Environment Variables for forms-flow-bpm//// //Insight Api End point - REACT_APP_INSIGHT_API_BASE: "Insight Api base end-point", - REACT_APP_INSIGHTS_API_KEY: "", + //REACT_APP_INSIGHT_API_BASE: "Insight Api base end-point", + //REACT_APP_INSIGHTS_API_KEY: "", //web Api End point REACT_APP_WEB_BASE_URL: "Web Api base end-point", //bpm base api @@ -45,7 +45,7 @@ window["_env_"] = { REACT_APP_APPLICATION_NAME:"formsflow.ai", //custom url REACT_APP_WEB_BASE_CUSTOM_URL:"Custom URL", - + REACT_APP_FORMIO_JWT_SECRET:"Jwt secret key", REACT_APP_USER_ACCESS_PERMISSIONS:{accessAllowApplications:false, accessAllowSubmissions:false} }; diff --git a/forms-flow-web/sample.env b/forms-flow-web/sample.env index 5cfb316e27..128bab0fcb 100644 --- a/forms-flow-web/sample.env +++ b/forms-flow-web/sample.env @@ -34,9 +34,6 @@ FORMIO_DEFAULT_PROJECT_URL=http://{your-ip-address}:3001 ##Keycloak base URL KEYCLOAK_URL=http://{your-ip-address}:8080 -##Insight Api End point -INSIGHT_API_URL=http://{your-ip-address}:7000 -INSIGHT_API_KEY={API Key from Redash} #formsflow web Api End point FORMSFLOW_API_URL=http://{your-ip-address}:5000 @@ -52,3 +49,6 @@ APPLICATION_NAME=formsflow.ai #WEB_BASE_CUSTOM_URL= #Role level permission defining - (Note: Maintain Object Format) USER_ACCESS_PERMISSIONS={"accessAllowApplications":false,"accessAllowSubmissions":false} + +#JWT SECRETE KEY +#FORMIO_JWT_SECRET=--- change me now --- diff --git a/forms-flow-web/src/_tests_/test-components/baserouting.test.js b/forms-flow-web/src/_tests_/test-components/baserouting.test.js new file mode 100644 index 0000000000..b61904440f --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/baserouting.test.js @@ -0,0 +1,62 @@ +import React from 'react' +import { render as rtlRender,screen } from '@testing-library/react' +import BaseRouting from '../../../src/components/BaseRouting' +import '@testing-library/jest-dom/extend-expect'; +import { Provider } from 'react-redux' +import { Router,Route } from 'react-router'; +import { createMemoryHistory } from "history"; +import configureStore from 'redux-mock-store'; + +let store; +let mockStore = configureStore([]); + +function renderWithRouterMatch( ui,{ + path = "/", + route = "/", + history = createMemoryHistory({ initialEntries: [route] }), + } = {}) { + return{ + ...rtlRender( + + + + + ) + } + + } + +it("should render the Baserouting component without breaking",async()=>{ + store = mockStore({ + user:{ + isAuthenticated:true, + roles:[ + "formsflow-client" + ] + } + }); + store.dispatch = jest.fn(); + renderWithRouterMatch(BaseRouting,{ + path:"/", + route:"/", + } + ) + expect(screen.getByText("Forms")).toBeInTheDocument() +}) + + +it("should not render the Baserouting component without authenticating breaking",async()=>{ + store = mockStore({ + user:{ + isAuthenticated:false, + roles:[] + } + }); + store.dispatch = jest.fn(); + renderWithRouterMatch(BaseRouting,{ + path:"/", + route:"/", + } + ) + expect(screen.queryByText("Forms")).not.toBeInTheDocument() +}) diff --git a/forms-flow-web/src/_tests_/test-components/test-BPMN/constants.js b/forms-flow-web/src/_tests_/test-components/test-BPMN/constants.js new file mode 100644 index 0000000000..7fa08d7bfe --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-BPMN/constants.js @@ -0,0 +1,5 @@ +export const initialstate = { + process:{ + isProcessDiagramLoading:false + } +} diff --git a/forms-flow-web/src/_tests_/test-components/test-BPMN/processDiagramhook.test.js b/forms-flow-web/src/_tests_/test-components/test-BPMN/processDiagramhook.test.js new file mode 100644 index 0000000000..49a1b52d9d --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-BPMN/processDiagramhook.test.js @@ -0,0 +1,43 @@ +import ProcessDiagram from '../../../components/BPMN/ProcessDiagramHook' +import React from 'react' +import { render as rtlRender } from '@testing-library/react' +import '@testing-library/jest-dom/extend-expect'; +import { Provider } from 'react-redux' +import { Router,Route } from 'react-router'; +import { createMemoryHistory } from "history"; +import * as redux from 'react-redux' +import StoreService from '../../../services/StoreService' +import {initialstate} from './constants' + +let store; +beforeEach(()=>{ + store = StoreService.configureStore(); + // store.dispatch = jest.fn(); +}) + +function renderWithRouterMatch( ui,{ + path = "/", + route = "/", + history = createMemoryHistory({ initialEntries: [route] }), + } = {}) { + return{ + ...rtlRender( + + + + + ) + } + + } + +it("should render the processDiagram component without breaking",async()=>{ + const spy = jest.spyOn(redux,"useSelector"); + spy.mockImplementation((callback) => callback(initialstate)) + renderWithRouterMatch(ProcessDiagram,{ + path:"/", + route:"/", + } + ) + expect(document.getElementById("process-diagram-container")).toBeInTheDocument(); +}) diff --git a/forms-flow-web/src/_tests_/test-components/test-admin/constants.js b/forms-flow-web/src/_tests_/test-components/test-admin/constants.js new file mode 100644 index 0000000000..10f1fcf6d2 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-admin/constants.js @@ -0,0 +1,104 @@ +export const dashboard = { + id:2, + name:'sample', + approvedGroups:[ + {name:"group2",id:'group2id'} + ] +} + +export const groups = [ + { + "id": "group2id", + "name": "group2", + "path": "/formsflow/formsflow-reviewer/redash/group2", + "subGroups": [], + "dashboards": [ + {'2': 'sample'}, + {'1': 'Freedom of Information Form'} + ] + }, + { + "id": "group3id", + "name": "group3", + "path": "/formsflow/formsflow-reviewer/redash/group3", + "subGroups": [], + "dashboards": [ + {'2': 'sample'} + ] + }, +] + +export const groups1 = [ + { + "id": "group1id", + "name": "group2", + "path": "/formsflow/formsflow-reviewer/redash/group2", + "subGroups": [], + "dashboards": [ + + ] + }, + { + "id": "group3id", + "name": "group3", + "path": "/formsflow/formsflow-reviewer/redash/group3", + "subGroups": [], + "dashboards": [ + + ] + }, +] + +export const approvedGroups = [ + {name:"group2",id:'group2id'}, + {name:"group3",id:'group3id'} +] + + + +export const updatedState = { + dashboards:[ + { + id:2, + name:'sample', + approvedGroups:[ + {name: 'group2', id: 'group2id'}, + {name: 'group3', id: 'group3id'}, + {name: 'group4', id: 'group4id'}, + {name: 'group5', id: 'group5id'}, + {name: 'group6', id: 'group6id'} + ], + } , + { + id:1, + name:'Freedom of Information Form', + approvedGroups:[ + {name: 'group1', id: 'group1id'}, + {name: 'group2', id: 'group2id'}, + {name: 'group5', id: 'group5id'}, + ], + } + ], + isloading:false, + iserror:false, + groups: [ + {id: 'group1id', name: 'group1',dashboards:[{1: 'Freedom of Information Form'}]}, + {id: 'group2id', name: 'group2',dashboards:[{2: 'sample'},{1: 'Freedom of Information Form'}]}, + {id: 'group3id', name: 'group3',dashboards:[{2: 'sample'}]}, + {id: 'group4id', name: 'group4',dashboards:[{2: 'sample'}]}, + {id: 'group5id', name: 'group5',dashboards:[{2: 'sample'},{1: 'Freedom of Information Form'}]}, + {id: 'group6id', name: 'group6',dashboards:[{2: 'sample'}]}, + ], + isDashUpdated:true, + isGroupUpdated:true, + +} + +export const dashboardToclean = + [ + "[{'5': 'Hello'}, {'4': 'testathira'}, {'6': 'New Business License Application'}, {'8': 'Sentiment Analysis'}, {'7': 'Freedom Of Information Form'}, {'3': 'test'}, {'12': 'dashboard4'}]" + ] +export const cleanedDashboards = + [ + {'5': 'Hello'}, {'4': 'testathira'}, {'6': 'New Business License Application'}, {'8': 'Sentiment Analysis'}, {'7': 'Freedom Of Information Form'}, {'3': 'test'}, {'12': 'dashboard4'} + ] diff --git a/forms-flow-web/src/_tests_/test-components/test-admin/dashboardReducer.test.js b/forms-flow-web/src/_tests_/test-components/test-admin/dashboardReducer.test.js new file mode 100644 index 0000000000..e4d3717a88 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-admin/dashboardReducer.test.js @@ -0,0 +1,15 @@ +import '@testing-library/jest-dom/extend-expect'; +import { getCleanedDashboards } from '../../../apiManager/services/dashboardsService'; +import {checkDashboardIngroups} from '../../../modules/dashboardReducer' +import {dashboard, dashboardToclean, cleanedDashboards, groups, approvedGroups, groups1} from './constants' + + + +test('Should select the groups where the given dashboard is present',()=>{ + expect(checkDashboardIngroups(dashboard,groups)).toEqual(approvedGroups); + expect(checkDashboardIngroups(dashboard,groups1)).toEqual([]) +}) + +test('should clean the data structure to expected format',()=>{ + expect(getCleanedDashboards(dashboardToclean)).toEqual(cleanedDashboards); +}) diff --git a/forms-flow-web/src/_tests_/test-components/test-admin/index.test.js b/forms-flow-web/src/_tests_/test-components/test-admin/index.test.js new file mode 100644 index 0000000000..10e18031c3 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-admin/index.test.js @@ -0,0 +1,34 @@ +import React from 'react' +import { render as rtlRender } from '@testing-library/react' +import Index from '../../../components/Admin/index' +import '@testing-library/jest-dom/extend-expect'; +import { Provider } from 'react-redux' +import StoreService from '../../../services/StoreService' +import { Router,Route } from 'react-router'; +import { createMemoryHistory } from "history"; + + +const store = StoreService.configureStore(); + +function renderWithRouterMatch( ui,{ + path = "/", + route = "/", + history = createMemoryHistory({ initialEntries: [route] }) + } = {}) { + return{ + ...rtlRender( + + + + + ) + } + + } + +it("should render the admin component without breaking",()=>{ + renderWithRouterMatch(Index,{ + path:"/", + route:"/" + }) +}) diff --git a/forms-flow-web/src/_tests_/test-components/test-admin/insightdashboard.test.js b/forms-flow-web/src/_tests_/test-components/test-admin/insightdashboard.test.js new file mode 100644 index 0000000000..8a8416f790 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-admin/insightdashboard.test.js @@ -0,0 +1,55 @@ +import React from 'react' +import { render as rtlRender,fireEvent,screen,cleanup,waitFor } from '@testing-library/react' +import {InsightDashboard} from '../../../components/Admin/Insightdashboard' +import '@testing-library/jest-dom/extend-expect'; +import { Provider } from 'react-redux' +import StoreService from '../../../services/StoreService' +import { initialState } from '../../../modules/dashboardReducer'; +import { updatedState } from './constants'; +import { act } from 'react-dom/test-utils'; + +const store = StoreService.configureStore(); + + const render = Component=>rtlRender( + + {Component} + + ) + + afterEach(()=>cleanup) + + test('renders the insightdashboard component with initial state', () => { + + render() + expect(screen.getByText(/Dashboard/i)).toBeInTheDocument(); + expect(screen.getByTestId(/loading-component/i)).toBeInTheDocument(); + }); + + test('should render the table with dashboards and groups mapped', () => { + + render() + expect(screen.getByText(/sample/i)).toBeInTheDocument(); + expect(screen.getByText(/Freedom of Information Form/i)).toBeInTheDocument(); + expect(screen.queryAllByText(/Add/i)).toHaveLength(2) + }); + + test("should open up the popup once the add button is clicked",async()=>{ + render() + expect(screen.queryByTestId('popup-component')).not.toBeInTheDocument(); + const element = screen.getByTestId('1'); + act(()=>{ + fireEvent.click(element); + }) + await waitFor(()=>screen.queryAllByTestId('popup-component')) + + expect(screen.getAllByTestId('popup-component')[0]).toBeInTheDocument(); + }) + + test("should remove the group once the corresponding remove is clicked",async()=>{ + render() + expect(screen.getByTestId('samplegroup2')).toBeInTheDocument(); + const element = screen.getByTestId('samplegroup2'); + act(()=>{ + fireEvent.click(element); + }); + }); diff --git a/forms-flow-web/src/_tests_/test-components/test-application/ApplicationHistory.test.js b/forms-flow-web/src/_tests_/test-components/test-application/ApplicationHistory.test.js new file mode 100644 index 0000000000..dfda2830c4 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/ApplicationHistory.test.js @@ -0,0 +1,88 @@ +import React from "react"; +import '@testing-library/jest-dom/extend-expect'; +import { render as rtlRender,screen,waitFor } from '@testing-library/react' +import { Provider } from 'react-redux' +import StoreService from '../../../services/StoreService' +import HistoryList from "../../../components/Application/ApplicationHistory"; +import { rest } from 'msw' +import { setupServer } from 'msw/node' +import API from "../../../apiManager/endpoints"; +import { replaceUrl } from "../../../helper/helper"; + +let store ; + +var render = Component=>rtlRender( + + {Component} + +) + +beforeEach(()=>{ + store = StoreService.configureStore(); +}) + +const apiUrlAppHistory = replaceUrl( + API.GET_APPLICATION_HISTORY_API, + "", + 100 + ); +const apiUrlAppHistoryError = replaceUrl( +API.GET_APPLICATION_HISTORY_API, +"", +101 +); +const apiUrlAppHistoryEmpty = replaceUrl( + API.GET_APPLICATION_HISTORY_API, + "", + 102 + ); + +export const handlers = [ + rest.get(apiUrlAppHistory, (req, res, ctx) => { + return res(ctx.status(200),ctx.json({ + applications:[ + { + applicationStatus: "New", + created: "2021-10-11 06:59:23.433982", + formUrl: "" + } + ] + }), ctx.delay(150)) + }), + rest.get(apiUrlAppHistoryError,(req,res,ctx)=>{ + return res(ctx.status(404),ctx.json({"error":"No data found"})) + }), + rest.get(apiUrlAppHistoryEmpty,(req,res,ctx)=>{ + return res(ctx.status(200),ctx.json({applications:[]})) + }) + ] + + const server = setupServer(...handlers) + + beforeAll(() => server.listen({ onUnhandledRequest: "bypass" })) + + afterEach(() => server.resetHandlers()) + afterAll(() => server.close()) + +describe("Integration test for HistoryList component",()=>{ + test("Should render the history list table when the valid props are passed",async()=>{ + render() + await waitFor(() => expect(screen.getByText("New")).toBeInTheDocument()); + await waitFor(() => expect(screen.getByText("View Submission")).toBeInTheDocument()); + }) + test("Should not render the history list table when the invalid props are passed",async()=>{ + render() + await waitFor(() => expect(screen.queryByText("New")).not.toBeInTheDocument()); + await waitFor(() => expect(screen.queryByText("View Submission")).not.toBeInTheDocument()); + await waitFor(() => expect(screen.getByText("No Application History found")).toBeInTheDocument()); + }) + test("Should not render the history list table when no props are passed",async()=>{ + render() + await waitFor(() => expect(screen.getByText("No Application History found")).toBeInTheDocument()); + }) + test("Should display no data message when historyList is empty",async()=>{ + render() + await waitFor(() => expect(screen.getByText("No Application History found")).toBeInTheDocument()); + }) +}) + diff --git a/forms-flow-web/src/_tests_/test-components/test-application/Constants.js b/forms-flow-web/src/_tests_/test-components/test-application/Constants.js new file mode 100644 index 0000000000..7f91814489 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/Constants.js @@ -0,0 +1,152 @@ +export const ApplicationLists = [ + { + applicationName: "Sample Form", + applicationStatus: "New", + created: "2021-11-24 10:10:14.728215", + createdBy: "name", + formId: "sample form id", + formProcessMapperId: "22", + formUrl: "http://localhost/form/6180c59a9004128298bc7e50/submission/619e0f8555ab3d622cae7044", + id: 5435, + isClientEdit: false, + modified: "2021-11-24 10:10:15.283969", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: null, + revisionNo: "1", + }, + { + applicationName: "Sample Form", + applicationStatus: "New", + created: "2021-11-24 10:09:21.869878", + createdBy: "name", + formId: "sample form id", + formProcessMapperId: "22", + formUrl: "http://localhost/form/6180c59a9006028298bc7e50/submission/619e0f8555ab3d622cae7044", + id: 5434, + isClientEdit: false, + modified: "2021-11-24 10:10:15.283969", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: "982b2dae-4d0e-11ec-9925-0242ac150007", + revisionNo: "1", + }, + { + applicationName: "Sample Form", + applicationStatus: "New", + created: "2021-11-24 10:10:14.728215", + createdBy: "name", + formId: "sample form id", + formProcessMapperId: "22", + formUrl: "http://localhost/form/6180c59a9006028298bc7e50/submission/619e0f8555ab3d622cae7044", + id: 5433, + isClientEdit: false, + modified: "2021-11-24 10:10:15.283969", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: "714cec02-4d0e-11ec-9925-0242ac150007", + revisionNo: "1", + } +] + +export const applicationStatus = [ + 'Approved', + 'New', + 'Rejected', + 'Resubmit', + 'Reviewed' +] + +export const Loadingstate = { + applicationsList:[], + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:true, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'', + activePage:1, + isFilterOn:false, + countPerPage:5 + } + + export const AfterLoadingWithresult = { + applicationsList:ApplicationLists, + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:3, + applicationDetailStatusCode:'', + activePage:1, + countPerPage:5, + applicationStatus:applicationStatus + } + export const AfterLoadingWithoutresult = { + applicationsList:[], + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'', + activePage:1, + countPerPage:5, + applicationStatus:[] + } + +const applicationDetails = { + applicationName: "Sample", + applicationStatus: "New", + created: "2021-12-03 04:49:18.813383", + createdBy: "sumathi", + formId: "sample form id", + formProcessMapperId: "34", + formUrl: "http://localhost/form/61a6fc8b5e9ef2746ba7c515/submission/61a9a1cd69193afa9fd819a6", + id: 5487, + modified: "2021-12-03 04:49:19.864880", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: "5ffc2b46-53f4-11ec-81c8-0242ac170007", + revisionNo: "1", + submissionId: "61a9a1cd69193afa9fd819a6" +} + +const applicationProcess = { + id: "34", + processKey: "onestepapproval", + processName: "One Step Approval", +} +export const AfterLoadingApplicationDetailt = { + applicationsList:[], + applicationDetail: applicationDetails, + applicationProcess: applicationProcess, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'', + activePage:1, + countPerPage:5, + applicationStatus:[] +} + +export const initialState = { + applicationsList:[], + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'', + activePage:1, + countPerPage:5, + applicationStatus:[], + iserror:false, + error:'' +} diff --git a/forms-flow-web/src/_tests_/test-components/test-application/Constatnts.js b/forms-flow-web/src/_tests_/test-components/test-application/Constatnts.js new file mode 100644 index 0000000000..7a7086ea61 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/Constatnts.js @@ -0,0 +1,138 @@ +export const ApplicationLists = [ + { + applicationName: "New Business License Application", + applicationStatus: "New", + created: "2021-11-24 10:10:14.728215", + createdBy: "john.honai", + formId: "6180c59a9006028298bc7e50", + formProcessMapperId: "22", + formUrl: "https://app2.aot-technologies.com/form/6180c59a9006028298bc7e50/submission/619e0f8555ab3d622cae7044", + id: 5435, + isClientEdit: false, + modified: "2021-11-24 10:10:15.283969", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: null, + revisionNo: "1", + submissionId: "619e0f8555ab3d622cae7044" + }, + { + applicationName: "New Business License Application", + applicationStatus: "New", + created: "2021-11-24 10:09:21.869878", + createdBy: "john.honai", + formId: "6180c59a9006028298bc7e50", + formProcessMapperId: "22", + formUrl: "https://app2.aot-technologies.com/form/6180c59a9006028298bc7e50/submission/619e0f8555ab3d622cae7044", + id: 5434, + isClientEdit: false, + modified: "2021-11-24 10:10:15.283969", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: "982b2dae-4d0e-11ec-9925-0242ac150007", + revisionNo: "1", + submissionId: "619e0f5055ab3d5a35ae7041" + }, + { + applicationName: "New Business License Application", + applicationStatus: "New", + created: "2021-11-24 10:10:14.728215", + createdBy: "john.honai", + formId: "6180c598900602d814bc7e4f", + formProcessMapperId: "22", + formUrl: "https://app2.aot-technologies.com/form/6180c59a9006028298bc7e50/submission/619e0f8555ab3d622cae7044", + id: 5433, + isClientEdit: false, + modified: "2021-11-24 10:10:15.283969", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: "714cec02-4d0e-11ec-9925-0242ac150007", + revisionNo: "1", + submissionId: "619e2ef055ab3db43aae7049" + } +] + +export const applicationStatus = [ + 'Approved', + 'New', + 'Rejected', + 'Resubmit', + 'Reviewed' +] + +export const Loadingstate = { + applicationsList:[], + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:true, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'', + activePage:1, + isFilterOn:false, + countPerPage:5 + } + + export const AfterLoadingWithresult = { + applicationsList:ApplicationLists, + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:3, + applicationDetailStatusCode:'', + activePage:1, + countPerPage:5, + applicationStatus:applicationStatus + } + export const AfterLoadingWithoutresult = { + applicationsList:[], + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'', + activePage:1, + countPerPage:5, + applicationStatus:[] + } + +const applicationDetails = { + applicationName: "NCQ", + applicationStatus: "New", + created: "2021-12-03 04:49:18.813383", + createdBy: "sumathi", + formId: "61a6fc8b5e9ef2746ba7c515", + formProcessMapperId: "34", + formUrl: "https://app2.aot-technologies.com/form/61a6fc8b5e9ef2746ba7c515/submission/61a9a1cd69193afa9fd819a6", + id: 5487, + modified: "2021-12-03 04:49:19.864880", + modifiedBy: "service-account-forms-flow-bpm", + processInstanceId: "5ffc2b46-53f4-11ec-81c8-0242ac170007", + revisionNo: "1", + submissionId: "61a9a1cd69193afa9fd819a6" +} + +const applicationProcess = { + id: "34", + processKey: "onestepapproval", + processName: "One Step Approval", +} +export const AfterLoadingApplicationDetailt = { + applicationsList:[], + applicationDetail: applicationDetails, + applicationProcess: applicationProcess, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'', + activePage:1, + countPerPage:5, + applicationStatus:[] +} \ No newline at end of file diff --git a/forms-flow-web/src/_tests_/test-components/test-application/ViewApplication.test.js b/forms-flow-web/src/_tests_/test-components/test-application/ViewApplication.test.js new file mode 100644 index 0000000000..4c819e1ba3 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/ViewApplication.test.js @@ -0,0 +1,99 @@ +import React from "react"; +import '@testing-library/jest-dom/extend-expect'; +import { render as rtlRender,fireEvent,screen,waitFor } from '@testing-library/react' +import { Provider } from 'react-redux' +import StoreService from '../../../services/StoreService' +import { Router ,Route} from 'react-router-dom'; +import ViewApplication from "../../../components/Application/ViewApplication"; +import { createMemoryHistory } from "history"; +import { rest } from 'msw' +import { setupServer } from 'msw/node' +import API from "../../../apiManager/endpoints"; +import { replaceUrl } from "../../../helper/helper"; + + +const apiUrlgetApplication = replaceUrl( + API.GET_APPLICATION, + "", + 100 + ); + const apiUrlgetApplicationError = replaceUrl( + API.GET_APPLICATION, + "", + 101 + ); +export const handlers = [ + rest.get(apiUrlgetApplication, (req, res, ctx) => { + return res(ctx.status(200),ctx.json({ + applicationName: "Sample Aplication Name", + applicationStatus: "Sample Application status", + created: "2021-12-03 04:49:18.813383", + createdBy: "firstName", + formId: "0123456", + formProcessMapperId: "11", + id: 100, + modified: "2021-12-03 04:49:19.864880", + modifiedBy: "sample modified by", + processInstanceId: "123456789", + revisionNo: "1", + submissionId: "123456789" + }), ctx.delay(150)) + }), + rest.get(apiUrlgetApplicationError,(req,res,ctx)=>{ + return res(ctx.status(404),ctx.json({"error":"No data found"})) + }) + ] + + const server = setupServer(...handlers) + + beforeAll(() => server.listen({ onUnhandledRequest: "bypass" })) + + afterEach(() => server.resetHandlers()) + + afterAll(() => server.close()) + + const store = StoreService.configureStore(); + +describe("Integration test for the ViewApplication component",()=>{ + + function renderWithRouterMatch( ui,{ + path = "/", + route = "/", + history = createMemoryHistory({ initialEntries: [route] }) + } = {}) { + return{ + ...rtlRender( + + + + + ) + } + + } + + test("it should render the application details",async()=>{ + renderWithRouterMatch(ViewApplication,{ + path :"/application/:applicationId", + route :"/application/100", + }) + expect(await screen.findByText(/firstName/i)).toBeInTheDocument(); + expect(await screen.findByText(/Sample Application status/i)).toBeInTheDocument(); + expect(await screen.findByText(/100/i)).toBeInTheDocument(); + const formLink = screen.getByText("Form"); + fireEvent.click(formLink); + await waitFor(() => expect(screen.getByTestId("loading-component")).toBeInTheDocument()); + expect(await screen.findByText(/Form/i)).toBeInTheDocument(); + expect(await screen.findByText(/History/i)).toBeInTheDocument(); + expect(await screen.findByText(/Process Diagram/i)).toBeInTheDocument(); + }) + test("it should not render the application details",async()=>{ + renderWithRouterMatch(ViewApplication,{ + path :"/application/:applicationId", + route :"/application/101", + }) + expect(await screen.findByText(/Access Denied/i)).toBeInTheDocument(); + +}) +}) + diff --git a/forms-flow-web/src/_tests_/test-components/test-application/index.test.js b/forms-flow-web/src/_tests_/test-components/test-application/index.test.js new file mode 100644 index 0000000000..27cb316525 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/index.test.js @@ -0,0 +1,35 @@ +import React from "react"; +import '@testing-library/jest-dom/extend-expect'; +import { render as rtlRender } from '@testing-library/react' +import Index from "../../../components/Application/index"; +import { Router ,Route} from 'react-router-dom'; +import { createMemoryHistory } from "history"; +import { Provider } from 'react-redux' +import StoreService from '../../../services/StoreService' + +const store = StoreService.configureStore(); + +function renderWithRouterMatch( ui,{ + path = "/", + route = "/", + history = createMemoryHistory({ initialEntries: [route] }) + } = {}) { + return{ + ...rtlRender( + + + + + ) + } + + } + +describe("Should render the exact componnent based on the route given",()=>{ + test("should render the index without crashing",async()=>{ + renderWithRouterMatch(Index,{ + route:'/', + path:'/' + }) + }) +}) diff --git a/forms-flow-web/src/_tests_/test-components/test-application/list.test.js b/forms-flow-web/src/_tests_/test-components/test-application/list.test.js new file mode 100644 index 0000000000..8a353f233d --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/list.test.js @@ -0,0 +1,78 @@ +import React from "react"; +import { render as rtlRender,screen } from '@testing-library/react' +import {ApplicationList} from "../../../components/Application/List"; +import { Provider } from 'react-redux' +import StoreService from '../../../services/StoreService' +import '@testing-library/jest-dom/extend-expect'; +import { Loadingstate,AfterLoadingWithresult,AfterLoadingWithoutresult,initialState } from "./Constants"; +import { BrowserRouter as Router } from 'react-router-dom'; +import * as redux from 'react-redux' + + +const store = StoreService.configureStore(); + +const render = Component=>rtlRender( + + + {Component} + + +) + + +test("Should render No Applications Found when initial state is passed",()=>{ + const spy = jest.spyOn(redux,"useSelector"); + spy.mockImplementation((callback) => callback({ + applications:initialState, + user:{ + roles:["formsflow-designer"] + } + })) + render(); + expect(screen.getByText(/No Applications Found/i)).toBeInTheDocument(); +}) + +test("Should render Loading state when loading state variable is truthy",()=>{ + const spy = jest.spyOn(redux,"useSelector"); + spy.mockImplementation((callback) => callback({ + applications:Loadingstate, + user:{ + roles:["formsflow-designer"] + } + })) + render(); + expect(screen.getByTestId(/loading-component/i)).toBeInTheDocument(); +}) +test("Should render the table with the data after data fetch is over with results",()=>{ + const spy = jest.spyOn(redux,"useSelector"); + spy.mockImplementation((callback) => callback({ + applications:AfterLoadingWithresult, + user:{ + roles:["formsflow-designer"] + } + })) + render(); + expect(screen.getByText(/Applications/i)).toBeInTheDocument(); + expect(screen.getAllByText(/Application ID/i).length).toBe(2); + expect(screen.getAllByText(/Application Name/i).length).toBe(2); + expect(screen.getByText("5434")).toBeInTheDocument(); + expect(screen.getAllByText(/Sample Form/i).length).toBe(3); + expect(screen.getByText(/Showing 1 to 3 of 3 Results/i)).toBeInTheDocument(); + +}) + +test("Should render No results found when providing a filter value which is not in db",async()=>{ + const spy = jest.spyOn(redux,"useSelector"); + spy.mockImplementation((callback) => callback({ + applications:AfterLoadingWithoutresult, + user:{ + roles:["formsflow-designer"] + } + })) + const statespy = jest.spyOn(React,"useState"); + statespy.mockImplementationOnce(() => React.useState({filtermode:true})) + render(); + expect(screen.getAllByText(/Applications/i).length).toBe(3); + expect(screen.queryByText('Please change the selected filters to view applications')).toBeInTheDocument(); +}) + diff --git a/forms-flow-web/src/_tests_/test-components/test-application/test-details/ApplicationDetails.test.js b/forms-flow-web/src/_tests_/test-components/test-application/test-details/ApplicationDetails.test.js new file mode 100644 index 0000000000..dd139756f3 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/test-details/ApplicationDetails.test.js @@ -0,0 +1,76 @@ +import React from 'react'; +import { render, screen, configure } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import startCase from "lodash/startCase"; +import ApplicationDetails from '../../../../components/Application/Details/ApplicationDetails'; +import {getLocalDateTime} from "../../../../apiManager/services/formatterService"; +import Details from "../../../../components/Application/Details"; +import {useSelector} from "react-redux"; +import {mockApplication1, mockApplication2} from "./constant"; +import { appState } from "../../../test-redux-states/redux-state-sample"; + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useDispatch: jest.fn(), + useSelector: jest.fn() +})); + + +//
+beforeAll(() => configure({testIdAttribute: 'id'})); +afterEach(() => { + useSelector.mockClear(); +}); + +test('Render Application Detail Component with application prop passed', () => { + render(); + expect(screen.getByText('Application Id')); + expect(screen.getByText('Application Name')); + expect(screen.getByText('Created By')); + expect(screen.getByText('Application Status')); + expect(screen.getByText('Submitted On')); + expect(screen.getByText('Modified On')); +}); + +test('Render Detail Component with application prop passed', () => { + useSelector.mockImplementation((callback) => callback(appState)); + const {rerender} = render(
); + expect(screen.queryByText('Loading...')).toBeNull() + expect(screen.getByText('Application Id')); + expect(screen.getByTestId('application-id')).toHaveTextContent(mockApplication1.id); + expect(screen.getByText('Application Name')); + expect(screen.getByText('Created By')); + expect(screen.getByText('Application Status')); + expect(screen.getByText('Submitted On')); + expect(screen.getByText('Modified On')); + + /** Test isApplicationDetailLoading true condition**/ + + const changeLoadingState = {...appState.applications,...{isApplicationDetailLoading:true}} + const newState = {...appState,...{applications:changeLoadingState}} + useSelector.mockImplementation((callback) => callback(newState)); + + rerender(
) + expect(screen.getByText('Loading...')); + expect(screen.queryByText('Loading...')).not.toBeNull(); + expect(screen.getByTestId('application-id')).toHaveTextContent(mockApplication2.id); +}); + +test('calling render Application Detail with different Props', () => { + const {rerender} = render(); + expect(screen.getByTestId('application-id')).toHaveTextContent(mockApplication1.id); + expect(screen.getByTestId('application-name')).toHaveTextContent(startCase(mockApplication1.applicationName)); + expect(screen.getByTestId('application-status')).toHaveTextContent(mockApplication1.applicationStatus); + expect(screen.getByTestId('created-by')).toHaveTextContent(mockApplication1.createdBy); + expect(screen.getByTestId('application-created')).toHaveTextContent(getLocalDateTime(mockApplication1.created)); + expect(screen.getByTestId('application-modified')).toHaveTextContent(getLocalDateTime(mockApplication1.modified)); + + // re-render the same component with different props + rerender() + expect(screen.getByTestId('application-id')).toHaveTextContent(mockApplication2.id); + expect(screen.getByTestId('application-name')).toHaveTextContent(startCase(mockApplication2.applicationName)); + expect(screen.getByTestId('application-status')).toHaveTextContent(mockApplication2.applicationStatus); + expect(screen.getByTestId('created-by')).toHaveTextContent(mockApplication2.createdBy); + expect(screen.getByTestId('application-created')).toHaveTextContent(getLocalDateTime(mockApplication2.created)); + expect(screen.getByTestId('application-modified')).toHaveTextContent(getLocalDateTime(mockApplication2.modified)); +}); diff --git a/forms-flow-web/src/_tests_/test-components/test-application/test-details/constant.js b/forms-flow-web/src/_tests_/test-components/test-application/test-details/constant.js new file mode 100644 index 0000000000..88b5b6e5b6 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/test-details/constant.js @@ -0,0 +1,45 @@ +export const mockApplication1 = { + id:1, + applicationName: "Sample Form", + applicationStatus: "Approved", + created: "2021-10-07 10:00:07.980032", + createdBy: "test-user", + formId: "615d4097163a6c58ae2e667", + formProcessMapperId: "2", + formUrl: "http://localhost/form/615d4097163a6c58ae2e667/submission/615ec54b163a6cf1175f3456", + modified: "2021-10-07 10:00:44.079736", + modifiedBy: "test-user", + processInstanceId: "5a37c2ff-2755-11ec-9906-0242ac1a1117", + revisionNo: "1", + submissionId: "615ec54b163a6cf1182e3456" +}; + +export const mockApplication2 = { + id:2, + applicationName: "Test Form", + applicationStatus: "New", + created: "2021-10-05 10:00:07.980032", + createdBy: "test-user2", + formId: "615d4097163a6c58ae2e111", + formProcessMapperId: "3", + formUrl: "http://localhost/form/615d4097163a6c58ae2e111/submission/615ec54b163a6cf1182e3222", + modified: "2021-10-05 10:00:44.079736", + modifiedBy: "test-user2", + processInstanceId: "5a37c2ff-2755-11ec-9906-0242ac1a4444", + revisionNo: "1", + submissionId: "615ec54b163a6cf1182e3222" +}; + +export const applicationState = { + applications:{ + applicationsList:[], + applicationDetail: {}, + applicationProcess: {}, + formApplicationsList:[], + isApplicationListLoading:false, + isApplicationDetailLoading:false, + isApplicationUpdating:false, + applicationCount:0, + applicationDetailStatusCode:'' + } +} diff --git a/forms-flow-web/src/_tests_/test-components/test-application/test-details/nodata.test.js b/forms-flow-web/src/_tests_/test-components/test-application/test-details/nodata.test.js new file mode 100644 index 0000000000..32411c5f62 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-application/test-details/nodata.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import Nodata from '../../../../components/Application/nodata'; + +test('render Nodata', () => { + render(); + expect(screen.getByText('No applications found')); + + +}); \ No newline at end of file diff --git a/forms-flow-web/src/_tests_/test-components/test-dashboard/ApplicationCounter.test.js b/forms-flow-web/src/_tests_/test-components/test-dashboard/ApplicationCounter.test.js new file mode 100644 index 0000000000..c001da19e3 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-dashboard/ApplicationCounter.test.js @@ -0,0 +1,22 @@ +import React from "react"; +import { render , screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import ApplicationCounter from '../../../components/Dashboard/ApplicationCounter'; +import {app,getStatusDetails,selectedMetricsId,appcount} from './Constants'; + + +test('Should render error message if no applications in the selected range',()=>{ + render() + expect(screen.getByText('No submissions available for the selected date range')).toBeInTheDocument(); +}) + +test('Render ApplicationCounter with props passed', () => { + render() + expect(screen.queryAllByText("Form Name")[0]).toBeInTheDocument(); + expect(screen.queryAllByText("Total Submissions")[0]).toBeInTheDocument() + }) diff --git a/forms-flow-web/src/_tests_/test-components/test-dashboard/Constants.js b/forms-flow-web/src/_tests_/test-components/test-dashboard/Constants.js new file mode 100644 index 0000000000..ceb9d08b88 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-dashboard/Constants.js @@ -0,0 +1,30 @@ +export const app = [ + { + count: 1, + mapperId: 23, + formName: 'Form Name' + }, + { + count: 1, + mapperId: 34, + formName: 'Form Name 1' + } + +] + +export const getStatusDetails = [ + { + statusName: 'Resubmit', + count: 1, + applicationName: 'Application Name' + }, + { + statusName: 'New', + count: 1, + applicationName: 'Sample1' + } +] + +export const selectedMetricsId = 42 ; + +export const appcount = 0 ; diff --git a/forms-flow-web/src/_tests_/test-components/test-dashboard/dashboard.test.js b/forms-flow-web/src/_tests_/test-components/test-dashboard/dashboard.test.js new file mode 100644 index 0000000000..24120d359e --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-dashboard/dashboard.test.js @@ -0,0 +1,101 @@ +import Dashboard from '../../../components/Dashboard/Dashboard' +import React from 'react' +import { render as rtlRender,screen } from '@testing-library/react' +import '@testing-library/jest-dom/extend-expect'; +import { Provider } from 'react-redux' +import { Router,Route } from 'react-router'; +import { createMemoryHistory } from "history"; +import StoreService from '../../../services/StoreService'; +import * as redux from 'react-redux'; + +let store; + +beforeEach(()=>{ + store = StoreService.configureStore(); +}) + +function renderWithRouterMatch( ui,{ + path = "/", + route = "/", + history = createMemoryHistory({ initialEntries: [route] }), + } = {}) { + return{ + ...rtlRender( + + + + + ) + } + + } + +it("Should render the dashboard without breaking",()=>{ + const spy = jest.spyOn(redux,"useSelector"); + spy.mockImplementation((callback) => callback({ + metrics:{ + submissionsList:[ + { + "count": 26, + "mapperId": 22, + "formName": "New Business License Application" + }, + { + "count": 29, + "mapperId": 23, + "formName": "Freedom of Information and Protection of Privacy" + }, + ], + submissionsStatusList:[ + { + "statusName": "Approved", + "count": 1, + "applicationName": "New Business License Application" + }, + { + "statusName": "New", + "count": 21, + "applicationName": "New Business License Application" + }, + ], + isMetricsLoading:false, + isMetricsStatusLoading:false, + selectedMetricsId:22, + metricsLoadError:false, + metricsStatusLoadError:false + } + })); + renderWithRouterMatch(Dashboard,{ + path:"/", + route:"/", + }) + expect(screen.getByText("Metrics")).toBeInTheDocument(); + expect(screen.getByText("Submissions")).toBeInTheDocument(); + expect(screen.getByText("New Business License Application")).toBeInTheDocument(); + expect(screen.getByText("Freedom of Information and Protection of Privacy")).toBeInTheDocument(); +}) + + + +it("Should not render the dashboard in case of error",()=>{ + const spy = jest.spyOn(redux,"useSelector"); + spy.mockImplementation((callback) => callback({ + metrics:{ + submissionsList:[ + ], + submissionsStatusList:[ + + ], + isMetricsLoading:false, + isMetricsStatusLoading:false, + selectedMetricsId:22, + metricsLoadError:true, + metricsStatusLoadError:false + } + })); + renderWithRouterMatch(Dashboard,{ + path:"/", + route:"/", + }) + expect(screen.getByText("The operation couldn't be completed. Please try after sometime")).toBeInTheDocument(); +}) diff --git a/forms-flow-web/src/_tests_/test-components/test-dashboard/index.test.js b/forms-flow-web/src/_tests_/test-components/test-dashboard/index.test.js new file mode 100644 index 0000000000..cac1db262a --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-dashboard/index.test.js @@ -0,0 +1,38 @@ +import Index from '../../../components/Dashboard/index' +import React from 'react' +import { render as rtlRender } from '@testing-library/react' +import '@testing-library/jest-dom/extend-expect'; +import { Provider } from 'react-redux' +import { Router,Route } from 'react-router'; +import { createMemoryHistory } from "history"; +import StoreService from '../../../services/StoreService'; + + +let store; + +beforeEach(()=>{ + store = StoreService.configureStore(); +}) + +function renderWithRouterMatch( ui,{ + path = "/", + route = "/", + history = createMemoryHistory({ initialEntries: [route] }), + } = {}) { + return{ + ...rtlRender( + + + + + ) + } + + } + +it("Should render the dashboard without breaking",()=>{ + renderWithRouterMatch(Index,{ + path:"/", + route:"/", + }) +}) diff --git a/forms-flow-web/src/_tests_/test-components/test-error/LoadError.test.js b/forms-flow-web/src/_tests_/test-components/test-error/LoadError.test.js new file mode 100644 index 0000000000..afaa960f95 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-error/LoadError.test.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import LoadError from '../../../components/Error/Loaderror'; + +test('render LoadError with nostyle', () => { + render(); + expect(screen.getByText('Something went wrong.')); + + +}); + +test('render LoadError', () => { + render(); + expect(screen.getByText('Something went wrong.')); +}); diff --git a/forms-flow-web/src/_tests_/test-components/test-error/index.test.js b/forms-flow-web/src/_tests_/test-components/test-error/index.test.js new file mode 100644 index 0000000000..fb84bc7efb --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-error/index.test.js @@ -0,0 +1,7 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import LoadError from '../../../components/Error/index'; + +test('render LoadError', () => { + render(); +}); diff --git a/forms-flow-web/src/_tests_/test-components/test-footer/Footer.test.js b/forms-flow-web/src/_tests_/test-components/test-footer/Footer.test.js new file mode 100644 index 0000000000..a672a3b123 --- /dev/null +++ b/forms-flow-web/src/_tests_/test-components/test-footer/Footer.test.js @@ -0,0 +1,8 @@ +import React from 'react'; +import { render,screen } from '@testing-library/react'; +import Footer from "../../../components/Footer/Footer"; + +test('render Footer', () => { + render(