@kalisio/kdk 2.1.7 → 2.1.9

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.
Files changed (796) hide show
  1. package/.codeclimate.yml +34 -34
  2. package/.nycrc +5 -5
  3. package/.travis.doc.sh +8 -8
  4. package/.travis.test.sh +40 -40
  5. package/CHANGELOG.md +727 -727
  6. package/LICENSE +21 -21
  7. package/README.md +32 -32
  8. package/core/api/application.js +591 -591
  9. package/core/api/authentication.js +203 -203
  10. package/core/api/db.js +226 -226
  11. package/core/api/hooks/hooks.authentication.js +73 -73
  12. package/core/api/hooks/hooks.authorisations.js +376 -376
  13. package/core/api/hooks/hooks.groups.js +48 -48
  14. package/core/api/hooks/hooks.logger.js +26 -26
  15. package/core/api/hooks/hooks.model.js +290 -290
  16. package/core/api/hooks/hooks.organisations.js +156 -156
  17. package/core/api/hooks/hooks.push.js +56 -56
  18. package/core/api/hooks/hooks.query.js +246 -246
  19. package/core/api/hooks/hooks.schemas.js +73 -73
  20. package/core/api/hooks/hooks.service.js +78 -78
  21. package/core/api/hooks/hooks.storage.js +36 -36
  22. package/core/api/hooks/hooks.users.js +261 -261
  23. package/core/api/hooks/index.js +12 -12
  24. package/core/api/index.js +21 -21
  25. package/core/api/marshall.js +90 -90
  26. package/core/api/models/groups.model.mongodb.js +8 -8
  27. package/core/api/models/organisations.model.mongodb.js +3 -3
  28. package/core/api/models/tags.model.mongodb.js +10 -10
  29. package/core/api/models/users.model.mongodb.js +10 -10
  30. package/core/api/services/account/account.hooks.js +37 -37
  31. package/core/api/services/account/account.service.js +117 -117
  32. package/core/api/services/authorisations/authorisations.hooks.js +33 -33
  33. package/core/api/services/authorisations/authorisations.service.js +139 -139
  34. package/core/api/services/databases/databases.hooks.js +36 -36
  35. package/core/api/services/databases/databases.service.js +5 -5
  36. package/core/api/services/groups/groups.hooks.js +31 -31
  37. package/core/api/services/index.js +126 -126
  38. package/core/api/services/mailer/mailer.hooks.js +35 -35
  39. package/core/api/services/mailer/mailer.service.js +11 -11
  40. package/core/api/services/organisations/organisations.hooks.js +31 -31
  41. package/core/api/services/organisations/organisations.service.js +86 -86
  42. package/core/api/services/push/push.hooks.js +35 -35
  43. package/core/api/services/push/push.service.js +12 -12
  44. package/core/api/services/storage/storage.hooks.js +35 -35
  45. package/core/api/services/storage/storage.service.js +29 -29
  46. package/core/api/services/tags/tags.hooks.js +31 -31
  47. package/core/api/services/users/users.hooks.js +75 -75
  48. package/core/api/utils.js +11 -11
  49. package/core/client/api.js +293 -293
  50. package/core/client/capabilities.js +22 -22
  51. package/core/client/components/KAction.vue +393 -393
  52. package/core/client/components/KAvatar.vue +129 -129
  53. package/core/client/components/KBlock.vue +67 -67
  54. package/core/client/components/KChip.vue +68 -68
  55. package/core/client/components/KChipsPane.vue +103 -103
  56. package/core/client/components/KContent.vue +105 -105
  57. package/core/client/components/KDialog.vue +160 -160
  58. package/core/client/components/KExpandable.vue +49 -49
  59. package/core/client/components/KLogo.vue +32 -32
  60. package/core/client/components/KModal.vue +173 -173
  61. package/core/client/components/KPanel.vue +64 -64
  62. package/core/client/components/KScrollArea.vue +88 -88
  63. package/core/client/components/KSponsor.vue +40 -40
  64. package/core/client/components/KStamp.vue +65 -65
  65. package/core/client/components/KStore.vue +102 -102
  66. package/core/client/components/KTextArea.vue +143 -143
  67. package/core/client/components/KTree.vue +31 -31
  68. package/core/client/components/KVersion.vue +19 -19
  69. package/core/client/components/account/KAccount.vue +68 -68
  70. package/core/client/components/account/KDeleteAccountManager.vue +62 -62
  71. package/core/client/components/account/KEmailManager.vue +128 -128
  72. package/core/client/components/account/KPasswordManager.vue +90 -90
  73. package/core/client/components/account/KProfile.vue +109 -109
  74. package/core/client/components/account/KResetPassword.vue +126 -120
  75. package/core/client/components/account/KSendResetPassword.vue +97 -97
  76. package/core/client/components/account/KSubscription.vue +71 -71
  77. package/core/client/components/account/KSubscriptionsManager.vue +46 -46
  78. package/core/client/components/account/KVerifyEmailManager.vue +105 -105
  79. package/core/client/components/account/index.js +7 -7
  80. package/core/client/components/app/KAbout.vue +98 -98
  81. package/core/client/components/app/KHome.vue +12 -12
  82. package/core/client/components/app/KPlatform.vue +55 -55
  83. package/core/client/components/app/KSettings.vue +42 -42
  84. package/core/client/components/app/KTerms.vue +41 -41
  85. package/core/client/components/app/KTour.vue +448 -448
  86. package/core/client/components/app/KWelcome.vue +133 -133
  87. package/core/client/components/app/index.js +11 -11
  88. package/core/client/components/chart/KChart.vue +197 -197
  89. package/core/client/components/chart/KDataTable.vue +183 -183
  90. package/core/client/components/chart/KStatisticsChart.vue +94 -94
  91. package/core/client/components/chart/KTimeSeriesChart.vue +431 -431
  92. package/core/client/components/chart/index.js +9 -9
  93. package/core/client/components/collection/KBoard.vue +65 -65
  94. package/core/client/components/collection/KCard.vue +196 -196
  95. package/core/client/components/collection/KCardSection.vue +52 -52
  96. package/core/client/components/collection/KColumn.vue +229 -229
  97. package/core/client/components/collection/KFilter.vue +158 -158
  98. package/core/client/components/collection/KGrid.vue +121 -121
  99. package/core/client/components/collection/KHistory.vue +118 -118
  100. package/core/client/components/collection/KHistoryEntry.vue +111 -111
  101. package/core/client/components/collection/KItem.vue +128 -128
  102. package/core/client/components/collection/KList.vue +135 -135
  103. package/core/client/components/collection/KSorter.vue +46 -46
  104. package/core/client/components/collection/KTable.vue +238 -238
  105. package/core/client/components/collection/index.js +19 -19
  106. package/core/client/components/editor/KEditor.vue +52 -52
  107. package/core/client/components/editor/KModalEditor.vue +96 -96
  108. package/core/client/components/editor/index.js +7 -7
  109. package/core/client/components/form/KChipsField.vue +162 -162
  110. package/core/client/components/form/KColorField.vue +69 -69
  111. package/core/client/components/form/KColorScaleField.vue +86 -86
  112. package/core/client/components/form/KDateTimeRangeField.vue +65 -65
  113. package/core/client/components/form/KDatetimeField.vue +70 -70
  114. package/core/client/components/form/KEmailField.vue +33 -33
  115. package/core/client/components/form/KFileField.vue +161 -161
  116. package/core/client/components/form/KForm.vue +247 -247
  117. package/core/client/components/form/KIconField.vue +101 -101
  118. package/core/client/components/form/KItemField.vue +123 -123
  119. package/core/client/components/form/KNumberField.vue +33 -33
  120. package/core/client/components/form/KOptionsField.vue +63 -63
  121. package/core/client/components/form/KPasswordField.vue +57 -57
  122. package/core/client/components/form/KPhoneField.vue +32 -32
  123. package/core/client/components/form/KPropertyItemField.vue +119 -119
  124. package/core/client/components/form/KRoleField.vue +60 -60
  125. package/core/client/components/form/KSelectField.vue +143 -143
  126. package/core/client/components/form/KTextField.vue +48 -48
  127. package/core/client/components/form/KTextareaField.vue +88 -88
  128. package/core/client/components/form/KToggleField.vue +46 -46
  129. package/core/client/components/form/KTokenField.vue +80 -80
  130. package/core/client/components/form/KUnitField.vue +57 -57
  131. package/core/client/components/form/KUrlField.vue +32 -32
  132. package/core/client/components/form/KView.vue +118 -118
  133. package/core/client/components/form/index.js +7 -7
  134. package/core/client/components/index.js +48 -48
  135. package/core/client/components/input/KColorChooser.vue +63 -63
  136. package/core/client/components/input/KIconChooser.vue +308 -308
  137. package/core/client/components/input/KOptionsChooser.vue +122 -122
  138. package/core/client/components/input/KPalette.vue +40 -40
  139. package/core/client/components/input/index.js +11 -11
  140. package/core/client/components/layout/KFab.vue +113 -113
  141. package/core/client/components/layout/KLayout.vue +64 -64
  142. package/core/client/components/layout/KOpener.vue +140 -140
  143. package/core/client/components/layout/KPage.vue +320 -320
  144. package/core/client/components/layout/KPageSticky.vue +53 -53
  145. package/core/client/components/layout/KWindow.vue +443 -443
  146. package/core/client/components/layout/index.js +13 -13
  147. package/core/client/components/media/KColorScale.vue +254 -254
  148. package/core/client/components/media/KImageViewer.vue +44 -44
  149. package/core/client/components/media/KMarkdownViewer.vue +55 -55
  150. package/core/client/components/media/KMediaBrowser.vue +301 -340
  151. package/core/client/components/media/KShape.vue +120 -120
  152. package/core/client/components/media/index.js +13 -13
  153. package/core/client/components/menu/KMenu.vue +147 -147
  154. package/core/client/components/menu/KRadialFab.vue +122 -122
  155. package/core/client/components/menu/KRadialFabItem.vue +73 -73
  156. package/core/client/components/menu/index.js +9 -9
  157. package/core/client/components/screen/KEndpointScreen.vue +80 -80
  158. package/core/client/components/screen/KErrorScreen.vue +24 -24
  159. package/core/client/components/screen/KLoginScreen.vue +84 -84
  160. package/core/client/components/screen/KLogoutScreen.vue +20 -20
  161. package/core/client/components/screen/KRegisterScreen.vue +114 -114
  162. package/core/client/components/screen/KScreen.vue +106 -106
  163. package/core/client/components/screen/KScreenFooter.vue +32 -32
  164. package/core/client/components/screen/KScreenHeader.vue +17 -17
  165. package/core/client/components/screen/index.js +5 -5
  166. package/core/client/components/team/KAddMember.vue +384 -375
  167. package/core/client/components/team/KAddTag.vue +121 -121
  168. package/core/client/components/team/KChangeRole.vue +118 -118
  169. package/core/client/components/team/KGroupCard.vue +110 -110
  170. package/core/client/components/team/KGroupsActivity.vue +66 -66
  171. package/core/client/components/team/KJoinGroup.vue +132 -132
  172. package/core/client/components/team/KMemberCard.vue +328 -328
  173. package/core/client/components/team/KMemberFilter.vue +49 -49
  174. package/core/client/components/team/KMembersActivity.vue +126 -126
  175. package/core/client/components/team/KOrganisationsActivity.vue +53 -53
  176. package/core/client/components/team/KTagCard.vue +72 -72
  177. package/core/client/components/team/KTagsActivity.vue +61 -61
  178. package/core/client/components/team/index.js +9 -9
  179. package/core/client/components/time/KAbsoluteTimeRange.vue +183 -183
  180. package/core/client/components/time/KDate.vue +75 -75
  181. package/core/client/components/time/KDateTime.vue +172 -172
  182. package/core/client/components/time/KDateTimeRange.vue +118 -118
  183. package/core/client/components/time/KRelativeTimeRanges.vue +193 -193
  184. package/core/client/components/time/KTime.vue +74 -74
  185. package/core/client/components/time/index.js +7 -7
  186. package/core/client/components/viewer/KModalViewer.vue +47 -47
  187. package/core/client/components/viewer/KViewer.vue +30 -30
  188. package/core/client/composables/activity.js +67 -67
  189. package/core/client/composables/collection.js +181 -181
  190. package/core/client/composables/index.js +8 -8
  191. package/core/client/composables/pwa.js +71 -71
  192. package/core/client/composables/schema.js +64 -64
  193. package/core/client/composables/selection.js +88 -88
  194. package/core/client/composables/session.js +172 -172
  195. package/core/client/composables/store.js +49 -49
  196. package/core/client/composables/version.js +47 -47
  197. package/core/client/events.js +3 -3
  198. package/core/client/filter.js +60 -60
  199. package/core/client/guards.js +101 -101
  200. package/core/client/hooks/hooks.events.js +7 -7
  201. package/core/client/hooks/hooks.logger.js +24 -24
  202. package/core/client/hooks/hooks.users.js +22 -22
  203. package/core/client/hooks/index.js +3 -3
  204. package/core/client/i18n/core_en.json +846 -845
  205. package/core/client/i18n/core_fr.json +844 -843
  206. package/core/client/i18n.js +88 -88
  207. package/core/client/index.js +84 -84
  208. package/core/client/layout.js +323 -323
  209. package/core/client/local-storage.js +28 -28
  210. package/core/client/mixins/index.js +12 -12
  211. package/core/client/mixins/mixin.account.js +61 -61
  212. package/core/client/mixins/mixin.base-activity.js +232 -232
  213. package/core/client/mixins/mixin.base-collection.js +162 -162
  214. package/core/client/mixins/mixin.base-context.js +54 -54
  215. package/core/client/mixins/mixin.base-editor.js +194 -194
  216. package/core/client/mixins/mixin.base-field.js +105 -105
  217. package/core/client/mixins/mixin.base-item.js +166 -166
  218. package/core/client/mixins/mixin.base-modal.js +36 -36
  219. package/core/client/mixins/mixin.base-viewer.js +43 -43
  220. package/core/client/mixins/mixin.object-proxy.js +46 -46
  221. package/core/client/mixins/mixin.schema-proxy.js +97 -97
  222. package/core/client/mixins/mixin.service.js +22 -22
  223. package/core/client/reader.js +65 -65
  224. package/core/client/readers/index.js +3 -3
  225. package/core/client/readers/reader.blob.js +39 -39
  226. package/core/client/readers/reader.csv.js +36 -36
  227. package/core/client/readers/reader.json.js +34 -34
  228. package/core/client/search.js +47 -47
  229. package/core/client/services/index.js +49 -49
  230. package/core/client/services/local-settings.service.js +67 -67
  231. package/core/client/sorter.js +31 -31
  232. package/core/client/storage.js +110 -102
  233. package/core/client/store.js +39 -39
  234. package/core/client/theme.js +40 -40
  235. package/core/client/time.js +167 -167
  236. package/core/client/units.js +218 -218
  237. package/core/client/utils/index.js +203 -203
  238. package/core/client/utils/utils.account.js +52 -52
  239. package/core/client/utils/utils.colors.js +36 -36
  240. package/core/client/utils/utils.content.js +185 -185
  241. package/core/client/utils/utils.locale.js +28 -28
  242. package/core/client/utils/utils.platform.js +11 -11
  243. package/core/client/utils/utils.push.js +53 -53
  244. package/core/client/utils/utils.pwa.js +62 -62
  245. package/core/client/utils/utils.session.js +89 -89
  246. package/core/common/errors.js +1 -1
  247. package/core/common/index.js +10 -10
  248. package/core/common/permissions.js +318 -318
  249. package/core/common/schema.js +35 -35
  250. package/core/common/schemas/groups.create.json +28 -28
  251. package/core/common/schemas/groups.update.json +28 -28
  252. package/core/common/schemas/organisations.create.json +28 -28
  253. package/core/common/schemas/organisations.update.json +49 -49
  254. package/core/common/schemas/settings.update.json +234 -234
  255. package/core/common/schemas/tags.create.json +35 -35
  256. package/core/common/schemas/tags.update.json +35 -35
  257. package/core/common/schemas/users.update-profile.json +33 -33
  258. package/core/common/utils.js +45 -45
  259. package/core.api.js +5 -5
  260. package/core.client.js +5 -5
  261. package/core.common.js +1 -1
  262. package/extras/css/core.variables.scss +38 -38
  263. package/extras/icons/center-on-feature.svg +315 -315
  264. package/extras/icons/json.svg +83 -83
  265. package/extras/icons/map-legend.svg +251 -251
  266. package/extras/icons/target.svg +37 -37
  267. package/extras/tours/core/account-profile.js +32 -32
  268. package/extras/tours/core/account.js +143 -143
  269. package/extras/tours/core/add-member.js +74 -74
  270. package/extras/tours/core/add-tag.js +12 -12
  271. package/extras/tours/core/create-group.js +19 -19
  272. package/extras/tours/core/create-organisation.js +19 -19
  273. package/extras/tours/core/create-tag.js +26 -26
  274. package/extras/tours/core/edit-member-role.js +13 -13
  275. package/extras/tours/core/groups.js +65 -65
  276. package/extras/tours/core/join-group.js +13 -13
  277. package/extras/tours/core/login.js +41 -41
  278. package/extras/tours/core/members.js +108 -108
  279. package/extras/tours/core/register.js +61 -61
  280. package/extras/tours/core/send-reset-password.js +14 -14
  281. package/extras/tours/core/tags.js +65 -65
  282. package/extras/tours/map/add-layer.js +28 -28
  283. package/extras/tours/map/catalog-categories.js +59 -59
  284. package/extras/tours/map/catalog-panel.js +112 -112
  285. package/extras/tours/map/connect-layer.js +39 -39
  286. package/extras/tours/map/create-layer.js +33 -33
  287. package/extras/tours/map/create-view.js +25 -25
  288. package/extras/tours/map/fab.js +26 -26
  289. package/extras/tours/map/import-layer.js +33 -33
  290. package/extras/tours/map/navigation-bar.js +185 -185
  291. package/extras/tours/map/side-nav.js +35 -35
  292. package/extras/tours/map/timeline.js +77 -77
  293. package/map/api/config/categories.cjs +42 -42
  294. package/map/api/config/layers.cjs +43 -43
  295. package/map/api/config/sublegends.cjs +42 -42
  296. package/map/api/hooks/hooks.catalog.js +85 -85
  297. package/map/api/hooks/hooks.features.js +84 -84
  298. package/map/api/hooks/hooks.query.js +361 -361
  299. package/map/api/hooks/index.js +3 -3
  300. package/map/api/index.js +18 -18
  301. package/map/api/marshall.js +31 -31
  302. package/map/api/models/alerts.model.mongodb.js +7 -7
  303. package/map/api/models/catalog.model.mongodb.js +14 -14
  304. package/map/api/models/features.model.mongodb.js +37 -37
  305. package/map/api/services/alerts/alerts.hooks.js +63 -63
  306. package/map/api/services/alerts/alerts.service.js +175 -175
  307. package/map/api/services/catalog/catalog.hooks.js +76 -76
  308. package/map/api/services/daptiles/daptiles.service.js +475 -475
  309. package/map/api/services/features/features.hooks.js +40 -40
  310. package/map/api/services/features/features.service.js +52 -52
  311. package/map/api/services/geocoder/geocoder.hooks.js +31 -31
  312. package/map/api/services/geocoder/geocoder.service.js +79 -79
  313. package/map/api/services/index.js +228 -228
  314. package/map/client/canvas-draw-context.js +16 -16
  315. package/map/client/cesium/utils.js +133 -133
  316. package/map/client/components/KCaptureToolbar.vue +155 -155
  317. package/map/client/components/KColorLegend.vue +349 -349
  318. package/map/client/components/KCompass.vue +143 -143
  319. package/map/client/components/KEditLayerData.vue +85 -85
  320. package/map/client/components/KFeatureActionButton.vue +119 -119
  321. package/map/client/components/KFeatureEditor.vue +92 -92
  322. package/map/client/components/KFeaturesChart.vue +285 -285
  323. package/map/client/components/KFeaturesFilter.vue +259 -259
  324. package/map/client/components/KFeaturesTable.vue +99 -99
  325. package/map/client/components/KLayerEditionToolbar.vue +54 -54
  326. package/map/client/components/KLayerEditor.vue +48 -48
  327. package/map/client/components/KLayerStyleEditor.vue +118 -118
  328. package/map/client/components/KLayerStyleForm.vue +906 -906
  329. package/map/client/components/KLevelSlider.vue +100 -100
  330. package/map/client/components/KMeasureTool.vue +568 -568
  331. package/map/client/components/KPositionIndicator.vue +90 -90
  332. package/map/client/components/KTimeline.vue +293 -293
  333. package/map/client/components/KTimezoneMap.vue +158 -158
  334. package/map/client/components/KUrlLegend.vue +122 -122
  335. package/map/client/components/catalog/KAddLayer.vue +66 -66
  336. package/map/client/components/catalog/KBaseLayersSelector.vue +114 -114
  337. package/map/client/components/catalog/KConnectLayer.vue +323 -323
  338. package/map/client/components/catalog/KCreateLayer.vue +184 -184
  339. package/map/client/components/catalog/KCreateView.vue +108 -108
  340. package/map/client/components/catalog/KFilteredLayerItem.vue +53 -53
  341. package/map/client/components/catalog/KImportLayer.vue +168 -168
  342. package/map/client/components/catalog/KLayerCategories.vue +274 -274
  343. package/map/client/components/catalog/KLayerItem.vue +70 -70
  344. package/map/client/components/catalog/KLayersPanel.vue +137 -137
  345. package/map/client/components/catalog/KLayersSelector.vue +78 -78
  346. package/map/client/components/catalog/KViewSelector.vue +46 -46
  347. package/map/client/components/catalog/KViewsPanel.vue +123 -123
  348. package/map/client/components/catalog/KWeatherLayersSelector.vue +129 -129
  349. package/map/client/components/form/KDirectionField.vue +113 -113
  350. package/map/client/components/form/KLayerCategoryField.vue +46 -46
  351. package/map/client/components/form/KLocationField.vue +189 -189
  352. package/map/client/components/form/KOwsLayerField.vue +130 -130
  353. package/map/client/components/form/KOwsServiceField.vue +238 -238
  354. package/map/client/components/form/KTimezoneField.vue +142 -142
  355. package/map/client/components/index.js +1 -1
  356. package/map/client/components/legend/KColorScaleLegend.vue +31 -31
  357. package/map/client/components/legend/KImageLegend.vue +52 -52
  358. package/map/client/components/legend/KLegend.vue +191 -191
  359. package/map/client/components/legend/KLegendRenderer.vue +20 -20
  360. package/map/client/components/legend/KSymbolsLegend.vue +101 -101
  361. package/map/client/components/location/KGeocodersFilter.vue +44 -44
  362. package/map/client/components/location/KLocationCardSection.vue +61 -61
  363. package/map/client/components/location/KLocationMap.vue +280 -280
  364. package/map/client/components/location/KLocationSearch.vue +144 -144
  365. package/map/client/components/location/KLocationTip.vue +29 -29
  366. package/map/client/components/tools/KGeolocateTool.vue +46 -46
  367. package/map/client/components/tools/KSearchTool.vue +93 -93
  368. package/map/client/components/widget/KElevationProfile.vue +454 -454
  369. package/map/client/components/widget/KInformationBox.vue +145 -145
  370. package/map/client/components/widget/KMapillaryViewer.vue +178 -178
  371. package/map/client/components/widget/KStackableTimeSeries.vue +214 -214
  372. package/map/client/components/widget/KTimeSeries.vue +500 -500
  373. package/map/client/composables/activity.js +88 -88
  374. package/map/client/composables/highlight.js +214 -214
  375. package/map/client/composables/index.js +7 -7
  376. package/map/client/composables/location.js +53 -53
  377. package/map/client/composables/measure.js +42 -42
  378. package/map/client/composables/probe.js +133 -133
  379. package/map/client/composables/selection.js +300 -300
  380. package/map/client/composables/weather.js +213 -213
  381. package/map/client/elevation-utils.js +258 -258
  382. package/map/client/geolocation.js +119 -119
  383. package/map/client/globe.js +13 -13
  384. package/map/client/i18n/map_en.json +645 -645
  385. package/map/client/i18n/map_fr.json +646 -646
  386. package/map/client/index.js +18 -18
  387. package/map/client/init.js +80 -80
  388. package/map/client/leaflet/GSMaPLayer.js +55 -55
  389. package/map/client/leaflet/GradientPath.js +180 -180
  390. package/map/client/leaflet/MaskLayer.js +57 -57
  391. package/map/client/leaflet/TiledFeatureLayer.js +572 -572
  392. package/map/client/leaflet/TiledMeshLayer.js +486 -486
  393. package/map/client/leaflet/TiledWindLayer.js +384 -384
  394. package/map/client/leaflet/utils.js +246 -246
  395. package/map/client/map.js +15 -15
  396. package/map/client/mixins/globe/index.js +8 -8
  397. package/map/client/mixins/globe/mixin.base-globe.js +462 -462
  398. package/map/client/mixins/globe/mixin.file-layers.js +40 -40
  399. package/map/client/mixins/globe/mixin.geojson-layers.js +314 -314
  400. package/map/client/mixins/globe/mixin.globe-activity.js +52 -52
  401. package/map/client/mixins/globe/mixin.opendap-layers.js +51 -51
  402. package/map/client/mixins/globe/mixin.popup.js +82 -82
  403. package/map/client/mixins/globe/mixin.style.js +110 -110
  404. package/map/client/mixins/globe/mixin.tooltip.js +101 -101
  405. package/map/client/mixins/index.js +9 -9
  406. package/map/client/mixins/map/index.js +16 -16
  407. package/map/client/mixins/map/mixin.base-map.js +592 -592
  408. package/map/client/mixins/map/mixin.canvas-layers.js +529 -529
  409. package/map/client/mixins/map/mixin.edit-layers.js +493 -474
  410. package/map/client/mixins/map/mixin.file-layers.js +49 -49
  411. package/map/client/mixins/map/mixin.forecast-layers.js +79 -79
  412. package/map/client/mixins/map/mixin.geojson-layers.js +557 -557
  413. package/map/client/mixins/map/mixin.georaster-layers.js +114 -114
  414. package/map/client/mixins/map/mixin.gsmap-layers.js +27 -27
  415. package/map/client/mixins/map/mixin.heatmap-layers.js +116 -116
  416. package/map/client/mixins/map/mixin.map-activity.js +38 -38
  417. package/map/client/mixins/map/mixin.mapillary-layers.js +45 -45
  418. package/map/client/mixins/map/mixin.popup.js +53 -53
  419. package/map/client/mixins/map/mixin.style.js +73 -73
  420. package/map/client/mixins/map/mixin.tiled-mesh-layers.js +120 -120
  421. package/map/client/mixins/map/mixin.tiled-wind-layers.js +126 -126
  422. package/map/client/mixins/map/mixin.tooltip.js +47 -47
  423. package/map/client/mixins/mixin.activity.js +477 -477
  424. package/map/client/mixins/mixin.catalog-panel.js +26 -26
  425. package/map/client/mixins/mixin.context.js +262 -262
  426. package/map/client/mixins/mixin.feature-selection.js +28 -28
  427. package/map/client/mixins/mixin.feature-service.js +403 -403
  428. package/map/client/mixins/mixin.infobox.js +29 -29
  429. package/map/client/mixins/mixin.levels.js +66 -66
  430. package/map/client/mixins/mixin.style.js +29 -29
  431. package/map/client/mixins/mixin.weacast.js +212 -212
  432. package/map/client/pixi-utils.js +256 -256
  433. package/map/client/readers/index.js +4 -4
  434. package/map/client/readers/reader.geojson.js +64 -64
  435. package/map/client/readers/reader.gpx.js +36 -36
  436. package/map/client/readers/reader.kml.js +36 -36
  437. package/map/client/readers/reader.shp.js +82 -82
  438. package/map/client/utils/index.js +3 -3
  439. package/map/client/utils/utils.js +228 -228
  440. package/map/client/utils/utils.location.js +45 -45
  441. package/map/client/utils/utils.schema.js +75 -75
  442. package/map/client/utils.all.js +3 -3
  443. package/map/client/utils.globe.js +2 -2
  444. package/map/client/utils.js +4 -4
  445. package/map/client/utils.map.js +2 -2
  446. package/map/common/dynamic-grid-source.js +127 -127
  447. package/map/common/errors.js +3 -3
  448. package/map/common/geotiff-grid-source.js +150 -150
  449. package/map/common/grid.js +509 -509
  450. package/map/common/index.js +29 -29
  451. package/map/common/meteo-model-grid-source.js +157 -157
  452. package/map/common/moment-utils.js +24 -24
  453. package/map/common/opendap-grid-source.js +261 -261
  454. package/map/common/opendap-utils.js +247 -247
  455. package/map/common/permissions.js +11 -11
  456. package/map/common/schemas/catalog.update.json +28 -28
  457. package/map/common/time-based-grid-source.js +111 -111
  458. package/map/common/tms-utils.js +63 -63
  459. package/map/common/wcs-grid-source.js +93 -93
  460. package/map/common/wcs-utils.js +167 -167
  461. package/map/common/weacast-grid-source.js +316 -316
  462. package/map/common/wfs-utils.js +163 -163
  463. package/map/common/wms-utils.js +117 -117
  464. package/map/common/wmts-utils.js +154 -154
  465. package/map.api.js +5 -5
  466. package/map.client.globe.js +5 -5
  467. package/map.client.js +5 -5
  468. package/map.client.map.js +5 -5
  469. package/map.common.js +1 -1
  470. package/map.config.cjs +9 -9
  471. package/package.json +161 -161
  472. package/test/api/core/account.test.js +485 -485
  473. package/test/api/core/client.test.js.skip +37 -37
  474. package/test/api/core/config/default.cjs +118 -118
  475. package/test/api/core/config/email-templates/confirmInvitation/html.ejs +18 -18
  476. package/test/api/core/config/email-templates/identityChange/html.ejs +14 -14
  477. package/test/api/core/config/email-templates/newDevice/html.ejs +7 -7
  478. package/test/api/core/config/email-templates/newSubscription/html.ejs +7 -7
  479. package/test/api/core/config/email-templates/passwordChange/html.ejs +5 -5
  480. package/test/api/core/config/email-templates/resendVerifySignup/html.ejs +12 -12
  481. package/test/api/core/config/email-templates/resetPwd/html.ejs +5 -5
  482. package/test/api/core/config/email-templates/sendResetPwd/html.ejs +12 -12
  483. package/test/api/core/config/email-templates/verifySignup/html.ejs +3 -3
  484. package/test/api/core/data/invalid-objects.json +59 -59
  485. package/test/api/core/data/schema.json +57 -57
  486. package/test/api/core/data/valid-objects.json +37 -37
  487. package/test/api/core/hooks.test.js +330 -330
  488. package/test/api/core/index.js +1 -1
  489. package/test/api/core/index.test.js +478 -478
  490. package/test/api/core/push.test.js +197 -197
  491. package/test/api/core/schemas.test.js +82 -82
  492. package/test/api/core/storage.test.js +153 -153
  493. package/test/api/core/team.test.js +670 -670
  494. package/test/api/core/test-log-2023-12-19.log +7 -0
  495. package/test/api/core/utils.js +92 -92
  496. package/test/api/index.js +3 -3
  497. package/test/api/map/alerts.test.js +560 -560
  498. package/test/api/map/config/default.cjs +125 -125
  499. package/test/api/map/config/layers.json +38 -38
  500. package/test/api/map/data/DescribeCoverage.xml +54 -54
  501. package/test/api/map/data/adsb.observations.json +131 -131
  502. package/test/api/map/data/dataset.grb.das +55 -55
  503. package/test/api/map/data/dataset.grb.dds +17 -17
  504. package/test/api/map/data/vigicrues.observations.json +47041 -47041
  505. package/test/api/map/data/vigicrues.stations.json +15421 -15421
  506. package/test/api/map/data/zones.json +1227 -1227
  507. package/test/api/map/grid-sources.test.js +313 -313
  508. package/test/api/map/hooks.test.js +98 -98
  509. package/test/api/map/index.test.js +563 -563
  510. package/test/api/map/test-log-2023-11-24.log +121 -0
  511. package/test/api/map/test-log-2023-12-12.log +29 -0
  512. package/test/api/map/test-log-2023-12-13.log +5 -0
  513. package/test/client/core/account.js +36 -36
  514. package/test/client/core/api.js +361 -361
  515. package/test/client/core/collection.js +64 -64
  516. package/test/client/core/index.js +8 -8
  517. package/test/client/core/layout.js +116 -116
  518. package/test/client/core/runner.js +224 -224
  519. package/test/client/core/screens.js +35 -35
  520. package/test/client/core/time.js +10 -10
  521. package/test/client/core/utils.js +260 -260
  522. package/test/client/index.js +3 -3
  523. package/test/client/map/catalog.js +193 -193
  524. package/test/client/map/controls.js +41 -41
  525. package/test/client/map/index.js +4 -4
  526. package/test/client/map/time.js +24 -24
  527. package/test/client/map/utils.js +27 -27
  528. package/coverage/base.css +0 -224
  529. package/coverage/block-navigation.js +0 -87
  530. package/coverage/core/api/application.js.html +0 -1789
  531. package/coverage/core/api/authentication.js.html +0 -694
  532. package/coverage/core/api/db.js.html +0 -751
  533. package/coverage/core/api/hooks/hooks.account.js.html +0 -169
  534. package/coverage/core/api/hooks/hooks.authentication.js.html +0 -274
  535. package/coverage/core/api/hooks/hooks.authorisations.js.html +0 -1201
  536. package/coverage/core/api/hooks/hooks.devices.js.html +0 -211
  537. package/coverage/core/api/hooks/hooks.groups.js.html +0 -229
  538. package/coverage/core/api/hooks/hooks.logger.js.html +0 -163
  539. package/coverage/core/api/hooks/hooks.model.js.html +0 -988
  540. package/coverage/core/api/hooks/hooks.organisations.js.html +0 -823
  541. package/coverage/core/api/hooks/hooks.pusher.js.html +0 -730
  542. package/coverage/core/api/hooks/hooks.query.js.html +0 -838
  543. package/coverage/core/api/hooks/hooks.schemas.js.html +0 -244
  544. package/coverage/core/api/hooks/hooks.service.js.html +0 -319
  545. package/coverage/core/api/hooks/hooks.storage.js.html +0 -193
  546. package/coverage/core/api/hooks/hooks.tags.js.html +0 -850
  547. package/coverage/core/api/hooks/hooks.users.js.html +0 -889
  548. package/coverage/core/api/hooks/index.html +0 -341
  549. package/coverage/core/api/hooks/index.js.html +0 -130
  550. package/coverage/core/api/index.html +0 -176
  551. package/coverage/core/api/index.js.html +0 -148
  552. package/coverage/core/api/marshall.js.html +0 -355
  553. package/coverage/core/api/models/groups.model.mongodb.js.html +0 -109
  554. package/coverage/core/api/models/index.html +0 -161
  555. package/coverage/core/api/models/organisations.model.mongodb.js.html +0 -94
  556. package/coverage/core/api/models/tags.model.mongodb.js.html +0 -115
  557. package/coverage/core/api/models/users.model.mongodb.js.html +0 -115
  558. package/coverage/core/api/oauth2-handler.js.html +0 -202
  559. package/coverage/core/api/oauth2-verifier.js.html +0 -355
  560. package/coverage/core/api/services/account/account.hooks.js.html +0 -196
  561. package/coverage/core/api/services/account/account.service.js.html +0 -448
  562. package/coverage/core/api/services/account/index.html +0 -131
  563. package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  564. package/coverage/core/api/services/authorisations/authorisations.service.js.html +0 -502
  565. package/coverage/core/api/services/authorisations/index.html +0 -131
  566. package/coverage/core/api/services/databases/databases.hooks.js.html +0 -193
  567. package/coverage/core/api/services/databases/databases.service.js.html +0 -100
  568. package/coverage/core/api/services/databases/index.html +0 -131
  569. package/coverage/core/api/services/devices/devices.hooks.js.html +0 -190
  570. package/coverage/core/api/services/devices/devices.service.js.html +0 -382
  571. package/coverage/core/api/services/devices/index.html +0 -131
  572. package/coverage/core/api/services/groups/groups.hooks.js.html +0 -184
  573. package/coverage/core/api/services/groups/index.html +0 -116
  574. package/coverage/core/api/services/index.html +0 -116
  575. package/coverage/core/api/services/index.js.html +0 -472
  576. package/coverage/core/api/services/mailer/index.html +0 -131
  577. package/coverage/core/api/services/mailer/mailer.hooks.js.html +0 -190
  578. package/coverage/core/api/services/mailer/mailer.service.js.html +0 -118
  579. package/coverage/core/api/services/organisations/index.html +0 -131
  580. package/coverage/core/api/services/organisations/organisations.hooks.js.html +0 -178
  581. package/coverage/core/api/services/organisations/organisations.service.js.html +0 -319
  582. package/coverage/core/api/services/pusher/index.html +0 -146
  583. package/coverage/core/api/services/pusher/pusher.channels.js.html +0 -94
  584. package/coverage/core/api/services/pusher/pusher.hooks.js.html +0 -193
  585. package/coverage/core/api/services/pusher/pusher.service.js.html +0 -1420
  586. package/coverage/core/api/services/storage/index.html +0 -131
  587. package/coverage/core/api/services/storage/storage.hooks.js.html +0 -190
  588. package/coverage/core/api/services/storage/storage.service.js.html +0 -172
  589. package/coverage/core/api/services/tags/index.html +0 -116
  590. package/coverage/core/api/services/tags/tags.hooks.js.html +0 -220
  591. package/coverage/core/api/services/users/index.html +0 -116
  592. package/coverage/core/api/services/users/users.hooks.js.html +0 -313
  593. package/coverage/core/common/errors.js.html +0 -88
  594. package/coverage/core/common/index.html +0 -176
  595. package/coverage/core/common/index.js.html +0 -115
  596. package/coverage/core/common/permissions.js.html +0 -1015
  597. package/coverage/core/common/schema.js.html +0 -190
  598. package/coverage/core/common/utils.js.html +0 -220
  599. package/coverage/favicon.png +0 -0
  600. package/coverage/index.html +0 -491
  601. package/coverage/lcov-report/base.css +0 -224
  602. package/coverage/lcov-report/block-navigation.js +0 -87
  603. package/coverage/lcov-report/core/api/application.js.html +0 -1789
  604. package/coverage/lcov-report/core/api/authentication.js.html +0 -694
  605. package/coverage/lcov-report/core/api/db.js.html +0 -751
  606. package/coverage/lcov-report/core/api/hooks/hooks.account.js.html +0 -169
  607. package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +0 -274
  608. package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +0 -1201
  609. package/coverage/lcov-report/core/api/hooks/hooks.devices.js.html +0 -211
  610. package/coverage/lcov-report/core/api/hooks/hooks.groups.js.html +0 -229
  611. package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +0 -163
  612. package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +0 -988
  613. package/coverage/lcov-report/core/api/hooks/hooks.organisations.js.html +0 -823
  614. package/coverage/lcov-report/core/api/hooks/hooks.pusher.js.html +0 -730
  615. package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +0 -838
  616. package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +0 -244
  617. package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +0 -319
  618. package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +0 -193
  619. package/coverage/lcov-report/core/api/hooks/hooks.tags.js.html +0 -850
  620. package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +0 -889
  621. package/coverage/lcov-report/core/api/hooks/index.html +0 -341
  622. package/coverage/lcov-report/core/api/hooks/index.js.html +0 -130
  623. package/coverage/lcov-report/core/api/index.html +0 -176
  624. package/coverage/lcov-report/core/api/index.js.html +0 -148
  625. package/coverage/lcov-report/core/api/marshall.js.html +0 -355
  626. package/coverage/lcov-report/core/api/models/groups.model.mongodb.js.html +0 -109
  627. package/coverage/lcov-report/core/api/models/index.html +0 -161
  628. package/coverage/lcov-report/core/api/models/organisations.model.mongodb.js.html +0 -94
  629. package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +0 -115
  630. package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +0 -115
  631. package/coverage/lcov-report/core/api/oauth2-handler.js.html +0 -202
  632. package/coverage/lcov-report/core/api/oauth2-verifier.js.html +0 -355
  633. package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +0 -196
  634. package/coverage/lcov-report/core/api/services/account/account.service.js.html +0 -448
  635. package/coverage/lcov-report/core/api/services/account/index.html +0 -131
  636. package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  637. package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +0 -502
  638. package/coverage/lcov-report/core/api/services/authorisations/index.html +0 -131
  639. package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +0 -193
  640. package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +0 -100
  641. package/coverage/lcov-report/core/api/services/databases/index.html +0 -131
  642. package/coverage/lcov-report/core/api/services/devices/devices.hooks.js.html +0 -190
  643. package/coverage/lcov-report/core/api/services/devices/devices.service.js.html +0 -382
  644. package/coverage/lcov-report/core/api/services/devices/index.html +0 -131
  645. package/coverage/lcov-report/core/api/services/groups/groups.hooks.js.html +0 -184
  646. package/coverage/lcov-report/core/api/services/groups/index.html +0 -116
  647. package/coverage/lcov-report/core/api/services/index.html +0 -116
  648. package/coverage/lcov-report/core/api/services/index.js.html +0 -472
  649. package/coverage/lcov-report/core/api/services/mailer/index.html +0 -131
  650. package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +0 -190
  651. package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +0 -118
  652. package/coverage/lcov-report/core/api/services/organisations/index.html +0 -131
  653. package/coverage/lcov-report/core/api/services/organisations/organisations.hooks.js.html +0 -178
  654. package/coverage/lcov-report/core/api/services/organisations/organisations.service.js.html +0 -319
  655. package/coverage/lcov-report/core/api/services/pusher/index.html +0 -146
  656. package/coverage/lcov-report/core/api/services/pusher/pusher.channels.js.html +0 -94
  657. package/coverage/lcov-report/core/api/services/pusher/pusher.hooks.js.html +0 -193
  658. package/coverage/lcov-report/core/api/services/pusher/pusher.service.js.html +0 -1420
  659. package/coverage/lcov-report/core/api/services/storage/index.html +0 -131
  660. package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +0 -190
  661. package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +0 -172
  662. package/coverage/lcov-report/core/api/services/tags/index.html +0 -116
  663. package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +0 -220
  664. package/coverage/lcov-report/core/api/services/users/index.html +0 -116
  665. package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +0 -313
  666. package/coverage/lcov-report/core/common/errors.js.html +0 -88
  667. package/coverage/lcov-report/core/common/index.html +0 -176
  668. package/coverage/lcov-report/core/common/index.js.html +0 -115
  669. package/coverage/lcov-report/core/common/permissions.js.html +0 -1015
  670. package/coverage/lcov-report/core/common/schema.js.html +0 -190
  671. package/coverage/lcov-report/core/common/utils.js.html +0 -220
  672. package/coverage/lcov-report/favicon.png +0 -0
  673. package/coverage/lcov-report/index.html +0 -491
  674. package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +0 -340
  675. package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +0 -337
  676. package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +0 -1162
  677. package/coverage/lcov-report/map/api/hooks/index.html +0 -161
  678. package/coverage/lcov-report/map/api/hooks/index.js.html +0 -94
  679. package/coverage/lcov-report/map/api/index.html +0 -131
  680. package/coverage/lcov-report/map/api/index.js.html +0 -139
  681. package/coverage/lcov-report/map/api/marshall.js.html +0 -178
  682. package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +0 -106
  683. package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +0 -127
  684. package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +0 -202
  685. package/coverage/lcov-report/map/api/models/index.html +0 -146
  686. package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +0 -274
  687. package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +0 -610
  688. package/coverage/lcov-report/map/api/services/alerts/index.html +0 -131
  689. package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +0 -313
  690. package/coverage/lcov-report/map/api/services/catalog/index.html +0 -116
  691. package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  692. package/coverage/lcov-report/map/api/services/daptiles/index.html +0 -116
  693. package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +0 -205
  694. package/coverage/lcov-report/map/api/services/features/features.service.js.html +0 -241
  695. package/coverage/lcov-report/map/api/services/features/index.html +0 -131
  696. package/coverage/lcov-report/map/api/services/geocoder/geocoder.hooks.js.html +0 -178
  697. package/coverage/lcov-report/map/api/services/geocoder/geocoder.service.js.html +0 -322
  698. package/coverage/lcov-report/map/api/services/geocoder/index.html +0 -131
  699. package/coverage/lcov-report/map/api/services/index.html +0 -116
  700. package/coverage/lcov-report/map/api/services/index.js.html +0 -760
  701. package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +0 -466
  702. package/coverage/lcov-report/map/common/errors.js.html +0 -94
  703. package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +0 -535
  704. package/coverage/lcov-report/map/common/grid.js.html +0 -1612
  705. package/coverage/lcov-report/map/common/index.html +0 -371
  706. package/coverage/lcov-report/map/common/index.js.html +0 -172
  707. package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +0 -556
  708. package/coverage/lcov-report/map/common/moment-utils.js.html +0 -157
  709. package/coverage/lcov-report/map/common/opendap-grid-source.js.html +0 -868
  710. package/coverage/lcov-report/map/common/opendap-utils.js.html +0 -826
  711. package/coverage/lcov-report/map/common/permissions.js.html +0 -118
  712. package/coverage/lcov-report/map/common/time-based-grid-source.js.html +0 -418
  713. package/coverage/lcov-report/map/common/tms-utils.js.html +0 -274
  714. package/coverage/lcov-report/map/common/wcs-grid-source.js.html +0 -364
  715. package/coverage/lcov-report/map/common/wcs-utils.js.html +0 -586
  716. package/coverage/lcov-report/map/common/weacast-grid-source.js.html +0 -1033
  717. package/coverage/lcov-report/map/common/wfs-utils.js.html +0 -574
  718. package/coverage/lcov-report/map/common/wms-utils.js.html +0 -436
  719. package/coverage/lcov-report/map/common/wmts-utils.js.html +0 -547
  720. package/coverage/lcov-report/prettify.css +0 -1
  721. package/coverage/lcov-report/prettify.js +0 -2
  722. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  723. package/coverage/lcov-report/sorter.js +0 -196
  724. package/coverage/lcov.info +0 -12501
  725. package/coverage/map/api/hooks/hooks.catalog.js.html +0 -340
  726. package/coverage/map/api/hooks/hooks.features.js.html +0 -337
  727. package/coverage/map/api/hooks/hooks.query.js.html +0 -1162
  728. package/coverage/map/api/hooks/index.html +0 -161
  729. package/coverage/map/api/hooks/index.js.html +0 -94
  730. package/coverage/map/api/index.html +0 -131
  731. package/coverage/map/api/index.js.html +0 -139
  732. package/coverage/map/api/marshall.js.html +0 -178
  733. package/coverage/map/api/models/alerts.model.mongodb.js.html +0 -106
  734. package/coverage/map/api/models/catalog.model.mongodb.js.html +0 -127
  735. package/coverage/map/api/models/features.model.mongodb.js.html +0 -202
  736. package/coverage/map/api/models/index.html +0 -146
  737. package/coverage/map/api/services/alerts/alerts.hooks.js.html +0 -274
  738. package/coverage/map/api/services/alerts/alerts.service.js.html +0 -610
  739. package/coverage/map/api/services/alerts/index.html +0 -131
  740. package/coverage/map/api/services/catalog/catalog.hooks.js.html +0 -313
  741. package/coverage/map/api/services/catalog/index.html +0 -116
  742. package/coverage/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  743. package/coverage/map/api/services/daptiles/index.html +0 -116
  744. package/coverage/map/api/services/features/features.hooks.js.html +0 -205
  745. package/coverage/map/api/services/features/features.service.js.html +0 -241
  746. package/coverage/map/api/services/features/index.html +0 -131
  747. package/coverage/map/api/services/geocoder/geocoder.hooks.js.html +0 -178
  748. package/coverage/map/api/services/geocoder/geocoder.service.js.html +0 -322
  749. package/coverage/map/api/services/geocoder/index.html +0 -131
  750. package/coverage/map/api/services/index.html +0 -116
  751. package/coverage/map/api/services/index.js.html +0 -760
  752. package/coverage/map/common/dynamic-grid-source.js.html +0 -466
  753. package/coverage/map/common/errors.js.html +0 -94
  754. package/coverage/map/common/geotiff-grid-source.js.html +0 -535
  755. package/coverage/map/common/grid.js.html +0 -1612
  756. package/coverage/map/common/index.html +0 -371
  757. package/coverage/map/common/index.js.html +0 -172
  758. package/coverage/map/common/meteo-model-grid-source.js.html +0 -556
  759. package/coverage/map/common/moment-utils.js.html +0 -157
  760. package/coverage/map/common/opendap-grid-source.js.html +0 -868
  761. package/coverage/map/common/opendap-utils.js.html +0 -826
  762. package/coverage/map/common/permissions.js.html +0 -118
  763. package/coverage/map/common/time-based-grid-source.js.html +0 -418
  764. package/coverage/map/common/tms-utils.js.html +0 -274
  765. package/coverage/map/common/wcs-grid-source.js.html +0 -364
  766. package/coverage/map/common/wcs-utils.js.html +0 -586
  767. package/coverage/map/common/weacast-grid-source.js.html +0 -1033
  768. package/coverage/map/common/wfs-utils.js.html +0 -574
  769. package/coverage/map/common/wms-utils.js.html +0 -436
  770. package/coverage/map/common/wmts-utils.js.html +0 -547
  771. package/coverage/prettify.css +0 -1
  772. package/coverage/prettify.js +0 -2
  773. package/coverage/sort-arrow-sprite.png +0 -0
  774. package/coverage/sorter.js +0 -196
  775. package/coverage/tmp/coverage-19264-1684834146599-0.json +0 -1
  776. package/coverage/tmp/coverage-2508-1684834182408-0.json +0 -1
  777. package/coverage/tmp/coverage-25908-1684834189369-0.json +0 -1
  778. package/coverage/tmp/coverage-32364-1684834189420-0.json +0 -1
  779. package/coverage/tmp/coverage-36604-1684834189485-0.json +0 -1
  780. package/coverage/tmp/coverage-40652-1684834182272-0.json +0 -1
  781. package/coverage/tmp/coverage-48484-1684834182342-0.json +0 -1
  782. package/coverage/tmp/coverage-51652-1684834189584-0.json +0 -1
  783. package/coverage/tmp/coverage-9776-1684834189519-0.json +0 -1
  784. package/test/api/core/test-log-2023-06-05.log +0 -0
  785. package/test/api/map/test-log-2022-12-01.log +0 -19
  786. package/test/api/map/test-log-2023-01-05.log +0 -4
  787. package/test/api/map/test-log-2023-01-09.log +0 -3
  788. package/test/api/map/test-log-2023-02-05.log +0 -11
  789. package/test/api/map/test-log-2023-02-14.log +0 -82
  790. package/test/api/map/test-log-2023-02-28.log +0 -28
  791. package/test/api/map/test-log-2023-03-02.log +0 -11
  792. package/test/api/map/test-log-2023-03-06.log +0 -11
  793. package/test/api/map/test-log-2023-03-07.log +0 -61
  794. package/test/api/map/test-log-2023-03-31.log +0 -11
  795. package/test/api/map/test-log-2023-05-23.log +0 -11
  796. package/test/api/map/test-log-2023-05-24.log +0 -11
@@ -1,376 +1,376 @@
1
- import _ from 'lodash'
2
- import makeDebug from 'debug'
3
- import common from 'feathers-hooks-common'
4
- import errors from '@feathersjs/errors'
5
- import { populateObject, unpopulateObject, populateObjects, unpopulateObjects } from './hooks.query.js'
6
- import { objectifyIDs } from '../db.js'
7
- import {
8
- hasServiceAbilities, hasResourceAbilities, getQueryForAbilities,
9
- Roles, RoleNames, countSubjectsForResource
10
- } from '../../common/permissions.js'
11
- import { isTagEqual } from '../utils.js'
12
-
13
- const { getItems, replaceItems } = common
14
- const { Forbidden } = errors
15
- const debug = makeDebug('kdk:core:authorisations:hooks')
16
-
17
- export function createJWT (options = {}) {
18
- return async function (hook) {
19
- const { jwtOptions: defaults } = hook.app.get('authentication') || hook.app.get('auth')
20
- const user = _.get(hook, 'params.user')
21
- let items = getItems(hook)
22
- const isArray = Array.isArray(items)
23
- items = (isArray ? items : [items])
24
- // Generate access tokens for all items
25
- const accessTokens = await Promise.all(items.map(item => hook.app.getService('authentication').createAccessToken(
26
- // Provided function can be used to pick or omit properties in JWT payload
27
- (typeof options.payload === 'function' ? options.payload(user) : {}),
28
- // Provided function can be used for custom options cdepending on the user,
29
- // then we merge with default auth options for global properties like aud, iss, etc.
30
- _.merge({}, defaults, (typeof options.jwt === 'function' ? options.jwt(user) : options)))
31
- ))
32
- // Store access token on items
33
- items.forEach((item, index) => _.set(item, options.name || 'accessToken', accessTokens[index]))
34
- replaceItems(hook, isArray ? items : items[0])
35
- return hook
36
- }
37
- }
38
-
39
- export function populateSubjects (hook) {
40
- if (hook.type !== 'before') {
41
- throw new Error('The \'populateSubjects\' hook should only be used as a \'before\' hook.')
42
- }
43
-
44
- return populateObjects({ serviceField: 'subjectsService', idField: 'subjects', throwOnNotFound: true })(hook)
45
- }
46
-
47
- export function unpopulateSubjects (hook) {
48
- if (hook.type !== 'after') {
49
- throw new Error('The \'unpopulateSubjects\' hook should only be used as a \'after\' hook.')
50
- }
51
-
52
- return unpopulateObjects({ serviceField: 'subjectsService', idField: 'subjects' })(hook)
53
- }
54
-
55
- export function populateResource (hook) {
56
- if (hook.type !== 'before') {
57
- throw new Error('The \'populateResource\' hook should only be used as a \'before\' hook.')
58
- }
59
-
60
- return populateObject({ serviceField: 'resourcesService', idField: 'resource', throwOnNotFound: true })(hook)
61
- }
62
-
63
- export function unpopulateResource (hook) {
64
- if (hook.type !== 'after') {
65
- throw new Error('The \'unpopulateResource\' hook should only be used as a \'after\' hook.')
66
- }
67
-
68
- return unpopulateObject({ serviceField: 'resourcesService', idField: 'resource' })(hook)
69
- }
70
-
71
- export function preventEscalation (hook) {
72
- if (hook.type !== 'before') {
73
- throw new Error('The \'preventEscalation\' hook should only be used as a \'before\' hook.')
74
- }
75
-
76
- const params = hook.params
77
- // If called internally we skip authorisation
78
- let checkEscalation = _.has(params, 'provider')
79
- debug('Escalation check ' + (checkEscalation ? 'enabled' : 'disabled') + ' for provider')
80
- // If explicitely asked to perform/skip, override defaults
81
- if (_.has(params, 'checkEscalation')) {
82
- checkEscalation = params.checkEscalation
83
- debug('Escalation check ' + (checkEscalation ? 'forced' : 'unforced'))
84
- }
85
-
86
- if (checkEscalation) {
87
- const user = params.user
88
- // Make hook usable on remove as well
89
- const data = hook.data || {}
90
- // Make hook usable with query params as well
91
- const query = params.query || {}
92
- const scopeName = data.scope || query.scope // Get scope name first
93
- // Retrieve the right scope on the user
94
- const scope = _.get(user, scopeName, [])
95
- // Then the target resource
96
- const resource = _.find(scope, resource => resource._id && (resource._id.toString() === params.resource._id.toString()))
97
- // Then user permission level
98
- const permissions = (resource ? resource.permissions : undefined)
99
- const role = (permissions ? Roles[permissions] : undefined)
100
- if (_.isUndefined(role)) {
101
- debug('Role for authorisation not found on user for scope ' + scopeName)
102
- throw new Forbidden('You are not allowed to change authorisation on resource')
103
- }
104
-
105
- // Check if privilege escalation might occur, if so clamp to user permission level
106
-
107
- // Input subjects need to be checked:
108
- // - on create you should not be able to change permissions on others having higher permissions than yourself
109
- // (e.g. cannot change a owner into a manager when you are a manager)
110
- // - on remove you should not be able to remove permissions on others having higher permissions than yourself
111
- // (e.g. cannot remove a owner when you are a manager)
112
- const subjects = params.subjects.filter(subject => {
113
- const subjectScope = _.get(subject, scopeName, [])
114
- const subjectResource = _.find(subjectScope, resource => resource._id && (resource._id.toString() === params.resource._id.toString()))
115
- const subjectPermissions = (subjectResource ? subjectResource.permissions : undefined)
116
- const subjectRole = (subjectPermissions ? Roles[subjectPermissions] : undefined)
117
- const hasRole = !_.isUndefined(subjectRole)
118
- if (hook.method === 'create') {
119
- return (!hasRole || (subjectRole <= role)) // The first time no authorisation can be found
120
- } else {
121
- return (hasRole && (subjectRole <= role)) // Authorisation must be found on remove
122
- }
123
- })
124
- if (subjects.length < params.subjects.length) {
125
- debug(`${(params.subjects.length - subjects.length)} subjects with higher permissions level found for scope ${scopeName}`)
126
- throw new Forbidden('You are not allowed to change authorisation on subject(s)')
127
- }
128
- // Input permissions needs to be checked since:
129
- // - you should not be able to give higher permissions than your own ones to others
130
- // (e.g. cannot create a owner when you are a manager)
131
- let authorisationRole
132
- if (data.permissions) {
133
- authorisationRole = Roles[data.permissions]
134
- } else if (query.permissions) {
135
- authorisationRole = Roles[query.permissions]
136
- }
137
- if (!_.isUndefined(authorisationRole)) {
138
- if (authorisationRole > role) {
139
- debug('Cannot escalate with higher permissions level for scope ' + scopeName)
140
- throw new Forbidden('You are not allowed to change authorisation on resource')
141
- }
142
- }
143
- }
144
-
145
- return hook
146
- }
147
-
148
- export async function authorise (hook) {
149
- if (hook.type !== 'before') {
150
- throw new Error('The \'authorise\' hook should only be used as a \'before\' hook.')
151
- }
152
- const operation = hook.method
153
- const resourceType = hook.service.name
154
- debug('Provider is', hook.params.provider)
155
- if (hook.params.user) debug('User is', hook.params.user)
156
- debug('Operation is', operation)
157
- if (resourceType) debug('Resource type is', resourceType)
158
-
159
- // If called internally we skip authorisation
160
- let checkAuthorisation = _.has(hook.params, 'provider')
161
- debug('Access check ' + (checkAuthorisation ? 'enabled' : 'disabled') + ' for provider')
162
- // If already checked we skip authorisation
163
- if (hook.params.authorised) {
164
- debug('Access already granted')
165
- checkAuthorisation = false
166
- }
167
- // We also skip authorisation for built-in Feathers services like authentication
168
- if (typeof hook.service.getPath !== 'function') {
169
- debug('Access disabled on built-in services')
170
- checkAuthorisation = false
171
- }
172
- // And if the authentication strategy is API key
173
- if (_.get(hook, 'params.connection.authentication.strategy') === 'api') {
174
- debug('Access disabled on API keys')
175
- checkAuthorisation = false
176
- }
177
- // If explicitely asked to perform/skip, override defaults
178
- if (_.has(hook.params, 'checkAuthorisation')) {
179
- checkAuthorisation = _.get(hook.params, 'checkAuthorisation')
180
- // Bypass authorisation for next hooks otherwise we will loop infinitely
181
- delete hook.params.checkAuthorisation
182
- debug('Access check ' + (checkAuthorisation ? 'forced' : 'unforced'))
183
- }
184
-
185
- const context = hook.service.context
186
- if (checkAuthorisation) {
187
- // Build ability for user
188
- const authorisationService = hook.app.getService('authorisations')
189
- const abilities = await authorisationService.getAbilities(hook.params.user)
190
- hook.params.abilities = abilities
191
- debug('User abilities are', abilities.rules)
192
-
193
- // Check for access to service fisrt
194
- if (!hasServiceAbilities(abilities, hook.service)) {
195
- debug('Service access not granted')
196
- throw new Forbidden(`You are not allowed to access service ${hook.service.getPath()}`)
197
- }
198
-
199
- if (!hook.id) {
200
- // In this specific case there is no query to be run,
201
- // simply check against the object we'd like to create
202
- // Support custom methods as create operation as they have similar signature
203
- const DEFAULT_METHODS = ['find', 'get', 'create', 'update', 'patch', 'remove']
204
- if ((operation === 'create') || !DEFAULT_METHODS.includes(operation)) {
205
- const resource = hook.data
206
- debug('Target resource is ', resource)
207
- if (!hasResourceAbilities(abilities, operation, resourceType, context, resource)) {
208
- debug('Resource access not granted')
209
- throw new Forbidden(`You are not allowed to perform ${operation} operation on ${resourceType}`)
210
- }
211
- } else {
212
- // When we find/update/patch/remove multiple items this ensures that
213
- // only the ones authorised by constraints on the resources will be fetched
214
- // This avoid fetching all first then check it one by one
215
- const dbQuery = objectifyIDs(getQueryForAbilities(abilities, operation, resourceType))
216
- if (dbQuery) {
217
- hook.params.query = _.transform(hook.params.query, (result, value, key) => {
218
- if (key === '$or') result.$and = [{ $or: value }]
219
- else result[key] = value
220
- }, {})
221
- _.merge(hook.params.query, dbQuery)
222
- } else {
223
- if (operation === 'find') { // You don't have right to read any items but you have access to the service so the result is empty
224
- hook.result = (!_.get(hook, 'params.paginate', true) ? [] : { total: 0, skip: 0, data: [] })
225
- } else { // You don't have the right to update/patch/remove any items so any tentative should throw
226
- debug('Resource access not granted')
227
- throw new Forbidden(`You are not allowed to perform ${operation} operation on ${resourceType}`)
228
- }
229
- }
230
- }
231
- debug('Resource access granted')
232
- // Some specific services might not expose a get function, in this case we cannot check for authorisation
233
- // this has to be implemented by the service itself
234
- } else if (typeof hook.service.get === 'function') {
235
- // In this case (single get/update/patch/remove) we need to fetch the item first
236
- // Take care we might have additional query parameters to be "catched" by before hooks,
237
- // however at this stage these query parameters might cause get to fail
238
- const params = Object.assign({ checkAuthorisation: false }, hook.params)
239
- _.unset(params, 'query')
240
- const resource = await hook.service.get(hook.id, params)
241
- debug('Target resource is', resource)
242
- // Then check against the object we'd like to manage
243
- if (!hasResourceAbilities(abilities, operation, resourceType, context, resource)) {
244
- debug('Resource access not granted')
245
- throw new Forbidden(`You are not allowed to perform ${operation} operation on ${resourceType}`)
246
- }
247
- // Avoid fetching again the object in this case
248
- if (operation === 'get') {
249
- hook.result = resource
250
- }
251
- hook.params.authorised = true
252
- debug('Resource access granted')
253
- return hook
254
- }
255
- } else {
256
- debug('Authorisation check skipped, access granted')
257
- }
258
-
259
- hook.params.authorised = true
260
- return hook
261
- }
262
-
263
- export function updateAbilities (options = {}) {
264
- return async function (hook) {
265
- const app = hook.app
266
- const params = hook.params
267
- const authorisationService = app.getService('authorisations')
268
- let subject = (options.subjectAsItem ? getItems(hook) : params.user)
269
- // Specific case of authentication result
270
- if (subject && subject.user) subject = subject.user
271
- // We might not have all information required eg on patch to compute new abilities,
272
- // in this case we have to fetch the whole subject
273
- if (options.fetchSubject) {
274
- subject = await app.getService('users').get(subject._id.toString())
275
- }
276
- const abilities = await authorisationService.updateAbilities(subject)
277
- debug('Abilities updated on subject', subject, abilities.rules)
278
- return hook
279
- }
280
- }
281
-
282
- export function preventRemovingLastOwner (resourceScope) {
283
- return async function (hook) {
284
- // By pass check ?
285
- if (hook.params.force) return hook
286
- const params = hook.params
287
- const data = hook.data || {}
288
- const query = params.query || {}
289
- const scope = data.scope || query.scope
290
- const grantedPermissions = data.permissions || query.permissions
291
- const grantedRole = (grantedPermissions ? Roles[grantedPermissions] : undefined)
292
- const resource = hook.params.resource
293
- const subjects = hook.params.subjects
294
- const subjectService = hook.params.subjectsService
295
- // On create check if we try to downgrade permissions otherwise let pass through
296
- if (!_.isUndefined(grantedRole) && (grantedRole === Roles.owner)) return hook
297
-
298
- if ((scope === resourceScope) && resource && resource._id) {
299
- // Count existing owners
300
- const owners = await countSubjectsForResource(subjectService, resourceScope, resource._id, Roles.owner)
301
- // Now count owners we change/remove permissions on
302
- const removedOwners = subjects.reduce((count, subject) => {
303
- const resources = _.get(subject, resourceScope, [])
304
- const ownedResource = _.find(resources, { _id: resource._id, permissions: RoleNames[Roles.owner] })
305
- return (ownedResource ? count + 1 : count)
306
- }, 0)
307
- // If none remains stop
308
- if (removedOwners >= owners.total) {
309
- debug('Cannot remove the last owner of resource ', resource)
310
- const resourceName = resource.name ? resource.name : resource._id.toString()
311
- throw new Forbidden('You are not allowed to remove the last owner of resource ' + resourceName, {
312
- translation: {
313
- key: 'CANNOT_REMOVE_LAST_OWNER',
314
- params: { resource: resourceName }
315
- }
316
- })
317
- }
318
- }
319
- return hook
320
- }
321
- }
322
-
323
- export async function removeOrganisationGroupsAuthorisations (hook) {
324
- const app = hook.app
325
- const authorisationService = app.getService('authorisations')
326
- const org = hook.params.resource
327
- const user = hook.params.user
328
- // Unset membership for the all org groups
329
- const orgGroupService = app.getService('groups', org)
330
- const groups = await orgGroupService.find({ paginate: false })
331
- await Promise.all(groups.map(group => {
332
- // Unset membership on group for the all org users
333
- return authorisationService.remove(group._id.toString(), {
334
- query: {
335
- scope: 'groups'
336
- },
337
- user,
338
- force: hook.params.force,
339
- // Because we already have resource set it as objects to avoid populating
340
- // Moreover used as an after hook the resource might not already exist anymore
341
- subjects: hook.params.subjects,
342
- subjectsService: hook.params.subjectsService,
343
- resource: group,
344
- resourcesService: orgGroupService
345
- })
346
- }))
347
- debug('Authorisations unset on groups for organisation ' + org._id)
348
- return hook
349
- }
350
-
351
- export async function removeOrganisationTagsAuthorisations (hook) {
352
- const app = hook.app
353
- const org = hook.params.resource
354
- const subjectService = hook.params.subjectsService
355
- const orgTagsService = app.getService('tags', org)
356
- const subjects = hook.params.subjects || []
357
- if (subjects.length === 0) return hook
358
- // Retrieve org tags
359
- const orgTags = await orgTagsService.find({ paginate: false })
360
- const promises = []
361
- subjects.forEach(subject => {
362
- const tags = subject.tags || []
363
- // Find tags from org
364
- const fromOrg = _.intersectionWith(tags, orgTags, isTagEqual)
365
- // Clear removed tags
366
- const notFromOrg = _.differenceWith(tags, orgTags, isTagEqual)
367
- // Update subject if required
368
- if (fromOrg.length > 0) {
369
- promises.push(subjectService.patch(subject._id.toString(), { tags: notFromOrg }))
370
- }
371
- })
372
- // Perform subject updates in parallel
373
- await Promise.all(promises)
374
- debug(`Tags unset on ${promises.length} subjects for organisation ` + org._id)
375
- return hook
376
- }
1
+ import _ from 'lodash'
2
+ import makeDebug from 'debug'
3
+ import common from 'feathers-hooks-common'
4
+ import errors from '@feathersjs/errors'
5
+ import { populateObject, unpopulateObject, populateObjects, unpopulateObjects } from './hooks.query.js'
6
+ import { objectifyIDs } from '../db.js'
7
+ import {
8
+ hasServiceAbilities, hasResourceAbilities, getQueryForAbilities,
9
+ Roles, RoleNames, countSubjectsForResource
10
+ } from '../../common/permissions.js'
11
+ import { isTagEqual } from '../utils.js'
12
+
13
+ const { getItems, replaceItems } = common
14
+ const { Forbidden } = errors
15
+ const debug = makeDebug('kdk:core:authorisations:hooks')
16
+
17
+ export function createJWT (options = {}) {
18
+ return async function (hook) {
19
+ const { jwtOptions: defaults } = hook.app.get('authentication') || hook.app.get('auth')
20
+ const user = _.get(hook, 'params.user')
21
+ let items = getItems(hook)
22
+ const isArray = Array.isArray(items)
23
+ items = (isArray ? items : [items])
24
+ // Generate access tokens for all items
25
+ const accessTokens = await Promise.all(items.map(item => hook.app.getService('authentication').createAccessToken(
26
+ // Provided function can be used to pick or omit properties in JWT payload
27
+ (typeof options.payload === 'function' ? options.payload(user) : {}),
28
+ // Provided function can be used for custom options cdepending on the user,
29
+ // then we merge with default auth options for global properties like aud, iss, etc.
30
+ _.merge({}, defaults, (typeof options.jwt === 'function' ? options.jwt(user) : options)))
31
+ ))
32
+ // Store access token on items
33
+ items.forEach((item, index) => _.set(item, options.name || 'accessToken', accessTokens[index]))
34
+ replaceItems(hook, isArray ? items : items[0])
35
+ return hook
36
+ }
37
+ }
38
+
39
+ export function populateSubjects (hook) {
40
+ if (hook.type !== 'before') {
41
+ throw new Error('The \'populateSubjects\' hook should only be used as a \'before\' hook.')
42
+ }
43
+
44
+ return populateObjects({ serviceField: 'subjectsService', idField: 'subjects', throwOnNotFound: true })(hook)
45
+ }
46
+
47
+ export function unpopulateSubjects (hook) {
48
+ if (hook.type !== 'after') {
49
+ throw new Error('The \'unpopulateSubjects\' hook should only be used as a \'after\' hook.')
50
+ }
51
+
52
+ return unpopulateObjects({ serviceField: 'subjectsService', idField: 'subjects' })(hook)
53
+ }
54
+
55
+ export function populateResource (hook) {
56
+ if (hook.type !== 'before') {
57
+ throw new Error('The \'populateResource\' hook should only be used as a \'before\' hook.')
58
+ }
59
+
60
+ return populateObject({ serviceField: 'resourcesService', idField: 'resource', throwOnNotFound: true })(hook)
61
+ }
62
+
63
+ export function unpopulateResource (hook) {
64
+ if (hook.type !== 'after') {
65
+ throw new Error('The \'unpopulateResource\' hook should only be used as a \'after\' hook.')
66
+ }
67
+
68
+ return unpopulateObject({ serviceField: 'resourcesService', idField: 'resource' })(hook)
69
+ }
70
+
71
+ export function preventEscalation (hook) {
72
+ if (hook.type !== 'before') {
73
+ throw new Error('The \'preventEscalation\' hook should only be used as a \'before\' hook.')
74
+ }
75
+
76
+ const params = hook.params
77
+ // If called internally we skip authorisation
78
+ let checkEscalation = _.has(params, 'provider')
79
+ debug('Escalation check ' + (checkEscalation ? 'enabled' : 'disabled') + ' for provider')
80
+ // If explicitely asked to perform/skip, override defaults
81
+ if (_.has(params, 'checkEscalation')) {
82
+ checkEscalation = params.checkEscalation
83
+ debug('Escalation check ' + (checkEscalation ? 'forced' : 'unforced'))
84
+ }
85
+
86
+ if (checkEscalation) {
87
+ const user = params.user
88
+ // Make hook usable on remove as well
89
+ const data = hook.data || {}
90
+ // Make hook usable with query params as well
91
+ const query = params.query || {}
92
+ const scopeName = data.scope || query.scope // Get scope name first
93
+ // Retrieve the right scope on the user
94
+ const scope = _.get(user, scopeName, [])
95
+ // Then the target resource
96
+ const resource = _.find(scope, resource => resource._id && (resource._id.toString() === params.resource._id.toString()))
97
+ // Then user permission level
98
+ const permissions = (resource ? resource.permissions : undefined)
99
+ const role = (permissions ? Roles[permissions] : undefined)
100
+ if (_.isUndefined(role)) {
101
+ debug('Role for authorisation not found on user for scope ' + scopeName)
102
+ throw new Forbidden('You are not allowed to change authorisation on resource')
103
+ }
104
+
105
+ // Check if privilege escalation might occur, if so clamp to user permission level
106
+
107
+ // Input subjects need to be checked:
108
+ // - on create you should not be able to change permissions on others having higher permissions than yourself
109
+ // (e.g. cannot change a owner into a manager when you are a manager)
110
+ // - on remove you should not be able to remove permissions on others having higher permissions than yourself
111
+ // (e.g. cannot remove a owner when you are a manager)
112
+ const subjects = params.subjects.filter(subject => {
113
+ const subjectScope = _.get(subject, scopeName, [])
114
+ const subjectResource = _.find(subjectScope, resource => resource._id && (resource._id.toString() === params.resource._id.toString()))
115
+ const subjectPermissions = (subjectResource ? subjectResource.permissions : undefined)
116
+ const subjectRole = (subjectPermissions ? Roles[subjectPermissions] : undefined)
117
+ const hasRole = !_.isUndefined(subjectRole)
118
+ if (hook.method === 'create') {
119
+ return (!hasRole || (subjectRole <= role)) // The first time no authorisation can be found
120
+ } else {
121
+ return (hasRole && (subjectRole <= role)) // Authorisation must be found on remove
122
+ }
123
+ })
124
+ if (subjects.length < params.subjects.length) {
125
+ debug(`${(params.subjects.length - subjects.length)} subjects with higher permissions level found for scope ${scopeName}`)
126
+ throw new Forbidden('You are not allowed to change authorisation on subject(s)')
127
+ }
128
+ // Input permissions needs to be checked since:
129
+ // - you should not be able to give higher permissions than your own ones to others
130
+ // (e.g. cannot create a owner when you are a manager)
131
+ let authorisationRole
132
+ if (data.permissions) {
133
+ authorisationRole = Roles[data.permissions]
134
+ } else if (query.permissions) {
135
+ authorisationRole = Roles[query.permissions]
136
+ }
137
+ if (!_.isUndefined(authorisationRole)) {
138
+ if (authorisationRole > role) {
139
+ debug('Cannot escalate with higher permissions level for scope ' + scopeName)
140
+ throw new Forbidden('You are not allowed to change authorisation on resource')
141
+ }
142
+ }
143
+ }
144
+
145
+ return hook
146
+ }
147
+
148
+ export async function authorise (hook) {
149
+ if (hook.type !== 'before') {
150
+ throw new Error('The \'authorise\' hook should only be used as a \'before\' hook.')
151
+ }
152
+ const operation = hook.method
153
+ const resourceType = hook.service.name
154
+ debug('Provider is', hook.params.provider)
155
+ if (hook.params.user) debug('User is', hook.params.user)
156
+ debug('Operation is', operation)
157
+ if (resourceType) debug('Resource type is', resourceType)
158
+
159
+ // If called internally we skip authorisation
160
+ let checkAuthorisation = _.has(hook.params, 'provider')
161
+ debug('Access check ' + (checkAuthorisation ? 'enabled' : 'disabled') + ' for provider')
162
+ // If already checked we skip authorisation
163
+ if (hook.params.authorised) {
164
+ debug('Access already granted')
165
+ checkAuthorisation = false
166
+ }
167
+ // We also skip authorisation for built-in Feathers services like authentication
168
+ if (typeof hook.service.getPath !== 'function') {
169
+ debug('Access disabled on built-in services')
170
+ checkAuthorisation = false
171
+ }
172
+ // And if the authentication strategy is API key
173
+ if (_.get(hook, 'params.connection.authentication.strategy') === 'api') {
174
+ debug('Access disabled on API keys')
175
+ checkAuthorisation = false
176
+ }
177
+ // If explicitely asked to perform/skip, override defaults
178
+ if (_.has(hook.params, 'checkAuthorisation')) {
179
+ checkAuthorisation = _.get(hook.params, 'checkAuthorisation')
180
+ // Bypass authorisation for next hooks otherwise we will loop infinitely
181
+ delete hook.params.checkAuthorisation
182
+ debug('Access check ' + (checkAuthorisation ? 'forced' : 'unforced'))
183
+ }
184
+
185
+ const context = hook.service.context
186
+ if (checkAuthorisation) {
187
+ // Build ability for user
188
+ const authorisationService = hook.app.getService('authorisations')
189
+ const abilities = await authorisationService.getAbilities(hook.params.user)
190
+ hook.params.abilities = abilities
191
+ debug('User abilities are', abilities.rules)
192
+
193
+ // Check for access to service fisrt
194
+ if (!hasServiceAbilities(abilities, hook.service)) {
195
+ debug('Service access not granted')
196
+ throw new Forbidden(`You are not allowed to access service ${hook.service.getPath()}`)
197
+ }
198
+
199
+ if (!hook.id) {
200
+ // In this specific case there is no query to be run,
201
+ // simply check against the object we'd like to create
202
+ // Support custom methods as create operation as they have similar signature
203
+ const DEFAULT_METHODS = ['find', 'get', 'create', 'update', 'patch', 'remove']
204
+ if ((operation === 'create') || !DEFAULT_METHODS.includes(operation)) {
205
+ const resource = hook.data
206
+ debug('Target resource is ', resource)
207
+ if (!hasResourceAbilities(abilities, operation, resourceType, context, resource)) {
208
+ debug('Resource access not granted')
209
+ throw new Forbidden(`You are not allowed to perform ${operation} operation on ${resourceType}`)
210
+ }
211
+ } else {
212
+ // When we find/update/patch/remove multiple items this ensures that
213
+ // only the ones authorised by constraints on the resources will be fetched
214
+ // This avoid fetching all first then check it one by one
215
+ const dbQuery = objectifyIDs(getQueryForAbilities(abilities, operation, resourceType))
216
+ if (dbQuery) {
217
+ hook.params.query = _.transform(hook.params.query, (result, value, key) => {
218
+ if (key === '$or') result.$and = [{ $or: value }]
219
+ else result[key] = value
220
+ }, {})
221
+ _.merge(hook.params.query, dbQuery)
222
+ } else {
223
+ if (operation === 'find') { // You don't have right to read any items but you have access to the service so the result is empty
224
+ hook.result = (!_.get(hook, 'params.paginate', true) ? [] : { total: 0, skip: 0, data: [] })
225
+ } else { // You don't have the right to update/patch/remove any items so any tentative should throw
226
+ debug('Resource access not granted')
227
+ throw new Forbidden(`You are not allowed to perform ${operation} operation on ${resourceType}`)
228
+ }
229
+ }
230
+ }
231
+ debug('Resource access granted')
232
+ // Some specific services might not expose a get function, in this case we cannot check for authorisation
233
+ // this has to be implemented by the service itself
234
+ } else if (typeof hook.service.get === 'function') {
235
+ // In this case (single get/update/patch/remove) we need to fetch the item first
236
+ // Take care we might have additional query parameters to be "catched" by before hooks,
237
+ // however at this stage these query parameters might cause get to fail
238
+ const params = Object.assign({ checkAuthorisation: false }, hook.params)
239
+ _.unset(params, 'query')
240
+ const resource = await hook.service.get(hook.id, params)
241
+ debug('Target resource is', resource)
242
+ // Then check against the object we'd like to manage
243
+ if (!hasResourceAbilities(abilities, operation, resourceType, context, resource)) {
244
+ debug('Resource access not granted')
245
+ throw new Forbidden(`You are not allowed to perform ${operation} operation on ${resourceType}`)
246
+ }
247
+ // Avoid fetching again the object in this case
248
+ if (operation === 'get') {
249
+ hook.result = resource
250
+ }
251
+ hook.params.authorised = true
252
+ debug('Resource access granted')
253
+ return hook
254
+ }
255
+ } else {
256
+ debug('Authorisation check skipped, access granted')
257
+ }
258
+
259
+ hook.params.authorised = true
260
+ return hook
261
+ }
262
+
263
+ export function updateAbilities (options = {}) {
264
+ return async function (hook) {
265
+ const app = hook.app
266
+ const params = hook.params
267
+ const authorisationService = app.getService('authorisations')
268
+ let subject = (options.subjectAsItem ? getItems(hook) : params.user)
269
+ // Specific case of authentication result
270
+ if (subject && subject.user) subject = subject.user
271
+ // We might not have all information required eg on patch to compute new abilities,
272
+ // in this case we have to fetch the whole subject
273
+ if (options.fetchSubject) {
274
+ subject = await app.getService('users').get(subject._id.toString())
275
+ }
276
+ const abilities = await authorisationService.updateAbilities(subject)
277
+ debug('Abilities updated on subject', subject, abilities.rules)
278
+ return hook
279
+ }
280
+ }
281
+
282
+ export function preventRemovingLastOwner (resourceScope) {
283
+ return async function (hook) {
284
+ // By pass check ?
285
+ if (hook.params.force) return hook
286
+ const params = hook.params
287
+ const data = hook.data || {}
288
+ const query = params.query || {}
289
+ const scope = data.scope || query.scope
290
+ const grantedPermissions = data.permissions || query.permissions
291
+ const grantedRole = (grantedPermissions ? Roles[grantedPermissions] : undefined)
292
+ const resource = hook.params.resource
293
+ const subjects = hook.params.subjects
294
+ const subjectService = hook.params.subjectsService
295
+ // On create check if we try to downgrade permissions otherwise let pass through
296
+ if (!_.isUndefined(grantedRole) && (grantedRole === Roles.owner)) return hook
297
+
298
+ if ((scope === resourceScope) && resource && resource._id) {
299
+ // Count existing owners
300
+ const owners = await countSubjectsForResource(subjectService, resourceScope, resource._id, Roles.owner)
301
+ // Now count owners we change/remove permissions on
302
+ const removedOwners = subjects.reduce((count, subject) => {
303
+ const resources = _.get(subject, resourceScope, [])
304
+ const ownedResource = _.find(resources, { _id: resource._id, permissions: RoleNames[Roles.owner] })
305
+ return (ownedResource ? count + 1 : count)
306
+ }, 0)
307
+ // If none remains stop
308
+ if (removedOwners >= owners.total) {
309
+ debug('Cannot remove the last owner of resource ', resource)
310
+ const resourceName = resource.name ? resource.name : resource._id.toString()
311
+ throw new Forbidden('You are not allowed to remove the last owner of resource ' + resourceName, {
312
+ translation: {
313
+ key: 'CANNOT_REMOVE_LAST_OWNER',
314
+ params: { resource: resourceName }
315
+ }
316
+ })
317
+ }
318
+ }
319
+ return hook
320
+ }
321
+ }
322
+
323
+ export async function removeOrganisationGroupsAuthorisations (hook) {
324
+ const app = hook.app
325
+ const authorisationService = app.getService('authorisations')
326
+ const org = hook.params.resource
327
+ const user = hook.params.user
328
+ // Unset membership for the all org groups
329
+ const orgGroupService = app.getService('groups', org)
330
+ const groups = await orgGroupService.find({ paginate: false })
331
+ await Promise.all(groups.map(group => {
332
+ // Unset membership on group for the all org users
333
+ return authorisationService.remove(group._id.toString(), {
334
+ query: {
335
+ scope: 'groups'
336
+ },
337
+ user,
338
+ force: hook.params.force,
339
+ // Because we already have resource set it as objects to avoid populating
340
+ // Moreover used as an after hook the resource might not already exist anymore
341
+ subjects: hook.params.subjects,
342
+ subjectsService: hook.params.subjectsService,
343
+ resource: group,
344
+ resourcesService: orgGroupService
345
+ })
346
+ }))
347
+ debug('Authorisations unset on groups for organisation ' + org._id)
348
+ return hook
349
+ }
350
+
351
+ export async function removeOrganisationTagsAuthorisations (hook) {
352
+ const app = hook.app
353
+ const org = hook.params.resource
354
+ const subjectService = hook.params.subjectsService
355
+ const orgTagsService = app.getService('tags', org)
356
+ const subjects = hook.params.subjects || []
357
+ if (subjects.length === 0) return hook
358
+ // Retrieve org tags
359
+ const orgTags = await orgTagsService.find({ paginate: false })
360
+ const promises = []
361
+ subjects.forEach(subject => {
362
+ const tags = subject.tags || []
363
+ // Find tags from org
364
+ const fromOrg = _.intersectionWith(tags, orgTags, isTagEqual)
365
+ // Clear removed tags
366
+ const notFromOrg = _.differenceWith(tags, orgTags, isTagEqual)
367
+ // Update subject if required
368
+ if (fromOrg.length > 0) {
369
+ promises.push(subjectService.patch(subject._id.toString(), { tags: notFromOrg }))
370
+ }
371
+ })
372
+ // Perform subject updates in parallel
373
+ await Promise.all(promises)
374
+ debug(`Tags unset on ${promises.length} subjects for organisation ` + org._id)
375
+ return hook
376
+ }