@saltcorn/server 1.3.1-beta.1 → 1.3.1-beta.10

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 +54 -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 +1 -1
  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 +89 -39
  387. package/public/saltcorn.css +12 -0
  388. package/public/saltcorn.js +8 -0
  389. package/routes/actions.js +14 -0
  390. package/routes/admin.js +5 -3
  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 +76 -13
  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 +24 -192
package/routes/actions.js CHANGED
@@ -179,6 +179,7 @@ const triggerForm = async (req, trigger) => {
179
179
  workflow: true,
180
180
  });
181
181
  const table_triggers = ["Insert", "Update", "Delete", "Validate"];
182
+ const additional_triggers_with_onlyif = ["Login", "PageLoad"];
182
183
  const action_options = {};
183
184
  const actionsNotRequiringRow = Trigger.action_options({
184
185
  notRequireRow: true,
@@ -337,6 +338,19 @@ const triggerForm = async (req, trigger) => {
337
338
  type: "String",
338
339
  showIf: { when_trigger: ["API call"], _raw_output: true },
339
340
  },
341
+ {
342
+ name: "_only_if",
343
+ label: req.__("Only if"),
344
+ type: "String",
345
+ class: "validate-expression",
346
+ sublabel: req.__(
347
+ "Optional JavaScript expression to determine if the trigger should run."
348
+ ),
349
+ parent_field: "configuration",
350
+ showIf: {
351
+ when_trigger: [...table_triggers, ...additional_triggers_with_onlyif],
352
+ },
353
+ },
340
354
  ],
341
355
  });
342
356
  // if (trigger) {
package/routes/admin.js CHANGED
@@ -500,11 +500,12 @@ router.get(
500
500
  "backup_s3_access_secret"
501
501
  );
502
502
  backupForm.values.backup_s3_region =
503
- getState().getConfig("backup_s3_region");
503
+ getState().getConfig("backup_s3_region");
504
504
  aBackupFilePrefixForm.values.backup_with_event_log = getState().getConfig(
505
505
  "backup_with_event_log"
506
506
  );
507
- aBackupFilePrefixForm.values.backup_password = getState().getConfig("backup_password");
507
+ aBackupFilePrefixForm.values.backup_password =
508
+ getState().getConfig("backup_password");
508
509
  const aSnapshotForm = snapshotForm(req);
509
510
  aSnapshotForm.values.snapshots_enabled =
510
511
  getState().getConfig("snapshots_enabled");
@@ -4126,6 +4127,8 @@ router.post(
4126
4127
  await db.deleteWhere("_sc_config", { not: { key: "letsencrypt" } });
4127
4128
  }
4128
4129
  await getState().refresh();
4130
+ await require("@saltcorn/data/standard-menu")();
4131
+
4129
4132
  if (form.values.users) {
4130
4133
  await db.deleteWhere("_sc_notifications");
4131
4134
 
@@ -4532,7 +4535,6 @@ admin_config_route({
4532
4535
  path: "/notifications",
4533
4536
  super_path: "/admin",
4534
4537
  field_names: [
4535
- "notification_in_menu",
4536
4538
  { section_header: "Progressive Web Application" },
4537
4539
  "pwa_enabled",
4538
4540
  { name: "pwa_display", showIf: { pwa_enabled: true } },
@@ -138,6 +138,7 @@ const tablesList = async (
138
138
  hover: true,
139
139
  tableClass: listClass(tagId, showList),
140
140
  tableId: domId,
141
+ class: "table-valign-middle",
141
142
  }
142
143
  ) +
143
144
  (tables.length == 0 && !filterOnTag
@@ -442,6 +443,7 @@ const viewsList = async (
442
443
  hover: true,
443
444
  tableClass: listClass(tagId, showList),
444
445
  tableId: domId,
446
+ class: "table-valign-middle",
445
447
  }
446
448
  ) +
447
449
  (views.length == 0 && !filterOnTag
@@ -625,6 +627,7 @@ const getPageList = async (
625
627
  hover: true,
626
628
  tableClass: tagId ? `collapse ${showList ? "show" : ""}` : "",
627
629
  tableId: domId,
630
+ class: "table-valign-middle",
628
631
  }
629
632
  );
630
633
  };
@@ -657,6 +660,7 @@ const getPageGroupList = (rows, roles, req) => {
657
660
  rows,
658
661
  {
659
662
  hover: true,
663
+ class: "table-valign-middle",
660
664
  }
661
665
  );
662
666
  };
@@ -729,6 +733,8 @@ const getTriggerList = async (
729
733
  )
730
734
  );
731
735
  };
736
+ const whenCanHaveTable = (when) =>
737
+ ["Insert", "Update", "Delete", "Validate", "Never"].includes(when);
732
738
  return mkTable(
733
739
  [
734
740
  { label: req.__("Name"), key: "name" },
@@ -781,7 +787,7 @@ const getTriggerList = async (
781
787
  {
782
788
  label: req.__("Table or Channel"),
783
789
  key: (r) =>
784
- r.table_name
790
+ r.table_name && whenCanHaveTable(r.when_trigger)
785
791
  ? user_can_inspect_tables
786
792
  ? a({ href: `/table/${r.table_name}` }, r.table_name)
787
793
  : r.table_name
@@ -807,6 +813,7 @@ const getTriggerList = async (
807
813
  hover: true,
808
814
  tableClass: tagId ? `collapse ${showList ? "show" : ""}` : "",
809
815
  tableId: domId,
816
+ class: "table-valign-middle",
810
817
  }
811
818
  );
812
819
  };
@@ -81,6 +81,18 @@ const logSettingsForm = async (req) => {
81
81
  input_type: "date",
82
82
  attributes: { minDate: new Date(), maxDate: hoursFuture(24 * 7 * 2) },
83
83
  },
84
+ {
85
+ input_type: "section_header",
86
+ label: req.__("Dynamic server side updates"),
87
+ },
88
+ {
89
+ name: "enable_dynamic_updates",
90
+ label: req.__("Enable dynamic updates"),
91
+ type: "Bool",
92
+ sublabel: req.__(
93
+ "Enable server side updates from within run_js_code actions"
94
+ ),
95
+ },
84
96
  {
85
97
  input_type: "section_header",
86
98
  label: req.__("Delete old workflow runs with status after days"),
@@ -168,6 +180,10 @@ router.get(
168
180
  "next_weekly_event",
169
181
  {}
170
182
  );
183
+ form.values.enable_dynamic_updates = getState().getConfig(
184
+ "enable_dynamic_updates",
185
+ true
186
+ );
171
187
  ["error", "finished", "running", "waiting"].forEach((k) => {
172
188
  let cfgk = `delete_${k}_workflows_days`;
173
189
  form.values[cfgk] = getState().getConfig(cfgk);
@@ -377,6 +393,10 @@ router.post(
377
393
  delete form.values[k];
378
394
  }
379
395
  }
396
+ await getState().setConfig(
397
+ "enable_dynamic_updates",
398
+ form.values.enable_dynamic_updates
399
+ );
380
400
  for (const status of ["error", "finished", "running", "waiting"]) {
381
401
  let k = `delete_${status}_workflows_days`;
382
402
  if (form.values[k]) {
package/routes/fields.js CHANGED
@@ -1530,7 +1530,7 @@ router.post(
1530
1530
  const table = Table.findOne({ name: table_name });
1531
1531
  const field = table.getField(field_name);
1532
1532
  let val = field.type?.read
1533
- ? field.type?.read(req.body[field_name])
1533
+ ? field.type?.read(req.body[field_name], field.attributes)
1534
1534
  : req.body[field_name];
1535
1535
  await db.withTransaction(async () => {
1536
1536
  await table.updateRow({ [field_name]: val }, pk, req.user);
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
@@ -290,7 +290,8 @@ const onMessageFromWorker =
290
290
  ///ie from saltcorn
291
291
  //broadcast
292
292
  Object.entries(cluster.workers).forEach(([wpid, w]) => {
293
- if (wpid !== pid) w.send(msg);
293
+ //if it is plugin refresh, we need sender to get it as wll
294
+ if (wpid !== pid || msg?.refresh_plugin_cfg) w.send(msg);
294
295
  });
295
296
  workerDispatchMsg(msg); //also master
296
297
  return true;
@@ -382,6 +383,13 @@ module.exports =
382
383
  masterState.listeningTo.add(id);
383
384
  }
384
385
  });
386
+ getState().sendMessageToWorkers = (msg) => {
387
+ Object.entries(cluster.workers).forEach(([wpid, w]) => {
388
+ w.send(msg);
389
+ });
390
+ workerDispatchMsg(msg); //also master
391
+ };
392
+
385
393
  if (masterState.listeningTo.size < useNCpus)
386
394
  setTimeout(initMasterListeners, 250);
387
395
  };
@@ -420,12 +428,21 @@ module.exports =
420
428
 
421
429
  if (forkAnyWorkers) {
422
430
  for (let i = 0; i < useNCpus; i++) addWorker(cluster.fork());
431
+ getState().sendMessageToWorkers = (msg) => {
432
+ Object.entries(cluster.workers).forEach(([wpid, w]) => {
433
+ w.send(msg);
434
+ });
435
+ workerDispatchMsg(msg); //also master
436
+ };
423
437
 
424
438
  cluster.on("exit", (worker, code, signal) => {
425
439
  console.log(`worker ${worker.process.pid} died`);
426
440
  addWorker(cluster.fork());
427
441
  });
428
442
  } else {
443
+ getState().sendMessageToWorkers = (msg) => {
444
+ workerDispatchMsg(msg); //also master
445
+ };
429
446
  await nonGreenlockWorkerSetup(appargs, port, host);
430
447
  runScheduler({
431
448
  port,
@@ -544,11 +561,26 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
544
561
  .emit("log_msg", { text: msg, time, level });
545
562
  });
546
563
 
547
- // Real-time collaboration emitter
564
+ // Real-time collaboration emitter (tied to views)
548
565
  getState().setCollabEmitter((tenant, type, data) => {
549
566
  io.of("/").to(`_${tenant}_collab_room_`).emit(type, data);
550
567
  });
551
568
 
569
+ // dynamic updates emitter (for run_js_actions)
570
+ getState().setDynamicUpdateEmitter((tenant, data, userIds) => {
571
+ if (userIds) {
572
+ for (const userId of userIds) {
573
+ io.of("/")
574
+ .to(`_${tenant}:${userId}_dynamic_update_room`)
575
+ .emit("dynamic_update", data);
576
+ }
577
+ } else {
578
+ io.of("/")
579
+ .to(`_${tenant}_dynamic_update_room`)
580
+ .emit("dynamic_update", data);
581
+ }
582
+ });
583
+
552
584
  io.of("/").on("connection", (socket) => {
553
585
  socket.on("join_room", ([viewname, room_id]) => {
554
586
  const ten = get_tenant_from_req(socket.request) || "public";
@@ -596,7 +628,7 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
596
628
  callback({ status: "error", msg: err.message || "unknown error" });
597
629
  }
598
630
  };
599
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
631
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
600
632
  else await f();
601
633
  });
602
634
 
@@ -620,7 +652,30 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
620
652
  callback({ status: "error", msg: err.message || "unknown error" });
621
653
  }
622
654
  };
623
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
655
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
656
+ else await f();
657
+ });
658
+
659
+ // join_dynamic_update_room for events emitted from run_js_actions
660
+ socket.on("join_dynamic_update_room", async (callback) => {
661
+ const tenant =
662
+ get_tenant_from_req(socket.request, subdomainOffset) || "public";
663
+ const f = async () => {
664
+ try {
665
+ const enabled = getState().getConfig("enable_dynamic_updates", true);
666
+ if (!enabled) throw new Error("Dynamic updates are not enabled");
667
+ const user = socket.request.user;
668
+ if (!user) throw new Error("Not authorized");
669
+ socket.join(`_${tenant}_dynamic_update_room`);
670
+ socket.join(`_${tenant}:${user.id}_dynamic_update_room`);
671
+ if (typeof callback === "function") callback({ status: "ok" });
672
+ } catch (err) {
673
+ getState().log(1, `Socket join_dynamic_update_room: ${err.stack}`);
674
+ if (typeof callback === "function")
675
+ callback({ status: "error", msg: err.message || "unknown error" });
676
+ }
677
+ };
678
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
624
679
  else await f();
625
680
  });
626
681
 
@@ -628,12 +683,20 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
628
683
  const tenant =
629
684
  get_tenant_from_req(socket.request, subdomainOffset) || "public";
630
685
  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);
686
+ const state = getState();
687
+ if (state) {
688
+ const socketIds = state.getConfig("joined_log_socket_ids");
689
+ const newSocketIds = socketIds.filter((id) => id !== socket.id);
690
+ await state.setConfig("joined_log_socket_ids", newSocketIds);
691
+ } else {
692
+ console.error("No state found in socket disconnect");
693
+ console.error("The current tenantSchema is:", db.getTenantSchema());
694
+ console.error("The current tenant from request is:", tenant);
695
+ console.error("node version:", process.version);
696
+ }
634
697
  };
635
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
636
- else f();
698
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
699
+ else await f();
637
700
  });
638
701
  });
639
702
 
@@ -681,8 +744,8 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
681
744
  callback({ status: "error", msg: err.message || "unknown error" });
682
745
  }
683
746
  };
684
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
685
- else f();
747
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
748
+ else await f();
686
749
  }
687
750
  );
688
751
  socket.on("write_to_stream", async (data, callback) => {
@@ -744,8 +807,8 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
744
807
  }
745
808
  });
746
809
  };
747
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
748
- else f();
810
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
811
+ else await f();
749
812
  });
750
813
  });
751
814
  };
@@ -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)