@kalisio/kdk 2.6.3 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/api/application.js +2 -4
- package/core/api/authentication.js +2 -3
- package/core/api/db.js +10 -2
- package/core/api/hooks/hooks.authorisations.js +4 -2
- package/core/api/hooks/hooks.push.js +6 -2
- package/core/api/hooks/hooks.query.js +29 -12
- package/core/api/hooks/hooks.users.js +30 -17
- package/core/api/models/configurations.model.mongodb.js +4 -0
- package/core/api/services/authorisations/authorisations.service.js +1 -1
- package/core/api/services/configurations/configurations.hooks.js +33 -0
- package/core/api/services/index.js +41 -7
- package/core/api/services/messages/messages.hooks.js +9 -3
- package/core/client/api.js +14 -1
- package/core/client/capabilities.js +1 -6
- package/core/client/components/KAvatar.vue +24 -20
- package/core/client/components/account/KProfile.vue +10 -71
- package/core/client/components/account/index.js +0 -2
- package/core/client/components/app/KSettings.vue +1 -0
- package/core/client/components/collection/KBoard.vue +4 -3
- package/core/client/components/collection/KCardSection.vue +1 -0
- package/core/client/components/collection/KGrid.vue +2 -0
- package/core/client/components/collection/KTable.vue +5 -1
- package/core/client/components/collection/KTimeLine.vue +9 -1
- package/core/client/components/collection/index.js +0 -2
- package/core/client/components/form/KChipsField.vue +2 -1
- package/core/client/components/form/KEmailField.vue +1 -0
- package/core/client/components/form/KFileField.vue +22 -1
- package/core/client/components/form/KForm.vue +2 -0
- package/core/client/components/form/KItemField.vue +1 -0
- package/core/client/components/form/KNumberField.vue +1 -0
- package/core/client/components/form/KPasswordField.vue +1 -0
- package/core/client/components/form/KPhoneField.vue +1 -0
- package/core/client/components/form/KPropertyItemField.vue +1 -0
- package/core/client/components/form/KResolutionField.vue +1 -0
- package/core/client/components/form/KSelectField.vue +31 -0
- package/core/client/components/form/KTagField.vue +1 -0
- package/core/client/components/form/KTextField.vue +1 -0
- package/core/client/components/form/KTokenField.vue +1 -0
- package/core/client/components/form/KUnitField.vue +1 -0
- package/core/client/components/form/KUrlField.vue +1 -0
- package/core/client/components/graphics/KIcon.vue +3 -4
- package/core/client/components/layout/KPage.vue +1 -0
- package/core/client/components/layout/KWindow.vue +6 -3
- package/core/client/components/messages/KMessageComposer.vue +2 -1
- package/core/client/components/messages/KMessagesTimeLine.vue +1 -1
- package/core/client/components/time/KDate.vue +1 -2
- package/core/client/components/time/KDateTime.vue +11 -11
- package/core/client/components/time/KTime.vue +1 -1
- package/core/client/composables/collection.js +33 -8
- package/core/client/composables/errors.js +1 -1
- package/core/client/composables/layout.js +9 -9
- package/core/client/configurations.js +50 -0
- package/core/client/exporter.js +1 -1
- package/core/client/i18n/core_en.json +6 -39
- package/core/client/i18n/core_fr.json +6 -39
- package/core/client/index.js +2 -0
- package/core/client/layout.js +8 -8
- package/core/client/mixins/mixin.base-activity.js +5 -2
- package/core/client/mixins/mixin.base-field.js +3 -3
- package/core/client/search.js +2 -1
- package/core/client/utils/utils.collection.js +8 -8
- package/core/client/utils/utils.items.js +4 -0
- package/core/client/utils/utils.push.js +3 -3
- package/core/client/utils/utils.session.js +7 -5
- package/core/client/utils/utils.shapes.js +38 -7
- package/core/client/utils/utils.time.js +21 -22
- package/core/common/schemas/users.update-profile.json +3 -2
- package/coverage/core/api/application.js.html +1 -1
- package/coverage/core/api/authentication.js.html +1 -1
- package/coverage/core/api/db.js.html +1 -1
- package/coverage/core/api/hooks/hooks.authentication.js.html +1 -1
- package/coverage/core/api/hooks/hooks.authorisations.js.html +1 -1
- package/coverage/core/api/hooks/hooks.logger.js.html +1 -1
- package/coverage/core/api/hooks/hooks.model.js.html +1 -1
- package/coverage/core/api/hooks/hooks.push.js.html +22 -10
- package/coverage/core/api/hooks/hooks.query.js.html +33 -6
- package/coverage/core/api/hooks/hooks.schemas.js.html +1 -1
- package/coverage/core/api/hooks/hooks.service.js.html +1 -1
- package/coverage/core/api/hooks/hooks.storage.js.html +1 -1
- package/coverage/core/api/hooks/hooks.tags.js.html +1 -1
- package/coverage/core/api/hooks/hooks.users.js.html +4 -4
- package/coverage/core/api/hooks/index.html +23 -23
- package/coverage/core/api/hooks/index.js.html +1 -1
- package/coverage/core/api/index.html +1 -1
- package/coverage/core/api/index.js.html +1 -1
- package/coverage/core/api/marshall.js.html +1 -1
- package/coverage/core/api/models/configurations.model.mongodb.js.html +1 -1
- package/coverage/core/api/models/index.html +1 -1
- package/coverage/core/api/models/messages.model.mongodb.js.html +1 -1
- package/coverage/core/api/models/tags.model.mongodb.js.html +1 -1
- package/coverage/core/api/models/users.model.mongodb.js.html +1 -1
- package/coverage/core/api/services/account/account.hooks.js.html +1 -1
- package/coverage/core/api/services/account/account.service.js.html +1 -1
- package/coverage/core/api/services/account/index.html +1 -1
- package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +1 -1
- package/coverage/core/api/services/authorisations/authorisations.service.js.html +1 -1
- package/coverage/core/api/services/authorisations/index.html +1 -1
- package/coverage/core/api/services/configurations/configurations.hooks.js.html +1 -1
- package/coverage/core/api/services/configurations/index.html +1 -1
- package/coverage/core/api/services/databases/databases.hooks.js.html +1 -1
- package/coverage/core/api/services/databases/databases.service.js.html +1 -1
- package/coverage/core/api/services/databases/index.html +1 -1
- package/coverage/core/api/services/import-export/import-export.hooks.js.html +1 -1
- package/coverage/core/api/services/import-export/import-export.service.js.html +1 -1
- package/coverage/core/api/services/import-export/index.html +1 -1
- package/coverage/core/api/services/index.html +1 -1
- package/coverage/core/api/services/index.js.html +1 -1
- package/coverage/core/api/services/mailer/index.html +1 -1
- package/coverage/core/api/services/mailer/mailer.hooks.js.html +1 -1
- package/coverage/core/api/services/mailer/mailer.service.js.html +1 -1
- package/coverage/core/api/services/messages/index.html +1 -1
- package/coverage/core/api/services/messages/messages.hooks.js.html +1 -1
- package/coverage/core/api/services/push/index.html +1 -1
- package/coverage/core/api/services/push/push.hooks.js.html +1 -1
- package/coverage/core/api/services/push/push.service.js.html +1 -1
- package/coverage/core/api/services/storage/index.html +1 -1
- package/coverage/core/api/services/storage/storage.hooks.js.html +1 -1
- package/coverage/core/api/services/storage/storage.service.js.html +1 -1
- package/coverage/core/api/services/tags/index.html +1 -1
- package/coverage/core/api/services/tags/tags.hooks.js.html +1 -1
- package/coverage/core/api/services/users/index.html +1 -1
- package/coverage/core/api/services/users/users.hooks.js.html +1 -1
- package/coverage/core/api/services/users/users.service.js.html +1 -1
- package/coverage/core/common/errors.js.html +1 -1
- package/coverage/core/common/index.html +1 -1
- package/coverage/core/common/index.js.html +1 -1
- package/coverage/core/common/permissions.js.html +1 -1
- package/coverage/core/common/schema.js.html +1 -1
- package/coverage/core/common/utils.js.html +1 -1
- package/coverage/core/common/utils.offline.js.html +1 -1
- package/coverage/index.html +17 -17
- package/coverage/lcov-report/core/api/application.js.html +1 -1
- package/coverage/lcov-report/core/api/authentication.js.html +1 -1
- package/coverage/lcov-report/core/api/db.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.push.js.html +22 -10
- package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +33 -6
- package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.tags.js.html +1 -1
- package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +4 -4
- package/coverage/lcov-report/core/api/hooks/index.html +23 -23
- package/coverage/lcov-report/core/api/hooks/index.js.html +1 -1
- package/coverage/lcov-report/core/api/index.html +1 -1
- package/coverage/lcov-report/core/api/index.js.html +1 -1
- package/coverage/lcov-report/core/api/marshall.js.html +1 -1
- package/coverage/lcov-report/core/api/models/configurations.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/core/api/models/index.html +1 -1
- package/coverage/lcov-report/core/api/models/messages.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/account/account.service.js.html +1 -1
- package/coverage/lcov-report/core/api/services/account/index.html +1 -1
- package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +1 -1
- package/coverage/lcov-report/core/api/services/authorisations/index.html +1 -1
- package/coverage/lcov-report/core/api/services/configurations/configurations.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/configurations/index.html +1 -1
- package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +1 -1
- package/coverage/lcov-report/core/api/services/databases/index.html +1 -1
- package/coverage/lcov-report/core/api/services/import-export/import-export.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/import-export/import-export.service.js.html +1 -1
- package/coverage/lcov-report/core/api/services/import-export/index.html +1 -1
- package/coverage/lcov-report/core/api/services/index.html +1 -1
- package/coverage/lcov-report/core/api/services/index.js.html +1 -1
- package/coverage/lcov-report/core/api/services/mailer/index.html +1 -1
- package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +1 -1
- package/coverage/lcov-report/core/api/services/messages/index.html +1 -1
- package/coverage/lcov-report/core/api/services/messages/messages.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/push/index.html +1 -1
- package/coverage/lcov-report/core/api/services/push/push.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/push/push.service.js.html +1 -1
- package/coverage/lcov-report/core/api/services/storage/index.html +1 -1
- package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +1 -1
- package/coverage/lcov-report/core/api/services/tags/index.html +1 -1
- package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/users/index.html +1 -1
- package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +1 -1
- package/coverage/lcov-report/core/api/services/users/users.service.js.html +1 -1
- package/coverage/lcov-report/core/common/errors.js.html +1 -1
- package/coverage/lcov-report/core/common/index.html +1 -1
- package/coverage/lcov-report/core/common/index.js.html +1 -1
- package/coverage/lcov-report/core/common/permissions.js.html +1 -1
- package/coverage/lcov-report/core/common/schema.js.html +1 -1
- package/coverage/lcov-report/core/common/utils.js.html +1 -1
- package/coverage/lcov-report/core/common/utils.offline.js.html +1 -1
- package/coverage/lcov-report/index.html +17 -17
- package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +1 -1
- package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +1 -1
- package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +184 -4
- package/coverage/lcov-report/map/api/hooks/index.html +5 -5
- package/coverage/lcov-report/map/api/hooks/index.js.html +1 -1
- package/coverage/lcov-report/map/api/index.html +1 -1
- package/coverage/lcov-report/map/api/index.js.html +1 -1
- package/coverage/lcov-report/map/api/marshall.js.html +1 -1
- package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/map/api/models/index.html +1 -1
- package/coverage/lcov-report/map/api/models/projects.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/map/api/models/styles.model.mongodb.js.html +1 -1
- package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +1 -1
- package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +1 -1
- package/coverage/lcov-report/map/api/services/alerts/index.html +1 -1
- package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +1 -1
- package/coverage/lcov-report/map/api/services/catalog/index.html +1 -1
- package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +1 -1
- package/coverage/lcov-report/map/api/services/daptiles/index.html +1 -1
- package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +1 -1
- package/coverage/lcov-report/map/api/services/features/features.service.js.html +1 -1
- package/coverage/lcov-report/map/api/services/features/index.html +1 -1
- package/coverage/lcov-report/map/api/services/index.html +1 -1
- package/coverage/lcov-report/map/api/services/index.js.html +1 -1
- package/coverage/lcov-report/map/api/services/projects/index.html +1 -1
- package/coverage/lcov-report/map/api/services/projects/projects.hooks.js.html +1 -1
- package/coverage/lcov-report/map/api/services/styles/index.html +1 -1
- package/coverage/lcov-report/map/api/services/styles/styles.hooks.js.html +1 -1
- package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +1 -1
- package/coverage/lcov-report/map/common/errors.js.html +1 -1
- package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +1 -1
- package/coverage/lcov-report/map/common/grid.js.html +1 -1
- package/coverage/lcov-report/map/common/index.html +1 -1
- package/coverage/lcov-report/map/common/index.js.html +1 -1
- package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +1 -1
- package/coverage/lcov-report/map/common/moment-utils.js.html +1 -1
- package/coverage/lcov-report/map/common/opendap-grid-source.js.html +1 -1
- package/coverage/lcov-report/map/common/opendap-utils.js.html +1 -1
- package/coverage/lcov-report/map/common/permissions.js.html +1 -1
- package/coverage/lcov-report/map/common/time-based-grid-source.js.html +1 -1
- package/coverage/lcov-report/map/common/tms-utils.js.html +1 -1
- package/coverage/lcov-report/map/common/wcs-grid-source.js.html +1 -1
- package/coverage/lcov-report/map/common/wcs-utils.js.html +1 -1
- package/coverage/lcov-report/map/common/weacast-grid-source.js.html +1 -1
- package/coverage/lcov-report/map/common/wfs-utils.js.html +1 -1
- package/coverage/lcov-report/map/common/wms-utils.js.html +1 -1
- package/coverage/lcov-report/map/common/wmts-utils.js.html +1 -1
- package/coverage/lcov.info +358 -280
- package/coverage/map/api/hooks/hooks.catalog.js.html +1 -1
- package/coverage/map/api/hooks/hooks.features.js.html +1 -1
- package/coverage/map/api/hooks/hooks.query.js.html +184 -4
- package/coverage/map/api/hooks/index.html +5 -5
- package/coverage/map/api/hooks/index.js.html +1 -1
- package/coverage/map/api/index.html +1 -1
- package/coverage/map/api/index.js.html +1 -1
- package/coverage/map/api/marshall.js.html +1 -1
- package/coverage/map/api/models/alerts.model.mongodb.js.html +1 -1
- package/coverage/map/api/models/catalog.model.mongodb.js.html +1 -1
- package/coverage/map/api/models/features.model.mongodb.js.html +1 -1
- package/coverage/map/api/models/index.html +1 -1
- package/coverage/map/api/models/projects.model.mongodb.js.html +1 -1
- package/coverage/map/api/models/styles.model.mongodb.js.html +1 -1
- package/coverage/map/api/services/alerts/alerts.hooks.js.html +1 -1
- package/coverage/map/api/services/alerts/alerts.service.js.html +1 -1
- package/coverage/map/api/services/alerts/index.html +1 -1
- package/coverage/map/api/services/catalog/catalog.hooks.js.html +1 -1
- package/coverage/map/api/services/catalog/index.html +1 -1
- package/coverage/map/api/services/daptiles/daptiles.service.js.html +1 -1
- package/coverage/map/api/services/daptiles/index.html +1 -1
- package/coverage/map/api/services/features/features.hooks.js.html +1 -1
- package/coverage/map/api/services/features/features.service.js.html +1 -1
- package/coverage/map/api/services/features/index.html +1 -1
- package/coverage/map/api/services/index.html +1 -1
- package/coverage/map/api/services/index.js.html +1 -1
- package/coverage/map/api/services/projects/index.html +1 -1
- package/coverage/map/api/services/projects/projects.hooks.js.html +1 -1
- package/coverage/map/api/services/styles/index.html +1 -1
- package/coverage/map/api/services/styles/styles.hooks.js.html +1 -1
- package/coverage/map/common/dynamic-grid-source.js.html +1 -1
- package/coverage/map/common/errors.js.html +1 -1
- package/coverage/map/common/geotiff-grid-source.js.html +1 -1
- package/coverage/map/common/grid.js.html +1 -1
- package/coverage/map/common/index.html +1 -1
- package/coverage/map/common/index.js.html +1 -1
- package/coverage/map/common/meteo-model-grid-source.js.html +1 -1
- package/coverage/map/common/moment-utils.js.html +1 -1
- package/coverage/map/common/opendap-grid-source.js.html +1 -1
- package/coverage/map/common/opendap-utils.js.html +1 -1
- package/coverage/map/common/permissions.js.html +1 -1
- package/coverage/map/common/time-based-grid-source.js.html +1 -1
- package/coverage/map/common/tms-utils.js.html +1 -1
- package/coverage/map/common/wcs-grid-source.js.html +1 -1
- package/coverage/map/common/wcs-utils.js.html +1 -1
- package/coverage/map/common/weacast-grid-source.js.html +1 -1
- package/coverage/map/common/wfs-utils.js.html +1 -1
- package/coverage/map/common/wms-utils.js.html +1 -1
- package/coverage/map/common/wmts-utils.js.html +1 -1
- package/coverage/tmp/coverage-1028514-1773134124472-0.json +1 -0
- package/coverage/tmp/coverage-1028526-1773134124448-0.json +1 -0
- package/coverage/tmp/coverage-1028537-1773134124431-0.json +1 -0
- package/coverage/tmp/coverage-1028549-1773134124401-0.json +1 -0
- package/coverage/tmp/{coverage-222566-1765963609278-0.json → coverage-1028556-1773134124353-0.json} +1 -1
- package/extras/configs/widgets.top.js +3 -3
- package/extras/tests/core/collection.mjs +2 -9
- package/map/api/hooks/hooks.catalog.js +18 -4
- package/map/api/services/catalog/catalog.hooks.js +3 -0
- package/map/api/services/features/features.hooks.js +3 -1
- package/map/api/services/index.js +2 -6
- package/map/api/services/styles/styles.hooks.js +6 -1
- package/map/client/components/KFeatureActionButton.vue +9 -3
- package/map/client/components/KFeaturesFilterManager.vue +5 -5
- package/map/client/components/KFilterCondition.vue +17 -10
- package/map/client/components/KLayerEditor.vue +49 -39
- package/map/client/components/KMeasureTool.vue +7 -1
- package/map/client/components/KTimezoneMap.vue +29 -9
- package/map/client/components/catalog/KLayersPanel.vue +26 -16
- package/map/client/components/catalog/KLayersSelector.vue +13 -2
- package/map/client/components/catalog/KViewsPanel.vue +5 -4
- package/map/client/components/form/KSelectLayersField.vue +28 -17
- package/map/client/components/form/KSelectViewsField.vue +18 -9
- package/map/client/components/form/KTimezoneField.vue +1 -2
- package/map/client/components/legend/KVariablesLegend.vue +10 -1
- package/map/client/components/location/KLocationCardSection.vue +7 -2
- package/map/client/components/location/KLocationMap.vue +31 -7
- package/map/client/components/selection/KSelectedLayerFeatures.vue +2 -2
- package/map/client/components/stickies/KZoomControl.vue +1 -1
- package/map/client/components/styles/KStyleManager.vue +4 -1
- package/map/client/components/widget/KTimeSeries.vue +174 -497
- package/map/client/components/widget/KTimeSeriesSelector.vue +72 -0
- package/map/client/components/widget/KTimeSeriesToolbar.vue +83 -0
- package/map/client/composables/catalog.js +6 -10
- package/map/client/composables/highlight.js +12 -9
- package/map/client/composables/project.js +1 -1
- package/map/client/composables/selection.js +8 -7
- package/map/client/composables/weather.js +9 -2
- package/map/client/geolocation.js +8 -5
- package/map/client/i18n/map_en.json +10 -8
- package/map/client/i18n/map_fr.json +9 -7
- package/map/client/leaflet/TiledFeatureLayer.js +85 -82
- package/map/client/leaflet/utils/utils.geojson.js +3 -3
- package/map/client/mixins/globe/mixin.base-globe.js +15 -6
- package/map/client/mixins/globe/mixin.geojson-layers.js +27 -18
- package/map/client/mixins/map/mixin.edit-layers.js +9 -1
- package/map/client/mixins/map/mixin.pmtiles-layers.js +118 -29
- package/map/client/mixins/map/mixin.tiled-mesh-layers.js +12 -5
- package/map/client/mixins/map/mixin.tiled-wind-layers.js +19 -10
- package/map/client/mixins/mixin.activity.js +23 -30
- package/map/client/mixins/mixin.feature-selection.js +41 -5
- package/map/client/planets.js +1 -1
- package/map/client/readers/reader.kml.js +2 -3
- package/map/client/utils/utils.catalog.js +36 -10
- package/map/client/utils/utils.layers.js +39 -8
- package/map/client/utils/utils.project.js +4 -0
- package/map/client/utils/utils.style.js +37 -7
- package/map/client/utils/utils.time-series.js +215 -6
- package/map/common/schemas/catalog.update.json +1 -1
- package/map/common/weacast-grid-source.js +1 -1
- package/package.json +3 -3
- package/scripts/kash/CHANGELOG.md +0 -4
- package/scripts/kash/README.md +0 -9
- package/scripts/kash/kash.sh +45 -40
- package/scripts/kash/scripts/run_tests.sh +1 -4
- package/test/api/core/authentication.test.js +9 -4
- package/test/api/core/config/default.cjs +1 -0
- package/test/api/core/hooks.test.js +6 -0
- package/test/api/core/index.test.js +43 -18
- package/test/api/core/push.test.js +8 -8
- package/test/api/core/test-log-2026-03-10.log +60 -0
- package/test/api/core/users.test.js +384 -0
- package/test/api/map/grid-sources.test.js +1 -1
- package/test/api/map/test-log-2026-03-10.log +56 -0
- package/vite/package.json +11 -2
- package/vite/test/core/composables.test.js +77 -0
- package/vite/vitest.config.js +13 -0
- package/vite/yarn.lock +1096 -18
- package/client/css/core.variables.scss +0 -72
- package/client/i18n/core_en.json +0 -744
- package/client/i18n/core_fr.json +0 -744
- package/client/i18n/map_en.json +0 -800
- package/client/i18n/map_fr.json +0 -800
- package/client/kdk.client.css +0 -47
- package/client/kdk.client.js +0 -41097
- package/client/kdk.client.map.css +0 -47
- package/client/kdk.client.map.js +0 -38182
- package/client/kdk.client.map.min.css +0 -1
- package/client/kdk.client.map.min.js +0 -27032
- package/client/kdk.client.min.css +0 -1
- package/client/kdk.client.min.js +0 -29074
- package/client/schemas/capture.create.json +0 -132
- package/client/schemas/catalog.update.json +0 -44
- package/client/schemas/messages.update.json +0 -16
- package/client/schemas/projects.create.json +0 -52
- package/client/schemas/projects.update.json +0 -52
- package/client/schemas/settings.update.json +0 -286
- package/client/schemas/tags.update.json +0 -35
- package/client/schemas/users.update-profile.json +0 -34
- package/core/client/components/account/KAccount.vue +0 -68
- package/core/client/components/account/KDeleteAccountManager.vue +0 -62
- package/core/client/components/account/KEmailManager.vue +0 -128
- package/core/client/components/account/KPasswordManager.vue +0 -90
- package/core/client/components/account/KVerifyEmailManager.vue +0 -105
- package/core/client/components/collection/KColumn.vue +0 -227
- package/core/client/components/collection/KHistory.vue +0 -113
- package/core/client/components/collection/KHistoryEntry.vue +0 -109
- package/coverage/tmp/coverage-222524-1765963609350-0.json +0 -1
- package/coverage/tmp/coverage-222536-1765963609335-0.json +0 -1
- package/coverage/tmp/coverage-222547-1765963609324-0.json +0 -1
- package/coverage/tmp/coverage-222559-1765963609309-0.json +0 -1
- package/scripts/kash/LICENSE +0 -21
- package/test/api/core/test-log-2025-07-31.log +0 -15
- package/test/api/core/test-log-2025-10-03.log +0 -18
- package/test/api/core/test-log-2025-11-10.log +0 -0
- package/test/api/core/test-log-2025-11-12.log +0 -117
- package/test/api/core/test-log-2025-11-27.log +0 -0
- package/test/api/core/test-log-2025-11-28.log +0 -17
- package/test/api/core/test-log-2025-12-09.log +0 -148
- package/test/api/core/test-log-2025-12-17.log +0 -58
- package/test/api/core/test-log-2026-01-29.log +0 -17
- package/test/api/map/test-log-2025-07-23.log +0 -1
- package/test/api/map/test-log-2025-11-28.log +0 -33
- package/test/api/map/test-log-2025-12-10.log +0 -2
- package/test/api/map/test-log-2026-01-06.log +0 -26
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import authentication from '@feathersjs/authentication'
|
|
3
|
+
import commonHooks from 'feathers-hooks-common'
|
|
4
|
+
import request from 'superagent'
|
|
5
|
+
import chai from 'chai'
|
|
6
|
+
import chailint from 'chai-lint'
|
|
7
|
+
import core, { kdk, hooks } from '../../../core/api/index.js'
|
|
8
|
+
|
|
9
|
+
const { authenticate } = authentication.hooks
|
|
10
|
+
const { util, expect } = chai
|
|
11
|
+
const { iff, disallow, isProvider, keep, discard } = commonHooks
|
|
12
|
+
const { isNotMe, onlyMe, preventChanges } = hooks
|
|
13
|
+
|
|
14
|
+
describe('core:users', () => {
|
|
15
|
+
let app, server, port, baseUrl, userIdAccessToken, emailAccessToken, phoneAccessToken, statelessAccessToken, adminAccessToken,
|
|
16
|
+
userService, userObject, anotherUserObject, authenticationService
|
|
17
|
+
|
|
18
|
+
before(async () => {
|
|
19
|
+
chailint(chai, util)
|
|
20
|
+
|
|
21
|
+
app = kdk()
|
|
22
|
+
port = app.get('port')
|
|
23
|
+
baseUrl = `http://localhost:${port}${app.get('apiPath')}`
|
|
24
|
+
await app.db.connect()
|
|
25
|
+
await app.db.instance.dropDatabase()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('registers the services', async () => {
|
|
29
|
+
await app.configure(core)
|
|
30
|
+
authenticationService = app.getService('authentication')
|
|
31
|
+
expect(authenticationService).toExist()
|
|
32
|
+
userService = app.getService('users')
|
|
33
|
+
expect(userService).toExist()
|
|
34
|
+
// Register hooks, what we'd like is a configuration so that:
|
|
35
|
+
// - information disclosure about internal user secrets like password is not permitted
|
|
36
|
+
// - information disclosure about others users is not permitted for a given user unless it has 'administrator' permissions
|
|
37
|
+
// - privilege escalation is not permitted for a given user
|
|
38
|
+
// - user with 'administrator' permissions can change others user permissions
|
|
39
|
+
// - changing others users information is not permitted for a given user unless it has 'administrator' permissions
|
|
40
|
+
// - external calls can only target myself except if I have administrator permissions
|
|
41
|
+
const isNotAdministrator = (context) => {
|
|
42
|
+
const userPermissions = _.get(context.params, 'user.permissions')
|
|
43
|
+
return userPermissions !== 'administrator'
|
|
44
|
+
}
|
|
45
|
+
userService.hooks({
|
|
46
|
+
before: {
|
|
47
|
+
all: authenticate('jwt'),
|
|
48
|
+
get: [iff(isNotMe(), disallow('external'))],
|
|
49
|
+
find: [iff(isProvider('external'), iff(isNotAdministrator, onlyMe()))],
|
|
50
|
+
create: [iff(isProvider('external'), keep('name', 'email', 'profile', 'password'))],
|
|
51
|
+
update: [disallow('external')],
|
|
52
|
+
patch: [iff(isProvider('external'), iff(isNotAdministrator, onlyMe(), preventChanges(true, ['permissions'])))],
|
|
53
|
+
remove: [iff(isProvider('external'), iff(isNotAdministrator, onlyMe()))]
|
|
54
|
+
},
|
|
55
|
+
after: {
|
|
56
|
+
all: [iff(isProvider('external'), iff(isNotMe(), iff(isNotAdministrator, discard('permissions'))))]
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
// Now app is configured launch the server
|
|
60
|
+
server = await app.listen(port)
|
|
61
|
+
await new Promise(resolve => server.once('listening', resolve))
|
|
62
|
+
})
|
|
63
|
+
// Let enough time to process
|
|
64
|
+
.timeout(10000)
|
|
65
|
+
|
|
66
|
+
it('creates users and tokens with different subject identifiers', async () => {
|
|
67
|
+
userObject = await userService.create({
|
|
68
|
+
email: 'test@test.org',
|
|
69
|
+
name: 'test user',
|
|
70
|
+
permissions: 'user',
|
|
71
|
+
profile: { phone: '0623256968' }
|
|
72
|
+
})
|
|
73
|
+
userIdAccessToken = await authenticationService.createAccessToken({
|
|
74
|
+
sub: userObject._id
|
|
75
|
+
})
|
|
76
|
+
emailAccessToken = await authenticationService.createAccessToken({
|
|
77
|
+
sub: userObject.email
|
|
78
|
+
})
|
|
79
|
+
phoneAccessToken = await authenticationService.createAccessToken({
|
|
80
|
+
sub: userObject.profile.phone
|
|
81
|
+
})
|
|
82
|
+
statelessAccessToken = await authenticationService.createAccessToken({
|
|
83
|
+
property: 'mycustomproperty'
|
|
84
|
+
}, {
|
|
85
|
+
subject: 'mycustomapp'
|
|
86
|
+
})
|
|
87
|
+
anotherUserObject = await userService.create({
|
|
88
|
+
email: 'another_test@test.org',
|
|
89
|
+
name: 'another test user',
|
|
90
|
+
permissions: 'administrator',
|
|
91
|
+
profile: { phone: '0623256969' }
|
|
92
|
+
})
|
|
93
|
+
adminAccessToken = await authenticationService.createAccessToken({
|
|
94
|
+
sub: anotherUserObject._id
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('checks all user tokens are recognized', async () => {
|
|
99
|
+
let response = await request
|
|
100
|
+
.post(`${baseUrl}/authentication`)
|
|
101
|
+
.send({ accessToken: userIdAccessToken, strategy: 'jwt' })
|
|
102
|
+
let accessToken = response.body.accessToken
|
|
103
|
+
let user = response.body.user
|
|
104
|
+
expect(accessToken).toExist()
|
|
105
|
+
expect(accessToken).not.to.equal(userIdAccessToken)
|
|
106
|
+
expect(user).toExist()
|
|
107
|
+
response = await request
|
|
108
|
+
.post(`${baseUrl}/authentication`)
|
|
109
|
+
.send({ accessToken: emailAccessToken, strategy: 'jwt' })
|
|
110
|
+
accessToken = response.body.accessToken
|
|
111
|
+
user = response.body.user
|
|
112
|
+
expect(accessToken).toExist()
|
|
113
|
+
expect(accessToken).not.to.equal(emailAccessToken)
|
|
114
|
+
expect(user).toExist()
|
|
115
|
+
response = await request
|
|
116
|
+
.post(`${baseUrl}/authentication`)
|
|
117
|
+
.send({ accessToken: phoneAccessToken, strategy: 'jwt' })
|
|
118
|
+
accessToken = response.body.accessToken
|
|
119
|
+
user = response.body.user
|
|
120
|
+
expect(accessToken).toExist()
|
|
121
|
+
expect(accessToken).not.to.equal(phoneAccessToken)
|
|
122
|
+
expect(user).toExist()
|
|
123
|
+
response = await request
|
|
124
|
+
.post(`${baseUrl}/authentication`)
|
|
125
|
+
.send({ accessToken: statelessAccessToken, strategy: 'jwt' })
|
|
126
|
+
accessToken = response.body.accessToken
|
|
127
|
+
user = response.body.user
|
|
128
|
+
expect(accessToken).toExist()
|
|
129
|
+
expect(accessToken).not.to.equal(statelessAccessToken)
|
|
130
|
+
expect(user).beUndefined()
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('checks for user information disclosure', async () => {
|
|
134
|
+
// Should not retrieve internal user secret information like password in any case
|
|
135
|
+
// Should not list others users in case of requests with identified user
|
|
136
|
+
let response = await request
|
|
137
|
+
.get(`${baseUrl}/users`)
|
|
138
|
+
.set('Authorization', 'Bearer ' + userIdAccessToken)
|
|
139
|
+
let users = response.body.data
|
|
140
|
+
expect(users.length).to.equal(1)
|
|
141
|
+
let user = users[0]
|
|
142
|
+
expect(user._id).to.equal(userObject._id.toString())
|
|
143
|
+
expect(user.password).beUndefined()
|
|
144
|
+
expect(user.previousPasswords).beUndefined()
|
|
145
|
+
expect(user.permissions).toExist()
|
|
146
|
+
response = await request
|
|
147
|
+
.get(`${baseUrl}/users`)
|
|
148
|
+
.set('Authorization', 'Bearer ' + emailAccessToken)
|
|
149
|
+
users = response.body.data
|
|
150
|
+
expect(users.length).to.equal(1)
|
|
151
|
+
user = users[0]
|
|
152
|
+
expect(user._id).to.equal(userObject._id.toString())
|
|
153
|
+
expect(user.password).beUndefined()
|
|
154
|
+
expect(user.previousPasswords).beUndefined()
|
|
155
|
+
expect(user.permissions).toExist()
|
|
156
|
+
response = await request
|
|
157
|
+
.get(`${baseUrl}/users`)
|
|
158
|
+
.set('Authorization', 'Bearer ' + phoneAccessToken)
|
|
159
|
+
users = response.body.data
|
|
160
|
+
expect(users.length).to.equal(1)
|
|
161
|
+
user = users[0]
|
|
162
|
+
expect(user._id).to.equal(userObject._id.toString())
|
|
163
|
+
expect(user.password).beUndefined()
|
|
164
|
+
expect(user.previousPasswords).beUndefined()
|
|
165
|
+
expect(user.permissions).toExist()
|
|
166
|
+
// Should not list users in case of request without identified user
|
|
167
|
+
try {
|
|
168
|
+
response = await request
|
|
169
|
+
.get(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
170
|
+
.set('Authorization', 'Bearer ' + statelessAccessToken)
|
|
171
|
+
} catch (error) {
|
|
172
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
173
|
+
expect(error.status).to.equal(500)
|
|
174
|
+
expect(error.response.text.includes('MethodNotAllowed')).beTrue()
|
|
175
|
+
}
|
|
176
|
+
/*
|
|
177
|
+
response = await request
|
|
178
|
+
.get(`${baseUrl}/users`)
|
|
179
|
+
.set('Authorization', 'Bearer ' + statelessAccessToken)
|
|
180
|
+
users = response.body.data
|
|
181
|
+
expect(users.length).to.equal(2)
|
|
182
|
+
user = users[0]
|
|
183
|
+
expect(user._id).to.equal(userObject._id.toString())
|
|
184
|
+
expect(user.password).beUndefined()
|
|
185
|
+
expect(user.previousPasswords).beUndefined()
|
|
186
|
+
expect(user.permissions).beUndefined()
|
|
187
|
+
user = users[1]
|
|
188
|
+
expect(user._id).to.equal(anotherUserObject._id.toString())
|
|
189
|
+
expect(user.password).beUndefined()
|
|
190
|
+
expect(user.previousPasswords).beUndefined()
|
|
191
|
+
expect(user.permissions).beUndefined()
|
|
192
|
+
*/
|
|
193
|
+
// Should not get others users in case of requests with identified user
|
|
194
|
+
try {
|
|
195
|
+
response = await request
|
|
196
|
+
.get(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
197
|
+
.set('Authorization', 'Bearer ' + userIdAccessToken)
|
|
198
|
+
} catch (error) {
|
|
199
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
200
|
+
expect(error.status).to.equal(500)
|
|
201
|
+
expect(error.response.text.includes('MethodNotAllowed')).beTrue()
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
response = await request
|
|
205
|
+
.get(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
206
|
+
.set('Authorization', 'Bearer ' + emailAccessToken)
|
|
207
|
+
} catch (error) {
|
|
208
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
209
|
+
expect(error.status).to.equal(500)
|
|
210
|
+
expect(error.response.text.includes('MethodNotAllowed')).beTrue()
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
response = await request
|
|
214
|
+
.get(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
215
|
+
.set('Authorization', 'Bearer ' + phoneAccessToken)
|
|
216
|
+
} catch (error) {
|
|
217
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
218
|
+
expect(error.status).to.equal(500)
|
|
219
|
+
expect(error.response.text.includes('MethodNotAllowed')).beTrue()
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
response = await request
|
|
223
|
+
.get(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
224
|
+
.set('Authorization', 'Bearer ' + statelessAccessToken)
|
|
225
|
+
} catch (error) {
|
|
226
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
227
|
+
expect(error.status).to.equal(500)
|
|
228
|
+
expect(error.response.text.includes('MethodNotAllowed')).beTrue()
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
it('checks for user information integrity', async () => {
|
|
233
|
+
// Should not be able to update information of others users if not administrator
|
|
234
|
+
try {
|
|
235
|
+
await request
|
|
236
|
+
.patch(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
237
|
+
.set('Authorization', 'Bearer ' + userIdAccessToken)
|
|
238
|
+
.send({ name: 'new name' })
|
|
239
|
+
} catch (error) {
|
|
240
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
241
|
+
expect(error.status).to.equal(500)
|
|
242
|
+
expect(error.response.text.includes('NotFound')).beTrue()
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
await request
|
|
246
|
+
.patch(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
247
|
+
.set('Authorization', 'Bearer ' + emailAccessToken)
|
|
248
|
+
.send({ name: 'new name' })
|
|
249
|
+
} catch (error) {
|
|
250
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
251
|
+
expect(error.status).to.equal(500)
|
|
252
|
+
expect(error.response.text.includes('NotFound')).beTrue()
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
await request
|
|
256
|
+
.patch(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
257
|
+
.set('Authorization', 'Bearer ' + phoneAccessToken)
|
|
258
|
+
.send({ name: 'new name' })
|
|
259
|
+
} catch (error) {
|
|
260
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
261
|
+
expect(error.status).to.equal(500)
|
|
262
|
+
expect(error.response.text.includes('NotFound')).beTrue()
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
await request
|
|
266
|
+
.patch(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
267
|
+
.set('Authorization', 'Bearer ' + statelessAccessToken)
|
|
268
|
+
.send({ name: 'new name' })
|
|
269
|
+
} catch (error) {
|
|
270
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
271
|
+
expect(error.status).to.equal(500)
|
|
272
|
+
expect(error.response.text.includes('Forbidden')).beTrue()
|
|
273
|
+
}
|
|
274
|
+
// Should be possible otherwise
|
|
275
|
+
const response = await request
|
|
276
|
+
.patch(`${baseUrl}/users/${userObject._id}`)
|
|
277
|
+
.set('Authorization', 'Bearer ' + adminAccessToken)
|
|
278
|
+
.send({ name: 'new name' })
|
|
279
|
+
const user = response.body
|
|
280
|
+
expect(user.name).to.equal('new name')
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
it('checks for user privilege escalation', async () => {
|
|
284
|
+
// Should not be able to upgrade user permissions when not administrator
|
|
285
|
+
try {
|
|
286
|
+
await request
|
|
287
|
+
.patch(`${baseUrl}/users/${userObject._id}`)
|
|
288
|
+
.set('Authorization', 'Bearer ' + userIdAccessToken)
|
|
289
|
+
.send({ permissions: 'administrator' })
|
|
290
|
+
} catch (error) {
|
|
291
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
292
|
+
expect(error.status).to.equal(500)
|
|
293
|
+
expect(error.response.text.includes('BadRequest')).beTrue()
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
await request
|
|
297
|
+
.patch(`${baseUrl}/users/${userObject._id}`)
|
|
298
|
+
.set('Authorization', 'Bearer ' + emailAccessToken)
|
|
299
|
+
.send({ permissions: 'administrator' })
|
|
300
|
+
} catch (error) {
|
|
301
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
302
|
+
expect(error.status).to.equal(500)
|
|
303
|
+
expect(error.response.text.includes('BadRequest')).beTrue()
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
await request
|
|
307
|
+
.patch(`${baseUrl}/users/${userObject._id}`)
|
|
308
|
+
.set('Authorization', 'Bearer ' + phoneAccessToken)
|
|
309
|
+
.send({ permissions: 'administrator' })
|
|
310
|
+
} catch (error) {
|
|
311
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
312
|
+
expect(error.status).to.equal(500)
|
|
313
|
+
expect(error.response.text.includes('BadRequest')).beTrue()
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
await request
|
|
317
|
+
.patch(`${baseUrl}/users/${userObject._id}`)
|
|
318
|
+
.set('Authorization', 'Bearer ' + statelessAccessToken)
|
|
319
|
+
.send({ permissions: 'administrator' })
|
|
320
|
+
} catch (error) {
|
|
321
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
322
|
+
expect(error.status).to.equal(500)
|
|
323
|
+
expect(error.response.text.includes('Forbidden')).beTrue()
|
|
324
|
+
}
|
|
325
|
+
// Should be possible otherwise
|
|
326
|
+
const response = await request
|
|
327
|
+
.patch(`${baseUrl}/users/${userObject._id}`)
|
|
328
|
+
.set('Authorization', 'Bearer ' + adminAccessToken)
|
|
329
|
+
.send({ permissions: 'manager' })
|
|
330
|
+
const user = response.body
|
|
331
|
+
expect(user.permissions).to.equal('manager')
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
it('checks users removal', async () => {
|
|
335
|
+
// Should not be able to remove others users if not administrator
|
|
336
|
+
try {
|
|
337
|
+
await request
|
|
338
|
+
.delete(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
339
|
+
.set('Authorization', 'Bearer ' + userIdAccessToken)
|
|
340
|
+
} catch (error) {
|
|
341
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
342
|
+
expect(error.status).to.equal(500)
|
|
343
|
+
expect(error.response.text.includes('NotFound')).beTrue()
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
await request
|
|
347
|
+
.delete(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
348
|
+
.set('Authorization', 'Bearer ' + emailAccessToken)
|
|
349
|
+
} catch (error) {
|
|
350
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
351
|
+
expect(error.status).to.equal(500)
|
|
352
|
+
expect(error.response.text.includes('NotFound')).beTrue()
|
|
353
|
+
}
|
|
354
|
+
try {
|
|
355
|
+
await request
|
|
356
|
+
.delete(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
357
|
+
.set('Authorization', 'Bearer ' + phoneAccessToken)
|
|
358
|
+
} catch (error) {
|
|
359
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
360
|
+
expect(error.status).to.equal(500)
|
|
361
|
+
expect(error.response.text.includes('NotFound')).beTrue()
|
|
362
|
+
}
|
|
363
|
+
try {
|
|
364
|
+
await request
|
|
365
|
+
.delete(`${baseUrl}/users/${anotherUserObject._id}`)
|
|
366
|
+
.set('Authorization', 'Bearer ' + statelessAccessToken)
|
|
367
|
+
} catch (error) {
|
|
368
|
+
// Not sure why but in this case the raised error is in text/html format
|
|
369
|
+
expect(error.status).to.equal(500)
|
|
370
|
+
expect(error.response.text.includes('Forbidden')).beTrue()
|
|
371
|
+
}
|
|
372
|
+
await userService.remove(userObject._id)
|
|
373
|
+
await userService.remove(anotherUserObject._id)
|
|
374
|
+
})
|
|
375
|
+
// Let enough time to process
|
|
376
|
+
.timeout(5000)
|
|
377
|
+
|
|
378
|
+
// Cleanup
|
|
379
|
+
after(async () => {
|
|
380
|
+
if (server) await server.close()
|
|
381
|
+
await app.db.instance.dropDatabase()
|
|
382
|
+
await app.db.disconnect()
|
|
383
|
+
})
|
|
384
|
+
})
|
|
@@ -276,7 +276,7 @@ describe('map:grid-source', () => {
|
|
|
276
276
|
|
|
277
277
|
it('is possible to create a Weacast source from makeGridSource', () => {
|
|
278
278
|
const [key, conf] = extractGridSourceConfig(weacastOptions)
|
|
279
|
-
source = makeGridSource(key, {
|
|
279
|
+
source = makeGridSource(key, { planetApi: weacastOptions.weacastApi })
|
|
280
280
|
expect(source).to.exist
|
|
281
281
|
expect(conf).to.deep.equal(weacastOptions.weacast)
|
|
282
282
|
sourceConfig = conf
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{"level":"info","message":"Logger configured"}
|
|
2
|
+
{"level":"info","message":"Initializing weacast-gfs plugin"}
|
|
3
|
+
{"level":"info","message":"Initializing gfs-world forecast"}
|
|
4
|
+
{"level":"info","message":"Checking for up-to-date forecast data on gfs-world/u-wind"}
|
|
5
|
+
{"level":"info","message":"Checking for up-to-date forecast data on gfs-world/v-wind"}
|
|
6
|
+
{"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-10T00:00:00Z"}
|
|
7
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-10_00-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
8
|
+
{"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-10T00:00:00Z"}
|
|
9
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-10_00-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
10
|
+
{"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T18:00:00Z"}
|
|
11
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_18-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
12
|
+
{"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T18:00:00Z"}
|
|
13
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_18-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
14
|
+
{"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T12:00:00Z"}
|
|
15
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_12-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
16
|
+
{"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T12:00:00Z"}
|
|
17
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_12-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
18
|
+
{"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-10T00:00:00Z"}
|
|
19
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-10_00-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
20
|
+
{"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-10T00:00:00Z"}
|
|
21
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-10_00-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
22
|
+
{"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T18:00:00Z"}
|
|
23
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_18-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
24
|
+
{"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T12:00:00Z"}
|
|
25
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_12-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
26
|
+
{"level":"info","message":"Completed forecast data update on gfs-world/v-wind"}
|
|
27
|
+
{"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T18:00:00Z"}
|
|
28
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_18-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
29
|
+
{"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T12:00:00Z"}
|
|
30
|
+
{"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_12-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
|
|
31
|
+
{"level":"info","message":"Completed forecast data update on gfs-world/u-wind"}
|
|
32
|
+
{"level":"error","message":"Cannot check alert 69afde354d314fa3bd9e24a8 as no data is available for gfs-world"}
|
|
33
|
+
{"level":"error","message":"Cannot check alert 69afde354d314fa3bd9e24a8 as no data is available for gfs-world"}
|
|
34
|
+
{"level":"error","message":"Cannot check alert 69afde354d314fa3bd9e24a8 as no data is available for gfs-world"}
|
|
35
|
+
{"level":"error","message":"Cannot check alert 69afde444d314fa3bd9e24a9 as no data is available for gfs-world"}
|
|
36
|
+
{"level":"error","message":"Cannot check alert 69afde444d314fa3bd9e24a9 as no data is available for gfs-world"}
|
|
37
|
+
{"level":"error","message":"Cannot check alert 69afde444d314fa3bd9e24a9 as no data is available for gfs-world"}
|
|
38
|
+
{"level":"error","message":"Cannot check alert 69afde534d314fa3bd9e24aa as no data is available for gfs-world"}
|
|
39
|
+
{"level":"error","message":"Cannot check alert 69afde724d314fa3bd9e29ed as no data is available for features service vigicrues-observations"}
|
|
40
|
+
{"level":"error","message":"error: api/catalog - Method: create: Object with name equals to dummy already exist for service catalog"}
|
|
41
|
+
{"level":"info","message":"Logger configured"}
|
|
42
|
+
{"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $accumulator operator"}
|
|
43
|
+
{"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $function operator"}
|
|
44
|
+
{"level":"info","message":"Logger configured"}
|
|
45
|
+
{"level":"info","message":"Initializing weacast-gfs plugin"}
|
|
46
|
+
{"level":"info","message":"Initializing gfs-world forecast"}
|
|
47
|
+
{"level":"info","message":"Checking for up-to-date forecast data on gfs-world/u-wind"}
|
|
48
|
+
{"level":"info","message":"Checking for up-to-date forecast data on gfs-world/v-wind"}
|
|
49
|
+
{"level":"info","message":"Completed forecast data update on gfs-world/v-wind"}
|
|
50
|
+
{"level":"info","message":"Completed forecast data update on gfs-world/u-wind"}
|
|
51
|
+
{"level":"error","message":"Cannot check alert 69afe195ae25fbb35c793f22 as no data is available for gfs-world"}
|
|
52
|
+
{"level":"error","message":"Cannot check alert 69afe1b3ae25fbb35c794465 as no data is available for features service vigicrues-observations"}
|
|
53
|
+
{"level":"error","message":"error: api/catalog - Method: create: Object with name equals to dummy already exist for service catalog"}
|
|
54
|
+
{"level":"info","message":"Logger configured"}
|
|
55
|
+
{"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $accumulator operator"}
|
|
56
|
+
{"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $function operator"}
|
package/vite/package.json
CHANGED
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"node": ">= 16.0.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
+
"fix-protomaps-leaflet": "fix-esm-import-path node_modules/protomaps-leaflet/dist/index.js",
|
|
40
41
|
"build:app": "cross-env BUILD_MODE=app vite build",
|
|
41
42
|
"build:app:globe": "cross-env BUILD_MODE=app GLOBE=1 vite build",
|
|
42
43
|
"extras:css": "shx mkdir -p ../client/css && shx cp -R ../extras/css/* ../client/css",
|
|
@@ -47,7 +48,9 @@
|
|
|
47
48
|
"build:lib:globe:debug": "cross-env BUILD_MODE=lib GLOBE=1 DEBUG=1 vite build",
|
|
48
49
|
"build:lib": "cross-env BUILD_MODE=lib vite build",
|
|
49
50
|
"build:lib:globe": "cross-env BUILD_MODE=lib GLOBE=1 vite build",
|
|
50
|
-
"build:libs": "npm run build:lib:extras && npm run build:lib:debug && npm run build:lib:globe:debug && npm run build:lib && npm run build:lib:globe",
|
|
51
|
+
"build:libs": "npm run build:lib:extras && npm run build:lib:debug && npm run build:lib:globe:debug && npm run fix-protomaps-leaflet && npm run build:lib && npm run build:lib:globe",
|
|
52
|
+
"test:core": "vitest --run --dir test/core",
|
|
53
|
+
"test": "npm-run-all --serial test:**",
|
|
51
54
|
"dev": "vite dev",
|
|
52
55
|
"dev:globe": "cross-env GLOBE=1 vite dev"
|
|
53
56
|
},
|
|
@@ -84,8 +87,9 @@
|
|
|
84
87
|
"@thumbmarkjs/thumbmarkjs": "^0.16.1",
|
|
85
88
|
"@tmcw/togeojson": "^4.5.0",
|
|
86
89
|
"@turf/turf": "^6.5.0",
|
|
87
|
-
"@weacast/core": "^2.2.1",
|
|
88
90
|
"@vitejs/plugin-vue": "^6.0.0",
|
|
91
|
+
"@vue/test-utils": "^2.4.6",
|
|
92
|
+
"@weacast/core": "^2.2.1",
|
|
89
93
|
"abort-controller": "^3.0.0",
|
|
90
94
|
"ajv": "^8.12.0",
|
|
91
95
|
"ajv-formats": "^2.1.1",
|
|
@@ -107,6 +111,7 @@
|
|
|
107
111
|
"debug": "^4.1.0",
|
|
108
112
|
"email-validator": "^2.0.4",
|
|
109
113
|
"feathers-reactive": "^0.11.0",
|
|
114
|
+
"fix-esm-import-path": "^1.10.0",
|
|
110
115
|
"formatcoords": "^1.1.3",
|
|
111
116
|
"fs-extra": "^8.1.0",
|
|
112
117
|
"geotiff": "^2.1.3",
|
|
@@ -115,11 +120,13 @@
|
|
|
115
120
|
"iso8601-js-period": "^0.2.1",
|
|
116
121
|
"jquery": "^3.2.1",
|
|
117
122
|
"js-yaml": "^3.13.1",
|
|
123
|
+
"jsdom": "^27.3.0",
|
|
118
124
|
"jsts": "^2.12.1",
|
|
119
125
|
"jwt-decode": "^3.1.2",
|
|
120
126
|
"leaflet": "1.6.0",
|
|
121
127
|
"leaflet-arrowheads": "^1.4.0",
|
|
122
128
|
"leaflet-fullscreen": "^1.0.2",
|
|
129
|
+
"leaflet-gesture-handling": "^1.2.2",
|
|
123
130
|
"leaflet-heatmap": "^1.0.0",
|
|
124
131
|
"leaflet-pixi-overlay": "1.9.3",
|
|
125
132
|
"leaflet-realtime": "^2.2.0",
|
|
@@ -140,6 +147,7 @@
|
|
|
140
147
|
"moment": "^2.29.3",
|
|
141
148
|
"moment-timezone": "^0.5.35",
|
|
142
149
|
"node-fetch": "^2.6.7",
|
|
150
|
+
"npm-run-all": "^4.1.1",
|
|
143
151
|
"papaparse": "^5.3.2",
|
|
144
152
|
"path-browserify": "^1.0.1",
|
|
145
153
|
"pinch-zoom-element": "^1.1.1",
|
|
@@ -162,6 +170,7 @@
|
|
|
162
170
|
"vite": "^7.0.6",
|
|
163
171
|
"vite-plugin-node-polyfills": "^0.24.0",
|
|
164
172
|
"vite-plugin-static-copy": "^3.1.1",
|
|
173
|
+
"vitest": "^4.0.15",
|
|
165
174
|
"vue": "3.2.45",
|
|
166
175
|
"vue-i18n": "^9.2.0-beta.35",
|
|
167
176
|
"vue-router": "4.1.3",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ref } from 'vue'
|
|
2
|
+
import { feathers } from '@feathersjs/feathers'
|
|
3
|
+
import { rx } from 'feathers-reactive'
|
|
4
|
+
import { memory } from '@feathersjs/memory'
|
|
5
|
+
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest'
|
|
6
|
+
import { flushPromises } from '@vue/test-utils'
|
|
7
|
+
import { kdkCore, kdkMap } from '../../../client/kdk.client.map.js'
|
|
8
|
+
|
|
9
|
+
describe('core:composables', () => {
|
|
10
|
+
let client
|
|
11
|
+
const nbItemsPerPage = ref(2)
|
|
12
|
+
const baseQuery = ref({ $sort: { _id: 1 } })
|
|
13
|
+
const filterQuery = ref({})
|
|
14
|
+
const getService = ref(() => client.service('/messages'))
|
|
15
|
+
|
|
16
|
+
beforeAll(() => {
|
|
17
|
+
client = feathers()
|
|
18
|
+
.configure(rx({ idField: '_id' }))
|
|
19
|
+
const service = memory({
|
|
20
|
+
id: '_id',
|
|
21
|
+
store: {
|
|
22
|
+
0: { _id: 1, name: 'xxx' },
|
|
23
|
+
1: { _id: 2, name: 'yyy' },
|
|
24
|
+
2: { _id: 3, name: 'zzz' }
|
|
25
|
+
},
|
|
26
|
+
paginate: { default: 5, max: 5 }
|
|
27
|
+
})
|
|
28
|
+
client.use('/messages', service).hooks({
|
|
29
|
+
before: {
|
|
30
|
+
// Required as some options like $locale are only supported by server-side services
|
|
31
|
+
all: [kdkCore.hooks.removeServerSideParameters]
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('refresh collection in paginated mode', async () => {
|
|
37
|
+
const { items, currentPage, refreshCollection } = kdkCore.composables.useCollection({
|
|
38
|
+
nbItemsPerPage, baseQuery, filterQuery, getService
|
|
39
|
+
})
|
|
40
|
+
refreshCollection()
|
|
41
|
+
await vi.waitFor(() => {
|
|
42
|
+
expect(items.value).to.deep.equal([{ _id: 1, name: 'xxx' }, { _id: 2, name: 'yyy' }])
|
|
43
|
+
})
|
|
44
|
+
currentPage.value++
|
|
45
|
+
refreshCollection()
|
|
46
|
+
await vi.waitFor(() => {
|
|
47
|
+
expect(items.value).to.deep.equal([{ _id: 3, name: 'zzz' }])
|
|
48
|
+
})
|
|
49
|
+
filterQuery.value = { name: 'yyy' }
|
|
50
|
+
await vi.waitFor(() => {
|
|
51
|
+
expect(items.value).to.deep.equal([{ _id: 2, name: 'yyy' }])
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('refresh collection in append mode', async () => {
|
|
56
|
+
// Reset any filter
|
|
57
|
+
filterQuery.value = {}
|
|
58
|
+
const { items, currentPage, refreshCollection } = kdkCore.composables.useCollection({
|
|
59
|
+
nbItemsPerPage, baseQuery, filterQuery, getService, appendItems: ref(true)
|
|
60
|
+
})
|
|
61
|
+
refreshCollection()
|
|
62
|
+
await vi.waitFor(() => {
|
|
63
|
+
expect(items.value).to.deep.equal([{ _id: 1, name: 'xxx' }, { _id: 2, name: 'yyy' }])
|
|
64
|
+
})
|
|
65
|
+
currentPage.value++
|
|
66
|
+
refreshCollection()
|
|
67
|
+
await vi.waitFor(() => {
|
|
68
|
+
expect(items.value).to.deep.equal([{ _id: 1, name: 'xxx' }, { _id: 2, name: 'yyy' }, { _id: 3, name: 'zzz' }])
|
|
69
|
+
})
|
|
70
|
+
filterQuery.value = { name: 'yyy' }
|
|
71
|
+
await vi.waitFor(() => {
|
|
72
|
+
expect(items.value).to.deep.equal([{ _id: 2, name: 'yyy' }])
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
afterAll(() => {})
|
|
77
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig, mergeConfig } from 'vite'
|
|
2
|
+
import viteConfig from './vite.config'
|
|
3
|
+
import 'vitest/config'
|
|
4
|
+
|
|
5
|
+
export default mergeConfig(
|
|
6
|
+
viteConfig,
|
|
7
|
+
defineConfig({
|
|
8
|
+
test: {
|
|
9
|
+
environment: 'jsdom',
|
|
10
|
+
disableConsoleIntercept: true
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
)
|