@saltcorn/server 1.3.1-beta.1 → 1.3.1-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 (404) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/auth/admin.js +9 -1
  3. package/auth/routes.js +50 -5
  4. package/docs/assets/search.js +1 -1
  5. package/docs/classes/_saltcorn_common_code.Relation.html +10 -10
  6. package/docs/classes/_saltcorn_common_code.RelationsFinder.html +5 -5
  7. package/docs/classes/_saltcorn_data.models.Crash.html +17 -17
  8. package/docs/classes/_saltcorn_data.models.EventLog-1.html +19 -19
  9. package/docs/classes/_saltcorn_data.models.Field.html +74 -74
  10. package/docs/classes/_saltcorn_data.models.FieldRepeat.html +16 -16
  11. package/docs/classes/_saltcorn_data.models.File-1.html +48 -48
  12. package/docs/classes/_saltcorn_data.models.Form-1.html +39 -39
  13. package/docs/classes/_saltcorn_data.models.Library.html +13 -13
  14. package/docs/classes/_saltcorn_data.models.Page.html +24 -24
  15. package/docs/classes/_saltcorn_data.models.PageGroup-1.html +25 -25
  16. package/docs/classes/_saltcorn_data.models.Plugin.html +25 -25
  17. package/docs/classes/_saltcorn_data.models.Role.html +9 -9
  18. package/docs/classes/_saltcorn_data.models.Table-1.html +92 -92
  19. package/docs/classes/_saltcorn_data.models.TableConstraint.html +14 -14
  20. package/docs/classes/_saltcorn_data.models.Trigger.html +71 -39
  21. package/docs/classes/_saltcorn_data.models.User.html +51 -49
  22. package/docs/classes/_saltcorn_data.models.View-1.html +68 -54
  23. package/docs/classes/_saltcorn_data.models.Workflow.html +17 -17
  24. package/docs/classes/_saltcorn_data.models.WorkflowRun.html +35 -35
  25. package/docs/classes/_saltcorn_data.models.WorkflowStep.html +25 -25
  26. package/docs/classes/_saltcorn_data.models.WorkflowTrace.html +18 -18
  27. package/docs/classes/_saltcorn_mobile_builder.MobileBuilder.html +37 -37
  28. package/docs/enums/_saltcorn_common_code.RelationType.html +7 -7
  29. package/docs/enums/_saltcorn_common_code.ViewDisplayType.html +4 -4
  30. package/docs/functions/_saltcorn_admin_models.backup.create_backup.html +1 -1
  31. package/docs/functions/_saltcorn_admin_models.backup.create_csv_from_rows.html +1 -1
  32. package/docs/functions/_saltcorn_admin_models.backup.restore.html +1 -1
  33. package/docs/functions/_saltcorn_admin_models.pack.add_to_menu.html +1 -1
  34. package/docs/functions/_saltcorn_admin_models.pack.can_install_pack.html +1 -1
  35. package/docs/functions/_saltcorn_admin_models.pack.fetch_available_packs.html +1 -1
  36. package/docs/functions/_saltcorn_admin_models.pack.fetch_pack_by_name.html +1 -1
  37. package/docs/functions/_saltcorn_admin_models.pack.install_pack.html +1 -1
  38. package/docs/functions/_saltcorn_admin_models.pack.library_pack.html +1 -1
  39. package/docs/functions/_saltcorn_admin_models.pack.model_instance_pack.html +1 -1
  40. package/docs/functions/_saltcorn_admin_models.pack.model_pack.html +1 -1
  41. package/docs/functions/_saltcorn_admin_models.pack.page_group_pack.html +1 -1
  42. package/docs/functions/_saltcorn_admin_models.pack.page_pack.html +1 -1
  43. package/docs/functions/_saltcorn_admin_models.pack.plugin_pack.html +1 -1
  44. package/docs/functions/_saltcorn_admin_models.pack.role_pack.html +1 -1
  45. package/docs/functions/_saltcorn_admin_models.pack.table_pack.html +1 -1
  46. package/docs/functions/_saltcorn_admin_models.pack.trigger_pack.html +1 -1
  47. package/docs/functions/_saltcorn_admin_models.pack.uninstall_pack.html +1 -1
  48. package/docs/functions/_saltcorn_admin_models.pack.view_pack.html +1 -1
  49. package/docs/functions/_saltcorn_admin_models.tenant.copy_tenant_template.html +1 -1
  50. package/docs/functions/_saltcorn_admin_models.tenant.create_tenant.html +1 -1
  51. package/docs/functions/_saltcorn_admin_models.tenant.deleteTenant.html +1 -1
  52. package/docs/functions/_saltcorn_admin_models.tenant.domain_sanitize.html +1 -1
  53. package/docs/functions/_saltcorn_admin_models.tenant.eachTenant.html +1 -1
  54. package/docs/functions/_saltcorn_admin_models.tenant.getAllTenantRows.html +1 -1
  55. package/docs/functions/_saltcorn_admin_models.tenant.getAllTenants.html +1 -1
  56. package/docs/functions/_saltcorn_admin_models.tenant.insertTenant.html +1 -1
  57. package/docs/functions/_saltcorn_admin_models.tenant.switchToTenant.html +1 -1
  58. package/docs/functions/_saltcorn_common_code.buildTableCaches.html +1 -1
  59. package/docs/functions/_saltcorn_common_code.parseLegacyRelation.html +1 -1
  60. package/docs/functions/_saltcorn_common_code.parseRelationPath.html +1 -1
  61. package/docs/functions/_saltcorn_data.models.config.check_email_mask.html +1 -1
  62. package/docs/functions/_saltcorn_data.models.config.deleteConfig.html +1 -1
  63. package/docs/functions/_saltcorn_data.models.config.getAllConfig.html +1 -1
  64. package/docs/functions/_saltcorn_data.models.config.getConfig.html +1 -1
  65. package/docs/functions/_saltcorn_data.models.config.get_base_url.html +1 -1
  66. package/docs/functions/_saltcorn_data.models.config.get_latest_npm_version.html +1 -1
  67. package/docs/functions/_saltcorn_data.models.config.remove_from_menu.html +1 -1
  68. package/docs/functions/_saltcorn_data.models.config.save_menu_items.html +1 -1
  69. package/docs/functions/_saltcorn_data.models.config.setConfig.html +1 -1
  70. package/docs/functions/_saltcorn_data.models.discovery.discover_tables.html +1 -1
  71. package/docs/functions/_saltcorn_data.models.discovery.discoverable_tables.html +1 -1
  72. package/docs/functions/_saltcorn_data.models.discovery.findType.html +1 -1
  73. package/docs/functions/_saltcorn_data.models.discovery.get_existing_views.html +1 -1
  74. package/docs/functions/_saltcorn_data.models.discovery.implement_discovery.html +1 -1
  75. package/docs/functions/_saltcorn_data.models.email.getMailTransport.html +1 -1
  76. package/docs/functions/_saltcorn_data.models.email.send_verification_email.html +1 -1
  77. package/docs/functions/_saltcorn_data.models.email.viewToEmailHtml.html +1 -1
  78. package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields.html +1 -1
  79. package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields_stored.html +1 -1
  80. package/docs/functions/_saltcorn_data.models.expression.eval_expression.html +1 -1
  81. package/docs/functions/_saltcorn_data.models.expression.expressionValidator.html +1 -1
  82. package/docs/functions/_saltcorn_data.models.expression.get_async_expression_function.html +1 -1
  83. package/docs/functions/_saltcorn_data.models.expression.get_expression_function.html +1 -1
  84. package/docs/functions/_saltcorn_data.models.expression.jsexprToWhere.html +1 -1
  85. package/docs/functions/_saltcorn_data.models.expression.recalculate_for_stored.html +1 -1
  86. package/docs/functions/_saltcorn_data.models.expression.transform_for_async.html +1 -1
  87. package/docs/functions/_saltcorn_data.models.layout.eachView.html +1 -1
  88. package/docs/functions/_saltcorn_data.models.layout.getStringsForI18n.html +1 -1
  89. package/docs/functions/_saltcorn_data.models.layout.getViews.html +1 -1
  90. package/docs/functions/_saltcorn_data.models.layout.translateLayout.html +1 -1
  91. package/docs/functions/_saltcorn_data.models.layout.traverse.html +1 -1
  92. package/docs/functions/_saltcorn_data.models.layout.traverseSync.html +1 -1
  93. package/docs/functions/_saltcorn_data.models.random.all_views.html +1 -1
  94. package/docs/functions/_saltcorn_data.models.random.fill_table_row.html +1 -1
  95. package/docs/functions/_saltcorn_data.models.random.initial_view.html +1 -1
  96. package/docs/functions/_saltcorn_data.models.random.random_table.html +1 -1
  97. package/docs/functions/_saltcorn_db_common.buildInsertBulkSql.html +2 -1
  98. package/docs/functions/_saltcorn_db_common.buildInsertSql.html +2 -1
  99. package/docs/functions/_saltcorn_db_common.commitAndBeginNewTransaction.html +103 -0
  100. package/docs/functions/_saltcorn_db_common.doCount.html +2 -1
  101. package/docs/functions/_saltcorn_db_common.doDeleteWhere.html +2 -1
  102. package/docs/functions/_saltcorn_db_common.doListScTables.html +2 -1
  103. package/docs/functions/_saltcorn_db_common.doListTables.html +2 -1
  104. package/docs/functions/_saltcorn_db_common.doListUserDefinedTables.html +2 -1
  105. package/docs/functions/_saltcorn_db_common.do_add_index.html +2 -1
  106. package/docs/functions/_saltcorn_db_common.do_drop_index.html +2 -1
  107. package/docs/functions/_saltcorn_db_common.ftsFieldsSqlExpr.html +2 -1
  108. package/docs/functions/_saltcorn_db_common.mkSelectOptions.html +2 -1
  109. package/docs/functions/_saltcorn_db_common.mkVal.html +2 -1
  110. package/docs/functions/_saltcorn_db_common.mkWhere.html +2 -1
  111. package/docs/functions/_saltcorn_db_common.multi_tenant.enable_multi_tenant.html +2 -1
  112. package/docs/functions/_saltcorn_db_common.multi_tenant.getRequestContext.html +2 -1
  113. package/docs/functions/_saltcorn_db_common.multi_tenant.getTenantSchema.html +2 -1
  114. package/docs/functions/_saltcorn_db_common.multi_tenant.init.html +2 -1
  115. package/docs/functions/_saltcorn_db_common.multi_tenant.is_it_multi_tenant.html +2 -1
  116. package/docs/functions/_saltcorn_db_common.multi_tenant.runWithTenant.html +2 -1
  117. package/docs/functions/_saltcorn_db_common.orderByIsObject.html +2 -1
  118. package/docs/functions/_saltcorn_db_common.orderByIsOperator.html +2 -1
  119. package/docs/functions/_saltcorn_db_common.prefixFieldsInWhere.html +2 -1
  120. package/docs/functions/_saltcorn_db_common.reprAsJson.html +2 -1
  121. package/docs/functions/_saltcorn_db_common.slugify.html +2 -1
  122. package/docs/functions/_saltcorn_db_common.sqlBinOp.html +2 -1
  123. package/docs/functions/_saltcorn_db_common.sqlFun.html +2 -1
  124. package/docs/functions/_saltcorn_db_common.sqlsanitize.html +2 -1
  125. package/docs/functions/_saltcorn_db_common.sqlsanitizeAllowDots.html +2 -1
  126. package/docs/functions/_saltcorn_db_common.subSelectWhere.html +2 -1
  127. package/docs/functions/_saltcorn_db_common.tryCatchInTransaction.html +2 -1
  128. package/docs/functions/_saltcorn_db_common.withTransaction.html +2 -1
  129. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidFeatures.html +1 -1
  130. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidPermissions.html +1 -1
  131. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.buildTablesFile.html +1 -1
  132. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyPrepopulatedDb.html +1 -1
  133. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyServerFiles.html +1 -1
  134. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyShareExtFiles.html +1 -1
  135. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copySiteLogo.html +1 -1
  136. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyTranslationFiles.html +1 -1
  137. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.createSqliteDb.html +1 -1
  138. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.decodeProvisioningProfile.html +1 -1
  139. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.extractDomain.html +1 -1
  140. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.generateAndroidVersionCode.html +1 -1
  141. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyAndroidManifest.html +1 -1
  142. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyConfigXml.html +1 -1
  143. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyGradleConfig.html +1 -1
  144. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyInfoPlist.html +1 -1
  145. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyXcodeProjectFile.html +1 -1
  146. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepAppIcon.html +1 -1
  147. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareAppIcon.html +1 -1
  148. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareBuildDir.html +1 -1
  149. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareExportOptionsPlist.html +1 -1
  150. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashIcon.html +1 -1
  151. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashPage.html +1 -1
  152. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCapacitorConfig.html +1 -1
  153. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCfgFile.html +1 -1
  154. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeDataExtractionRules.html +1 -1
  155. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeNetworkSecurityConfig.html +1 -1
  156. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePodfile.html +1 -1
  157. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePrivacyInfo.html +1 -1
  158. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundleMobileAppCode.html +1 -1
  159. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundlePackagesAndPlugins.html +1 -1
  160. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyMobileAppDirs.html +1 -1
  161. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyPublicDirs.html +1 -1
  162. package/docs/functions/_saltcorn_sqlite.add_index.html +1 -1
  163. package/docs/functions/_saltcorn_sqlite.add_unique_constraint.html +1 -1
  164. package/docs/functions/_saltcorn_sqlite.begin.html +1 -1
  165. package/docs/functions/_saltcorn_sqlite.changeConnection.html +1 -1
  166. package/docs/functions/_saltcorn_sqlite.close.html +1 -1
  167. package/docs/functions/_saltcorn_sqlite.commit.html +1 -1
  168. package/docs/functions/_saltcorn_sqlite.count.html +1 -1
  169. package/docs/functions/_saltcorn_sqlite.deleteWhere.html +1 -1
  170. package/docs/functions/_saltcorn_sqlite.dropTable.html +1 -1
  171. package/docs/functions/_saltcorn_sqlite.dropTables.html +1 -1
  172. package/docs/functions/_saltcorn_sqlite.drop_index.html +1 -1
  173. package/docs/functions/_saltcorn_sqlite.drop_reset_schema.html +1 -1
  174. package/docs/functions/_saltcorn_sqlite.drop_unique_constraint.html +1 -1
  175. package/docs/functions/_saltcorn_sqlite.getVersion.html +1 -1
  176. package/docs/functions/_saltcorn_sqlite.get_db_filepath.html +1 -1
  177. package/docs/functions/_saltcorn_sqlite.get_sql_logging.html +1 -1
  178. package/docs/functions/_saltcorn_sqlite.init.html +1 -1
  179. package/docs/functions/_saltcorn_sqlite.insert.html +1 -1
  180. package/docs/functions/_saltcorn_sqlite.listScTables.html +1 -1
  181. package/docs/functions/_saltcorn_sqlite.listTables.html +1 -1
  182. package/docs/functions/_saltcorn_sqlite.listUserDefinedTables.html +1 -1
  183. package/docs/functions/_saltcorn_sqlite.query.html +1 -1
  184. package/docs/functions/_saltcorn_sqlite.rollback.html +1 -1
  185. package/docs/functions/_saltcorn_sqlite.select.html +1 -1
  186. package/docs/functions/_saltcorn_sqlite.selectMaybeOne.html +1 -1
  187. package/docs/functions/_saltcorn_sqlite.selectOne.html +1 -1
  188. package/docs/functions/_saltcorn_sqlite.set_sql_logging.html +1 -1
  189. package/docs/functions/_saltcorn_sqlite.sql_log.html +1 -1
  190. package/docs/functions/_saltcorn_sqlite.update.html +1 -1
  191. package/docs/functions/_saltcorn_sqlite.updateWhere.html +1 -1
  192. package/docs/functions/_saltcorn_sqlite_mobile.add_index.html +1 -1
  193. package/docs/functions/_saltcorn_sqlite_mobile.add_unique_constraint.html +1 -1
  194. package/docs/functions/_saltcorn_sqlite_mobile.count.html +1 -1
  195. package/docs/functions/_saltcorn_sqlite_mobile.deleteWhere.html +1 -1
  196. package/docs/functions/_saltcorn_sqlite_mobile.drop_index.html +1 -1
  197. package/docs/functions/_saltcorn_sqlite_mobile.drop_reset_schema.html +1 -1
  198. package/docs/functions/_saltcorn_sqlite_mobile.drop_unique_constraint.html +1 -1
  199. package/docs/functions/_saltcorn_sqlite_mobile.init.html +1 -1
  200. package/docs/functions/_saltcorn_sqlite_mobile.insert.html +1 -1
  201. package/docs/functions/_saltcorn_sqlite_mobile.insertRows.html +1 -1
  202. package/docs/functions/_saltcorn_sqlite_mobile.listScTables.html +1 -1
  203. package/docs/functions/_saltcorn_sqlite_mobile.listTables.html +1 -1
  204. package/docs/functions/_saltcorn_sqlite_mobile.listUserDefinedTables.html +1 -1
  205. package/docs/functions/_saltcorn_sqlite_mobile.query.html +1 -1
  206. package/docs/functions/_saltcorn_sqlite_mobile.select.html +1 -1
  207. package/docs/functions/_saltcorn_sqlite_mobile.selectMaybeOne.html +1 -1
  208. package/docs/functions/_saltcorn_sqlite_mobile.selectOne.html +1 -1
  209. package/docs/functions/_saltcorn_sqlite_mobile.setConnectionObject.html +1 -1
  210. package/docs/functions/_saltcorn_sqlite_mobile.tableExists.html +1 -1
  211. package/docs/functions/_saltcorn_sqlite_mobile.time.html +1 -1
  212. package/docs/functions/_saltcorn_sqlite_mobile.update.html +1 -1
  213. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_field.instanceOfField.html +1 -1
  214. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_page.instanceOfPage.html +1 -1
  215. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_view.instanceOfView.html +1 -1
  216. package/docs/functions/_saltcorn_types.Types.base_types.instanceOWithHtmlFile.html +1 -1
  217. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfErrorMsg.html +1 -1
  218. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfSuccessMsg.html +1 -1
  219. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfType.html +1 -1
  220. package/docs/functions/_saltcorn_types.generators.generateBool.html +1 -1
  221. package/docs/functions/_saltcorn_types.generators.generateString.html +1 -1
  222. package/docs/functions/_saltcorn_types.generators.num_between.html +1 -1
  223. package/docs/functions/_saltcorn_types.generators.oneOf.html +1 -1
  224. package/docs/interfaces/_saltcorn_mobile_builder.common_build_utils.ScCapacitorConfig.html +10 -10
  225. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractField.html +15 -15
  226. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractFieldRepeat.html +3 -3
  227. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_form.AbstractForm.html +27 -27
  228. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_page.AbstractPage.html +7 -7
  229. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_role.AbstractRole.html +3 -3
  230. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_table.AbstractTable.html +11 -11
  231. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_trigger.AbstractTrigger.html +38 -16
  232. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_view.AbstractView.html +10 -10
  233. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_workflow.AbstractWorkflow.html +13 -13
  234. package/docs/modules/_saltcorn_admin_models.backup.html +1 -1
  235. package/docs/modules/_saltcorn_admin_models.html +1 -1
  236. package/docs/modules/_saltcorn_admin_models.pack.html +1 -1
  237. package/docs/modules/_saltcorn_admin_models.tenant.html +1 -1
  238. package/docs/modules/_saltcorn_common_code.html +1 -1
  239. package/docs/modules/_saltcorn_data.html +3 -3
  240. package/docs/modules/_saltcorn_data.models.EventLog.html +2 -2
  241. package/docs/modules/_saltcorn_data.models.File.html +2 -2
  242. package/docs/modules/_saltcorn_data.models.Form.html +2 -2
  243. package/docs/modules/_saltcorn_data.models.PageGroup.html +2 -2
  244. package/docs/modules/_saltcorn_data.models.Table.html +2 -2
  245. package/docs/modules/_saltcorn_data.models.View.html +2 -2
  246. package/docs/modules/_saltcorn_data.models.config.html +1 -1
  247. package/docs/modules/_saltcorn_data.models.discovery.html +1 -1
  248. package/docs/modules/_saltcorn_data.models.email.html +1 -1
  249. package/docs/modules/_saltcorn_data.models.expression.html +1 -1
  250. package/docs/modules/_saltcorn_data.models.html +1 -1
  251. package/docs/modules/_saltcorn_data.models.layout.html +1 -1
  252. package/docs/modules/_saltcorn_data.models.random.html +1 -1
  253. package/docs/modules/_saltcorn_data.models.scheduler.html +1 -1
  254. package/docs/modules/_saltcorn_data.plugin_helper.html +1 -1
  255. package/docs/modules/_saltcorn_data.utils.html +1 -1
  256. package/docs/modules/_saltcorn_db_common.html +4 -2
  257. package/docs/modules/_saltcorn_db_common.multi_tenant.html +2 -1
  258. package/docs/modules/_saltcorn_markup.html +2 -2
  259. package/docs/modules/_saltcorn_mobile_builder.common_build_utils.html +1 -1
  260. package/docs/modules/_saltcorn_mobile_builder.html +1 -1
  261. package/docs/modules/_saltcorn_mobile_builder.package_bundle_utils.html +1 -1
  262. package/docs/modules/_saltcorn_sqlite.html +1 -1
  263. package/docs/modules/_saltcorn_sqlite_mobile.html +1 -1
  264. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_field.html +1 -1
  265. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_form.html +1 -1
  266. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_library.html +1 -1
  267. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_page.html +1 -1
  268. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_plugin.html +1 -1
  269. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_role.html +1 -1
  270. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_table.html +1 -1
  271. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_trigger.html +1 -1
  272. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_view.html +1 -1
  273. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_workflow.html +1 -1
  274. package/docs/modules/_saltcorn_types.ModelAbstracts.html +1 -1
  275. package/docs/modules/_saltcorn_types.Types.base_types.html +1 -1
  276. package/docs/modules/_saltcorn_types.Types.common_types.html +1 -1
  277. package/docs/modules/_saltcorn_types.Types.html +1 -1
  278. package/docs/modules/_saltcorn_types.generators.html +1 -1
  279. package/docs/modules/_saltcorn_types.html +1 -1
  280. package/docs/types/_saltcorn_data.models.EventLog.EventLogCfg.html +1 -1
  281. package/docs/types/_saltcorn_data.models.File.FileCfg.html +1 -1
  282. package/docs/types/_saltcorn_data.models.Form.AdditionalButton.html +1 -1
  283. package/docs/types/_saltcorn_data.models.Form.FormCfg.html +1 -1
  284. package/docs/types/_saltcorn_data.models.PageGroup.ScreenInfoParams.html +1 -1
  285. package/docs/types/_saltcorn_data.models.Table.ChildRelations.html +1 -1
  286. package/docs/types/_saltcorn_data.models.Table.ParentRelations.html +1 -1
  287. package/docs/types/_saltcorn_data.models.Table.RelationData.html +1 -1
  288. package/docs/types/_saltcorn_data.models.View.FindViewsPred.html +1 -1
  289. package/docs/types/_saltcorn_db_common.AggregationOptions.html +2 -1
  290. package/docs/types/_saltcorn_db_common.CoordOpts.html +2 -1
  291. package/docs/types/_saltcorn_db_common.DatabaseClient.html +2 -1
  292. package/docs/types/_saltcorn_db_common.JoinField.html +2 -1
  293. package/docs/types/_saltcorn_db_common.JoinFields.html +2 -1
  294. package/docs/types/_saltcorn_db_common.JoinOptions.html +2 -1
  295. package/docs/types/_saltcorn_db_common.JsonPath.html +2 -1
  296. package/docs/types/_saltcorn_db_common.JsonPathElem.html +2 -1
  297. package/docs/types/_saltcorn_db_common.Operator.html +2 -1
  298. package/docs/types/_saltcorn_db_common.PartialSome.html +2 -1
  299. package/docs/types/_saltcorn_db_common.PrimaryKeyValue.html +2 -1
  300. package/docs/types/_saltcorn_db_common.Row.html +2 -1
  301. package/docs/types/_saltcorn_db_common.SelectOptions.html +2 -1
  302. package/docs/types/_saltcorn_db_common.SqlAndValues.html +2 -1
  303. package/docs/types/_saltcorn_db_common.StrongRow.html +2 -1
  304. package/docs/types/_saltcorn_db_common.SubselectOptions.html +2 -1
  305. package/docs/types/_saltcorn_db_common.Value.html +2 -1
  306. package/docs/types/_saltcorn_db_common.Where.html +2 -1
  307. package/docs/types/_saltcorn_mobile_builder.IosCfg.html +1 -1
  308. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.FieldCfg.html +1 -1
  309. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.InputType.html +1 -1
  310. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_form.AdditionalButton.html +1 -1
  311. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryCfg.html +1 -1
  312. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryPack.html +1 -1
  313. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PageCfg.html +1 -1
  314. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PagePack.html +1 -1
  315. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginCfg.html +1 -1
  316. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginPack.html +1 -1
  317. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RoleCfg.html +1 -1
  318. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RolePack.html +1 -1
  319. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TableCfg.html +1 -1
  320. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TablePack.html +1 -1
  321. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerCfg.html +1 -1
  322. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerPack.html +1 -1
  323. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewCfg.html +1 -1
  324. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewPack.html +1 -1
  325. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.ConfigWorkflowStep.html +1 -1
  326. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.RunResult.html +1 -1
  327. package/docs/types/_saltcorn_types.Types.base_types.Action.html +1 -1
  328. package/docs/types/_saltcorn_types.Types.base_types.AuthenticationMethod.html +1 -1
  329. package/docs/types/_saltcorn_types.Types.base_types.CalcJoinfield.html +1 -1
  330. package/docs/types/_saltcorn_types.Types.base_types.CapacitorPlugin.html +1 -1
  331. package/docs/types/_saltcorn_types.Types.base_types.CodePagePack.html +1 -1
  332. package/docs/types/_saltcorn_types.Types.base_types.Column.html +1 -1
  333. package/docs/types/_saltcorn_types.Types.base_types.ConnectObjType.html +4 -2
  334. package/docs/types/_saltcorn_types.Types.base_types.ConnectedObjects.html +1 -1
  335. package/docs/types/_saltcorn_types.Types.base_types.CopilotSkill.html +1 -1
  336. package/docs/types/_saltcorn_types.Types.base_types.ErrorObj.html +1 -1
  337. package/docs/types/_saltcorn_types.Types.base_types.FieldLike.html +1 -1
  338. package/docs/types/_saltcorn_types.Types.base_types.FieldView.html +1 -1
  339. package/docs/types/_saltcorn_types.Types.base_types.Header.html +1 -1
  340. package/docs/types/_saltcorn_types.Types.base_types.JoinFieldOption.html +1 -1
  341. package/docs/types/_saltcorn_types.Types.base_types.Layout.html +1 -1
  342. package/docs/types/_saltcorn_types.Types.base_types.MobileConfig.html +1 -1
  343. package/docs/types/_saltcorn_types.Types.base_types.ModelPattern.html +1 -1
  344. package/docs/types/_saltcorn_types.Types.base_types.Pack.html +1 -1
  345. package/docs/types/_saltcorn_types.Types.base_types.Plugin.html +1 -1
  346. package/docs/types/_saltcorn_types.Types.base_types.PluginFunction.html +1 -1
  347. package/docs/types/_saltcorn_types.Types.base_types.PluginLayout.html +1 -1
  348. package/docs/types/_saltcorn_types.Types.base_types.PluginRoute.html +1 -1
  349. package/docs/types/_saltcorn_types.Types.base_types.PluginSourceType.html +1 -1
  350. package/docs/types/_saltcorn_types.Types.base_types.PluginType.html +1 -1
  351. package/docs/types/_saltcorn_types.Types.base_types.PluginWrap.html +1 -1
  352. package/docs/types/_saltcorn_types.Types.base_types.PluginWrapArg.html +1 -1
  353. package/docs/types/_saltcorn_types.Types.base_types.RelationOption.html +1 -1
  354. package/docs/types/_saltcorn_types.Types.base_types.Req.html +1 -1
  355. package/docs/types/_saltcorn_types.Types.base_types.Res.html +1 -1
  356. package/docs/types/_saltcorn_types.Types.base_types.ResultType.html +1 -1
  357. package/docs/types/_saltcorn_types.Types.base_types.RouteAction.html +1 -1
  358. package/docs/types/_saltcorn_types.Types.base_types.RunExtra.html +1 -1
  359. package/docs/types/_saltcorn_types.Types.base_types.SlugStepType.html +1 -1
  360. package/docs/types/_saltcorn_types.Types.base_types.StepResType.html +1 -1
  361. package/docs/types/_saltcorn_types.Types.base_types.SubField.html +1 -1
  362. package/docs/types/_saltcorn_types.Types.base_types.TableProvider.html +1 -1
  363. package/docs/types/_saltcorn_types.Types.base_types.TableQuery.html +1 -1
  364. package/docs/types/_saltcorn_types.Types.base_types.Tablely.html +1 -1
  365. package/docs/types/_saltcorn_types.Types.base_types.ViewTemplate.html +4 -2
  366. package/docs/types/_saltcorn_types.Types.common_types.ErrorMessage.html +1 -1
  367. package/docs/types/_saltcorn_types.Types.common_types.GenObj.html +1 -1
  368. package/docs/types/_saltcorn_types.Types.common_types.ReqRes.html +1 -1
  369. package/docs/types/_saltcorn_types.Types.common_types.ResultMessage.html +1 -1
  370. package/docs/types/_saltcorn_types.Types.common_types.SuccessMessage.html +1 -1
  371. package/docs/types/_saltcorn_types.Types.common_types.Type.html +1 -1
  372. package/docs/variables/_saltcorn_data.db.html +1 -1
  373. package/docs/variables/_saltcorn_data.migrations.html +1 -1
  374. package/docs/variables/_saltcorn_data.models.config.available_languages.html +1 -1
  375. package/docs/variables/_saltcorn_data.models.config.configTypes.html +1 -1
  376. package/docs/variables/_saltcorn_data.models.scheduler.runScheduler.html +1 -1
  377. package/docs/variables/_saltcorn_data.plugin_helper.run_action_column.html +1 -1
  378. package/docs/variables/_saltcorn_data.utils.NotAuthorized.html +1 -1
  379. package/docs/variables/_saltcorn_data.utils.isPushEnabled.html +1 -1
  380. package/docs/variables/_saltcorn_data.utils.sleep.html +1 -1
  381. package/docs/variables/_saltcorn_db_common.multi_tenant.tenantNamespace.html +2 -1
  382. package/help/JavaScript action code.tmd +10 -0
  383. package/locales/en.json +32 -1
  384. package/package.json +9 -9
  385. package/public/log_viewer_utils.js +3 -2
  386. package/public/saltcorn-common.js +94 -39
  387. package/public/saltcorn.css +12 -0
  388. package/public/saltcorn.js +44 -6
  389. package/routes/actions.js +14 -0
  390. package/routes/admin.js +71 -18
  391. package/routes/common_lists.js +8 -1
  392. package/routes/eventlog.js +20 -0
  393. package/routes/fields.js +1 -1
  394. package/routes/menu.js +98 -6
  395. package/routes/page.js +4 -1
  396. package/routes/pageedit.js +1 -0
  397. package/routes/plugins.js +8 -7
  398. package/routes/tables.js +11 -0
  399. package/routes/view.js +12 -3
  400. package/serve.js +97 -43
  401. package/tests/admin.test.js +3 -3
  402. package/tests/auth.test.js +1 -0
  403. package/tests/viewedit.test.js +2 -0
  404. package/wrapper.js +23 -191
package/routes/menu.js CHANGED
@@ -119,6 +119,8 @@ const menuForm = async (req) => {
119
119
  "View",
120
120
  "Page",
121
121
  "Page Group",
122
+ "Admin Page",
123
+ "User Page",
122
124
  "Link",
123
125
  "Header",
124
126
  "Dynamic",
@@ -150,6 +152,39 @@ const menuForm = async (req) => {
150
152
  options: pages.map((r) => r.name),
151
153
  showIf: { type: "Page" },
152
154
  },
155
+ {
156
+ name: "admin_page",
157
+ label: req.__("Admin Page"),
158
+ input_type: "select",
159
+ class: "item-menu",
160
+ options: [
161
+ "Tables",
162
+ "Views",
163
+ "Pages",
164
+ "About application",
165
+ "Modules",
166
+ "Users and security",
167
+ "Site structure",
168
+ "Files",
169
+ "Events",
170
+ "Settings",
171
+ ],
172
+ showIf: { type: "Admin Page" },
173
+ },
174
+ {
175
+ name: "user_page",
176
+ label: req.__("User Page"),
177
+ input_type: "select",
178
+ class: "item-menu",
179
+ options: [
180
+ "Notifications",
181
+ "User settings",
182
+ "Login",
183
+ "Logout",
184
+ "Signup",
185
+ ],
186
+ showIf: { type: "User Page" },
187
+ },
153
188
  {
154
189
  name: "viewname",
155
190
  label: req.__("View"),
@@ -247,6 +282,16 @@ const menuForm = async (req) => {
247
282
  required: true,
248
283
  showIf: { type: "Dynamic" },
249
284
  },
285
+ {
286
+ name: "user_menu_header",
287
+ label: req.__("User menu header"),
288
+ sublabel: req.__("Some themes display this header differently"),
289
+ type: "Bool",
290
+ class: "item-menu",
291
+ required: false,
292
+ default: false,
293
+ showIf: { type: "Header" },
294
+ },
250
295
  {
251
296
  name: "text",
252
297
  label: req.__("Text label"),
@@ -263,6 +308,8 @@ const menuForm = async (req) => {
263
308
  "Dynamic",
264
309
  "Search",
265
310
  "Action",
311
+ "Admin Page",
312
+ "User Page",
266
313
  ],
267
314
  },
268
315
  },
@@ -274,7 +321,16 @@ const menuForm = async (req) => {
274
321
  html: `<button type="button" id="myEditor_icon" class="btn btn-outline-secondary"></button>`,
275
322
  },
276
323
  showIf: {
277
- type: ["View", "Page", "Page Group", "Link", "Header", "Action"],
324
+ type: [
325
+ "View",
326
+ "Page",
327
+ "Page Group",
328
+ "Link",
329
+ "Header",
330
+ "Action",
331
+ "Admin Page",
332
+ "User Page",
333
+ ],
278
334
  },
279
335
  },
280
336
  {
@@ -282,7 +338,16 @@ const menuForm = async (req) => {
282
338
  class: "item-menu",
283
339
  input_type: "hidden",
284
340
  showIf: {
285
- type: ["View", "Page", "Page Group", "Link", "Header", "Action"],
341
+ type: [
342
+ "View",
343
+ "Page",
344
+ "Page Group",
345
+ "Link",
346
+ "Header",
347
+ "Action",
348
+ "Admin Page",
349
+ "User Page",
350
+ ],
286
351
  },
287
352
  },
288
353
  {
@@ -301,6 +366,8 @@ const menuForm = async (req) => {
301
366
  "Dynamic",
302
367
  "Search",
303
368
  "Action",
369
+ "Admin Page",
370
+ "User Page",
304
371
  ],
305
372
  },
306
373
  },
@@ -343,7 +410,16 @@ const menuForm = async (req) => {
343
410
  type: "Bool",
344
411
  required: false,
345
412
  class: "item-menu",
346
- showIf: { type: ["View", "Page", "Page Group", "Link"] },
413
+ showIf: {
414
+ type: [
415
+ "View",
416
+ "Page",
417
+ "Page Group",
418
+ "Link",
419
+ "Admin Page",
420
+ "User Page",
421
+ ],
422
+ },
347
423
  },
348
424
  {
349
425
  name: "in_modal",
@@ -351,7 +427,16 @@ const menuForm = async (req) => {
351
427
  type: "Bool",
352
428
  required: false,
353
429
  class: "item-menu",
354
- showIf: { type: ["View", "Page", "Page Group", "Link"] },
430
+ showIf: {
431
+ type: [
432
+ "View",
433
+ "Page",
434
+ "Page Group",
435
+ "Link",
436
+ "Admin Page",
437
+ "User Page",
438
+ ],
439
+ },
355
440
  },
356
441
  {
357
442
  name: "style",
@@ -369,6 +454,8 @@ const menuForm = async (req) => {
369
454
  "Header",
370
455
  "Dynamic",
371
456
  "Action",
457
+ "Admin Page",
458
+ "User Page",
372
459
  ],
373
460
  },
374
461
  attributes: {
@@ -403,6 +490,8 @@ const menuForm = async (req) => {
403
490
  "Search",
404
491
  "Separator",
405
492
  "Action",
493
+ "Admin Page",
494
+ "User Page",
406
495
  ],
407
496
  },
408
497
  sublabel: req.__("Not all themes support all locations"),
@@ -628,14 +717,17 @@ router.post(
628
717
  "/action/:rndid",
629
718
  error_catcher(async (req, res, next) => {
630
719
  const state = getState();
631
- const maintenanceModeEnabled = state.getConfig("maintenance_mode_enabled", false);
720
+ const maintenanceModeEnabled = state.getConfig(
721
+ "maintenance_mode_enabled",
722
+ false
723
+ );
632
724
 
633
725
  if (maintenanceModeEnabled && (!req.user || req.user.role_id > 1)) {
634
726
  res.status(503).json({ error: "in maintenance mode" });
635
727
  return;
636
728
  }
637
729
  next();
638
- }),
730
+ })
639
731
  );
640
732
 
641
733
  const getIcons = () => {
package/routes/page.js CHANGED
@@ -46,18 +46,21 @@ const findPageOrGroup = (pagename) => {
46
46
 
47
47
  const runPage = async (page, req, res, tic) => {
48
48
  const role = req.user && req.user.id ? req.user.role_id : 100;
49
+ // let resultCollector = {};
49
50
  if (role <= page.min_role) {
50
51
  const contents = await page.run(req.query, { res, req });
51
52
  const title = scan_for_page_title(contents, page.title);
52
53
  const tock = new Date();
53
54
  const ms = tock.getTime() - tic.getTime();
54
- if (!isTest())
55
+
56
+ if (!isTest()) {
55
57
  Trigger.emitEvent("PageLoad", null, req.user, {
56
58
  text: req.__("Page '%s' was loaded", page.name),
57
59
  type: "page",
58
60
  name: page.name,
59
61
  render_time: ms,
60
62
  });
63
+ }
61
64
  if (contents.html_file) await sendHtmlFile(req, res, contents.html_file);
62
65
  else
63
66
  res.sendWrap(
@@ -201,6 +201,7 @@ const pageBuilderData = async (req, context) => {
201
201
  const actionsNotRequiringRow = Trigger.action_options({
202
202
  notRequireRow: true,
203
203
  apiNeverTriggers: true,
204
+ forBuilder: true,
204
205
  builtInLabel: "Page Actions",
205
206
  builtIns: ["GoBack"],
206
207
  });
package/routes/plugins.js CHANGED
@@ -238,7 +238,7 @@ const cfg_link = (req, row) => {
238
238
  if (plugin.configuration_workflow)
239
239
  return a(
240
240
  {
241
- class: "btn btn-secondary btn-sm d-inline me-1",
241
+ class: "btn btn-secondary btn-sm d-inline-block",
242
242
  role: "button",
243
243
  href: `/plugins/configure/${encodeURIComponent(row.name)}`,
244
244
  title: req.__("Configure plugin"),
@@ -256,7 +256,7 @@ const cfg_link = (req, row) => {
256
256
  const info_link = (req, row) =>
257
257
  a(
258
258
  {
259
- class: "btn btn-secondary btn-sm d-inline",
259
+ class: "btn btn-secondary btn-sm d-inline-block me-1",
260
260
  role: "button",
261
261
  href: `/plugins/info/${encodeURIComponent(row.name)}`,
262
262
  title: req.__("Information about plugin"),
@@ -306,7 +306,7 @@ const store_item_html = (req) => (item) => ({
306
306
  !item.installed &&
307
307
  item.plugin &&
308
308
  div(
309
- { class: "me-2 d-inline" },
309
+ { class: "d-inline" },
310
310
  post_btn(
311
311
  `/plugins/install/${encodeURIComponent(item.name)}`,
312
312
  req.__("Install"),
@@ -331,10 +331,11 @@ const store_item_html = (req) => (item) => ({
331
331
  onClick: "press_store_button(this)",
332
332
  }
333
333
  ),
334
-
335
- item.installed && item.plugin && cfg_link(req, item),
336
- item.installed && item.plugin && info_link(req, item),
337
-
334
+ div(
335
+ { class: "btn-group", role: "group" },
336
+ item.installed && item.plugin && cfg_link(req, item),
337
+ item.installed && item.plugin && info_link(req, item)
338
+ ),
338
339
  item.installed &&
339
340
  item.pack &&
340
341
  post_btn(
package/routes/tables.js CHANGED
@@ -1309,6 +1309,17 @@ router.post(
1309
1309
  } else rest.ownership_formula = null;
1310
1310
  await db.withTransaction(async () => {
1311
1311
  await table.update(rest);
1312
+ // Update table field's min_role_write attributes
1313
+ const fields = table.getFields();
1314
+
1315
+ for (const f of fields) {
1316
+ if (f.attributes?.min_role_write) {
1317
+ f.attributes.min_role_write = parseInt(rest.min_role_write);
1318
+ await f.update({
1319
+ attributes: f.attributes,
1320
+ });
1321
+ }
1322
+ }
1312
1323
  });
1313
1324
  await getState().refresh_tables();
1314
1325
  if (!req.xhr) {
package/routes/view.js CHANGED
@@ -43,7 +43,10 @@ router.get(
43
43
  ["/:viewname", "/:viewname/*slug"],
44
44
  error_catcher(async (req, res) => {
45
45
  const state = getState();
46
- const maintenanceModeEnabled = state.getConfig("maintenance_mode_enabled", false);
46
+ const maintenanceModeEnabled = state.getConfig(
47
+ "maintenance_mode_enabled",
48
+ false
49
+ );
47
50
  const maintenanceModePage = state.getConfig("maintenance_mode_page", "");
48
51
 
49
52
  if (
@@ -242,7 +245,10 @@ router.post(
242
245
  "/:viewname/:route",
243
246
  error_catcher(async (req, res, next) => {
244
247
  const state = getState();
245
- const maintenanceModeEnabled = state.getConfig("maintenance_mode_enabled", false);
248
+ const maintenanceModeEnabled = state.getConfig(
249
+ "maintenance_mode_enabled",
250
+ false
251
+ );
246
252
 
247
253
  if (maintenanceModeEnabled && (!req.user || req.user.role_id > 1)) {
248
254
  res.status(503).json({ error: "in maintenance mode" });
@@ -287,7 +293,10 @@ router.post(
287
293
  ["/:viewname", "/:viewname/*slug"],
288
294
  error_catcher(async (req, res, next) => {
289
295
  const state = getState();
290
- const maintenanceModeEnabled = state.getConfig("maintenance_mode_enabled", false);
296
+ const maintenanceModeEnabled = state.getConfig(
297
+ "maintenance_mode_enabled",
298
+ false
299
+ );
291
300
  if (maintenanceModeEnabled && (!req.user || req.user.role_id > 1)) {
292
301
  res.status(503).send("Page Unavailable: in maintenance mode");
293
302
  return;
package/serve.js CHANGED
@@ -14,6 +14,7 @@ const {
14
14
  init_multi_tenant,
15
15
  restart_tenant,
16
16
  add_tenant,
17
+ get_other_domain_tenant,
17
18
  } = require("@saltcorn/data/db/state");
18
19
  const { create_tenant } = require("@saltcorn/admin-models/models/tenant");
19
20
 
@@ -79,17 +80,6 @@ const ensureJwtSecret = () => {
79
80
  }
80
81
  };
81
82
 
82
- /**
83
- * Ensure the engines cache is up to date with the current sc version
84
- */
85
- const ensureEnginesCache = async () => {
86
- const cacheScVersion = await getConfig("engines_cache_sc_version", "");
87
- if (!cacheScVersion || cacheScVersion !== getState().scVersion) {
88
- await setConfig("engines_cache", {});
89
- await setConfig("engines_cache_sc_version", getState().scVersion);
90
- }
91
- };
92
-
93
83
  /**
94
84
  * validate all plugins folders and remove invalid entries
95
85
  * A folder is invalid when it has dependencies but not node_modules directory
@@ -205,12 +195,6 @@ const initMaster = async ({ disableMigrate }, useClusterAdaptor = true) => {
205
195
  const tenants = await getAllTenants();
206
196
  await init_multi_tenant(loadAllPlugins, disableMigrate, tenants);
207
197
  }
208
- eachTenant(async () => {
209
- const state = getState();
210
- if (state) {
211
- await state.setConfig("joined_log_socket_ids", []);
212
- }
213
- });
214
198
  if (useClusterAdaptor) setupPrimary();
215
199
  };
216
200
 
@@ -234,7 +218,11 @@ const workerDispatchMsg = ({ tenant, ...msg }) => {
234
218
  console.error("no State for tenant", tenant);
235
219
  return;
236
220
  }
237
- if (msg.refresh) getState()[`refresh_${msg.refresh}`](true);
221
+ if (msg.refresh) {
222
+ if (msg.refresh === "ephemeral_config")
223
+ getState().refresh_ephemeral_config(msg.key, msg.value);
224
+ else getState()[`refresh_${msg.refresh}`](true);
225
+ }
238
226
  if (msg.createTenant) {
239
227
  const tenant_template = getState().getConfig("tenant_template");
240
228
  add_tenant(msg.createTenant);
@@ -290,7 +278,8 @@ const onMessageFromWorker =
290
278
  ///ie from saltcorn
291
279
  //broadcast
292
280
  Object.entries(cluster.workers).forEach(([wpid, w]) => {
293
- if (wpid !== pid) w.send(msg);
281
+ //if it is plugin refresh, we need sender to get it as wll
282
+ if (wpid !== pid || msg?.refresh_plugin_cfg) w.send(msg);
294
283
  });
295
284
  workerDispatchMsg(msg); //also master
296
285
  return true;
@@ -322,7 +311,6 @@ module.exports =
322
311
  } = {}) => {
323
312
  if (cluster.isMaster) {
324
313
  ensureJwtSecret();
325
- await ensureEnginesCache();
326
314
  await ensurePluginsFolder();
327
315
  await ensureNotificationSubscriptions();
328
316
  }
@@ -382,6 +370,13 @@ module.exports =
382
370
  masterState.listeningTo.add(id);
383
371
  }
384
372
  });
373
+ getState().sendMessageToWorkers = (msg) => {
374
+ Object.entries(cluster.workers).forEach(([wpid, w]) => {
375
+ w.send(msg);
376
+ });
377
+ workerDispatchMsg(msg); //also master
378
+ };
379
+
385
380
  if (masterState.listeningTo.size < useNCpus)
386
381
  setTimeout(initMasterListeners, 250);
387
382
  };
@@ -420,12 +415,21 @@ module.exports =
420
415
 
421
416
  if (forkAnyWorkers) {
422
417
  for (let i = 0; i < useNCpus; i++) addWorker(cluster.fork());
418
+ getState().sendMessageToWorkers = (msg) => {
419
+ Object.entries(cluster.workers).forEach(([wpid, w]) => {
420
+ w.send(msg);
421
+ });
422
+ workerDispatchMsg(msg); //also master
423
+ };
423
424
 
424
425
  cluster.on("exit", (worker, code, signal) => {
425
426
  console.log(`worker ${worker.process.pid} died`);
426
427
  addWorker(cluster.fork());
427
428
  });
428
429
  } else {
430
+ getState().sendMessageToWorkers = (msg) => {
431
+ workerDispatchMsg(msg); //also master
432
+ };
429
433
  await nonGreenlockWorkerSetup(appargs, port, host);
430
434
  runScheduler({
431
435
  port,
@@ -508,6 +512,16 @@ const nonGreenlockWorkerSetup = async (appargs, port, host) => {
508
512
  getState().processSend("Start");
509
513
  };
510
514
 
515
+ const tenantFromSocket = (socket, hostPartOffset) => {
516
+ const header = socket.request.headers.host;
517
+ const hostOnly = header?.split(":")[0];
518
+ if (hostOnly) {
519
+ const tenant = get_other_domain_tenant(hostOnly);
520
+ if (tenant) return tenant;
521
+ }
522
+ return get_tenant_from_req(socket.request, hostPartOffset);
523
+ };
524
+
511
525
  /**
512
526
  *
513
527
  * @param {...*} servers
@@ -544,14 +558,29 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
544
558
  .emit("log_msg", { text: msg, time, level });
545
559
  });
546
560
 
547
- // Real-time collaboration emitter
561
+ // Real-time collaboration emitter (tied to views)
548
562
  getState().setCollabEmitter((tenant, type, data) => {
549
563
  io.of("/").to(`_${tenant}_collab_room_`).emit(type, data);
550
564
  });
551
565
 
566
+ // dynamic updates emitter (for run_js_actions)
567
+ getState().setDynamicUpdateEmitter((tenant, data, userIds) => {
568
+ if (userIds) {
569
+ for (const userId of userIds) {
570
+ io.of("/")
571
+ .to(`_${tenant}:${userId}_dynamic_update_room`)
572
+ .emit("dynamic_update", data);
573
+ }
574
+ } else {
575
+ io.of("/")
576
+ .to(`_${tenant}_dynamic_update_room`)
577
+ .emit("dynamic_update", data);
578
+ }
579
+ });
580
+
552
581
  io.of("/").on("connection", (socket) => {
553
582
  socket.on("join_room", ([viewname, room_id]) => {
554
- const ten = get_tenant_from_req(socket.request) || "public";
583
+ const ten = tenantFromSocket(socket, subdomainOffset) || "public";
555
584
  const f = () => {
556
585
  try {
557
586
  const view = View.findOne({ name: viewname });
@@ -571,8 +600,7 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
571
600
  });
572
601
 
573
602
  socket.on("join_log_room", async (callback) => {
574
- const tenant =
575
- get_tenant_from_req(socket.request, subdomainOffset) || "public";
603
+ const tenant = tenantFromSocket(socket, subdomainOffset) || "public";
576
604
  const f = async () => {
577
605
  try {
578
606
  const user = socket.request.user;
@@ -596,14 +624,13 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
596
624
  callback({ status: "error", msg: err.message || "unknown error" });
597
625
  }
598
626
  };
599
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
627
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
600
628
  else await f();
601
629
  });
602
630
 
603
631
  // or join the room more generally and later register views ??
604
632
  socket.on("join_collab_room", async (viewname, callback) => {
605
- const tenant =
606
- get_tenant_from_req(socket.request, subdomainOffset) || "public";
633
+ const tenant = tenantFromSocket(socket, subdomainOffset) || "public";
607
634
  const f = async () => {
608
635
  try {
609
636
  const view = View.findOne({ name: viewname });
@@ -620,20 +647,49 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
620
647
  callback({ status: "error", msg: err.message || "unknown error" });
621
648
  }
622
649
  };
623
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
650
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
651
+ else await f();
652
+ });
653
+
654
+ // join_dynamic_update_room for events emitted from run_js_actions
655
+ socket.on("join_dynamic_update_room", async (callback) => {
656
+ const tenant = tenantFromSocket(socket, subdomainOffset) || "public";
657
+ const f = async () => {
658
+ try {
659
+ const enabled = getState().getConfig("enable_dynamic_updates", true);
660
+ if (!enabled) throw new Error("Dynamic updates are not enabled");
661
+ const user = socket.request.user;
662
+ if (!user) throw new Error("Not authorized");
663
+ socket.join(`_${tenant}_dynamic_update_room`);
664
+ socket.join(`_${tenant}:${user.id}_dynamic_update_room`);
665
+ if (typeof callback === "function") callback({ status: "ok" });
666
+ } catch (err) {
667
+ getState().log(1, `Socket join_dynamic_update_room: ${err.stack}`);
668
+ if (typeof callback === "function")
669
+ callback({ status: "error", msg: err.message || "unknown error" });
670
+ }
671
+ };
672
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
624
673
  else await f();
625
674
  });
626
675
 
627
676
  socket.on("disconnect", async () => {
628
- const tenant =
629
- get_tenant_from_req(socket.request, subdomainOffset) || "public";
677
+ const tenant = tenantFromSocket(socket, subdomainOffset) || "public";
630
678
  const f = async () => {
631
- const socketIds = await getState().getConfig("joined_log_socket_ids");
632
- const newSocketIds = socketIds.filter((id) => id !== socket.id);
633
- await getState().setConfig("joined_log_socket_ids", newSocketIds);
679
+ const state = getState();
680
+ if (state) {
681
+ const socketIds = state.getConfig("joined_log_socket_ids");
682
+ const newSocketIds = socketIds.filter((id) => id !== socket.id);
683
+ await state.setConfig("joined_log_socket_ids", newSocketIds);
684
+ } else {
685
+ console.error("No state found in socket disconnect");
686
+ console.error("The current tenantSchema is:", db.getTenantSchema());
687
+ console.error("The current tenant from request is:", tenant);
688
+ console.error("node version:", process.version);
689
+ }
634
690
  };
635
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
636
- else f();
691
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
692
+ else await f();
637
693
  });
638
694
  });
639
695
 
@@ -643,8 +699,7 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
643
699
  socket.on(
644
700
  "open_data_stream",
645
701
  async ([viewName, id, fieldName, fieldView, targetOpts], callback) => {
646
- const tenant =
647
- get_tenant_from_req(socket.request, subdomainOffset) || "public";
702
+ const tenant = tenantFromSocket(socket, subdomainOffset) || "public";
648
703
  const f = async () => {
649
704
  try {
650
705
  const user = socket.request.user;
@@ -681,8 +736,8 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
681
736
  callback({ status: "error", msg: err.message || "unknown error" });
682
737
  }
683
738
  };
684
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
685
- else f();
739
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
740
+ else await f();
686
741
  }
687
742
  );
688
743
  socket.on("write_to_stream", async (data, callback) => {
@@ -723,8 +778,7 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
723
778
  });
724
779
 
725
780
  socket.on("disconnect", async () => {
726
- const tenant =
727
- get_tenant_from_req(socket.request, subdomainOffset) || "public";
781
+ const tenant = tenantFromSocket(socket, subdomainOffset) || "public";
728
782
  const f = async () => {
729
783
  if (dataStream)
730
784
  dataStream.close((err) => {
@@ -744,8 +798,8 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
744
798
  }
745
799
  });
746
800
  };
747
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
748
- else f();
801
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
802
+ else await f();
749
803
  });
750
804
  });
751
805
  };
@@ -387,7 +387,7 @@ describe("actions", () => {
387
387
  .send("table_id=2")
388
388
  .send("name=mynewaction")
389
389
  .send("when_trigger=Insert")
390
- .expect(toRedirect("/actions/configure/3"));
390
+ .expect(toRedirect("/actions/configure/7"));
391
391
  });
392
392
  it("show edit", async () => {
393
393
  const app = await getApp({ disableCsrf: true });
@@ -451,9 +451,9 @@ describe("actions", () => {
451
451
  .send("action=run_js_code")
452
452
  .send("when_trigger=API+call")
453
453
  .send("min_role=1")
454
- .expect(toRedirect("/actions/configure/4"));
454
+ .expect(toRedirect("/actions/configure/8"));
455
455
  await request(app)
456
- .post("/actions/configure/4")
456
+ .post("/actions/configure/8")
457
457
  .set("Cookie", loginCookie)
458
458
  .send("code=return 27")
459
459
  .expect(toRedirect("/actions/"));
@@ -166,6 +166,7 @@ describe("AuthTest forgot password", () => {
166
166
  .post("/auth/reset")
167
167
  .send("email=staff1@foo.com")
168
168
  .send("password=bazzRGGR65zoo")
169
+ .send("confirm_password=bazzRGGR65zoo")
169
170
  .send("token=" + token)
170
171
  .expect(toRedirect("/auth/login"));
171
172
  await request(app)
@@ -208,6 +208,7 @@ describe("viewedit new List", () => {
208
208
  .send("contextEnc=" + ctx)
209
209
  .send("stepName=Options")
210
210
  .send("_row_click_type=Nothing")
211
+ .send("_cell_valign=Middle")
211
212
  .set("Cookie", loginCookie)
212
213
  .expect(toRedirect("/viewedit"));
213
214
  });
@@ -332,6 +333,7 @@ describe("viewedit new List with one field", () => {
332
333
  .send("contextEnc=" + ctx)
333
334
  .send("stepName=Options")
334
335
  .send("_row_click_type=Nothing")
336
+ .send("_cell_valign=Middle")
335
337
  .set("Cookie", loginCookie)
336
338
  .expect(toRedirect("/viewedit"));
337
339
  });