@saltcorn/server 1.6.0-beta.1 → 1.6.0-beta.11

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 (789) hide show
  1. package/CHANGELOG.md +72 -3
  2. package/app.js +32 -12
  3. package/auth/admin.js +109 -22
  4. package/auth/routes.js +178 -61
  5. package/auth/testhelp.js +9 -19
  6. package/docs/assets/hierarchy.js +1 -1
  7. package/docs/assets/navigation.js +1 -1
  8. package/docs/assets/search.js +1 -1
  9. package/docs/classes/_saltcorn_admin-models.models_snapshot.Snapshot.html +2 -2
  10. package/docs/classes/_saltcorn_common-code.relations_relation.Relation.html +3 -3
  11. package/docs/classes/_saltcorn_common-code.relations_relations_finder.RelationsFinder.html +5 -5
  12. package/docs/classes/_saltcorn_data.diagram_cy_raster.CytoscapeRaster.html +4 -4
  13. package/docs/classes/_saltcorn_data.diagram_nodes_dummy_node.DummyNode.html +4 -4
  14. package/docs/classes/_saltcorn_data.diagram_nodes_node.Node.html +4 -4
  15. package/docs/classes/_saltcorn_data.diagram_nodes_page_node.PageNode.html +4 -4
  16. package/docs/classes/_saltcorn_data.diagram_nodes_table_node.TableNode.html +4 -4
  17. package/docs/classes/_saltcorn_data.diagram_nodes_trigger_node.TriggerNode.html +4 -4
  18. package/docs/classes/_saltcorn_data.diagram_nodes_view_node.ViewNode.html +4 -4
  19. package/docs/classes/_saltcorn_data.mobile-mocks_node_async_hooks.AsyncLocalStorage.html +2 -2
  20. package/docs/classes/_saltcorn_data.models_crash.Crash.html +2 -2
  21. package/docs/classes/_saltcorn_data.models_eventlog.EventLog.html +2 -2
  22. package/docs/classes/_saltcorn_data.models_field.Field.html +9 -9
  23. package/docs/classes/_saltcorn_data.models_fieldrepeat.FieldRepeat.html +2 -2
  24. package/docs/classes/_saltcorn_data.models_file.File.html +21 -21
  25. package/docs/classes/_saltcorn_data.models_form.Form.html +2 -2
  26. package/docs/classes/_saltcorn_data.models_internal_mail_queue.MailQueue.html +4 -4
  27. package/docs/classes/_saltcorn_data.models_internal_push_message_helper.PushMessageHelper.html +7 -7
  28. package/docs/classes/_saltcorn_data.models_library.Library.html +2 -2
  29. package/docs/classes/_saltcorn_data.models_model.Model.html +2 -2
  30. package/docs/classes/_saltcorn_data.models_model_instance.ModelInstance.html +2 -2
  31. package/docs/classes/_saltcorn_data.models_notification.Notification.html +2 -2
  32. package/docs/classes/_saltcorn_data.models_page.Page.html +12 -11
  33. package/docs/classes/_saltcorn_data.models_page_group.PageGroup.html +16 -16
  34. package/docs/classes/_saltcorn_data.models_page_group_member.PageGroupMember.html +8 -8
  35. package/docs/classes/_saltcorn_data.models_plugin.Plugin.html +45 -10
  36. package/docs/classes/_saltcorn_data.models_role.Role.html +2 -2
  37. package/docs/classes/_saltcorn_data.models_table.Table.html +67 -65
  38. package/docs/classes/_saltcorn_data.models_table_constraints.TableConstraint.html +2 -2
  39. package/docs/classes/_saltcorn_data.models_tag.Tag.html +2 -2
  40. package/docs/classes/_saltcorn_data.models_tag_entry.TagEntry.html +2 -2
  41. package/docs/classes/_saltcorn_data.models_trigger.Trigger.html +22 -20
  42. package/docs/classes/_saltcorn_data.models_user.User.html +32 -32
  43. package/docs/classes/_saltcorn_data.models_view.View.html +16 -15
  44. package/docs/classes/_saltcorn_data.models_workflow.Workflow.html +2 -2
  45. package/docs/classes/_saltcorn_data.models_workflow_run.WorkflowRun.html +2 -2
  46. package/docs/classes/_saltcorn_data.models_workflow_step.WorkflowStep.html +2 -2
  47. package/docs/classes/_saltcorn_data.models_workflow_trace.MetaData.html +2 -2
  48. package/docs/classes/_saltcorn_data.models_workflow_trace.WorkflowTrace.html +2 -2
  49. package/docs/classes/_saltcorn_mobile-builder.mobile-builder.MobileBuilder.html +2 -3
  50. package/docs/classes/_saltcorn_mobile-builder.utils_capacitor-helper.CapacitorHelper.html +2 -2
  51. package/docs/enums/_saltcorn_common-code.relations_relation_types.RelationType.html +2 -2
  52. package/docs/enums/_saltcorn_common-code.relations_relation_types.ViewDisplayType.html +2 -2
  53. package/docs/functions/_saltcorn_admin-models.models_config-check.runConfigurationCheck.html +1 -1
  54. package/docs/functions/_saltcorn_common-code.relations_relation_helpers.buildRelationPath.html +1 -1
  55. package/docs/functions/_saltcorn_common-code.relations_relation_helpers.buildTableCaches.html +1 -1
  56. package/docs/functions/_saltcorn_common-code.relations_relation_helpers.parseLegacyRelation.html +1 -1
  57. package/docs/functions/_saltcorn_common-code.relations_relation_helpers.parseRelationPath.html +1 -1
  58. package/docs/functions/_saltcorn_common-code.tests_test_data.fixturesData.html +1 -1
  59. package/docs/functions/_saltcorn_common-code.tests_test_data.withAnotherUserField.html +1 -1
  60. package/docs/functions/_saltcorn_common-code.tests_test_data.withKeyFromLayerThree.html +1 -1
  61. package/docs/functions/_saltcorn_common-code.tests_test_data.withKeyFromLayerTwo.html +1 -1
  62. package/docs/functions/_saltcorn_common-code.tests_test_data.withMultipleInbounds.html +1 -1
  63. package/docs/functions/_saltcorn_common-code.tests_test_data.withSecondTopicField.html +1 -1
  64. package/docs/functions/_saltcorn_common-code.tests_test_data.withSimplePostTopicrelation.html +1 -1
  65. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.action_link.html +1 -1
  66. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.action_url.html +1 -1
  67. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.fill_presets.html +1 -1
  68. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.getForm.html +1 -1
  69. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.get_view_link_query.html +1 -1
  70. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.get_viewable_fields.html +1 -1
  71. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.get_viewable_fields_from_layout.html +1 -1
  72. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.make_link.html +1 -1
  73. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.objToQueryString.html +1 -1
  74. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.parse_view_select.html +1 -1
  75. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.setDateLocales.html +1 -1
  76. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.splitUniques.html +1 -1
  77. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.standardBlockDispatch.html +1 -1
  78. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.standardLayoutRowVisitor.html +1 -1
  79. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.transformForm.html +1 -1
  80. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.updateViewSelect.html +1 -1
  81. package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.view_linker.html +1 -1
  82. package/docs/functions/_saltcorn_data.db_connect_mobile.getConnectObject.html +1 -1
  83. package/docs/functions/_saltcorn_data.db_reset_schema.reset.html +1 -1
  84. package/docs/functions/_saltcorn_data.diagram_cy_generate_utils.generateCyCode.html +1 -1
  85. package/docs/functions/_saltcorn_data.diagram_cy_generate_utils.genereateCyCfg.html +1 -1
  86. package/docs/functions/_saltcorn_data.diagram_node_extract_utils.buildObjectTrees.html +1 -1
  87. package/docs/functions/_saltcorn_data.diagram_node_extract_utils.extractFromColumns.html +1 -1
  88. package/docs/functions/_saltcorn_data.diagram_node_extract_utils.extractFromLayout.html +1 -1
  89. package/docs/functions/_saltcorn_data.diagram_node_extract_utils.extractViewToCreate.html +1 -1
  90. package/docs/functions/_saltcorn_data.migrate.create_blank_migration.html +1 -1
  91. package/docs/functions/_saltcorn_data.migrate.getMigrationsInDB.html +1 -1
  92. package/docs/functions/_saltcorn_data.migrate.migrate.html +1 -1
  93. package/docs/functions/_saltcorn_data.migrations_202102091312.js.html +1 -1
  94. package/docs/functions/_saltcorn_data.migrations_202210051058.js.html +1 -1
  95. package/docs/functions/_saltcorn_data.migrations_202210101540.js.html +1 -1
  96. package/docs/functions/_saltcorn_data.migrations_202304281224.js.html +1 -1
  97. package/docs/functions/_saltcorn_data.migrations_202307211459.js.html +1 -1
  98. package/docs/functions/_saltcorn_data.migrations_202502131103.js.html +1 -1
  99. package/docs/functions/_saltcorn_data.migrations_202508011455.js.html +1 -1
  100. package/docs/functions/_saltcorn_data.migrations_202510152058.js.html +1 -1
  101. package/docs/functions/_saltcorn_data.migrations_202603101553.sql_pg.html +1 -1
  102. package/docs/functions/_saltcorn_data.migrations_202604111200.js.html +1 -0
  103. package/docs/functions/_saltcorn_data.migrations_202604141200.js.html +1 -0
  104. package/docs/functions/_saltcorn_data.mobile-mocks_node_child_process.execSync.html +1 -1
  105. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs.createReadStream.html +1 -1
  106. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs.readdirSync.html +1 -1
  107. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs.writeFileSync.html +1 -1
  108. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.mkdir.html +1 -1
  109. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.readFile.html +1 -1
  110. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.readdir.html +1 -0
  111. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.stat.html +1 -1
  112. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.unlink.html +1 -1
  113. package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.writeFile.html +1 -1
  114. package/docs/functions/_saltcorn_data.mobile-mocks_node_latest-version.latestVersion.html +1 -1
  115. package/docs/functions/_saltcorn_data.mobile-mocks_node_v8.deserialize.html +1 -1
  116. package/docs/functions/_saltcorn_data.mobile-mocks_node_v8.serialize.html +1 -1
  117. package/docs/functions/_saltcorn_data.mobile-mocks_npm_env-paths.envPaths.html +1 -1
  118. package/docs/functions/_saltcorn_data.model-helper.get_predictor.html +1 -1
  119. package/docs/functions/_saltcorn_data.model-helper.run_jupyter_model.html +1 -1
  120. package/docs/functions/_saltcorn_data.model-helper.shorten_trackback.html +1 -1
  121. package/docs/functions/_saltcorn_data.model-helper.write_csv.html +1 -1
  122. package/docs/functions/_saltcorn_data.models_internal_async_json_stream.async_json_stream.html +1 -1
  123. package/docs/functions/_saltcorn_data.models_internal_query.aggregation_query_fields.html +1 -1
  124. package/docs/functions/_saltcorn_data.models_internal_query.getAggAndField.html +1 -1
  125. package/docs/functions/_saltcorn_data.models_internal_query.joinfield_renamer.html +1 -1
  126. package/docs/functions/_saltcorn_data.models_internal_query.process_aggregations.html +1 -1
  127. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.buildKeyFromRelative.html +1 -1
  128. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.copyObject.html +1 -1
  129. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.deleteObject.html +1 -1
  130. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.downloadBuffer.html +1 -1
  131. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getPublicFileUrl.html +1 -1
  132. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getResolvedBucket.html +1 -1
  133. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getS3Client.html +1 -1
  134. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getServeUrl.html +1 -1
  135. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getSignedFileUrl.html +1 -1
  136. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.headObject.html +1 -1
  137. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.isS3Enabled.html +1 -1
  138. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.listS3Folder.html +1 -1
  139. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.publicUrlToRelativePath.html +1 -1
  140. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.relativeKeyToPath.html +1 -1
  141. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.setObjectMetadata.html +1 -1
  142. package/docs/functions/_saltcorn_data.models_internal_s3_helpers.uploadBuffer.html +1 -1
  143. package/docs/functions/_saltcorn_data.models_internal_table_helper.boolExamples.html +1 -1
  144. package/docs/functions/_saltcorn_data.models_internal_table_helper.colorExamples.html +1 -1
  145. package/docs/functions/_saltcorn_data.models_internal_table_helper.floatExamples.html +1 -1
  146. package/docs/functions/_saltcorn_data.models_internal_table_helper.get_formula_examples.html +1 -1
  147. package/docs/functions/_saltcorn_data.models_internal_table_helper.intExamples.html +1 -1
  148. package/docs/functions/_saltcorn_data.models_internal_table_helper.stringExamples.html +1 -1
  149. package/docs/functions/_saltcorn_data.plugin-helper.build_schema_data.html +1 -1
  150. package/docs/functions/_saltcorn_data.plugin-helper.calcfldViewConfig.html +1 -1
  151. package/docs/functions/_saltcorn_data.plugin-helper.calcfldViewOptions.html +1 -1
  152. package/docs/functions/_saltcorn_data.plugin-helper.calcrelViewOptions.html +1 -1
  153. package/docs/functions/_saltcorn_data.plugin-helper.displayType.html +1 -1
  154. package/docs/functions/_saltcorn_data.plugin-helper.field_picker_fields.html +1 -1
  155. package/docs/functions/_saltcorn_data.plugin-helper.generate_joined_query.html +1 -1
  156. package/docs/functions/_saltcorn_data.plugin-helper.getActionConfigFields.html +1 -1
  157. package/docs/functions/_saltcorn_data.plugin-helper.get_child_views.html +1 -1
  158. package/docs/functions/_saltcorn_data.plugin-helper.get_inbound_relation_opts.html +1 -1
  159. package/docs/functions/_saltcorn_data.plugin-helper.get_inbound_self_relation_opts.html +1 -1
  160. package/docs/functions/_saltcorn_data.plugin-helper.get_link_view_opts.html +1 -1
  161. package/docs/functions/_saltcorn_data.plugin-helper.get_many_to_many_relation_opts.html +1 -1
  162. package/docs/functions/_saltcorn_data.plugin-helper.get_parent_views.html +1 -1
  163. package/docs/functions/_saltcorn_data.plugin-helper.initial_config_all_fields.html +1 -1
  164. package/docs/functions/_saltcorn_data.plugin-helper.json_list_to_external_table.html +1 -1
  165. package/docs/functions/_saltcorn_data.plugin-helper.link_view.html +1 -1
  166. package/docs/functions/_saltcorn_data.plugin-helper.pathToState.html +1 -1
  167. package/docs/functions/_saltcorn_data.plugin-helper.picked_fields_to_query.html +1 -1
  168. package/docs/functions/_saltcorn_data.plugin-helper.readState.html +1 -1
  169. package/docs/functions/_saltcorn_data.plugin-helper.readStateStrict.html +1 -1
  170. package/docs/functions/_saltcorn_data.plugin-helper.runCollabEvents.html +1 -1
  171. package/docs/functions/_saltcorn_data.plugin-helper.run_action_column.html +1 -1
  172. package/docs/functions/_saltcorn_data.plugin-helper.stateFieldsToQuery.html +1 -1
  173. package/docs/functions/_saltcorn_data.plugin-helper.stateFieldsToWhere.html +1 -1
  174. package/docs/functions/_saltcorn_data.plugin-helper.stateToQueryString.html +1 -1
  175. package/docs/functions/_saltcorn_data.plugin-helper.strictParseInt.html +1 -1
  176. package/docs/functions/_saltcorn_data.plugin-testing.auto_test_plugin.html +1 -1
  177. package/docs/functions/_saltcorn_data.plugin-testing.check_view_columns.html +1 -1
  178. package/docs/functions/_saltcorn_data.plugin-testing.generate_attributes.html +1 -1
  179. package/docs/functions/_saltcorn_data.standard-menu.create_standard_menu.html +1 -1
  180. package/docs/functions/_saltcorn_data.tests_assertions.assertIsErrorMsg.html +1 -1
  181. package/docs/functions/_saltcorn_data.tests_assertions.assertIsErrorsMsg.html +1 -1
  182. package/docs/functions/_saltcorn_data.tests_assertions.assertIsRow.html +1 -1
  183. package/docs/functions/_saltcorn_data.tests_assertions.assertIsSet.html +1 -1
  184. package/docs/functions/_saltcorn_data.tests_assertions.assertIsType.html +1 -1
  185. package/docs/functions/_saltcorn_data.tests_assertions.assertsIsSuccessMessage.html +1 -1
  186. package/docs/functions/_saltcorn_data.tests_assertions.assertsObjectIsUser.html +1 -1
  187. package/docs/functions/_saltcorn_data.tests_common_helpers.createAnotherUserField.html +1 -1
  188. package/docs/functions/_saltcorn_data.tests_common_helpers.createKeyFromLevelTwo.html +1 -1
  189. package/docs/functions/_saltcorn_data.tests_common_helpers.createLevelThreeInbound.html +1 -1
  190. package/docs/functions/_saltcorn_data.tests_common_helpers.createMultipleInbounds.html +1 -1
  191. package/docs/functions/_saltcorn_data.tests_common_helpers.createSecondTopicField.html +1 -1
  192. package/docs/functions/_saltcorn_data.tests_common_helpers.prepareEmployeeDepartment.html +1 -1
  193. package/docs/functions/_saltcorn_data.tests_common_helpers.prepareSimpleTopicPostRelation.html +1 -1
  194. package/docs/functions/_saltcorn_data.tests_remote_query_helper.deleteViewFromServer.html +1 -1
  195. package/docs/functions/_saltcorn_data.tests_remote_query_helper.prepareQueryEnviroment.html +1 -1
  196. package/docs/functions/_saltcorn_data.tests_remote_query_helper.sendViewToServer.html +1 -1
  197. package/docs/functions/_saltcorn_data.translate.hasLLM.html +1 -1
  198. package/docs/functions/_saltcorn_data.translate.translate.html +1 -1
  199. package/docs/functions/_saltcorn_db-common.internal.ftsFieldsSqlExpr.html +1 -1
  200. package/docs/functions/_saltcorn_db-common.internal.mkSelectOptions.html +1 -1
  201. package/docs/functions/_saltcorn_db-common.internal.mkWhere.html +1 -1
  202. package/docs/functions/_saltcorn_db-common.internal.orderByIsObject.html +1 -1
  203. package/docs/functions/_saltcorn_db-common.internal.orderByIsOperator.html +1 -1
  204. package/docs/functions/_saltcorn_db-common.internal.prefixFieldsInWhere.html +1 -1
  205. package/docs/functions/_saltcorn_db-common.internal.sqlBinOp.html +1 -1
  206. package/docs/functions/_saltcorn_db-common.internal.sqlFun.html +1 -1
  207. package/docs/functions/_saltcorn_db-common.internal.sqlsanitize.html +1 -1
  208. package/docs/functions/_saltcorn_db-common.internal.sqlsanitizeAllowDots.html +1 -1
  209. package/docs/functions/_saltcorn_db-common.internal.subSelectWhere.html +1 -1
  210. package/docs/functions/_saltcorn_db-common.multi-tenant.enable_multi_tenant.html +1 -1
  211. package/docs/functions/_saltcorn_db-common.multi-tenant.getRequestContext.html +1 -1
  212. package/docs/functions/_saltcorn_db-common.multi-tenant.getTenantSchema.html +1 -1
  213. package/docs/functions/_saltcorn_db-common.multi-tenant.init.html +1 -1
  214. package/docs/functions/_saltcorn_db-common.multi-tenant.is_it_multi_tenant.html +1 -1
  215. package/docs/functions/_saltcorn_db-common.multi-tenant.runWithTenant.html +1 -1
  216. package/docs/functions/_saltcorn_db-common.sqlite-commons.buildInsertBulkSql.html +1 -1
  217. package/docs/functions/_saltcorn_db-common.sqlite-commons.buildInsertSql.html +1 -1
  218. package/docs/functions/_saltcorn_db-common.sqlite-commons.commitAndBeginNewTransaction.html +1 -1
  219. package/docs/functions/_saltcorn_db-common.sqlite-commons.doCount.html +1 -1
  220. package/docs/functions/_saltcorn_db-common.sqlite-commons.doDeleteWhere.html +1 -1
  221. package/docs/functions/_saltcorn_db-common.sqlite-commons.doListScTables.html +1 -1
  222. package/docs/functions/_saltcorn_db-common.sqlite-commons.doListTables.html +1 -1
  223. package/docs/functions/_saltcorn_db-common.sqlite-commons.doListUserDefinedTables.html +1 -1
  224. package/docs/functions/_saltcorn_db-common.sqlite-commons.do_add_index.html +1 -1
  225. package/docs/functions/_saltcorn_db-common.sqlite-commons.do_drop_index.html +1 -1
  226. package/docs/functions/_saltcorn_db-common.sqlite-commons.mkVal.html +1 -1
  227. package/docs/functions/_saltcorn_db-common.sqlite-commons.openOrUseTransaction.html +1 -1
  228. package/docs/functions/_saltcorn_db-common.sqlite-commons.reprAsJson.html +1 -1
  229. package/docs/functions/_saltcorn_db-common.sqlite-commons.slugify.html +1 -1
  230. package/docs/functions/_saltcorn_db-common.sqlite-commons.tryCatchInTransaction.html +1 -1
  231. package/docs/functions/_saltcorn_db-common.sqlite-commons.whenTransactionisFree.html +1 -1
  232. package/docs/functions/_saltcorn_db-common.sqlite-commons.withTransaction.html +1 -1
  233. package/docs/functions/_saltcorn_markup.mktag.mkTag.html +1 -1
  234. package/docs/functions/_saltcorn_markup.tabs.tabs.html +1 -1
  235. package/docs/functions/_saltcorn_markup.workflow.renderWorkflow.html +1 -1
  236. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.androidFeatures.html +1 -1
  237. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.androidPermissions.html +1 -1
  238. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.buildTablesFile.html +1 -1
  239. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyPrepopulatedDb.html +1 -1
  240. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyServerFiles.html +1 -1
  241. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyShareExtFiles.html +1 -1
  242. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copySiteLogo.html +1 -1
  243. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyTranslationFiles.html +1 -1
  244. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.createSqliteDb.html +1 -1
  245. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.extractDomain.html +1 -1
  246. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.generateAndroidVersionCode.html +1 -1
  247. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.hasAuthMethod.html +1 -1
  248. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyAndroidManifest.html +1 -1
  249. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyAppDelegate.html +1 -1
  250. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyConfigXml.html +1 -1
  251. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyGradleConfig.html +1 -1
  252. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyInfoPlist.html +1 -1
  253. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyShareViewController.html +1 -1
  254. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyXcodeProjectFile.html +1 -1
  255. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepAppIcon.html +1 -1
  256. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareAppIcon.html +1 -1
  257. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareBuildDir.html +1 -1
  258. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareExportOptionsPlist.html +1 -1
  259. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareSplashIcon.html +1 -1
  260. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareSplashPage.html +1 -1
  261. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.runAddEntitlementsScript.html +1 -1
  262. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeCapacitorConfig.html +1 -1
  263. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeCfgFile.html +1 -1
  264. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeDataExtractionRules.html +1 -1
  265. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeEntitlementsPlist.html +1 -1
  266. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeNetworkSecurityConfig.html +1 -1
  267. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writePodfile.html +1 -1
  268. package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writePrivacyInfo.html +1 -1
  269. package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.bundleMobileAppCode.html +1 -1
  270. package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.bundlePackagesAndPlugins.html +1 -1
  271. package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.copyOptionalSource.html +1 -1
  272. package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.copyPluginMobileAppDirs.html +1 -1
  273. package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.copyPublicDirs.html +1 -1
  274. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.add_index.html +1 -1
  275. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.add_unique_constraint.html +1 -1
  276. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.count.html +1 -1
  277. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.deleteWhere.html +1 -1
  278. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.drop_index.html +1 -1
  279. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.drop_reset_schema.html +1 -1
  280. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.drop_unique_constraint.html +1 -1
  281. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.init.html +1 -1
  282. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.insert.html +1 -1
  283. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.insertRows.html +1 -1
  284. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.listScTables.html +1 -1
  285. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.listTables.html +1 -1
  286. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.listUserDefinedTables.html +1 -1
  287. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.query.html +1 -1
  288. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.select.html +1 -1
  289. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.selectMaybeOne.html +1 -1
  290. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.selectOne.html +1 -1
  291. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.setConnectionObject.html +1 -1
  292. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.tableExists.html +1 -1
  293. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.time.html +1 -1
  294. package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.update.html +1 -1
  295. package/docs/functions/_saltcorn_sqlite.sqlite.add_index.html +1 -1
  296. package/docs/functions/_saltcorn_sqlite.sqlite.add_unique_constraint.html +1 -1
  297. package/docs/functions/_saltcorn_sqlite.sqlite.begin.html +1 -1
  298. package/docs/functions/_saltcorn_sqlite.sqlite.changeConnection.html +1 -1
  299. package/docs/functions/_saltcorn_sqlite.sqlite.close.html +1 -1
  300. package/docs/functions/_saltcorn_sqlite.sqlite.commit.html +1 -1
  301. package/docs/functions/_saltcorn_sqlite.sqlite.count.html +1 -1
  302. package/docs/functions/_saltcorn_sqlite.sqlite.deleteWhere.html +1 -1
  303. package/docs/functions/_saltcorn_sqlite.sqlite.dropTable.html +1 -1
  304. package/docs/functions/_saltcorn_sqlite.sqlite.dropTables.html +1 -1
  305. package/docs/functions/_saltcorn_sqlite.sqlite.drop_index.html +1 -1
  306. package/docs/functions/_saltcorn_sqlite.sqlite.drop_reset_schema.html +1 -1
  307. package/docs/functions/_saltcorn_sqlite.sqlite.drop_unique_constraint.html +1 -1
  308. package/docs/functions/_saltcorn_sqlite.sqlite.getVersion.html +1 -1
  309. package/docs/functions/_saltcorn_sqlite.sqlite.get_db_filepath.html +1 -1
  310. package/docs/functions/_saltcorn_sqlite.sqlite.get_sql_logging.html +1 -1
  311. package/docs/functions/_saltcorn_sqlite.sqlite.init.html +1 -1
  312. package/docs/functions/_saltcorn_sqlite.sqlite.insert.html +1 -1
  313. package/docs/functions/_saltcorn_sqlite.sqlite.listScTables.html +1 -1
  314. package/docs/functions/_saltcorn_sqlite.sqlite.listTables.html +1 -1
  315. package/docs/functions/_saltcorn_sqlite.sqlite.listUserDefinedTables.html +1 -1
  316. package/docs/functions/_saltcorn_sqlite.sqlite.query.html +1 -1
  317. package/docs/functions/_saltcorn_sqlite.sqlite.rollback.html +1 -1
  318. package/docs/functions/_saltcorn_sqlite.sqlite.select.html +1 -1
  319. package/docs/functions/_saltcorn_sqlite.sqlite.selectMaybeOne.html +1 -1
  320. package/docs/functions/_saltcorn_sqlite.sqlite.selectOne.html +1 -1
  321. package/docs/functions/_saltcorn_sqlite.sqlite.set_sql_logging.html +1 -1
  322. package/docs/functions/_saltcorn_sqlite.sqlite.sql_log.html +1 -1
  323. package/docs/functions/_saltcorn_sqlite.sqlite.update.html +1 -1
  324. package/docs/functions/_saltcorn_sqlite.sqlite.updateWhere.html +1 -1
  325. package/docs/functions/_saltcorn_types.base_types.instanceOWithHtmlFile.html +1 -1
  326. package/docs/functions/_saltcorn_types.base_types.instanceOfFieldViewEdit.html +1 -1
  327. package/docs/functions/_saltcorn_types.base_types.instanceOfFieldViewShow.html +1 -1
  328. package/docs/functions/_saltcorn_types.base_types.instanceOfPack.html +1 -1
  329. package/docs/functions/_saltcorn_types.common_types.instanceOfErrorMsg.html +1 -1
  330. package/docs/functions/_saltcorn_types.common_types.instanceOfSuccessMsg.html +1 -1
  331. package/docs/functions/_saltcorn_types.common_types.instanceOfType.html +1 -1
  332. package/docs/functions/_saltcorn_types.model-abstracts_abstract_field.instanceOfField.html +1 -1
  333. package/docs/functions/_saltcorn_types.model-abstracts_abstract_page.instanceOfPage.html +1 -1
  334. package/docs/functions/_saltcorn_types.model-abstracts_abstract_plugin.instanceOfPlugin.html +1 -1
  335. package/docs/functions/_saltcorn_types.model-abstracts_abstract_table.instanceOfTable.html +1 -1
  336. package/docs/functions/_saltcorn_types.model-abstracts_abstract_view.instanceOfView.html +1 -1
  337. package/docs/hierarchy.html +1 -1
  338. package/docs/interfaces/_saltcorn_db-common.dbtypes.UserLike.html +2 -2
  339. package/docs/interfaces/_saltcorn_markup.types.TagExports.html +2 -2
  340. package/docs/interfaces/_saltcorn_mobile-builder.utils_common-build-utils.ScCapacitorConfig.html +2 -2
  341. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_field.AbstractField.html +2 -2
  342. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_field.AbstractFieldRepeat.html +2 -2
  343. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_form.AbstractForm.html +2 -2
  344. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_page.AbstractPage.html +2 -2
  345. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_page_group.AbstractPageGroup.html +2 -2
  346. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_page_group_member.AbstractPageGroupMember.html +2 -2
  347. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_plugin.AbstractPlugin.html +2 -2
  348. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_role.AbstractRole.html +2 -2
  349. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_table.AbstractTable.html +2 -2
  350. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_tag.AbstractTag.html +2 -2
  351. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_tag_entry.AbstractTagEntry.html +2 -2
  352. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_trigger.AbstractTrigger.html +2 -2
  353. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_user.AbstractUser.html +2 -2
  354. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_user.ForUserRequest.html +2 -2
  355. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_view.AbstractView.html +2 -2
  356. package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_workflow.AbstractWorkflow.html +2 -2
  357. package/docs/modules/_saltcorn_data.html +1 -1
  358. package/docs/modules/_saltcorn_data.migrations_202604091531.html +1 -0
  359. package/docs/modules/_saltcorn_data.migrations_202604111200.html +1 -0
  360. package/docs/modules/_saltcorn_data.migrations_202604141200.html +1 -0
  361. package/docs/modules/_saltcorn_data.mobile-mocks_node_fs.html +1 -1
  362. package/docs/modules/_saltcorn_data.mobile-mocks_node_fs_promises.html +1 -1
  363. package/docs/modules/_saltcorn_data.mobile-mocks_npm_npm-registry-fetch.html +1 -0
  364. package/docs/modules/_saltcorn_data.mobile-mocks_saltcorn_admin-models-tenant.html +1 -0
  365. package/docs/modules/_saltcorn_data.mobile-mocks_saltcorn_plugins-loader-plugin-installer.html +1 -0
  366. package/docs/modules/_saltcorn_data.mobile-mocks_saltcorn_plugins-loader-stable-versioning.html +1 -0
  367. package/docs/modules/_saltcorn_data.models_index.discovery.html +1 -1
  368. package/docs/types/_saltcorn_data.diagram_node_extract_utils.ExtractOpts.html +2 -2
  369. package/docs/types/_saltcorn_data.diagram_node_extract_utils.ExtractResult.html +2 -2
  370. package/docs/types/_saltcorn_data.diagram_nodes_node.NodeType.html +1 -1
  371. package/docs/types/_saltcorn_data.models_config.ConfigTypes.html +1 -1
  372. package/docs/types/_saltcorn_data.models_config.SingleConfig.html +1 -1
  373. package/docs/types/_saltcorn_data.models_eventlog.EventLogCfg.html +2 -2
  374. package/docs/types/_saltcorn_data.models_file.FileCfg.html +2 -2
  375. package/docs/types/_saltcorn_data.models_form.AdditionalButton.html +1 -1
  376. package/docs/types/_saltcorn_data.models_form.FormCfg.html +2 -2
  377. package/docs/types/_saltcorn_data.models_internal_push_message_helper.MobileSubscription.html +2 -2
  378. package/docs/types/_saltcorn_data.models_internal_push_message_helper.WebPushSubscription.html +2 -2
  379. package/docs/types/_saltcorn_data.models_internal_s3_helpers.S3HeadResult.html +1 -1
  380. package/docs/types/_saltcorn_data.models_internal_s3_helpers.S3ListResult.html +2 -2
  381. package/docs/types/_saltcorn_data.models_page_group.ScreenInfoParams.html +2 -2
  382. package/docs/types/_saltcorn_data.models_table.ChildRelations.html +2 -2
  383. package/docs/types/_saltcorn_data.models_table.ParentRelations.html +2 -2
  384. package/docs/types/_saltcorn_data.models_table.RelationData.html +2 -2
  385. package/docs/types/_saltcorn_data.models_tag_entry.TagEntryCfg.html +1 -1
  386. package/docs/types/_saltcorn_data.models_view.FindViewsPred.html +1 -1
  387. package/docs/types/_saltcorn_db-common.dbtypes.AggregationOptions.html +2 -2
  388. package/docs/types/_saltcorn_db-common.dbtypes.CoordOpts.html +2 -2
  389. package/docs/types/_saltcorn_db-common.dbtypes.DatabaseClient.html +2 -2
  390. package/docs/types/_saltcorn_db-common.dbtypes.JoinField.html +2 -2
  391. package/docs/types/_saltcorn_db-common.dbtypes.JoinFields.html +1 -1
  392. package/docs/types/_saltcorn_db-common.dbtypes.JoinOptions.html +1 -1
  393. package/docs/types/_saltcorn_db-common.dbtypes.JsonPath.html +1 -1
  394. package/docs/types/_saltcorn_db-common.dbtypes.JsonPathElem.html +1 -1
  395. package/docs/types/_saltcorn_db-common.dbtypes.Operator.html +1 -1
  396. package/docs/types/_saltcorn_db-common.dbtypes.PartialSome.html +1 -1
  397. package/docs/types/_saltcorn_db-common.dbtypes.PrimaryKeyValue.html +1 -1
  398. package/docs/types/_saltcorn_db-common.dbtypes.Row.html +1 -1
  399. package/docs/types/_saltcorn_db-common.dbtypes.SelectOptions.html +2 -2
  400. package/docs/types/_saltcorn_db-common.dbtypes.StrongRow.html +1 -1
  401. package/docs/types/_saltcorn_db-common.dbtypes.SubselectOptions.html +2 -2
  402. package/docs/types/_saltcorn_db-common.dbtypes.Value.html +1 -1
  403. package/docs/types/_saltcorn_db-common.dbtypes.Where.html +2 -2
  404. package/docs/types/_saltcorn_db-common.sqlite-commons.SqlAndValues.html +2 -2
  405. package/docs/types/_saltcorn_db-common.types.DbExportsType.html +2 -2
  406. package/docs/types/_saltcorn_db-common.types.GenObj.html +1 -1
  407. package/docs/types/_saltcorn_markup.emergency_layout.WrapParams.html +2 -2
  408. package/docs/types/_saltcorn_markup.helpers.CheckBoxGroupOpts.html +2 -2
  409. package/docs/types/_saltcorn_markup.helpers.PaginationOpts.html +2 -2
  410. package/docs/types/_saltcorn_markup.helpers.RadioGroupOpts.html +2 -2
  411. package/docs/types/_saltcorn_markup.helpers.SearchBarOpts.html +2 -2
  412. package/docs/types/_saltcorn_markup.layout.RenderOpts-1.html +2 -2
  413. package/docs/types/_saltcorn_markup.layout.RenderOpts.html +2 -2
  414. package/docs/types/_saltcorn_markup.mjml-layout.RenderOpts.html +2 -2
  415. package/docs/types/_saltcorn_markup.table.HeadersParams.html +2 -2
  416. package/docs/types/_saltcorn_markup.table.OptsParams.html +2 -2
  417. package/docs/types/_saltcorn_markup.types.AttributeVal.html +1 -1
  418. package/docs/types/_saltcorn_markup.types.Attributes.html +2 -2
  419. package/docs/types/_saltcorn_markup.types.ClassVal.html +1 -1
  420. package/docs/types/_saltcorn_markup.types.Element.html +1 -1
  421. package/docs/types/_saltcorn_markup.types.Falsy.html +1 -1
  422. package/docs/types/_saltcorn_markup.types.StyleVal.html +1 -1
  423. package/docs/types/_saltcorn_markup.types.TagFunction.html +1 -1
  424. package/docs/types/_saltcorn_mobile-builder.mobile-builder.IosCfg.html +2 -2
  425. package/docs/types/_saltcorn_mobile-builder.utils_capacitor-helper.CapacitorCfg.html +2 -2
  426. package/docs/types/_saltcorn_types.base_types.Action.html +5 -4
  427. package/docs/types/_saltcorn_types.base_types.AuthenticationMethod.html +2 -2
  428. package/docs/types/_saltcorn_types.base_types.CalcJoinfield.html +2 -2
  429. package/docs/types/_saltcorn_types.base_types.CapacitorPlugin.html +2 -2
  430. package/docs/types/_saltcorn_types.base_types.CodePagePack.html +2 -2
  431. package/docs/types/_saltcorn_types.base_types.Column.html +2 -2
  432. package/docs/types/_saltcorn_types.base_types.ConnectObjType.html +2 -2
  433. package/docs/types/_saltcorn_types.base_types.ConnectedObjects.html +2 -2
  434. package/docs/types/_saltcorn_types.base_types.CopilotSkill.html +2 -2
  435. package/docs/types/_saltcorn_types.base_types.ErrorObj.html +2 -2
  436. package/docs/types/_saltcorn_types.base_types.FieldLike.html +1 -1
  437. package/docs/types/_saltcorn_types.base_types.FieldView.html +1 -1
  438. package/docs/types/_saltcorn_types.base_types.Header.html +2 -2
  439. package/docs/types/_saltcorn_types.base_types.JoinFieldOption.html +2 -2
  440. package/docs/types/_saltcorn_types.base_types.Layout.html +1 -1
  441. package/docs/types/_saltcorn_types.base_types.MenuItem.html +2 -2
  442. package/docs/types/_saltcorn_types.base_types.MobileConfig.html +2 -3
  443. package/docs/types/_saltcorn_types.base_types.ModelPattern.html +6 -6
  444. package/docs/types/_saltcorn_types.base_types.Pack.html +2 -2
  445. package/docs/types/_saltcorn_types.base_types.Plugin.html +1 -1
  446. package/docs/types/_saltcorn_types.base_types.PluginFunction.html +3 -2
  447. package/docs/types/_saltcorn_types.base_types.PluginLayout.html +2 -2
  448. package/docs/types/_saltcorn_types.base_types.PluginRoute.html +2 -2
  449. package/docs/types/_saltcorn_types.base_types.PluginSourceType.html +1 -1
  450. package/docs/types/_saltcorn_types.base_types.PluginType.html +2 -2
  451. package/docs/types/_saltcorn_types.base_types.PluginWrap.html +1 -1
  452. package/docs/types/_saltcorn_types.base_types.PluginWrapArg.html +2 -2
  453. package/docs/types/_saltcorn_types.base_types.RelationOption.html +2 -2
  454. package/docs/types/_saltcorn_types.base_types.Req.html +2 -2
  455. package/docs/types/_saltcorn_types.base_types.Res.html +2 -2
  456. package/docs/types/_saltcorn_types.base_types.ResultType.html +2 -2
  457. package/docs/types/_saltcorn_types.base_types.RouteAction.html +1 -1
  458. package/docs/types/_saltcorn_types.base_types.RunExtra.html +1 -1
  459. package/docs/types/_saltcorn_types.base_types.SlugStepType.html +2 -2
  460. package/docs/types/_saltcorn_types.base_types.StepResType.html +1 -1
  461. package/docs/types/_saltcorn_types.base_types.SubField.html +2 -2
  462. package/docs/types/_saltcorn_types.base_types.TableProvider.html +2 -2
  463. package/docs/types/_saltcorn_types.base_types.TableQuery.html +2 -2
  464. package/docs/types/_saltcorn_types.base_types.Tablely.html +1 -1
  465. package/docs/types/_saltcorn_types.base_types.ViewTemplate.html +3 -2
  466. package/docs/types/_saltcorn_types.common_types.ErrorMessage.html +2 -2
  467. package/docs/types/_saltcorn_types.common_types.GenObj.html +1 -1
  468. package/docs/types/_saltcorn_types.common_types.ReqRes.html +2 -2
  469. package/docs/types/_saltcorn_types.common_types.ResultMessage.html +1 -1
  470. package/docs/types/_saltcorn_types.common_types.SuccessMessage.html +2 -2
  471. package/docs/types/_saltcorn_types.common_types.Type.html +2 -2
  472. package/docs/types/_saltcorn_types.model-abstracts_abstract_event_log.EventLogPack.html +2 -2
  473. package/docs/types/_saltcorn_types.model-abstracts_abstract_field.FieldCfg.html +2 -2
  474. package/docs/types/_saltcorn_types.model-abstracts_abstract_field.InputType.html +1 -1
  475. package/docs/types/_saltcorn_types.model-abstracts_abstract_form.AdditionalButton.html +2 -2
  476. package/docs/types/_saltcorn_types.model-abstracts_abstract_library.LibraryCfg.html +2 -2
  477. package/docs/types/_saltcorn_types.model-abstracts_abstract_library.LibraryPack.html +1 -1
  478. package/docs/types/_saltcorn_types.model-abstracts_abstract_model.ModelCfg.html +2 -2
  479. package/docs/types/_saltcorn_types.model-abstracts_abstract_model.ModelPack.html +1 -1
  480. package/docs/types/_saltcorn_types.model-abstracts_abstract_model_instance.ModelInstanceCfg.html +2 -2
  481. package/docs/types/_saltcorn_types.model-abstracts_abstract_model_instance.ModelInstancePack.html +1 -1
  482. package/docs/types/_saltcorn_types.model-abstracts_abstract_page.PageCfg.html +3 -2
  483. package/docs/types/_saltcorn_types.model-abstracts_abstract_page.PagePack.html +1 -1
  484. package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group.PageGroupCfg.html +2 -2
  485. package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group.PageGroupPack.html +1 -1
  486. package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group_member.PageGroupMemberCfg.html +2 -2
  487. package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group_member.PageGroupMemberPack.html +1 -1
  488. package/docs/types/_saltcorn_types.model-abstracts_abstract_plugin.PluginCfg.html +3 -2
  489. package/docs/types/_saltcorn_types.model-abstracts_abstract_plugin.PluginPack.html +1 -1
  490. package/docs/types/_saltcorn_types.model-abstracts_abstract_role.RoleCfg.html +1 -1
  491. package/docs/types/_saltcorn_types.model-abstracts_abstract_role.RolePack.html +1 -1
  492. package/docs/types/_saltcorn_types.model-abstracts_abstract_table.TableCfg.html +3 -2
  493. package/docs/types/_saltcorn_types.model-abstracts_abstract_table.TablePack.html +1 -1
  494. package/docs/types/_saltcorn_types.model-abstracts_abstract_tag.TagPack.html +2 -2
  495. package/docs/types/_saltcorn_types.model-abstracts_abstract_tag_entry.TagEntryPack.html +2 -2
  496. package/docs/types/_saltcorn_types.model-abstracts_abstract_trigger.TriggerCfg.html +3 -2
  497. package/docs/types/_saltcorn_types.model-abstracts_abstract_trigger.TriggerPack.html +1 -1
  498. package/docs/types/_saltcorn_types.model-abstracts_abstract_view.ViewCfg.html +3 -2
  499. package/docs/types/_saltcorn_types.model-abstracts_abstract_view.ViewPack.html +1 -1
  500. package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow.ConfigWorkflowStep.html +1 -1
  501. package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow.RunResult.html +2 -2
  502. package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_run.WorkflowRunCfg.html +2 -2
  503. package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_step.WorkflowStepCfg.html +2 -2
  504. package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_step.WorkflowStepPack.html +1 -1
  505. package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_trace.WorkflowTraceCfg.html +2 -2
  506. package/docs/variables/_saltcorn_admin-models..backup.create_backup.html +1 -1
  507. package/docs/variables/_saltcorn_admin-models..backup.create_csv_from_rows.html +1 -1
  508. package/docs/variables/_saltcorn_admin-models..backup.restore.html +1 -1
  509. package/docs/variables/_saltcorn_admin-models..pack.add_to_menu.html +1 -1
  510. package/docs/variables/_saltcorn_admin-models..pack.can_install_pack.html +1 -1
  511. package/docs/variables/_saltcorn_admin-models..pack.fetch_available_packs.html +1 -1
  512. package/docs/variables/_saltcorn_admin-models..pack.fetch_pack_by_name.html +1 -1
  513. package/docs/variables/_saltcorn_admin-models..pack.install_pack.html +1 -1
  514. package/docs/variables/_saltcorn_admin-models..pack.library_pack.html +1 -1
  515. package/docs/variables/_saltcorn_admin-models..pack.model_instance_pack.html +1 -1
  516. package/docs/variables/_saltcorn_admin-models..pack.model_pack.html +1 -1
  517. package/docs/variables/_saltcorn_admin-models..pack.page_group_pack.html +1 -1
  518. package/docs/variables/_saltcorn_admin-models..pack.page_pack.html +1 -1
  519. package/docs/variables/_saltcorn_admin-models..pack.plugin_pack.html +1 -1
  520. package/docs/variables/_saltcorn_admin-models..pack.role_pack.html +1 -1
  521. package/docs/variables/_saltcorn_admin-models..pack.table_pack.html +1 -1
  522. package/docs/variables/_saltcorn_admin-models..pack.trigger_pack.html +1 -1
  523. package/docs/variables/_saltcorn_admin-models..pack.uninstall_pack.html +1 -1
  524. package/docs/variables/_saltcorn_admin-models..pack.view_pack.html +1 -1
  525. package/docs/variables/_saltcorn_admin-models..tenant.copy_tenant_template.html +1 -1
  526. package/docs/variables/_saltcorn_admin-models..tenant.create_tenant.html +1 -1
  527. package/docs/variables/_saltcorn_admin-models..tenant.deleteTenant.html +1 -1
  528. package/docs/variables/_saltcorn_admin-models..tenant.domain_sanitize.html +1 -1
  529. package/docs/variables/_saltcorn_admin-models..tenant.eachTenant.html +1 -1
  530. package/docs/variables/_saltcorn_admin-models..tenant.getAllTenantRows.html +1 -1
  531. package/docs/variables/_saltcorn_admin-models..tenant.getAllTenants.html +1 -1
  532. package/docs/variables/_saltcorn_admin-models..tenant.insertTenant.html +1 -1
  533. package/docs/variables/_saltcorn_admin-models..tenant.switchToTenant.html +1 -1
  534. package/docs/variables/_saltcorn_admin-models.models_backup.backup.html +1 -1
  535. package/docs/variables/_saltcorn_admin-models.pack.pack.html +3 -3
  536. package/docs/variables/_saltcorn_admin-models.tenant.tenant.html +1 -1
  537. package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedFive.html +1 -1
  538. package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedFour.html +1 -1
  539. package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedOne.html +1 -1
  540. package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedSix.html +1 -1
  541. package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedThree.html +1 -1
  542. package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedTwo.html +1 -1
  543. package/docs/variables/_saltcorn_data..migrations.html +1 -1
  544. package/docs/variables/_saltcorn_data..plugin_helper.run_action_column.html +1 -1
  545. package/docs/variables/_saltcorn_data..utils.NotAuthorized.html +1 -1
  546. package/docs/variables/_saltcorn_data..utils.isPushEnabled.html +1 -1
  547. package/docs/variables/_saltcorn_data..utils.sleep.html +1 -1
  548. package/docs/variables/_saltcorn_data.base-plugin_actions.actions.html +13 -13
  549. package/docs/variables/_saltcorn_data.base-plugin_fieldviews.fieldviews.html +3 -3
  550. package/docs/variables/_saltcorn_data.base-plugin_fileview.fileviews.html +1 -1
  551. package/docs/variables/_saltcorn_data.base-plugin_index.index.html +15 -15
  552. package/docs/variables/_saltcorn_data.base-plugin_types.types.html +7 -7
  553. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_edit.edit.html +1 -1
  554. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_feed.feed.html +1 -1
  555. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_filter.filter.html +1 -1
  556. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_list.list.html +1 -1
  557. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_listshowlist.listshowlist.html +1 -1
  558. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_room.room-1.html +1 -1
  559. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_room.room.html +1 -1
  560. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_show.show.html +1 -1
  561. package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.edit_build_in_actions.html +1 -1
  562. package/docs/variables/_saltcorn_data.contract.contract.html +1 -1
  563. package/docs/variables/_saltcorn_data.db_connect.connect.html +1 -1
  564. package/docs/variables/_saltcorn_data.db_fa5-icons.fa5Icons.html +1 -1
  565. package/docs/variables/_saltcorn_data.db_fixtures.fixtures.html +1 -1
  566. package/docs/variables/_saltcorn_data.db_index.dbExports.html +1 -1
  567. package/docs/variables/_saltcorn_data.db_state.state.html +3 -3
  568. package/docs/variables/_saltcorn_data.migrations_202005141503.sql.html +1 -1
  569. package/docs/variables/_saltcorn_data.migrations_202005241712.sql.html +1 -1
  570. package/docs/variables/_saltcorn_data.migrations_202005251037.sql.html +1 -1
  571. package/docs/variables/_saltcorn_data.migrations_202005282134.sql.html +1 -1
  572. package/docs/variables/_saltcorn_data.migrations_202006022156.sql.html +1 -1
  573. package/docs/variables/_saltcorn_data.migrations_202006051507.sql.html +1 -1
  574. package/docs/variables/_saltcorn_data.migrations_202006240906.sql.html +1 -1
  575. package/docs/variables/_saltcorn_data.migrations_202007091707.sql.html +1 -1
  576. package/docs/variables/_saltcorn_data.migrations_202007202144.sql.html +1 -1
  577. package/docs/variables/_saltcorn_data.migrations_202008031500.sql.html +1 -1
  578. package/docs/variables/_saltcorn_data.migrations_202008051415.sql.html +1 -1
  579. package/docs/variables/_saltcorn_data.migrations_202008121149.sql_pg.html +1 -1
  580. package/docs/variables/_saltcorn_data.migrations_202008121149.sql_sqlite.html +1 -1
  581. package/docs/variables/_saltcorn_data.migrations_202009112140.sql_pg.html +1 -1
  582. package/docs/variables/_saltcorn_data.migrations_202009112140.sql_sqlite.html +1 -1
  583. package/docs/variables/_saltcorn_data.migrations_202009181655.sql.html +1 -1
  584. package/docs/variables/_saltcorn_data.migrations_202009221105.sql.html +1 -1
  585. package/docs/variables/_saltcorn_data.migrations_202009231331.sql.html +1 -1
  586. package/docs/variables/_saltcorn_data.migrations_202009301531.sql.html +1 -1
  587. package/docs/variables/_saltcorn_data.migrations_202010231444.sql.html +1 -1
  588. package/docs/variables/_saltcorn_data.migrations_202010251412.sql.html +1 -1
  589. package/docs/variables/_saltcorn_data.migrations_202011021749.sql.html +1 -1
  590. package/docs/variables/_saltcorn_data.migrations_202011051353.sql.html +1 -1
  591. package/docs/variables/_saltcorn_data.migrations_202011111127.sql.html +1 -1
  592. package/docs/variables/_saltcorn_data.migrations_202012011203.sql.html +1 -1
  593. package/docs/variables/_saltcorn_data.migrations_202012100841.sql.html +1 -1
  594. package/docs/variables/_saltcorn_data.migrations_202012281835.sql.html +1 -1
  595. package/docs/variables/_saltcorn_data.migrations_202101061051.sql.html +1 -1
  596. package/docs/variables/_saltcorn_data.migrations_202101141128.sql.html +1 -1
  597. package/docs/variables/_saltcorn_data.migrations_202102091312.sql.html +1 -1
  598. package/docs/variables/_saltcorn_data.migrations_202102101624.sql.html +1 -1
  599. package/docs/variables/_saltcorn_data.migrations_202102172148.sql.html +1 -1
  600. package/docs/variables/_saltcorn_data.migrations_202102261650.sql.html +1 -1
  601. package/docs/variables/_saltcorn_data.migrations_202106102347.sql.html +1 -1
  602. package/docs/variables/_saltcorn_data.migrations_202106112120.sql.html +1 -1
  603. package/docs/variables/_saltcorn_data.migrations_202106120012.sql.html +1 -1
  604. package/docs/variables/_saltcorn_data.migrations_202106120220.sql.html +1 -1
  605. package/docs/variables/_saltcorn_data.migrations_202106121701.sql.html +1 -1
  606. package/docs/variables/_saltcorn_data.migrations_202106121703.sql_pg.html +1 -1
  607. package/docs/variables/_saltcorn_data.migrations_202106121703.sql_sqlite.html +1 -1
  608. package/docs/variables/_saltcorn_data.migrations_202106251126.sql.html +1 -1
  609. package/docs/variables/_saltcorn_data.migrations_202107281619.sql.html +1 -1
  610. package/docs/variables/_saltcorn_data.migrations_202107302158.sql_pg.html +1 -1
  611. package/docs/variables/_saltcorn_data.migrations_202107302158.sql_sqlite.html +1 -1
  612. package/docs/variables/_saltcorn_data.migrations_202108022257.sql.html +1 -1
  613. package/docs/variables/_saltcorn_data.migrations_202109201624.sql.html +1 -1
  614. package/docs/variables/_saltcorn_data.migrations_202109301031.sql_pg.html +1 -1
  615. package/docs/variables/_saltcorn_data.migrations_202109301031.sql_sqlite.html +1 -1
  616. package/docs/variables/_saltcorn_data.migrations_202111290253.sql_pg.html +1 -1
  617. package/docs/variables/_saltcorn_data.migrations_202111290253.sql_sqlite.html +1 -1
  618. package/docs/variables/_saltcorn_data.migrations_202112282254.sql_pg.html +1 -1
  619. package/docs/variables/_saltcorn_data.migrations_202112282254.sql_sqlite.html +1 -1
  620. package/docs/variables/_saltcorn_data.migrations_202207022002.sql.html +1 -1
  621. package/docs/variables/_saltcorn_data.migrations_202207252150.sql_pg.html +1 -1
  622. package/docs/variables/_saltcorn_data.migrations_202207252150.sql_sqlite.html +1 -1
  623. package/docs/variables/_saltcorn_data.migrations_202207261221.sql.html +1 -1
  624. package/docs/variables/_saltcorn_data.migrations_202208101144.sql_pg.html +1 -1
  625. package/docs/variables/_saltcorn_data.migrations_202208101144.sql_sqlite.html +1 -1
  626. package/docs/variables/_saltcorn_data.migrations_202211040031.sql.html +1 -1
  627. package/docs/variables/_saltcorn_data.migrations_202212112152.sql_pg.html +1 -1
  628. package/docs/variables/_saltcorn_data.migrations_202212112152.sql_sqlite.html +1 -1
  629. package/docs/variables/_saltcorn_data.migrations_202301130917.sql.html +1 -1
  630. package/docs/variables/_saltcorn_data.migrations_202303201126.sql_pg.html +1 -1
  631. package/docs/variables/_saltcorn_data.migrations_202303201126.sql_sqlite.html +1 -1
  632. package/docs/variables/_saltcorn_data.migrations_202303221944.sql_pg.html +1 -1
  633. package/docs/variables/_saltcorn_data.migrations_202303221944.sql_sqlite.html +1 -1
  634. package/docs/variables/_saltcorn_data.migrations_202304281224.sql.html +1 -1
  635. package/docs/variables/_saltcorn_data.migrations_202305031518.sql_pg.html +1 -1
  636. package/docs/variables/_saltcorn_data.migrations_202305031518.sql_sqlite.html +1 -1
  637. package/docs/variables/_saltcorn_data.migrations_202308211648.sql.html +1 -1
  638. package/docs/variables/_saltcorn_data.migrations_202311011755.sql_pg.html +1 -1
  639. package/docs/variables/_saltcorn_data.migrations_202311011755.sql_sqlite.html +1 -1
  640. package/docs/variables/_saltcorn_data.migrations_202311231356.sql.html +1 -1
  641. package/docs/variables/_saltcorn_data.migrations_202402071125.sql.html +1 -1
  642. package/docs/variables/_saltcorn_data.migrations_202406260915.sql.html +1 -1
  643. package/docs/variables/_saltcorn_data.migrations_202412051957.sql_pg.html +1 -1
  644. package/docs/variables/_saltcorn_data.migrations_202412051957.sql_sqlite.html +1 -1
  645. package/docs/variables/_saltcorn_data.migrations_202412111526.sql_pg.html +1 -1
  646. package/docs/variables/_saltcorn_data.migrations_202412111526.sql_sqlite.html +1 -1
  647. package/docs/variables/_saltcorn_data.migrations_202501081226.sql_pg.html +1 -1
  648. package/docs/variables/_saltcorn_data.migrations_202501081226.sql_sqlite.html +1 -1
  649. package/docs/variables/_saltcorn_data.migrations_202501201239.sql_sqlite.html +1 -1
  650. package/docs/variables/_saltcorn_data.migrations_202501262157.sql.html +1 -1
  651. package/docs/variables/_saltcorn_data.migrations_202503071353.sql_pg.html +1 -1
  652. package/docs/variables/_saltcorn_data.migrations_202506050958.sql.html +1 -1
  653. package/docs/variables/_saltcorn_data.migrations_202510110312.sql_pg.html +1 -1
  654. package/docs/variables/_saltcorn_data.migrations_202510110312.sql_sqlite.html +1 -1
  655. package/docs/variables/_saltcorn_data.migrations_202511081024.sql.html +1 -1
  656. package/docs/variables/_saltcorn_data.migrations_202604091531.sql.html +1 -0
  657. package/docs/variables/_saltcorn_data.mobile-mocks_npm_npm-registry-fetch.npmRegistryFetch.html +1 -0
  658. package/docs/variables/_saltcorn_data.mobile-mocks_saltcorn_html-pdf-node.htmlPdfNode.html +1 -1
  659. package/docs/variables/_saltcorn_data.models_config.configExports.html +1 -1
  660. package/docs/variables/_saltcorn_data.models_discovery.discovery.html +6 -2
  661. package/docs/variables/_saltcorn_data.models_email.email.html +3 -3
  662. package/docs/variables/_saltcorn_data.models_expression.expression.html +3 -3
  663. package/docs/variables/_saltcorn_data.models_index.config.available_languages.html +1 -1
  664. package/docs/variables/_saltcorn_data.models_index.config.check_email_mask.html +1 -1
  665. package/docs/variables/_saltcorn_data.models_index.config.configTypes.html +1 -1
  666. package/docs/variables/_saltcorn_data.models_index.config.deleteConfig.html +1 -1
  667. package/docs/variables/_saltcorn_data.models_index.config.getAllConfig.html +1 -1
  668. package/docs/variables/_saltcorn_data.models_index.config.getConfig.html +1 -1
  669. package/docs/variables/_saltcorn_data.models_index.config.get_base_url.html +1 -1
  670. package/docs/variables/_saltcorn_data.models_index.config.get_latest_npm_version.html +1 -1
  671. package/docs/variables/_saltcorn_data.models_index.config.remove_from_menu.html +1 -1
  672. package/docs/variables/_saltcorn_data.models_index.config.save_menu_items.html +1 -1
  673. package/docs/variables/_saltcorn_data.models_index.config.setConfig.html +1 -1
  674. package/docs/variables/_saltcorn_data.models_index.discovery.discover_tables.html +1 -1
  675. package/docs/variables/_saltcorn_data.models_index.discovery.discoverable_tables.html +1 -1
  676. package/docs/variables/_saltcorn_data.models_index.discovery.findType.html +1 -1
  677. package/docs/variables/_saltcorn_data.models_index.discovery.get_existing_views.html +1 -1
  678. package/docs/variables/_saltcorn_data.models_index.discovery.implement_discovery.html +1 -1
  679. package/docs/variables/_saltcorn_data.models_index.discovery.make_field.html +1 -0
  680. package/docs/variables/_saltcorn_data.models_index.discovery.reconcile_table.html +7 -0
  681. package/docs/variables/_saltcorn_data.models_index.email.getMailTransport.html +1 -1
  682. package/docs/variables/_saltcorn_data.models_index.email.send_verification_email.html +1 -1
  683. package/docs/variables/_saltcorn_data.models_index.email.viewToEmailHtml.html +1 -1
  684. package/docs/variables/_saltcorn_data.models_index.expression.apply_calculated_fields.html +1 -1
  685. package/docs/variables/_saltcorn_data.models_index.expression.apply_calculated_fields_stored.html +1 -1
  686. package/docs/variables/_saltcorn_data.models_index.expression.eval_expression.html +9 -1
  687. package/docs/variables/_saltcorn_data.models_index.expression.expressionValidator.html +1 -1
  688. package/docs/variables/_saltcorn_data.models_index.expression.get_async_expression_function.html +1 -1
  689. package/docs/variables/_saltcorn_data.models_index.expression.get_expression_function.html +1 -1
  690. package/docs/variables/_saltcorn_data.models_index.expression.jsexprToWhere.html +1 -1
  691. package/docs/variables/_saltcorn_data.models_index.expression.recalculate_for_stored.html +1 -1
  692. package/docs/variables/_saltcorn_data.models_index.expression.transform_for_async.html +1 -1
  693. package/docs/variables/_saltcorn_data.models_index.layout.eachView.html +1 -1
  694. package/docs/variables/_saltcorn_data.models_index.layout.getStringsForI18n.html +1 -1
  695. package/docs/variables/_saltcorn_data.models_index.layout.getViews.html +1 -1
  696. package/docs/variables/_saltcorn_data.models_index.layout.translateLayout.html +1 -1
  697. package/docs/variables/_saltcorn_data.models_index.layout.traverse.html +1 -1
  698. package/docs/variables/_saltcorn_data.models_index.layout.traverseSync.html +1 -1
  699. package/docs/variables/_saltcorn_data.models_index.random.all_views.html +1 -1
  700. package/docs/variables/_saltcorn_data.models_index.random.fill_table_row.html +1 -1
  701. package/docs/variables/_saltcorn_data.models_index.random.initial_view.html +1 -1
  702. package/docs/variables/_saltcorn_data.models_index.random.random_table.html +1 -1
  703. package/docs/variables/_saltcorn_data.models_index.scheduler.runScheduler.html +1 -1
  704. package/docs/variables/_saltcorn_data.models_layout.layout.html +1 -1
  705. package/docs/variables/_saltcorn_data.models_random.random.html +1 -1
  706. package/docs/variables/_saltcorn_data.models_scheduler.scheduler.html +1 -1
  707. package/docs/variables/_saltcorn_data.plugin-helper.add_free_variables_to_joinfields.html +1 -1
  708. package/docs/variables/_saltcorn_data.tests_mocks.mocks.html +1 -1
  709. package/docs/variables/_saltcorn_data.tests_remote_query_helper.renderEditInEditConfig.html +1 -1
  710. package/docs/variables/_saltcorn_data.utils.utils.html +11 -5
  711. package/docs/variables/_saltcorn_data.web-mobile-commons.webMobileCommons.html +1 -1
  712. package/docs/variables/_saltcorn_db-common.internal.dbCommonModulePath.html +1 -1
  713. package/docs/variables/_saltcorn_db-common.multi-tenant.tenantNamespace.html +1 -1
  714. package/docs/variables/_saltcorn_db-common.tenants.tenants.html +1 -1
  715. package/docs/variables/_saltcorn_markup..export_.html +1 -1
  716. package/docs/variables/_saltcorn_markup.builder.builder.html +1 -1
  717. package/docs/variables/_saltcorn_markup.emergency_layout.EmergencyLayoutExports.html +1 -1
  718. package/docs/variables/_saltcorn_markup.form.form.html +1 -1
  719. package/docs/variables/_saltcorn_markup.helpers.HelpersExports.html +1 -1
  720. package/docs/variables/_saltcorn_markup.layout.LayoutExports-1.html +1 -1
  721. package/docs/variables/_saltcorn_markup.layout.LayoutExports.html +1 -1
  722. package/docs/variables/_saltcorn_markup.layout_utils.layoutUtils.html +1 -1
  723. package/docs/variables/_saltcorn_markup.mjml-layout.LayoutExports.html +1 -1
  724. package/docs/variables/_saltcorn_markup.mjml-tags.tagsExports.html +1 -1
  725. package/docs/variables/_saltcorn_markup.table.TableExports.html +1 -1
  726. package/docs/variables/_saltcorn_markup.tags.tagsExports.html +1 -1
  727. package/docs/variables/_saltcorn_types..generators.generateBool.html +1 -1
  728. package/docs/variables/_saltcorn_types..generators.generateString.html +1 -1
  729. package/docs/variables/_saltcorn_types..generators.num_between.html +1 -1
  730. package/docs/variables/_saltcorn_types..generators.oneOf.html +1 -1
  731. package/docs/variables/_saltcorn_types.generators.generators.html +1 -1
  732. package/errors.js +4 -4
  733. package/help/Event channel and payload.tmd +5 -0
  734. package/help/Extra state formula.tmd +1 -1
  735. package/help/Group by formula.tmd +15 -0
  736. package/help/JavaScript action code.tmd +5 -1
  737. package/load_plugins.js +7 -398
  738. package/locales/ar.json +262 -1
  739. package/locales/de.json +264 -3
  740. package/locales/en.json +38 -9
  741. package/locales/es.json +265 -4
  742. package/locales/fr.json +263 -2
  743. package/locales/ur.json +273 -4
  744. package/markup/admin.js +14 -9
  745. package/markup/expression_blurb.js +1 -1
  746. package/package.json +14 -14
  747. package/public/monaco/loader.js +0 -2
  748. package/public/popper.min.js +0 -1
  749. package/public/saltcorn-builder.css +82 -0
  750. package/public/saltcorn-common.js +36 -2
  751. package/public/saltcorn.css +138 -0
  752. package/public/saltcorn.js +1458 -29
  753. package/public/socket.io.min.js +0 -1
  754. package/public/tabulator.min.js +2 -3
  755. package/public/tabulator_bootstrap4.min.css +1 -2
  756. package/public/tabulator_bootstrap5.min.css +1 -2
  757. package/routes/actions.js +275 -22
  758. package/routes/admin.js +148 -40
  759. package/routes/api.js +96 -60
  760. package/routes/delete.js +2 -5
  761. package/routes/edit.js +2 -5
  762. package/routes/entities.js +65 -1245
  763. package/routes/eventlog.js +47 -0
  764. package/routes/fields.js +125 -14
  765. package/routes/files.js +36 -4
  766. package/routes/homepage.js +4 -1
  767. package/routes/list.js +69 -11
  768. package/routes/packs.js +2 -3
  769. package/routes/page.js +18 -1
  770. package/routes/pageedit.js +1 -0
  771. package/routes/plugins.js +56 -21
  772. package/routes/scapi.js +1 -2
  773. package/routes/sync.js +183 -54
  774. package/routes/tables.js +492 -2
  775. package/routes/tenant.js +3 -3
  776. package/routes/utils.js +17 -6
  777. package/routes/viewedit.js +10 -6
  778. package/serve.js +35 -23
  779. package/tests/admin.test.js +5 -5
  780. package/tests/api.test.js +424 -2
  781. package/tests/auth.test.js +230 -1
  782. package/tests/fields.test.js +16 -0
  783. package/tests/files.test.js +43 -7
  784. package/tests/page.test.js +53 -0
  785. package/tests/plugin_install.test.js +132 -13
  786. package/tests/plugins.test.js +1 -2
  787. package/tests/sync.test.js +900 -18
  788. package/tests/view.test.js +32 -0
  789. package/wrapper.js +3 -1
@@ -8,8 +8,8 @@ const {
8
8
  toRedirect,
9
9
  toInclude,
10
10
  toSucceed,
11
+ resToLoginCookie,
11
12
  } = require("../auth/testhelp");
12
- const load_plugins = require("../load_plugins");
13
13
  const db = require("@saltcorn/data/db");
14
14
  const { sleep } = require("@saltcorn/data/tests/mocks");
15
15
 
@@ -38,7 +38,7 @@ const initSyncInfo = async (tbls) => {
38
38
  };
39
39
 
40
40
  const createAnswersTbl = async () => {
41
- await load_plugins.loadAndSaveNewPlugin(
41
+ await Plugin.loadAndSaveNewPlugin(
42
42
  new Plugin({
43
43
  name: "json",
44
44
  source: "npm",
@@ -101,7 +101,7 @@ describe("load remote insert/updates", () => {
101
101
  loadUntil: loadUntil.valueOf(),
102
102
  syncInfos: {
103
103
  books: {
104
- maxLoadedId: 0,
104
+ lastModifiedAt: 0,
105
105
  },
106
106
  },
107
107
  });
@@ -111,15 +111,16 @@ describe("load remote insert/updates", () => {
111
111
  for (const row of data.books.rows) {
112
112
  const fromDb = await books.getRows({ id: row._sync_info_tbl_ref_ });
113
113
  expect(fromDb.length).toBe(1);
114
- expect(row._sync_info_tbl_last_modified_).toBe(loadUntil.valueOf());
115
- expect(row._sync_info_tbl_deleted_).toBe(null);
114
+ expect(typeof row._sync_info_tbl_last_modified_).toBe("number");
115
+ expect(row._sync_info_tbl_deleted_).toBe(false);
116
116
  }
117
117
  });
118
118
 
119
- it("with syncFrom, without sync_infos", async () => {
119
+ it("with syncFrom, no changes in window", async () => {
120
120
  const app = await getApp({ disableCsrf: true });
121
121
  const loginCookie = await getAdminLoginCookie();
122
122
  const loadUntil = new Date();
123
+ // syncFrom == loadUntil → empty time window → no rows
123
124
  const resp = await request(app)
124
125
  .post("/sync/load_changes")
125
126
  .set("Cookie", loginCookie)
@@ -127,8 +128,8 @@ describe("load remote insert/updates", () => {
127
128
  loadUntil: loadUntil.valueOf(),
128
129
  syncInfos: {
129
130
  books: {
130
- maxLoadedId: 0,
131
- syncFrom: 1000,
131
+ lastModifiedAt: 0,
132
+ syncFrom: loadUntil.valueOf(),
132
133
  },
133
134
  },
134
135
  });
@@ -154,7 +155,7 @@ describe("load remote insert/updates", () => {
154
155
  loadUntil: (await db.time()).valueOf(),
155
156
  syncInfos: {
156
157
  books: {
157
- maxLoadedId: 0,
158
+ lastModifiedAt: 0,
158
159
  syncFrom: dbTime.valueOf(),
159
160
  },
160
161
  },
@@ -169,7 +170,7 @@ describe("load remote insert/updates", () => {
169
170
  _sync_info_tbl_deleted_,
170
171
  ...rest
171
172
  } = data.books.rows[0];
172
- expect(_sync_info_tbl_ref_).toBe(2);
173
+ expect(Number(_sync_info_tbl_ref_)).toBe(2);
173
174
  expect(_sync_info_tbl_last_modified_).toBe(last_modified.valueOf());
174
175
  expect(_sync_info_tbl_deleted_).toBe(false);
175
176
  expect(rest.author).toBe("Leo Tolstoy");
@@ -183,7 +184,7 @@ describe("load remote insert/updates", () => {
183
184
  loadUntil: (await db.time()).valueOf(),
184
185
  syncInfos: {
185
186
  books: {
186
- maxLoadedId: 0,
187
+ lastModifiedAt: 0,
187
188
  syncFrom: dbTime.valueOf(),
188
189
  },
189
190
  },
@@ -198,13 +199,13 @@ describe("load remote insert/updates", () => {
198
199
  _sync_info_tbl_deleted_,
199
200
  ...rest
200
201
  } = row;
201
- expect(_sync_info_tbl_ref_).toBe(rest.id);
202
+ expect(Number(_sync_info_tbl_ref_)).toBe(rest.id);
202
203
  const { last_modified } = await books.latestSyncInfo(rest.id);
203
204
  expect(_sync_info_tbl_last_modified_).toBe(last_modified.valueOf());
204
205
  expect(_sync_info_tbl_deleted_).toBe(false);
205
206
  }
206
- expect(data.books.rows[0].author).toBe("Herman Melville");
207
- expect(data.books.rows[1].author).toBe("Leo Tolstoy");
207
+ expect(data.books.rows[0].author).toBe("Leo Tolstoy");
208
+ expect(data.books.rows[1].author).toBe("Herman Melville");
208
209
  }
209
210
  });
210
211
 
@@ -246,7 +247,7 @@ describe("load remote insert/updates", () => {
246
247
  loadUntil: (await db.time()).valueOf(),
247
248
  syncInfos: {
248
249
  "Table with capitals": {
249
- maxLoadedId: 0,
250
+ lastModifiedAt: 0,
250
251
  syncFrom: dbTime.valueOf(),
251
252
  },
252
253
  },
@@ -265,7 +266,7 @@ describe("load remote insert/updates", () => {
265
266
  loadUntil: loadUntil.valueOf(),
266
267
  syncInfos: {
267
268
  patients: {
268
- maxLoadedId: 0,
269
+ lastModifiedAt: 0,
269
270
  syncFrom: 1000,
270
271
  },
271
272
  },
@@ -304,7 +305,7 @@ describe("load remote insert/updates", () => {
304
305
  loadUntil: loadUntil.valueOf(),
305
306
  syncInfos: {
306
307
  patients: {
307
- maxLoadedId: 0,
308
+ lastModifiedAt: 0,
308
309
  },
309
310
  },
310
311
  });
@@ -334,7 +335,7 @@ describe("load remote insert/updates", () => {
334
335
  loadUntil: loadUntil.valueOf(),
335
336
  syncInfos: {
336
337
  patients: {
337
- maxLoadedId: 0,
338
+ lastModifiedAt: 0,
338
339
  syncFrom: 1000,
339
340
  },
340
341
  },
@@ -849,6 +850,580 @@ describe("Upload changes", () => {
849
850
  });
850
851
  });
851
852
 
853
+ describe("sync dir access control", () => {
854
+ if (!db.isSQLite) {
855
+ beforeAll(async () => {
856
+ await initSyncInfo(["books"]);
857
+ });
858
+
859
+ it("upload_finished rejects access to another user's sync dir", async () => {
860
+ const app = await getApp({ disableCsrf: true });
861
+ const adminCookie = await getAdminLoginCookie();
862
+ const userCookie = await getUserLoginCookie();
863
+
864
+ const resp = await doUpload(
865
+ app,
866
+ adminCookie,
867
+ new Date().valueOf(),
868
+ new Date().valueOf(),
869
+ { books: { inserts: [] } }
870
+ );
871
+ expect(resp.status).toBe(200);
872
+ const { syncDir } = resp._body;
873
+
874
+ const pollResp = await request(app)
875
+ .get(`/sync/upload_finished?dir_name=${encodeURIComponent(syncDir)}`)
876
+ .set("Cookie", userCookie);
877
+ expect(pollResp.status).toBe(403);
878
+
879
+ await cleanSyncDir(app, adminCookie, syncDir);
880
+ });
881
+
882
+ it("clean_sync_dir rejects deletion of another user's sync dir", async () => {
883
+ const app = await getApp({ disableCsrf: true });
884
+ const adminCookie = await getAdminLoginCookie();
885
+ const userCookie = await getUserLoginCookie();
886
+
887
+ const resp = await doUpload(
888
+ app,
889
+ adminCookie,
890
+ new Date().valueOf(),
891
+ new Date().valueOf(),
892
+ { books: { inserts: [] } }
893
+ );
894
+ expect(resp.status).toBe(200);
895
+ const { syncDir } = resp._body;
896
+
897
+ const deleteResp = await request(app)
898
+ .post("/sync/clean_sync_dir")
899
+ .send({ dir_name: syncDir })
900
+ .set("Cookie", userCookie);
901
+ expect(deleteResp.status).toBe(403);
902
+
903
+ await cleanSyncDir(app, adminCookie, syncDir);
904
+ });
905
+ } else
906
+ it("only pq support", () => {
907
+ expect(true).toBe(true);
908
+ });
909
+ });
910
+
911
+ describe("SQL injection protection", () => {
912
+ if (!db.isSQLite) {
913
+ beforeAll(async () => {
914
+ await initSyncInfo(["books"]);
915
+ });
916
+
917
+ // --- /sync/load_changes : lastModifiedAt ---
918
+
919
+ it("rejects SQL injection in lastModifiedAt (OR 1=1)", async () => {
920
+ const app = await getApp({ disableCsrf: true });
921
+ const loginCookie = await getAdminLoginCookie();
922
+ await request(app)
923
+ .post("/sync/load_changes")
924
+ .set("Cookie", loginCookie)
925
+ .send({
926
+ loadUntil: new Date().valueOf(),
927
+ syncInfos: { books: { lastModifiedAt: "0 OR 1=1--" } },
928
+ })
929
+ .expect(
930
+ respondJsonWith(
931
+ 400,
932
+ (resp) => resp.error === "Invalid lastModifiedAt"
933
+ )
934
+ );
935
+ });
936
+
937
+ it("rejects SQL injection in lastModifiedAt (UNION SELECT)", async () => {
938
+ const app = await getApp({ disableCsrf: true });
939
+ const loginCookie = await getAdminLoginCookie();
940
+ await request(app)
941
+ .post("/sync/load_changes")
942
+ .set("Cookie", loginCookie)
943
+ .send({
944
+ loadUntil: new Date().valueOf(),
945
+ syncInfos: {
946
+ books: { lastModifiedAt: "0 UNION SELECT * FROM users--" },
947
+ },
948
+ })
949
+ .expect(
950
+ respondJsonWith(
951
+ 400,
952
+ (resp) => resp.error === "Invalid lastModifiedAt"
953
+ )
954
+ );
955
+ });
956
+
957
+ it("rejects SQL injection in lastModifiedAt (stacked query)", async () => {
958
+ const app = await getApp({ disableCsrf: true });
959
+ const loginCookie = await getAdminLoginCookie();
960
+ await request(app)
961
+ .post("/sync/load_changes")
962
+ .set("Cookie", loginCookie)
963
+ .send({
964
+ loadUntil: new Date().valueOf(),
965
+ syncInfos: {
966
+ books: { lastModifiedAt: "0; DROP TABLE books; --" },
967
+ },
968
+ })
969
+ .expect(
970
+ respondJsonWith(
971
+ 400,
972
+ (resp) => resp.error === "Invalid lastModifiedAt"
973
+ )
974
+ );
975
+ });
976
+
977
+ it("rejects non-numeric string for lastModifiedAt", async () => {
978
+ const app = await getApp({ disableCsrf: true });
979
+ const loginCookie = await getAdminLoginCookie();
980
+ await request(app)
981
+ .post("/sync/load_changes")
982
+ .set("Cookie", loginCookie)
983
+ .send({
984
+ loadUntil: new Date().valueOf(),
985
+ syncInfos: { books: { lastModifiedAt: "abc" } },
986
+ })
987
+ .expect(
988
+ respondJsonWith(
989
+ 400,
990
+ (resp) => resp.error === "Invalid lastModifiedAt"
991
+ )
992
+ );
993
+ });
994
+
995
+ it("rejects float lastModifiedAt", async () => {
996
+ const app = await getApp({ disableCsrf: true });
997
+ const loginCookie = await getAdminLoginCookie();
998
+ await request(app)
999
+ .post("/sync/load_changes")
1000
+ .set("Cookie", loginCookie)
1001
+ .send({
1002
+ loadUntil: new Date().valueOf(),
1003
+ syncInfos: { books: { lastModifiedAt: 1.5 } },
1004
+ })
1005
+ .expect(
1006
+ respondJsonWith(
1007
+ 400,
1008
+ (resp) => resp.error === "Invalid lastModifiedAt"
1009
+ )
1010
+ );
1011
+ });
1012
+
1013
+ // --- /sync/load_changes : syncFrom ---
1014
+
1015
+ it("rejects invalid syncFrom date", async () => {
1016
+ const app = await getApp({ disableCsrf: true });
1017
+ const loginCookie = await getAdminLoginCookie();
1018
+ await request(app)
1019
+ .post("/sync/load_changes")
1020
+ .set("Cookie", loginCookie)
1021
+ .send({
1022
+ loadUntil: new Date().valueOf(),
1023
+ syncInfos: { books: { lastModifiedAt: 0, syncFrom: "not-a-date" } },
1024
+ })
1025
+ .expect(
1026
+ respondJsonWith(400, (resp) => resp.error === "Invalid syncFrom")
1027
+ );
1028
+ });
1029
+
1030
+ it("rejects SQL injection payload as syncFrom", async () => {
1031
+ const app = await getApp({ disableCsrf: true });
1032
+ const loginCookie = await getAdminLoginCookie();
1033
+ await request(app)
1034
+ .post("/sync/load_changes")
1035
+ .set("Cookie", loginCookie)
1036
+ .send({
1037
+ loadUntil: new Date().valueOf(),
1038
+ syncInfos: {
1039
+ books: { lastModifiedAt: 0, syncFrom: "0); SELECT pg_sleep(5)--" },
1040
+ },
1041
+ })
1042
+ .expect(
1043
+ respondJsonWith(400, (resp) => resp.error === "Invalid syncFrom")
1044
+ );
1045
+ });
1046
+
1047
+ // --- /sync/load_changes : loadUntil (syncUntil) ---
1048
+
1049
+ it("rejects invalid loadUntil date", async () => {
1050
+ const app = await getApp({ disableCsrf: true });
1051
+ const loginCookie = await getAdminLoginCookie();
1052
+ await request(app)
1053
+ .post("/sync/load_changes")
1054
+ .set("Cookie", loginCookie)
1055
+ .send({
1056
+ loadUntil: "not-a-date",
1057
+ syncInfos: { books: { lastModifiedAt: 0 } },
1058
+ })
1059
+ .expect(
1060
+ respondJsonWith(400, (resp) => resp.error === "Invalid syncUntil")
1061
+ );
1062
+ });
1063
+
1064
+ // --- /sync/deletes : syncTimestamp ---
1065
+
1066
+ it("rejects invalid syncTimestamp in /sync/deletes", async () => {
1067
+ const app = await getApp({ disableCsrf: true });
1068
+ const loginCookie = await getAdminLoginCookie();
1069
+ await request(app)
1070
+ .post("/sync/deletes")
1071
+ .set("Cookie", loginCookie)
1072
+ .send({
1073
+ syncTimestamp: "not-a-date",
1074
+ syncInfos: { books: { syncFrom: new Date(1000).valueOf() } },
1075
+ })
1076
+ .expect(
1077
+ respondJsonWith(400, (resp) => resp.error === "Invalid syncUntil")
1078
+ );
1079
+ });
1080
+
1081
+ it("rejects SQL injection payload as syncTimestamp in /sync/deletes", async () => {
1082
+ const app = await getApp({ disableCsrf: true });
1083
+ const loginCookie = await getAdminLoginCookie();
1084
+ await request(app)
1085
+ .post("/sync/deletes")
1086
+ .set("Cookie", loginCookie)
1087
+ .send({
1088
+ syncTimestamp: "0); SELECT * FROM users--",
1089
+ syncInfos: { books: { syncFrom: new Date(1000).valueOf() } },
1090
+ })
1091
+ .expect(
1092
+ respondJsonWith(400, (resp) => resp.error === "Invalid syncUntil")
1093
+ );
1094
+ });
1095
+
1096
+ // --- /sync/deletes : syncFrom ---
1097
+
1098
+ it("rejects invalid syncFrom in /sync/deletes", async () => {
1099
+ const app = await getApp({ disableCsrf: true });
1100
+ const loginCookie = await getAdminLoginCookie();
1101
+ await request(app)
1102
+ .post("/sync/deletes")
1103
+ .set("Cookie", loginCookie)
1104
+ .send({
1105
+ syncTimestamp: new Date().valueOf(),
1106
+ syncInfos: { books: { syncFrom: "not-a-date" } },
1107
+ })
1108
+ .expect(
1109
+ respondJsonWith(400, (resp) => resp.error === "Invalid syncFrom")
1110
+ );
1111
+ });
1112
+
1113
+ it("rejects SQL injection payload as syncFrom in /sync/deletes", async () => {
1114
+ const app = await getApp({ disableCsrf: true });
1115
+ const loginCookie = await getAdminLoginCookie();
1116
+ await request(app)
1117
+ .post("/sync/deletes")
1118
+ .set("Cookie", loginCookie)
1119
+ .send({
1120
+ syncTimestamp: new Date().valueOf(),
1121
+ syncInfos: {
1122
+ books: { syncFrom: "0); SELECT pg_sleep(5)--" },
1123
+ },
1124
+ })
1125
+ .expect(
1126
+ respondJsonWith(400, (resp) => resp.error === "Invalid syncFrom")
1127
+ );
1128
+ });
1129
+
1130
+ // --- regression: valid requests still succeed ---
1131
+
1132
+ it("valid lastModifiedAt value still works", async () => {
1133
+ const app = await getApp({ disableCsrf: true });
1134
+ const loginCookie = await getAdminLoginCookie();
1135
+ const resp = await request(app)
1136
+ .post("/sync/load_changes")
1137
+ .set("Cookie", loginCookie)
1138
+ .send({
1139
+ loadUntil: new Date().valueOf(),
1140
+ syncInfos: { books: { lastModifiedAt: 0 } },
1141
+ });
1142
+ expect(resp.status).toBe(200);
1143
+ expect(resp._body.books).toBeDefined();
1144
+ });
1145
+
1146
+ it("valid syncFrom timestamp still works", async () => {
1147
+ const app = await getApp({ disableCsrf: true });
1148
+ const loginCookie = await getAdminLoginCookie();
1149
+ const resp = await request(app)
1150
+ .post("/sync/load_changes")
1151
+ .set("Cookie", loginCookie)
1152
+ .send({
1153
+ loadUntil: new Date().valueOf(),
1154
+ syncInfos: { books: { lastModifiedAt: 0, syncFrom: 1000 } },
1155
+ });
1156
+ expect(resp.status).toBe(200);
1157
+ });
1158
+
1159
+ it("valid /sync/deletes request still works", async () => {
1160
+ const app = await getApp({ disableCsrf: true });
1161
+ const loginCookie = await getAdminLoginCookie();
1162
+ const resp = await request(app)
1163
+ .post("/sync/deletes")
1164
+ .set("Cookie", loginCookie)
1165
+ .send({
1166
+ syncTimestamp: new Date().valueOf(),
1167
+ syncInfos: { books: { syncFrom: 1000 } },
1168
+ });
1169
+ expect(resp.status).toBe(200);
1170
+ expect(resp._body.deletes).toBeDefined();
1171
+ });
1172
+ } else
1173
+ it("only pq support", () => {
1174
+ expect(true).toBe(true);
1175
+ });
1176
+ });
1177
+
1178
+ describe("deletes authorization", () => {
1179
+ if (!db.isSQLite) {
1180
+ beforeAll(async () => {
1181
+ await initSyncInfo(["patients"]);
1182
+ });
1183
+
1184
+ it("should not return deletes for tables the user cannot read", async () => {
1185
+ const app = await getApp({ disableCsrf: true });
1186
+ const patients = Table.findOne({ name: "patients" });
1187
+ // patients has min_role_read=40 (staff), user role is 80
1188
+ expect(patients.min_role_read).toBe(40);
1189
+
1190
+ const syncFrom = new Date(Date.now() - 10000);
1191
+
1192
+ // Insert and delete a row so there is a delete event in sync_info
1193
+ const newId = await patients.insertRow({ name: "Secret Patient" });
1194
+ await patients.deleteRows({ id: newId });
1195
+ await sleep(200);
1196
+
1197
+ const syncUntil = new Date(Date.now() + 10000);
1198
+
1199
+ // As a regular user (role 80), try to see the deletion
1200
+ const userCookie = await getUserLoginCookie();
1201
+ const resp = await request(app)
1202
+ .post("/sync/deletes")
1203
+ .set("Cookie", userCookie)
1204
+ .send({
1205
+ syncTimestamp: syncUntil.valueOf(),
1206
+ syncInfos: {
1207
+ patients: {
1208
+ syncFrom: syncFrom.valueOf(),
1209
+ },
1210
+ },
1211
+ });
1212
+ expect(resp.status).toBe(200);
1213
+ const data = resp._body;
1214
+ // The user should NOT be able to see deletes from the patients table
1215
+ // because they lack the required min_role_read (40 < 80).
1216
+ // If deletes.patients exists and has rows, that is the vulnerability.
1217
+ const patientDeletes = data.deletes?.patients || [];
1218
+ expect(patientDeletes.length).toBe(0);
1219
+ });
1220
+ } else
1221
+ it("only pq support", () => {
1222
+ expect(true).toBe(true);
1223
+ });
1224
+ });
1225
+
1226
+ describe("deletes authorization with ownership_formula", () => {
1227
+ if (!db.isSQLite) {
1228
+ let userA, userB;
1229
+ let ownedTable, childTable;
1230
+ let userACookie, userBCookie;
1231
+
1232
+ const loginAs = async (email, password) => {
1233
+ const app = await getApp({ disableCsrf: true });
1234
+ const res = await request(app)
1235
+ .post("/auth/login/")
1236
+ .send(`email=${email}`)
1237
+ .send(`password=${password}`);
1238
+ return res.headers["set-cookie"];
1239
+ };
1240
+
1241
+ beforeAll(async () => {
1242
+ await resetToFixtures();
1243
+
1244
+ // Two regular users — userA owns the rows, userB does not
1245
+ userA = await User.create({
1246
+ email: "userA_sync@test.com",
1247
+ password: "TestPassA1!",
1248
+ role_id: 80,
1249
+ });
1250
+ userB = await User.create({
1251
+ email: "userB_sync@test.com",
1252
+ password: "TestPassB1!",
1253
+ role_id: 80,
1254
+ });
1255
+ userACookie = await loginAs("userA_sync@test.com", "TestPassA1!");
1256
+ userBCookie = await loginAs("userB_sync@test.com", "TestPassB1!");
1257
+
1258
+ const usersTable = Table.findOne({ name: "users" });
1259
+
1260
+ // Parent table: min_role_read=40 so regular users (role 80) access via
1261
+ // ownership only. ownership_formula is a direct field reference.
1262
+ ownedTable = await Table.create("sync_owned", { min_role_read: 40 });
1263
+ await Field.create({
1264
+ table: ownedTable,
1265
+ name: "item_name",
1266
+ label: "Item name",
1267
+ type: "String",
1268
+ });
1269
+ await Field.create({
1270
+ table: ownedTable,
1271
+ name: "owner",
1272
+ label: "Owner",
1273
+ type: "Key",
1274
+ reftable: usersTable,
1275
+ attributes: { summary_field: "email" },
1276
+ });
1277
+ ownedTable = Table.findOne({ name: "sync_owned" });
1278
+ ownedTable.ownership_formula = "owner === user.id";
1279
+ await ownedTable.update(ownedTable);
1280
+ ownedTable = Table.findOne({ name: "sync_owned" });
1281
+
1282
+ // Child table: ownership resolved through a join field.
1283
+ // formula: "sync_owned_ref?.owner === user.id"
1284
+ // After getJoinedRows, row.sync_owned_ref is { id, owner } so the
1285
+ // formula evaluates correctly.
1286
+ childTable = await Table.create("sync_child", { min_role_read: 40 });
1287
+ await Field.create({
1288
+ table: childTable,
1289
+ name: "child_name",
1290
+ label: "Child name",
1291
+ type: "String",
1292
+ });
1293
+ await Field.create({
1294
+ table: childTable,
1295
+ name: "sync_owned_ref",
1296
+ label: "Sync owned ref",
1297
+ type: "Key",
1298
+ reftable: ownedTable,
1299
+ attributes: { summary_field: "item_name" },
1300
+ });
1301
+ childTable = Table.findOne({ name: "sync_child" });
1302
+ childTable.ownership_formula = "sync_owned_ref?.owner === user.id";
1303
+ await childTable.update(childTable);
1304
+ childTable = Table.findOne({ name: "sync_child" });
1305
+
1306
+ // Enable sync tracking on both tables
1307
+ await initSyncInfo(["sync_owned", "sync_child"]);
1308
+ // Re-fetch so has_sync_info = true is reflected in the local references
1309
+ ownedTable = Table.findOne({ name: "sync_owned" });
1310
+ childTable = Table.findOne({ name: "sync_child" });
1311
+ });
1312
+
1313
+ afterAll(async () => {
1314
+ if (childTable) await childTable.delete();
1315
+ if (ownedTable) await ownedTable.delete();
1316
+ if (userA) await userA.delete();
1317
+ if (userB) await userB.delete();
1318
+ });
1319
+
1320
+ it("direct formula: owner sees their own deleted rows", async () => {
1321
+ const syncFrom = new Date(Date.now() - 10000);
1322
+ const itemId = await ownedTable.insertRow({
1323
+ item_name: "userA item",
1324
+ owner: userA.id,
1325
+ });
1326
+ await ownedTable.deleteRows({ id: itemId });
1327
+ await sleep(200);
1328
+ const syncUntil = new Date(Date.now() + 10000);
1329
+
1330
+ const app = await getApp({ disableCsrf: true });
1331
+ const resp = await request(app)
1332
+ .post("/sync/deletes")
1333
+ .set("Cookie", userACookie)
1334
+ .send({
1335
+ syncTimestamp: syncUntil.valueOf(),
1336
+ syncInfos: { sync_owned: { syncFrom: syncFrom.valueOf() } },
1337
+ });
1338
+ expect(resp.status).toBe(200);
1339
+ const deletes = resp._body.deletes?.sync_owned || [];
1340
+ expect(deletes.length).toBe(1);
1341
+ expect(Number(deletes[0].ref)).toBe(itemId);
1342
+ });
1343
+
1344
+ it("direct formula: non-owner does not see deleted rows", async () => {
1345
+ const syncFrom = new Date(Date.now() - 10000);
1346
+ const itemId = await ownedTable.insertRow({
1347
+ item_name: "another userA item",
1348
+ owner: userA.id,
1349
+ });
1350
+ await ownedTable.deleteRows({ id: itemId });
1351
+ await sleep(200);
1352
+ const syncUntil = new Date(Date.now() + 10000);
1353
+
1354
+ const app = await getApp({ disableCsrf: true });
1355
+ const resp = await request(app)
1356
+ .post("/sync/deletes")
1357
+ .set("Cookie", userBCookie)
1358
+ .send({
1359
+ syncTimestamp: syncUntil.valueOf(),
1360
+ syncInfos: { sync_owned: { syncFrom: syncFrom.valueOf() } },
1361
+ });
1362
+ expect(resp.status).toBe(200);
1363
+ const deletes = resp._body.deletes?.sync_owned || [];
1364
+ expect(deletes.length).toBe(0);
1365
+ });
1366
+
1367
+ it("join formula: owner sees deleted child rows", async () => {
1368
+ const syncFrom = new Date(Date.now() - 10000);
1369
+ const parentId = await ownedTable.insertRow({
1370
+ item_name: "parent for join test",
1371
+ owner: userA.id,
1372
+ });
1373
+ const childId = await childTable.insertRow({
1374
+ child_name: "child of userA",
1375
+ sync_owned_ref: parentId,
1376
+ });
1377
+ await childTable.deleteRows({ id: childId });
1378
+ await sleep(200);
1379
+ const syncUntil = new Date(Date.now() + 10000);
1380
+
1381
+ const app = await getApp({ disableCsrf: true });
1382
+ const resp = await request(app)
1383
+ .post("/sync/deletes")
1384
+ .set("Cookie", userACookie)
1385
+ .send({
1386
+ syncTimestamp: syncUntil.valueOf(),
1387
+ syncInfos: { sync_child: { syncFrom: syncFrom.valueOf() } },
1388
+ });
1389
+ expect(resp.status).toBe(200);
1390
+ const deletes = resp._body.deletes?.sync_child || [];
1391
+ expect(deletes.length).toBe(1);
1392
+ expect(Number(deletes[0].ref)).toBe(childId);
1393
+ });
1394
+
1395
+ it("join formula: non-owner does not see deleted child rows", async () => {
1396
+ const syncFrom = new Date(Date.now() - 10000);
1397
+ const parentId = await ownedTable.insertRow({
1398
+ item_name: "parent for join test 2",
1399
+ owner: userA.id,
1400
+ });
1401
+ const childId = await childTable.insertRow({
1402
+ child_name: "child of userA 2",
1403
+ sync_owned_ref: parentId,
1404
+ });
1405
+ await childTable.deleteRows({ id: childId });
1406
+ await sleep(200);
1407
+ const syncUntil = new Date(Date.now() + 10000);
1408
+
1409
+ const app = await getApp({ disableCsrf: true });
1410
+ const resp = await request(app)
1411
+ .post("/sync/deletes")
1412
+ .set("Cookie", userBCookie)
1413
+ .send({
1414
+ syncTimestamp: syncUntil.valueOf(),
1415
+ syncInfos: { sync_child: { syncFrom: syncFrom.valueOf() } },
1416
+ });
1417
+ expect(resp.status).toBe(200);
1418
+ const deletes = resp._body.deletes?.sync_child || [];
1419
+ expect(deletes.length).toBe(0);
1420
+ });
1421
+ } else
1422
+ it("only pq support", () => {
1423
+ expect(true).toBe(true);
1424
+ });
1425
+ });
1426
+
852
1427
  describe("field level conflicts", () => {
853
1428
  if (!db.isSQLite) {
854
1429
  beforeAll(async () => {
@@ -952,3 +1527,310 @@ describe("field level conflicts", () => {
952
1527
  expect(true).toBe(true);
953
1528
  });
954
1529
  });
1530
+
1531
+ describe("load_changes authorization with ownership_formula", () => {
1532
+ if (!db.isSQLite) {
1533
+ let userA, userB;
1534
+ let ownedTable, childTable;
1535
+ let userACookie, userBCookie;
1536
+
1537
+ const loginAs = async (email, password) => {
1538
+ const app = await getApp({ disableCsrf: true });
1539
+ const res = await request(app)
1540
+ .post("/auth/login/")
1541
+ .send(`email=${email}`)
1542
+ .send(`password=${password}`);
1543
+ return res.headers["set-cookie"];
1544
+ };
1545
+
1546
+ beforeAll(async () => {
1547
+ await resetToFixtures();
1548
+
1549
+ userA = await User.create({
1550
+ email: "userA_lc@test.com",
1551
+ password: "TestPassA1!",
1552
+ role_id: 80,
1553
+ });
1554
+ userB = await User.create({
1555
+ email: "userB_lc@test.com",
1556
+ password: "TestPassB1!",
1557
+ role_id: 80,
1558
+ });
1559
+ userACookie = await loginAs("userA_lc@test.com", "TestPassA1!");
1560
+ userBCookie = await loginAs("userB_lc@test.com", "TestPassB1!");
1561
+
1562
+ const usersTable = Table.findOne({ name: "users" });
1563
+
1564
+ // Direct formula table: min_role_read=40, ownership_formula = "owner === user.id"
1565
+ ownedTable = await Table.create("lc_owned", { min_role_read: 40 });
1566
+ await Field.create({
1567
+ table: ownedTable,
1568
+ name: "item_name",
1569
+ label: "Item name",
1570
+ type: "String",
1571
+ });
1572
+ await Field.create({
1573
+ table: ownedTable,
1574
+ name: "owner",
1575
+ label: "Owner",
1576
+ type: "Key",
1577
+ reftable: usersTable,
1578
+ attributes: { summary_field: "email" },
1579
+ });
1580
+ ownedTable = Table.findOne({ name: "lc_owned" });
1581
+ ownedTable.ownership_formula = "owner === user.id";
1582
+ await ownedTable.update(ownedTable);
1583
+ ownedTable = Table.findOne({ name: "lc_owned" });
1584
+
1585
+ // Join formula table: ownership resolved through a join field
1586
+ childTable = await Table.create("lc_child", { min_role_read: 40 });
1587
+ await Field.create({
1588
+ table: childTable,
1589
+ name: "child_name",
1590
+ label: "Child name",
1591
+ type: "String",
1592
+ });
1593
+ await Field.create({
1594
+ table: childTable,
1595
+ name: "lc_owned_ref",
1596
+ label: "Lc owned ref",
1597
+ type: "Key",
1598
+ reftable: ownedTable,
1599
+ attributes: { summary_field: "item_name" },
1600
+ });
1601
+ childTable = Table.findOne({ name: "lc_child" });
1602
+ childTable.ownership_formula = "lc_owned_ref?.owner === user.id";
1603
+ await childTable.update(childTable);
1604
+ childTable = Table.findOne({ name: "lc_child" });
1605
+
1606
+ await initSyncInfo(["lc_owned", "lc_child"]);
1607
+ ownedTable = Table.findOne({ name: "lc_owned" });
1608
+ childTable = Table.findOne({ name: "lc_child" });
1609
+ });
1610
+
1611
+ afterAll(async () => {
1612
+ if (childTable) await childTable.delete();
1613
+ if (ownedTable) await ownedTable.delete();
1614
+ if (userA) await userA.delete();
1615
+ if (userB) await userB.delete();
1616
+ });
1617
+
1618
+ it("direct formula: owner sees their own rows in load_changes", async () => {
1619
+ const itemId = await ownedTable.insertRow({
1620
+ item_name: "userA lc item",
1621
+ owner: userA.id,
1622
+ });
1623
+ const loadUntil = new Date(Date.now() + 10000);
1624
+
1625
+ const app = await getApp({ disableCsrf: true });
1626
+ const resp = await request(app)
1627
+ .post("/sync/load_changes")
1628
+ .set("Cookie", userACookie)
1629
+ .send({
1630
+ loadUntil: loadUntil.valueOf(),
1631
+ syncInfos: {
1632
+ lc_owned: { lastModifiedAt: 0 },
1633
+ },
1634
+ });
1635
+ expect(resp.status).toBe(200);
1636
+ const rows = resp._body.lc_owned?.rows || [];
1637
+ expect(rows.some((r) => r.id === itemId)).toBe(true);
1638
+ });
1639
+
1640
+ it("direct formula: non-owner does not see rows in load_changes", async () => {
1641
+ const itemId = await ownedTable.insertRow({
1642
+ item_name: "userA lc item 2",
1643
+ owner: userA.id,
1644
+ });
1645
+ const loadUntil = new Date(Date.now() + 10000);
1646
+
1647
+ const app = await getApp({ disableCsrf: true });
1648
+ const resp = await request(app)
1649
+ .post("/sync/load_changes")
1650
+ .set("Cookie", userBCookie)
1651
+ .send({
1652
+ loadUntil: loadUntil.valueOf(),
1653
+ syncInfos: {
1654
+ lc_owned: { lastModifiedAt: 0 },
1655
+ },
1656
+ });
1657
+ expect(resp.status).toBe(200);
1658
+ const rows = resp._body.lc_owned?.rows || [];
1659
+ expect(rows.some((r) => r.id === itemId)).toBe(false);
1660
+ });
1661
+
1662
+ it("join formula: owner sees their child rows in load_changes", async () => {
1663
+ const parentId = await ownedTable.insertRow({
1664
+ item_name: "parent for lc join test",
1665
+ owner: userA.id,
1666
+ });
1667
+ const childId = await childTable.insertRow({
1668
+ child_name: "child of userA lc",
1669
+ lc_owned_ref: parentId,
1670
+ });
1671
+ const loadUntil = new Date(Date.now() + 10000);
1672
+
1673
+ const app = await getApp({ disableCsrf: true });
1674
+ const resp = await request(app)
1675
+ .post("/sync/load_changes")
1676
+ .set("Cookie", userACookie)
1677
+ .send({
1678
+ loadUntil: loadUntil.valueOf(),
1679
+ syncInfos: {
1680
+ lc_child: { lastModifiedAt: 0 },
1681
+ },
1682
+ });
1683
+ expect(resp.status).toBe(200);
1684
+ const rows = resp._body.lc_child?.rows || [];
1685
+ expect(rows.some((r) => r.id === childId)).toBe(true);
1686
+ });
1687
+
1688
+ it("join formula: non-owner does not see child rows in load_changes", async () => {
1689
+ const parentId = await ownedTable.insertRow({
1690
+ item_name: "parent for lc join test 2",
1691
+ owner: userA.id,
1692
+ });
1693
+ const childId = await childTable.insertRow({
1694
+ child_name: "child of userA lc 2",
1695
+ lc_owned_ref: parentId,
1696
+ });
1697
+ const loadUntil = new Date(Date.now() + 10000);
1698
+
1699
+ const app = await getApp({ disableCsrf: true });
1700
+ const resp = await request(app)
1701
+ .post("/sync/load_changes")
1702
+ .set("Cookie", userBCookie)
1703
+ .send({
1704
+ loadUntil: loadUntil.valueOf(),
1705
+ syncInfos: {
1706
+ lc_child: { lastModifiedAt: 0 },
1707
+ },
1708
+ });
1709
+ expect(resp.status).toBe(200);
1710
+ const rows = resp._body.lc_child?.rows || [];
1711
+ expect(rows.some((r) => r.id === childId)).toBe(false);
1712
+ });
1713
+
1714
+ it("direct formula: owner sees updated rows via syncFrom in load_changes", async () => {
1715
+ const itemId = await ownedTable.insertRow({
1716
+ item_name: "userA lc syncFrom item",
1717
+ owner: userA.id,
1718
+ });
1719
+ const syncFrom = await db.time();
1720
+ await sleep(100);
1721
+ await ownedTable.updateRow({ item_name: "userA lc updated" }, itemId);
1722
+ const loadUntil = new Date(Date.now() + 10000);
1723
+
1724
+ const app = await getApp({ disableCsrf: true });
1725
+ const resp = await request(app)
1726
+ .post("/sync/load_changes")
1727
+ .set("Cookie", userACookie)
1728
+ .send({
1729
+ loadUntil: loadUntil.valueOf(),
1730
+ syncInfos: {
1731
+ lc_owned: { lastModifiedAt: 0, syncFrom: syncFrom.valueOf() },
1732
+ },
1733
+ });
1734
+ expect(resp.status).toBe(200);
1735
+ const rows = resp._body.lc_owned?.rows || [];
1736
+ expect(rows.some((r) => r.id === itemId)).toBe(true);
1737
+ });
1738
+
1739
+ it("direct formula: non-owner does not see updated rows via syncFrom in load_changes", async () => {
1740
+ const itemId = await ownedTable.insertRow({
1741
+ item_name: "userA lc syncFrom item 2",
1742
+ owner: userA.id,
1743
+ });
1744
+ const syncFrom = await db.time();
1745
+ await sleep(100);
1746
+ await ownedTable.updateRow({ item_name: "userA lc updated 2" }, itemId);
1747
+ const loadUntil = new Date(Date.now() + 10000);
1748
+
1749
+ const app = await getApp({ disableCsrf: true });
1750
+ const resp = await request(app)
1751
+ .post("/sync/load_changes")
1752
+ .set("Cookie", userBCookie)
1753
+ .send({
1754
+ loadUntil: loadUntil.valueOf(),
1755
+ syncInfos: {
1756
+ lc_owned: { lastModifiedAt: 0, syncFrom: syncFrom.valueOf() },
1757
+ },
1758
+ });
1759
+ expect(resp.status).toBe(200);
1760
+ const rows = resp._body.lc_owned?.rows || [];
1761
+ expect(rows.some((r) => r.id === itemId)).toBe(false);
1762
+ });
1763
+ } else
1764
+ it("only pq support", () => {
1765
+ expect(true).toBe(true);
1766
+ });
1767
+ });
1768
+
1769
+ describe("sync dir email suffix attack", () => {
1770
+ if (!db.isSQLite) {
1771
+ beforeAll(async () => {
1772
+ await initSyncInfo(["books"]);
1773
+ });
1774
+
1775
+ it("rejects access when attacker email is a suffix of victim email", async () => {
1776
+ // Create a victim user whose email contains "_user@foo.com" as a suffix
1777
+ // The existing user@foo.com has suffix "_user@foo.com"
1778
+ // "timestamp_x_user@foo.com".endsWith("_user@foo.com") === true
1779
+ // so user@foo.com could access x_user@foo.com's sync dir
1780
+ const victimEmail = "x_user@foo.com";
1781
+ const victimPassword = "TestPass123!";
1782
+ await User.create({
1783
+ email: victimEmail,
1784
+ password: victimPassword,
1785
+ role_id: 80,
1786
+ });
1787
+
1788
+ const app = await getApp({ disableCsrf: true });
1789
+
1790
+ // Login as victim
1791
+ const victimRes = await request(app)
1792
+ .post("/auth/login/")
1793
+ .send(`email=${victimEmail}`)
1794
+ .send(`password=${victimPassword}`);
1795
+ const victimCookie = resToLoginCookie(victimRes);
1796
+
1797
+ // Victim creates a sync directory
1798
+ const resp = await doUpload(
1799
+ app,
1800
+ victimCookie,
1801
+ new Date().valueOf(),
1802
+ new Date().valueOf(),
1803
+ { books: { inserts: [] } }
1804
+ );
1805
+ expect(resp.status).toBe(200);
1806
+ const { syncDir } = resp._body;
1807
+ // syncDir looks like "1234567890123_x_user@foo.com"
1808
+ // endsWith("_user@foo.com") is true!
1809
+ expect(syncDir.endsWith("_user@foo.com")).toBe(true);
1810
+
1811
+ // Login as the attacker (user@foo.com)
1812
+ const attackerCookie = await getUserLoginCookie();
1813
+
1814
+ // Attacker tries to read victim's sync results
1815
+ const pollResp = await request(app)
1816
+ .get(`/sync/upload_finished?dir_name=${encodeURIComponent(syncDir)}`)
1817
+ .set("Cookie", attackerCookie);
1818
+ // Should be 403 - attacker must not access victim's sync dir
1819
+ expect(pollResp.status).toBe(403);
1820
+
1821
+ // Attacker tries to delete victim's sync dir
1822
+ const deleteResp = await request(app)
1823
+ .post("/sync/clean_sync_dir")
1824
+ .send({ dir_name: syncDir })
1825
+ .set("Cookie", attackerCookie);
1826
+ // Should be 403
1827
+ expect(deleteResp.status).toBe(403);
1828
+
1829
+ // Cleanup
1830
+ await cleanSyncDir(app, victimCookie, syncDir);
1831
+ });
1832
+ } else
1833
+ it("only pq support", () => {
1834
+ expect(true).toBe(true);
1835
+ });
1836
+ });